Skip to main content
Associate III
January 21, 2026
Solved

Serial communication limited to 512 bytes

  • January 21, 2026
  • 4 replies
  • 521 views

Hello, I am using a NUCLEO-H7A3ZI-Q to send and receive packets over serial. I have a varying payload size, so I am using: HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_buffer, 4096); as this searches for an idle at the end of the frame to begin processing this data. 

To process this data and copy it into a look up table (LUT)  capable of being 0-4096 bytes long I have this following script; which comprises two uint8_t into one uint16_t to be represented by a 12-bit DAC, hence the clipping if they exceed 0FFF (4095).

This receives and writes perfectly up to 512 bytes of memory (256 uint16_t within the LUT), however above this all remaining values in the LUT are left unpopulated. 

uint16_t length = 0;
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size){
 if (lut != NULL) {
 HAL_DAC_Stop_DMA(&hdac1, DAC_CHANNEL_1);
 free (lut);
 lut = NULL;
 }
 if(rx_buffer[0] == 0XAA) {
 length = rx_buffer[2] | (rx_buffer[1] <<8);
 frame_rate = rx_buffer[3];
 mode = rx_buffer[4];
 if (mode >=3){
 mode = 0;
 }
 uint16_t receive = __HAL_DMA_GET_COUNTER(huart3.hdmarx);
 if (receive >= length + 5) {
 lut = malloc ((length/2)*sizeof(uint16_t));
 for (uint16_t k = 0, i = 5; i < length + 5; ++k, i += 2){
 lut[k] = (rx_buffer[i+1] | rx_buffer[i] << 8);
 if (lut[k] >= 4095) {
 lut[k] = 4095;
 }
 }
 }
 mode_init = 0;
 HAL_StatusTypeDef status = HAL_UART_Transmit_DMA(&huart3, lut, length);
 }
 HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_buffer, 4096);
}

I have tried moving the DMA ram address to 0x3 and the rx_buffer appears to be populating fully, however this is not being transfered to the LUT

.RxDmaSection :
{
KEEP(*(.RxDmaSection))
} > RAM_CD

Edited to apply source code formatting - please see How to insert source code for future reference.

Best answer by Pincate

This was caused by a hardware limitation on my DMA. I worked around this with a circular buffer copying data to memory as soon as it arrived with half time and full time events with idle events capturing remaining data.

 

This guide covers the basis for the method I used.

 

STM32 UART DMA Receive Example | Normal & Circular Mode

4 replies

gbm
Principal
January 21, 2026

I would first suggest to get rid of dynamic allocation which is not useful in your case and could lead to serious errors. simply declare the array for the maximum possible size of data.

Show the declaration of lut  and rx_buffer. Check the DMA settings - both source and destination sizes should be the same - byte.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
mƎALLEm
Technical Moderator
January 21, 2026

+

what would be the scenario when malloc returns a NULL pointer in the callback?

 lut = malloc ((length/2)*sizeof(uint16_t));

 

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."
PincateAuthor
Associate III
January 21, 2026

If length/2=0 there shouldn't be any values in the payload, therefor the payload is assigned zero bytes of memory and nothing is populated. If the payload is populated then (receive >= length + 5) would be voided and the LUT would not be populated. 

PincateAuthor
Associate III
January 21, 2026

Pincate_0-1769013381125.png

Initial state where a 127 uint16_t sample sin wave is transmitted over UART to the MCU, and is outputted to the DAC

Pincate_1-1769013464892.png

The interrupt is retriggered and the frame: AA 00 00 00 01 is sent containing length and frame rate of 0, and no payload, resulting in no hard fault, and stopping output from the DAC

Pincate_2-1769013874520.png

 

and then returning to the sin wave

 

Are you able to shed any insight on how HAL_UARTEx_ReceiveToIdle_DMA and HAL_UART_Receive_DMA work? Especially with varying payloads? And how HAL_UART_Receive_DMA can trigger without size being satisfied? 

PincateAuthor
Associate III
February 18, 2026

The rx_buffer is not populating, so the issue lies outside of this code, I have reworded this question in this forum: New Forum Post .

mƎALLEm
Technical Moderator
February 18, 2026

Hello @Pincate ,

If you solved the issue and you raised another question, you need to accept as solution one of the posts above that answered your question or at least guided you to the solution.

Otherwise, you need to keep the discussion here instead of creating another post for the same issue.

Thank you.

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."
PincateAuthorBest answer
Associate III
February 26, 2026

This was caused by a hardware limitation on my DMA. I worked around this with a circular buffer copying data to memory as soon as it arrived with half time and full time events with idle events capturing remaining data.

 

This guide covers the basis for the method I used.

 

STM32 UART DMA Receive Example | Normal & Circular Mode