Synchronizing UART TX

The sketch of your control flow is basically ok, but see below. A customer of mine has used exactly that strategy successfully for a long time.

An alternative would be to use a flag along with a mutex: A task wanting to access the TX stream would claim the mutex, then clear the flag, then start the transmission and then poll the flag with a (2) delay. The flag would be set by the ISR. That strategy would use a mutex instead of a semaphore and make it easier to implement application level timeouts but of course would force a granularity to the transmission.

Note, however, that a UART in very very few instances is employed for a full duplex (or unacknowledged) protocol,and that means that there is no point in allowing several tasks to access the same UART concurrently, as each task that wants to transmit something must also synchronously wait for a response before another transmission can start. Generally it is preferrable to have only one task (typically a message pump) serve the UART exclusively (we discussed this before). The architecture to access the UART very strongly relies on the requirements and the restrictions of the protocol realized over it.

(cf Issue with uart RX data when sharing with multiple tasks - #6 by RAc)