cancel
Showing results for 
Search instead for 
Did you mean: 

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

nobbyv77
Associate II

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

2 REPLIES 2

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 Venmo
Up vote any posts that you find helpful, it shows what's working..
Guenael Cadier
ST Employee

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