2026-02-27 11:46 AM
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?
2026-02-27 12:38 PM
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.
2026-03-03 11:23 AM
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.
2026-03-03 12:16 PM
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.
2026-03-04 6:53 AM - edited 2026-03-04 6:54 AM
This project started last year, so I wouldn't think the libraries would be four years out of date. I'll try to get that MCRE worked up this week.