cancel
Showing results for 
Search instead for 
Did you mean: 

Is the HAL_UART_Transmit_IT function thread safe?

jg_spitfire
Senior

Hi, I am developing an application which involves UART for the STM32F411VE, I am using FreeRTOS and I want to know if the HAL APIs and the HAL_UART_Transmit_IT in this case are thread safe, thanks

1 ACCEPTED SOLUTION

Accepted Solutions
Foued_KH
ST Employee

Hello @jg_spitfire​ ,

UART hardware generally have a transmit shift register (TSR) and some kind of data register (DR). The software loads the DR, and if the TSR is empty, DR is instantly transferred into TSR and TX begins. The software is free to load another byte into DR, and the hardware loads the new byte from DR to TSR whenever the TX (shift-out) of the previous byte finishes.

Hardware provides status bits for querying the status of DR & TSR. This way, the software can using polling method and still achieve continuous transmission with no gaps between the bytes.

for freeRTOS, obviously, your TX task needs to be polling UART status bits.

The general rule of RTOS is that if you are waiting for something to happen, your task needs to be blocked so other tasks can run.

Your task blocks on task notification, (ulTaskNotifyTake()), and the interrupt gives the notification using xTaskNotifyGive().

So, I can't imagine any other way without using interrupts. It makes no sense to block - unblock with each byte.

So, Move TX handling completely to interrupt handler (ISR), and notify the task when TX is completed.

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

3 REPLIES 3
Foued_KH
ST Employee

Hello @jg_spitfire​ ,

UART hardware generally have a transmit shift register (TSR) and some kind of data register (DR). The software loads the DR, and if the TSR is empty, DR is instantly transferred into TSR and TX begins. The software is free to load another byte into DR, and the hardware loads the new byte from DR to TSR whenever the TX (shift-out) of the previous byte finishes.

Hardware provides status bits for querying the status of DR & TSR. This way, the software can using polling method and still achieve continuous transmission with no gaps between the bytes.

for freeRTOS, obviously, your TX task needs to be polling UART status bits.

The general rule of RTOS is that if you are waiting for something to happen, your task needs to be blocked so other tasks can run.

Your task blocks on task notification, (ulTaskNotifyTake()), and the interrupt gives the notification using xTaskNotifyGive().

So, I can't imagine any other way without using interrupts. It makes no sense to block - unblock with each byte.

So, Move TX handling completely to interrupt handler (ISR), and notify the task when TX is completed.

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Pavel A.
Evangelist III

In addition to what @KHALSI_Foued​ replied - HAL_UART_Transmit_IT by itself (and most of HAL interfaces generally) is not reentrant because it modifies a shared data structure (huart).

The HAL public functions look like they are protected by some lock, but in fact this thing is not a real RTOS-level lock (TL;DR) so if you call these functions from several threads, either add your own RTOS lock - or redesign and call them from a single thread.

gbm
Lead III

Hint: that's what mutexes were created for.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice