cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H753ZI UART DMA issue

A3
Associate III

I am using UART Receive DMA in circular mode. I am expecting 8 bytes of data to be received on the UART from another device. Hence, I am using "HAL_UART_Receive_DMA(&UartHandle, (uint8_t *)aRxBuffer, 8)". The problem is when a burst of more than 8 bytes of data comes, it overflows to the start of the buffer. In a burst of more than 8 bytes, let's say 5 bytes more. That 5 bytes I want to ignore and don't want that 5 bytes to overflow at start and update the buffer. Please let me know the possible solution. With the present configuration, when USARTx_DMA_RX_IRQHandler is triggered, buffer has already received and overflowed data. How can we keep track that 8 bytes received and how we can avoid updating the buffer for next 5 unwanted bytes

Below is the code snippet to configure UART RX DMA:

 

/* Configure the DMA handler for reception process */

hdma_rx.Instance         = USARTx_RX_DMA_STREAM;

hdma_rx.Init.Direction      = DMA_PERIPH_TO_MEMORY;

hdma_rx.Init.PeriphInc      = DMA_PINC_DISABLE;

hdma_rx.Init.MemInc       = DMA_MINC_ENABLE;

hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_rx.Init.MemDataAlignment  = DMA_MDATAALIGN_BYTE;

hdma_rx.Init.Mode        = DMA_CIRCULAR;

hdma_rx.Init.Priority      = DMA_PRIORITY_HIGH;

hdma_rx.Init.FIFOMode      = DMA_FIFOMODE_DISABLE;

hdma_rx.Init.FIFOThreshold    = DMA_FIFO_THRESHOLD_FULL;

hdma_rx.Init.MemBurst      = DMA_MBURST_INC4;

hdma_rx.Init.PeriphBurst     = DMA_PBURST_INC4;

hdma_rx.Init.Request       = USARTx_RX_DMA_REQUEST;

6 REPLIES 6
Pavel A.
Evangelist III

when a burst of more than 8 bytes of data comes, it overflows to the start of the buffer.

For this, there's the "half size completed" callback. There you can save the first 4 bytes.

 

 

Karl Yamashita
Lead III

Copy the DMA buffer to a larger secondary circular buffer. That way you can parse the secondary buffer while the DMA is filling the primary buffer without worrying about the previous data being overwritten.

Make use of HAL_UART_RxCpltCallback and HAL_UART_RxHalfCpltCallback so that way you can't miss any data while copying data from the primary buffer to a secondary buffer.

 

 

Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.

Hi,

Thanks for prompt reply!

I am using HAL_UART_RxCpltCallback and inside that I am parsing 8 byte of data.

The data received will not be a continous data. It will be a 8 byte data and will be triggered only when something is required to be executed. It is like a command data. In normal scenario, it is always working fine, but sometimes when garbage data comes, the size of the burst becomes more than 8 byte, which is when the next reception onwards, it fails to understand the command, since there is a shift of X bytes in the next HAL_UART_RxCpltCallback.
Is there any way to know that x number of data is received in circular DMA buffer and any option to reset the DMA buffer to start at first memory location.

Note: There is no start of frame and end of frame for the command (8 byte data)

KnarfB
Principal III

two more options, depending on your use case:

- use the idle interrupt which will will trigger after the burst,

- use DMA with a larger circular buffer and read periodically in a background task wihtout using the DMA interrupts.

The background task inspects the DMA registers and find out what's newly arrived, see MaJerle/stm32-usart-uart-dma-rx-tx: STM32 examples for USART using DMA for efficient RX and TX transmission

It doesn't habe to be a task, could be the main loop, the idle interrupt.

Then, parse the new stuff in a defensive way, prepared to handle any kind of error.

hth

KnarfB  

A3
Associate III

How to enable the idle interrupt? Can you share any link for the same

Ideally, you should be fixing the issue with why the sending device is sending more than 8 bytes.

 

I assume your 8 bytes are binary data? If you can restructure your packet to include a checksum, then take a look at this project https://github.com/karlyamashita/Nucleo-G431RB_UART_Packets

This will sort through a packet that has extra bytes, missing bytes and corrupt bytes. It will then queue the good packet while discarding any bad packets.

The project will then check for a pending packet and echo it back. In your case, you can do what you need to with a good packet. 

For project/demonstration, I use Docklight to send a packet of 7 bytes that will append a MOD256 checksum, so total of 8 bytes. In your case you would need to update the data structure to receive 9 bytes.

For your sending device you can use this checksum driver https://onlinegdb.com/6b1pl9jq0

 

 

 

 

Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.