cancel
Showing results for 
Search instead for 
Did you mean: 

Are HAL_UART_RxCpltCallback() and HAL_UART_RxHalfCpltCallback() called to late?

TheaArt
Associate III

Hello community,

I experienced a strange behavior, when when using the UART-DMA-mechanism.

The MCU is a STM32L051R6T6, and I use CubeIDE with HAL-drivers.

I receive a cyclic telegram of 40 bytes on both USARTs.

The telegram starts with two detection bytes, then a telegram counter byte follows. After this header follows the payload and the last 4 bytes are a CRC32. It runs on 9600 baud, the telegram (oscill. checked) is 40ms long, the a idle time of about 10ms.

Since a DMAbuffer of 40 bytes brought me to the result, that sometimes a telegam is overwitten before I could copy it away in HAL_UART_RxCpltCallback, I now use a 80 bytes DMAbuffer. and both, the HAL_UART_RxCpltCallback and HAL_UART_RxHalfCpltCallback.

In most cases this works: At first I copy away the DMABuffer, then I scan for the header bytes. (In HAL_UART_RxHalfCpltCallback I scan from the middle of the buffercopy, in HAL_UART_RxCpltCallback I scan from the start to the middle). So I should find one telegram, while the UART writes the other one and then pauses for the 10ms gap between the telegrams.

But sometimes it seems, that the callback are called so late, that also the telegram after the next is in write progress. I debugged the dmacopy and I saw it on the telegram counters. Called from HAL_UART_RxHalfCpltCallback in the second part should be the lower telegram counter and in the first part should be the higher telegram counter and called from HAL_UART_RxCpltCallback I should find the lower counter first then the higher counter. Thats not the case sometimes. So I get a CRC Error. (when I manually decremet the counter, the CRC is ok). So it is partly overwritten by the after next one.

This behavior only happens, if I transmit on the UARTS (by interrupt) meanwhile in the maincycle.Without transmitting, everything works without any problem.

Is it possible, that the the Rxcallbacks of the HAL are called to late somehow?

Thank you. I hope you could understand, what I mean.

3 REPLIES 3
KnarfB
Principal III

> (In HAL_UART_RxHalfCpltCallback I scan from the middle of the buffercopy, in HAL_UART_RxCpltCallback I scan from the start to the middle)

No. When HAL_UART_RxHalfCpltCallback is called, the first half of the entire DMA buffer has just been written by DMA and shall be scanned by your software. When HAL_UART_RxCpltCallback is called, the second half of the entire DMA buffer has just been written by DMA and shall be scanned by your software.

If you have already used a scope, use a GPIO to indicate when callbacks are called and get an idea about the timing.

Generally HAL introduces some overhead but that should not be relevant for 9600 baud UART input.

hth

KnarfB

I also thought, that 9600 is not so fast.

The idea with scanning in the "wrong" part of DMAbuffer is because DMABuffer start is not telegram start. Maybe I could do a little ascii graphic:

|0|0|0|0|0|0|0|0|0|0|1|1|1|1|1|1|1|1|1|1|
|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|
|c|c|c|a|b|5|d|d|d|c$c|c|c|a|b|6|d|d|d|c|
 
a and b header
number counter
d payload
c crc32
$ halfComplete position
Telegramlength 10
Dmalength 20

This is (or should be) the situation at HAL_UART_RxCpltCallback:

in first part lower telegram counter 5, in second part higher number 6. When I would start to read in the middle, I would only find a half telegram (number 6) and then onwards from the start some old crc data from a past telegram (or maybe the crc of telegram number 6, thats not shure).

But when I start from the DMAstart + 1 (and scan for a single telegram length) I will find telegram (number 5). After the interrupt the DMA is written up to position 02, then there should be a 10ms pause because of the gap in the telegrams. My telegram to be scanned is not overwritten upto this time.

Am I wrong somehow?

But what I really saw in debugger when I look into the dma copy (which is created as the first instruction in callback) is this:

|c|c|c|a|b|7|d|d|d|c$c|c|c|a|b|6|d|d|d|c|

Where the crc on position 9,10,11,12 matches the telegram, if I change the telegrams number from 7 to 5.

So the copy has been created after writing the Header of the telegram but before writing its crc.

(mind you I'm in HAL_UART_RxCpltCallback).

Actually I'm testing a version, where I use two different dmacopys, one for halfCplt and one for Cplt. maybe this makes it better.

This was the solution: using two independent dmacopys in HAL_UART_RxCpltCallback and HAL_UART_RxHalfCpltCallback did the trick.

Now it seems to work.