cancel
Showing results for 
Search instead for 
Did you mean: 

How to send a single USART character under interrupt, on an STM32H743?

CDew.1
Associate III

I have the following code, which is *almost* always working. (It typically gets stuck after 10-100K characters.)

void USART3_IRQHandler(void)
{
	if (LL_USART_IsActiveFlag_TXE(USART3)) {
		stats.txe++;
		if (LL_USART_IsEnabledIT_TXE(USART3)) {
			LL_USART_EnableIT_TC(USART3);
			LL_USART_DisableIT_TXE(USART3);
		}
	}
	if (LL_USART_IsActiveFlag_TC(USART3)) {
		stats.tc++;
		if (txbusy) {
			txbusy = 0;
		} else {
			Error_Handler();
		}
		LL_USART_DisableIT_TC(USART3);
	}
}

The intent is that txbusy should be set false once the serial port is ready to accept another outgoing character. (The type of txbusy is a global "volatile _Bool".)

The code above works for 10-100K characters, but then an interrupt is missed, txbusy is left as 1 and the rest of the program stalls.

What is the reliable way of sending single characters, and being able to test (without blocking) whether another character can be sent without corrupting the last character? (I want to poll to see if another character can be safely sent, in an infinite loop containing other tasks. No RTOS is in use.)

(I initially tried just using TXE, but I found I was missing ~30% of characters. The combined TXE/TC code does not miss characters, but does eventually gets stuck.)

1 ACCEPTED SOLUTION

Accepted Solutions
KnarfB
Principal III

> The type of txbusy is a global "volatile _Bool"

But, how is txbusy used? If you are polling txbusy, why are you using the interrupt and not polling the flag(s) instead?

View solution in original post

10 REPLIES 10
KnarfB
Principal III

> The type of txbusy is a global "volatile _Bool"

But, how is txbusy used? If you are polling txbusy, why are you using the interrupt and not polling the flag(s) instead?

You can poll to see if it is safe to write a character? Could you point me at documentation? (I'm new to the STM32.)

Seems convoluted , can't you just service the TXE with data from a buffer?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
KnarfB
Principal III
    while( (USART1->ISR & USART_ISR_TXE) == 0 );
    USART1->TDR = ... // next char

I don't use H7 but should work the same. There maybe LL macros for it too.

RM0433 Reference manual Chapter 48.

Thanks for the manual. I had found a 500-odd page PDF for the H743 and thought that it should have been complete. This monster is 3037 pages.

No, sorry, I have been instructed to do this character by character. It's not about efficiency, it's about working with (and not changing) existing code.

I don't need to use interrupts at all (for sending). I now just check LL_USART_IsActiveFlag_TC(USART3); if it's true, the code sends a byte with LL_USART_TransmitData8(USART3, byte); otherwise it tries again on the next run of the infinite loop.