cancel
Showing results for 
Search instead for 
Did you mean: 

UART interrupt handler callback is called twice, if bus idle happens at "dma pos"="half dma buffer size"

HSagh.1
Associate II

STM32CubeL4, v1.17.2 in function HAL_UART_IRQHandler() at line 2524.

When handling bus ideal situation, there is no condition to prohibit calling the callback if nb_remaining_rx_data = huart->RxXferSize/2. So, both Dma half transfer complete and bus ideal situations call the callback function. Then, the callback is called twice with the same "pos", and therefore, the user code in the callback routine may think a whole dma length is recieved and dma buffer pos is wrapped back to the same "pos". This causes data corruption.

Adding the condition above to the already existing condition for dma full transfter complete fixes the problem.


_legacyfs_online_stmicro_images_0693W00000bktGYQAY.pngpossible fix:


_legacyfs_online_stmicro_images_0693W00000bktGiQAI.png

2 REPLIES 2
Karl Yamashita
Lead III

Assuming you're using HAL_UARTEx_ReceiveToIdle_DMA, yes there is an interrupt for half and full callback so there will be 2 interrupts, if you set the Size to receive for the size you are expecting.

So you just have to think ahead of these half/full callbacks by setting the data size to twice as big as the biggest packet you are expecting.

So if your packet is 20 bytes, then set the size to receive to 40 bytes. That way HAL_UARTEx_ReceiveToIdle_DMA will interrupt at 20 bytes which is half callback of 40 bytes. The Size will return 20 as well. Then you call HAL_UARTEx_ReceiveToIdle_DMA again. Doing it this way you don't get the full callback interrupt or the 2nd interrupt.

It also won't hurt if you set for 256 bytes because after 20 bytes you'll get the idle interrupt which will still return the 20 bytes and the Size argument returned is 20. So you will only get one interrupt for the 20 bytes you are expecting.

So there is no need to modify the HAL file.

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.
HSagh.1
Associate II

Actually I'm using DMA in circular mode so I don't have to keep calling that function.

Anyway, this does not answer my quesion. If you have a look at the comment in the above line, it says "If all expected data are received, do nothing, (DMA cplt callback will be called)." which is right. However, the same thing must be applied to half interrupt as well. Idle and half interrupts musn't call the callback at the same time. This condition is missing.