cancel
Showing results for 
Search instead for 
Did you mean: 

UART receive command with DMA

Pincate
Associate III

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.

1 ACCEPTED SOLUTION

Accepted Solutions
Pincate
Associate III

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.

View solution in original post

6 REPLIES 6
TDK
Super User

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".
Pincate
Associate III

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

TDK
Super User

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".
Pincate
Associate III

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.

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".
Pincate
Associate III

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.