UART, UART, UART (and shell)

As explained in this post, we have decided to use FreeRTOS on our main board. Last week, Sibille and Vlaya have successfully adapted the frame sending code for SPI buses. For The past few days, Sibille and I have wrestled with the UART communication code. 

Here is how the code evolved since my last post.

Shell implementation

At first, when I began coding the UART server, it was closely related to the shell (over WiFi). I also communicated with the ChibiOS shell on the other side of the UART. The next step of my reflexion was to realize that it wasn’t natural to have the shell on the STM32 rather than the ESP32 and I stopped using the ChibiOS shell. 

Naturally, the immediate conclusion would be that I switched to a FreeRTOS shell on the ESP32 directly connected via WiFi to a distant client. However, the reality is not as convenient. It is possible to create a real flow similar to the one going through the UART. However, it is far more difficult here as it does not exist naturally like in the UART case. Moreover, we only need the shell for a few basic control commands. Thus, I estimated that it was not worth it to go through this. And I rapidly imitated the basic structure of the ChibiOS shell.

When the shell migrated to the ESP32 came the problem of parsing shell commands. When I first deleted the ChibiOS shell, nothing really replaced it. The ESP32 associated the commands to the correct UART port and sent the data directly through the UART. Then, I could get data from the UART either as raw data or as shell commands. The latter parsed the data so that it would be received as the traditional int argc, char** argv.

However, I realized that it was not good enough when I got an application waiting for data that could either come from the shell or a normal command. To be direct, it was the bottom_pcb application receiving the speed objective. The natural way for an application to send this is through an int, but the shell sends strings. Thus, I understood that the parsing was to be done directly on the ESP32 rather than when leaving the UART. I then changed the association of strings command names with UART ports to association with function pointers in charge of parsing the arguments and sending them in the UART if need be.

Transmitting binary data

I began coding the UART server and the shell at the same time. At this period, the shell was still on the STM32. Thus, I naturally used the “\r\n” sequence to spot the end of the messages when receiving as the shell needed them to acknowledge commands. Then, when the shell migrated on the ESP32, I realized that it was not very appropriate anymore and I switched to the classical ‘\0’ to end strings. However, I soon understood often, what would actually transit would be binary data rather than strings.

To tackle this problem, I first implemented a simple encoding from 4 bytes to 5. Indeed, we would mostly have to send integers. However, I soon decided to instead add a byte prefix to provide the length of the message. Indeed, not only is it simpler that way, it is also a lot faster and the message length is always shorter as well as in the best case of the encoded solution, we have to send one more bytes than the actual data (for one to four bytes of actual data).

Switching UART communication to FreeRTOS

Last step : adapting the code because of the migration under FreeRTOS. It seemed at first really simple but we struggled for a long time with baud rate issues. 

We still haven’t really understood why there is a problem : the ESP32 baud rate is 115200bps, and the configuration we set in STM32CubeMX (which generates code for the STM32) is also 115200bps. We manually verified the values inside STM32 USART registers, and they were consistent with a 115200bps baud rate. The logic analyser didn’t have any problem reading correctly the data transiting on the UART bus while configured with a 115200bps baud rate. Finally, we avoid the problem using the “Auto baud rate” option of the CPU : the baud rate is computed when any character starting with a ‘1’ is received. We simply had to send one more byte for each transaction from ESP32 to STM32 to guarantee the synchronization. It works fine but we didn’t have to use it with ChibiOS. 

Then, we had some troubles with task priorities. The thread receiving data prevented the thread sending data from using the UART bus even though it was asleep, waiting for data. What was even more troubling was that neither on ChibiOS nor with esp-idf (ESP32) did we have to care about this previously. We rather quickly solved this and the UART communication between the CPU and the ESP32 of the main board is now operational with FreeRTOS.

Next steps

In the days to come, Sibille and I will continue to work on the WiFi communication to share a common time reference between Phyllos and especially choosing a master for sending the tops. We will tackle the display of an animation synchronously by several Phyllos as well. We’ll keep you posted !

Leave a Reply

Your email address will not be published. Required fields are marked *