cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UARTEx_ReceiveToIdle_DMA() isn't working as expected

Praneeth
Associate II

Hi Everyone, I'm using Nucleo-f429 board and using HAL UART API's on it. I have observed that on using HAL_UARTEx_ReceiveToIdle_DMA()  for a receiving data of length 800. I found that Buffer getting filled / Interrupt is called once its size reached 64 even though there isn't any idle state and regardless of what data I'm passing.  

I have tried using this API for receiving data of length 50 (<64). Its working and interrupt is getting triggered once the idle state is seen at 50th element.
Could anyone help me out on this.

Required code snippets attached below

Thanks

 

edit:

 

#define BUFFER_SIZE 1000

extern unsigned char rxData[BUFFER_SIZE];

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */

/* USER CODE END USART2_MspInit 0 */
/* USART2 clock enable */
__HAL_RCC_USART2_CLK_ENABLE();

__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**USART2 GPIO Configuration
PA3 ------> USART2_RX
PD5 ------> USART2_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

/* USART2 DMA Init */
/* USART2_RX Init */
hdma_usart2_rx.Instance = DMA1_Stream5;
hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_rx.Init.Mode = DMA_NORMAL;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_usart2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_usart2_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_usart2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
{
Error_Handler();
}

__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);

/* USART2 interrupt Init */
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspInit 1 */

/* USER CODE END USART2_MspInit 1 */
}
}



void UART_data_Receive(void)
{
HAL_UARTEx_ReceiveToIdle_DMA(&huart2,rxData,BUFFER_SIZE);
  while(!UARTreceiveComplete){}  // Waiting till the UART data is received
}


void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart,uint16_t Size)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
if (huart -> Instance == USART2)
    {
HAL_GPIO_TogglePin(GPIOB, LD1_Pin);   // glowing the led1 for indication of data received
UARTreceiveComplete=1; // Enabling the flag
    }
}

 

 

7 REPLIES 7
TDK
Guru

What is BUFFER_SIZE?

Probably there is an idle interrupt, or your buffer size is too small to receive everything that once. Do you have a logic analyzer to verify there is no idle time on the bus? Probably your terminal program is breaking up the message into 64 byte chunks.

If you feel a post has answered your question, please click "Accept as Solution".
SofLit
ST Employee

Hello,

Please copy paste your code using the button </> instead of providing screenshots of your code.

Thank you for your understanding.

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

I have kept BUFFER_SIZE as 1000. Currently I don't have LA plot but I have checked it before and its not idle

The peripheral only triggers an interrupt on (a) line IDLE, (b) half-transfer complete, and (c) full transfer complete. There is no mechanism for HAL_UARTEx_RxEventCallback to get called without one of these taking place. You can view the source code yourself to verify this.

If you feel a post has answered your question, please click "Accept as Solution".

Is it anyway linked with FIFO size?

> Is it anyway linked with FIFO size?

No.

Set a breakpoint in HAL_UARTEx_RxEventCallback and look back through the call stack to see what flag exactly triggered it. Probably it is the idle frame, but perhaps we're missing something.

If you feel a post has answered your question, please click "Accept as Solution".

Your callback has no code checking for which interrupt occurred so how would you know it wasn't an idle interrupt?

Check the RxEventType to be sure what caused it to interrupt at 64 bytes

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart == uart2.huart)
	{
		switch(huart->RxEventType)
		{
		case HAL_UART_RXEVENT_HT:

			break;
		case HAL_UART_RXEVENT_TC:

			break;
		case HAL_UART_RXEVENT_IDLE:

			break;
		}

 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.