cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UARTEx_ReceiveToIdle_DMA() => No reaction on IDLE event

Markus Spiekermann
Associate III

I'm trying to make use of the HAL_UARTEx_ReceiveToIdle_DMA() functionality.

So far no reaction on an IDLE event. The corresponding HAL_UARTEx_RxEventCallback

gets called when a certain amount of bytes has been received, but not on an IDLE event.

The development board I use: NUCLEO-L031K6

The UART of interest:USART2

So here's my setup:

0693W00000bhDtDQAU.jpg0693W00000bhDtIQAU.jpg0693W00000bhDtNQAU.jpg0693W00000bhDtSQAU.jpg0693W00000bhDtcQAE.jpgI added the following code:

...

/* USER CODE BEGIN PFP */

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size);

/* USER CODE END PFP */

...

/* USER CODE BEGIN 2 */

HAL_UARTEx_ReceiveToIdle_DMA(&huart2, rx_buf_usart2, rx_buf_size);

__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

/* USER CODE END 2 */

...

/* USER CODE BEGIN 4 */

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)

{

if (huart->Instance == USART2)

{

HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);

HAL_UARTEx_ReceiveToIdle_DMA(&huart2, rx_buf_usart2, rx_buf_size);

__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

}

}

/* USER CODE BEGIN 4 */

...

rx_buf_size is set to 16. And exactly after 16 bytes the RxEventCallback gets executed.

What am I missing?

As you can see in my setup, the USART2 global interrupt ist set.

Could somebody point me in the right direction to look for the problem?

Thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
Karl Yamashita
Lead III

That's right i forgot that you get the 16 bytes.

I'd check the HAL status when you call HAL_UARTEx_ReceiveToIdle_DMA. More than likely it returns as HAL_ERROR. So based from the notes i highlighted it reverted to HAL_UART_RECEPTION_STANDARD. That would be the only explanation why you're not getting interrupts on idle.

Check the HALdriver stm32l0xx_hal_uart_ex.c and put a breakpoint on line 775 and see during debug if it breaks.

0693W00000bhGTSQA2.png

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.

View solution in original post

12 REPLIES 12
Karl Yamashita
Lead III

Here is a clue, you call __HAL_DMA_DISABLE_IT to disable the DMA interrupt, after you call HAL_UARTEx_ReceiveToIdle_DMA to enable the interrupt.

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.
Markus Spiekermann
Associate III

Hi Karl,

thank you for your post. The line

__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

should only disable the interrupt generated after half of the expected data has been received.

According to certain threads and forum messages this interrupt and the subsequently calling of

HAL_UART_RxHalfCpltCallback() are not necessary.

Anyhow, I'll try to comment this line and come back with the result.

Karl Yamashita
Lead III

Well if you design a ring buffer then you don't need to worry about trying to parse the first part of data when HAL_UART_RxHalfCpltCallback interrupts while the second part of the data is being saved in the data array.

See this post where i can accept up to 64 bytes and i have a queue to hold up to 4 RX messages. The Tx routine has the same concept so a message will never get lost because HAL was busy transmitting a previous message. https://community.st.com/s/question/0D53W00002CeLaOSAV/cannot-receive-full-string-on-uart-receive-st32h745-disco-board

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.
Markus Spiekermann
Associate III

In the end I will use a ring buffer, cause that is from my point of view the most convenient way to handle received data.

Ok back to the previous approach: I commented the line

__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);

out, but no change. No call to HAL_UARTEx_RxEventCallback after an IDLE situation.

Is there anything else what I could try?

Karl Yamashita
Lead III

I assume you're using the VCP? Did you check with an oscilloscope to see if the PC is sending data and you see data activity on PA15? Baud rates match?

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.
Yes, I am using the VCP. And I connected an oscilloscope with decoding functionality to monitor PA15.
The terminal software to send data via serial line is PUTTY. And as I already mentioned, I know that
data has been received, cause after exactly 16 Bytes the callback function gets executed due to
the RxCplt event.
Karl Yamashita
Lead III

That's right i forgot that you get the 16 bytes.

I'd check the HAL status when you call HAL_UARTEx_ReceiveToIdle_DMA. More than likely it returns as HAL_ERROR. So based from the notes i highlighted it reverted to HAL_UART_RECEPTION_STANDARD. That would be the only explanation why you're not getting interrupts on idle.

Check the HALdriver stm32l0xx_hal_uart_ex.c and put a breakpoint on line 775 and see during debug if it breaks.

0693W00000bhGTSQA2.png

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.
Piranha
Chief II

If the DMA (half)complete callbacks are working, but the IDLE does not, it means the UART interrupt for some reason doesn't work. Stop clicking and check the actual CubeMX generated bloatware.

Hi Karl,

it was not exactly the reason but the right direction. In fact I missed to check the

Status of the HAL between two conscutive called DMA functions.

Thanks