cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 TXE flag not activating

Rob Meades
Senior

We have a very simple, blocking, UART transmit routine, which writes a byte and waits for TXE to become active. Every so often, and I mean something like 1 in 100,000 or more calls, it gets stuck at line 3 of the code pasted in below; TXE never becomes active, the byte we have written to the transmit data register is never, ever, transferred out of the transmit data register. We're pretty sure that flow control is not the cause; the device at the other end of the link should not be pulling CTS low, and certainly wouldn't be doing so indefinitely.

Is there anything else, anything else at all, which might prevent the transmit data register emptying on such a very intermittent basis?

while (sizeBytes > 0) {
    LL_USART_TransmitData8(pReg, pBuffer));
    while (!LL_USART_IsActiveFlag_TXE(pReg)) {}
    pBuffer++;
    sizeBytes--;
}
while (!LL_USART_IsActiveFlag_TC(pReg)) {}

The full source file for the entire UART driver that this is a part of can be found here:

https://github.com/u-blox/ubxlib/blob/master/port/platform/stm32cube/src/u_port_uart.c#L1303

8 REPLIES 8

Should really front-test for TXE, so you're not blindly writing to a register that's not empty.

There's a TE bit in the configuration register. Also UE bit

Dependency on the input clock.

Whats the reporting on the status registers in this situation?

Sure it's not hung up on the TC bit ?

Shouldn't get impacted by Rx side, or viewing registers via debugger.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Rob Meades
Senior

Thanks for the swift suggestions.

Could front test for TXE but this function is the only one writing to it and we don't _really_ care if we lose whatever could have been left there after the various LL init calls.

We identified that it is line 3 through an inactivity detector task (set to 60 seconds) that derives a back-trace; I will try instrumenting that detector with some reads of the other UART register contents and will re-run until this happens again; it really is very rare but when it happens it is darned irritating.

TDK
Guru

> LL_USART_TransmitData8(pReg, pBuffer));

Missing a parenthesis there, and seems like yo should be passing *pBuffer instead. Perhaps unrelated to the issue.

Check for OVR error condition.

Reading and printing out the UART register values in the "stuck" condition would no doubt be enlightening.

> We're pretty sure that flow control is not the cause; the device at the other end of the link should not be pulling CTS low, and certainly wouldn't be doing so indefinitely.

I would add checks to the CTS signal line to verify that's not the case. "Pretty sure" does not inspire confidence.

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

Coincidentally I was debugging a UART Tx hang yesterday. This was an afterthought, to tap into an existing stream using USB for debug purposes, and while at it, enable changing baudrate from USB for extra flexibility - as long as there's no application running on host, there's nothing to set the baudrate, right? Wrong. The class driver in Windows is kind enough to proactively set zero baudrate upon connection, just to show who's the boss here. And, zero bauds in STM32 UART means hanging Tx (I may have a gotcha on this, so it's double the shame on me).

Debugged as usually: using debugger broke in when froze and observed ALL UART registers. It's post-mortem so it already doesn't matter tha it's intrusive.

JW

PS. Surely, "pretty sure" with CTS involves observing the CTS line physically?

Rob Meades
Senior

@TDK​: yes, sorry, `pBuffer` is a void pointer so there are casts to make the compiler happy, removed in the code I pasted [since there is nothing "statically" wrong with this code] to make it easier to read and I introduced some syntax errors in doing so; the full code is at the link.

The problem takes a day or two to occur, and on an automated test system which tests this and other (non-ST) platforms, hence it is difficult to do intrusive hands-on type debug/monitoring: can I read the state of the CTS line as seen by the STM32F4 UART HW?

@Community member​: interesting! The CTS line thing is, of course, an assertion on my part, based on the same peer entity being stimulated with the same test sequences that are being run from Nordic, Espressif, Linux and Windows platforms as well this STM32F4 case; this is the only case in which we see the problem. But, as you point out, it is an assumption.

> The problem takes a day or two to occur,

I usually start with attempting to increase problem occurence with artificially throwing at the target as much stimuli as possible, regardless of whether it realistically can occur or not.

You can also connect debugger while avoiding reset, this has different names in various toolchains (HotPlug, for example).

> can I read the state of the CTS line as seen by the STM32F4 UART HW?

Digital inputs work as long as pin is not set to Analog.

JW

Rob Meades
Senior

@Community member​: great, I will instrument the inactivity detector task and set off as many automated test runs as I can [without upsetting everyone else who uses the system] in the hope of catching an instance of the "stuck" case along with some useful information.

Rob Meades
Senior

To conclude this, after a few more occurrences of the failure mode over the last three weeks, I now believe the problem is NOT anything to do with the STM32F4: it appears to occur only with one of the two test peers we are using, the thing at the other end of the UART, and always in a similar place in a sequence of commands that we are sending to the test peer.

Hence I now believe the problem is actually with the thing at the far end crashing in an interesting/rare way and letting CTS float high; this is just more noticeable on STM32F4 because of the very small UART transmit buffer.

Thanks anyway for the help guys!