Skip to main content
Brian H
Senior
February 27, 2026
Question

HAL_UART_Receive_* causes active transmission to stall

  • February 27, 2026
  • 1 reply
  • 197 views

tl;dr - HAL_UART_Receive_XXX, HAL_UART_Transmit_XXX == happiness; HAL_UART_Transmit_XXX, HAL_UART_Receive_XXX == misery.  The call to HAL_UART_Receive_XXX causes the transmission started by HAL_UART_Transmit_XXX to stall in both interrupt and DMA modes.

Longer story:

This affects both interrupt-driven and DMA operation, which is why I've added the DMA label.

I am using FreeRTOS, and implementing a serial protocol that, while practically half-duplex in behavior, is written in a full-duplex form.  What I mean is the protocol doesn't really expect both sides to be transmitting at the same time, but the code isn't written to prevent it.  Theoretically parts of the protocol could overlap.

The typical behavior for a transmission is to first call HAL_UART_Receive_DMA(..) to prime the receiver for a response, and then call HAL_UART_Transmit_DMA(..) to send a message.

When the calls occur in that order, everything works perfectly.

Unfortunately, sometimes the task responsible for calling HAL_UART_Receive_DMA is preempted by the task which calls HAL_UART_Transmit_DMA, reversing the order of the calls.

This predictably leads to the transmission stalling.  This happens whether I'm using interrupt-driven or DMA transmission.

With interrupt-driven transmission, I was able to instrument the UART IRQ handler and discover that transmission stalled because the TXEIE bit wasn't set, so the TXE interrupt didn't fire and the IRQ handler didn't feed more data to the TX FIFO.  With DMA operation, I haven't uncovered the cause of the stall but I expect it's something similar.

My hypothesis is that something in the HAL_UART_Receive_* code leads to TXEIE being cleared (or similar for DMA), although reading the library code, I don't see where it would happen (but the effect is observable; the TXEIE bit is not set when it should be).

I think I've successfully coded around the problem, using state variables to ensure the TX and RX calls happen in the correct order (tests are underway as I write), but...I shouldn't have to do that, should I?  Is there a reason I should expect HAL_UART_Receive_* to cause an active transmission to stall?  Can I call this a HAL bug?

1 reply

TDK
Super User
February 27, 2026

The recent HAL releases treat RX and TX independently. They should work okay regardless of the order in which you call them.

Showing the full code that is producing the problem may help. Strip things down to a minimally reproducible example. 

"If you feel a post has answered your question, please click ""Accept as Solution""."
Brian H
Brian HAuthor
Senior
March 3, 2026

How recent?  I know I'm not on the latest*, as updating has a nasty habit of breaking things.  Is the "recent" behavior a noted change from older versions, such that I might reasonably expect a difference if I update?

An MCRE will have to be a project for another day.  It should be easy enough to prove, but I'll have to filter the work in with my other responsibilities.  The full code of my project is definitely not suitable for sharing.  Hopefully I'll have time for that next week.

 

* - my version doesn't have const-correct APIs in a lot of places, which I've learned was fixed somewhere along the way.

TDK
Super User
March 3, 2026

The full history is available online:

STMicroelectronics/stm32f1xx-hal-driver at fee494a92b5ad331f92ad21f76c66a5cb83773ee

Treating TX/RX independently correctly has been there for 4 years.

> updating has a nasty habit of breaking things

And fixing things, such as this. Two steps forward, one step back (sometimes). That is the nature of progress.

"If you feel a post has answered your question, please click ""Accept as Solution""."