How to send a single USART character under interrupt, on an STM32H743?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-23 9:06 AM
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.)
Solved! Go to Solution.
- Labels:
-
STM32H7 Series
-
UART-USART
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-23 9:17 AM
> 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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-23 9:17 AM
> 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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-23 9:21 AM
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.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-23 9:32 AM
Seems convoluted , can't you just service the TXE with data from a buffer?
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-23 9:33 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-23 9:43 AM
RM0433 Reference manual Chapter 48.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-24 2:10 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-24 2:18 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-24 3:02 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-24 5:17 PM
Do the same but wait for TXE bit. Look at @KnarfB​'s example.
