Skip to main content
nobbyv77
Associate II
April 24, 2023
Question

UART Data Getting DMA'd In Wrong Order After First Packet

  • April 24, 2023
  • 2 replies
  • 1402 views

I have a device that receives six bytes via the UART. There is a known SOF and EOF byte. The first time I get the data, all is well. But subsequent receptions are "corrupted": either the EOF byte is first, or sometimes I get two SOF bytes in a row (and no EOF byte at all).

The DMA is set up for normal (non-circular) operation. Does anyone see why this would be happening? I only call the RX transfer after the callback has been run, so data still being transferred shouldn't be an issue.

int main(void)
{
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 
 /* Configure the system clock */
 SystemClock_Config();
 
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_USART2_UART_Init();
 MX_LPUART1_UART_Init();
 
 /* Infinite loop */
 while (1)
 {
	 switch(state)
	 {
	 case STATE_READY_TO_RECEIVE:
	 Result = HAL_UART_Receive_DMA (&huart2, RX_Data, 6);
	 // check result for errors
	 break;
 
	 case STATE_READY_TO_SEND:
	 Result = HAL_UART_Transmit_DMA(&hlpuart1, ACK_Data, 3);
	 // check result for errors
	 state = STATE_SENDING;
	 break;
 
	 case STATE_RECEIVING:
	 case STATE_SENDING:
	 // Nothing to do, waiting for the hardware
	 break;
 
	 default:
	 // handle bad state error
	 break;
	 }
 }
}
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(RX_Data[0] == 0xA1)
 {
 state = STATE_READY_TO_SEND;
 }
 else
 {
 	memset(RX_Data, 0, 6);
 }
 //Process data
}
 
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
 if (state == STATE_SENDING)
 {
 state = STATE_READY_TO_RECEIVE;
 }
 else
 {
 // error - state machine broken
 }
}

This topic has been closed for replies.

2 replies

Tesla DeLorean
Guru
April 24, 2023

If you're dealing with multiple bytes you need to be dealing with the potential for bytes lost in reception, or synchronization issues.

The DMA/IT forms don't handle/manage timeout situations well.

On most STM32 there's an interrupt per-byte on UARTs, make something that manages this in a stateful manner. If the HAL doesn't suit this well, you're not obliged to use it.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Guenael Cadier
ST Employee
April 25, 2023

Hi @Community member​ 

Some questions to be sure to understand your use case :

  • what happens if some bytes are received during the transmit of Ack message ? I guess they will fill reception register and could lead to have overrun flag raised.
  • If Fifo are available on your STM32, are you using Tx and/or Rx FIFO ? this could help to reduce cases of overrun if Rx Fifo is enabled.
  • How is declared your "state" variable ? as addressed from IRQ routine and from main program, depending on compiler optimizations options, please make sure it is declared as "volatile" (or __IO).

Regards