yoneken / rosserial_stm32

This is a part of [rosserial](https://github.com/ros-drivers/rosserial) repository to communicate with ROS system through a USART for STM32 embedded system.
BSD 2-Clause "Simplified" License
218 stars 72 forks source link

Immediately send second half of message in case of tx bufferoverflow … #40

Closed maxi-naeher closed 1 year ago

maxi-naeher commented 2 years ago

Hello yoneken,

after doing some timing and performance testing I found a delay issue within the stm32 implementation.

Following scenario: A stm32 device communicates through rosserial with a raspberry pi. On the stm32 there is a input signal (green signal in image). When the input signal changes its level it publishes some information over rosserial/ros so the raspi sets a output signal (yellow signal in image). For example, for the time I press a button on the stm32, a LED lights up on the raspi.

Having that in mind, both the signals should have the same level sequence but with a normal delay in between (seen in blue square in image).

But this is not always true. As u can see in the red square in the image, in some cases the rosserial agent on the raspi doesnt process a incoming message. Meanwhile another message is beeing sent. At some point the rosserial agent on the raspi processes both message immediately one after another. The input pattern doesnt match the output pattern anymore and the timing gets falsified.

After digging into it, I found the problem inside of the flush method of STM32Hardware.h. Everytime the tx buffer overflows, half of the message is being stored in the remaining buffer space at the end of the tx buffer, while the other half is stored in the front of the tx buffer. The Problem is, only the first half of the message in the remaining buffer space is being sent out over UART. The other half in the front of the buffer is remaining there until another new message gets written into the buffer. Then the remaining half of the message is being sent out together with the new message.

As a result of this, everytime the tx buffer overflows, the rosserial agent on the raspi gets half of a message and waits therefore for the other half, which is only being processed with another new message (in a worst case scenario, the next message would be the time synch package which gets send out every 2,499 sec). This results in a delay which falsifies the timing history.

My approach of fixing this: Immediately send out the second half of the message in the front of the tx buffer after a buffer overflow occured.

example

yoneken commented 1 year ago

Genius!

tianyuZ commented 1 year ago

When the DMA transfer is completed, it will enter the interrupt and finally call the HAL_UART_TxCpltCallback callback function to transfer the remaining data again, so there is no need to immediately send out the second half of the message in the front of the tx buffer after a buffer overflow occured.