Skip to main content
Markus Spiekermann
Associate III
March 30, 2023
Solved

HAL_UARTEx_ReceiveToIdle_DMA() => No reaction on IDLE event

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.

This topic has been closed for replies.
Karl Yamashita
Karl YamashitaBest answer
Principal
March 31, 2023

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

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source

12 replies

Karl Yamashita
Principal
March 30, 2023

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.

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Markus Spiekermann
Associate III
March 31, 2023

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
Principal
March 31, 2023

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

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Markus Spiekermann
Associate III
March 31, 2023

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
Principal
March 31, 2023

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?

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Markus Spiekermann
Associate III
March 31, 2023
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
Karl YamashitaBest answer
Principal
March 31, 2023

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

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Markus Spiekermann
Associate III
March 31, 2023

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

Karl Yamashita
Principal
March 31, 2023

That is good to hear and that I was able to help get you in the right direction.

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Piranha
Principal III
March 31, 2023

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.

Markus Spiekermann
Associate III
April 21, 2023

Hi MClau.1,

well it would probably help in your situation if you would show us some portions of the code that you use to handle DMA transfers.

In general the ReceiveToIdle call activates three kind of interrupts:

IDLE => Reacts on IDLE events and the IDLE duration to react on depends on your configuration

HC => Reacts on DMA transfers when half of the data to receive or to send has been handled

TC => Reacts on DMA transfers when the entire amount of data to receive or to send has been handled

If the DMA request has been set to normal mode, then subsequently performed DMA transfers have

to be reinitiated by calling the ReceiveToIdle function again in case of an IDLE ot TC event.

And I think it is good practice to call HAL_DMA_GetState for the DMA channel of interest before

calling ReceiveToIdle. This way you ensure that all related DMA processes are done.