Skip to main content
Associate III
Jan 22, 2026 9:58 AM UTC
Solved

UART receive command with DMA

Hello, I have a query about how HAL_UART_Receive_DMA and HAL_UARTEx_ReceiveToIdle_DMA work?

For my application there is a varying payload size, so I am wondering how would I trigger the HAL_UART_Receive_DMA(&huart3, rx_buffer, 4096, 0xFFFF); interupt? As from my understanding it would be waiting for all 4096 bytes of data which won't arrive unless a different frame was sent.

Whereas  HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_buffer, 4096); triggers once the serial port stops communicating, however it stores the received data in 512 byte chunks, which has proven difficult to access when generating a LUT from the rx_buffer.

If anyone can shed some insight over how these interrupts work? And how to make them applicable for a variable payload would be great.

PincateBest answer
Associate III
Feb 19, 2026 1:50 PM UTC

The issue was caused by the DMA being configured to normal mode, and my hardware had a 512 byte cache that was filling up before triggering the interrupt or populating the buffer.

This was fixed by switching to circular mode.

6 replies

TDK
Jan 22, 2026 2:35 PM UTC

HAL_UARTEx_ReceiveToIdle_DMA should be used if you want notified when the stream becomes idle. Data is processed within the HAL_UARTEx_RxEventCallback callback which gets called in three cases:

  • When the data buffer is half-full (process first half of buffer)
  • When the data is complete (process second half of buffer)
  • When the stream becomes idle (process characters received)
"If you feel a post has answered your question, please click ""Accept as Solution""."
PincateAuthor
Associate III
Jan 22, 2026 3:46 PM UTC

Thank you. Do you know how the data is stored for both of these cases if using a DMA?

TDK
Jan 22, 2026 3:47 PM UTC

Data is stored in the buffer you point to. DMA transfers data from the peripheral to memory.

"If you feel a post has answered your question, please click ""Accept as Solution""."
PincateAuthor
Associate III
Jan 22, 2026 5:20 PM UTC

Thank you, from my understanding receive_to_idle stores the data in 512 byte segments, however when trying to write from this memory I have been struggling to access any data beyond this, even if I edit the address in the linker code, and check my buffer is fully populated.
the writing to a look up table is conducted as below:

 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;
 }
 }

 


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

TDK
Jan 22, 2026 5:49 PM UTC

There is no 512-byte restriction or limitation or feature within HAL_UARTEx_ReceiveToIdle_DMA. The length of data depends on the size of the buffer and how much data was received.

You can see a working example of HAL_UARTEx_ReceiveToIdle_DMA here:

STM32CubeF4/Projects/STM32446E-Nucleo/Examples/UART/UART_ReceptionToIdle_CircularDMA/Src/main.c at 7c6a0a09ecb81b360de396479e048907563f1d10 · STMicroelectronics/STM32CubeF4

Data available in buffer is passed as a parameter to HAL_UARTEx_RxEventCallback.

"If you feel a post has answered your question, please click ""Accept as Solution""."
PincateAuthorBest answer
Associate III
Feb 19, 2026 1:50 PM UTC

The issue was caused by the DMA being configured to normal mode, and my hardware had a 512 byte cache that was filling up before triggering the interrupt or populating the buffer.

This was fixed by switching to circular mode.