cancel
Showing results for 
Search instead for 
Did you mean: 

Will USART send a TXE interrupt to NVIC if TXEIE is enabled AFTER TXE became set?

ilyus
Senior II

STM32F746-Disco board; Windows 10, STM32CubeIDE 1.7.0, empty project, only CMSIS and nothing else.

I'm writing an interrupt-based UART transmit driver with ring buffer on registers for the sake of learning (no DMA, that will come later, after I grow some IQ). Reading datasheet, reference manual and programming manual (for NVIC), I think I understand the stuff. The driver is not test-ready yet, it's work in progress, although the setup is done. I want to make sure I understand the stuff correctly.

To the point:

See the picture attached, top notch paint skills to explain how my uart tx ring buffer works.

In written form: I have an array that I use as a ring buffer for transmission. There is a pointer to the element that is currently being sent and the "after last element" pointer. When I reach the last element of array, I move to the beginning of the array. Hence, ring buffer.

Now, imagine I'm already sending something. At that moment I have another send request. What I do is I check how much free space my ring buffer has (buffer size minus how many chars are still waiting to be sent), and if it fits, it sits I write that new data into the buffer and move after last pointer accordingly. Basically, append it to what's already waiting to be sent.

However, it got me thinking. Since I have a whole UART frame to load the next byte into send register (Transmit Data Register, USART1->TDR) before Transmission Complete flag is set, I thought I could disable UART interrupts (transmit, more specifically TXE) while I load new data into buffer ring array. But I still want them to become "pending" so that when I reactivate interrupts after the data is loaded into buffer, the program will see those interrupts happened and deal with them (so if I need 1 UART bit of time to copy the data into buffer, on bit 2 the MCU will load the next byte into USART1->TDR).

There are several things to consider here:

  1. I don't want to disable UART interrupts in NVIC in general as it will damage receiver function (not written yet, but will be of course)
  2. Which means, I need to disable UART TXEIE (TDR empty interrupt enable), then run buffer load function, then re-enable the interrupt.

Question: imagine I have TXEIE=1 (TXE interrupt enabled), but TXE = 0 (no interrupt). Then I disable TXEIE=0, so TXE=1 will trigger no interrupt. But TXE=1 happens, no interrupt is sent to NVIC. AFTER TXE=1 happened, I enable TXEIE again. Will TXE interrupt fire or do I need to check TXE manually for being 1 immediately after I enable TXEIE?

As promised, here is my crude visual representation of what I'm doing. Not really that important for the question, but still.

Also, question 2. Not directly related, but while I'm at it. If I have UART trigger interrupt, but UART interrupt is disabled in NVIC, will it fire after I enable interrupt in NVIC?

Also, if you're in the mood, feel free to criticize my algorithm, always open to feedback, especially given I'm a developer larva.

0693W00000JO5qQQAT.png 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

> which means once the interrupt fires I need to make sure TXE is cleared

Yes, you need to clear the interrupt or disable it.

You can't clear the TXE flag with a clear flag in UART mode, you can only write to TDR to clear it.

> Also, question 2. Not directly related, but while I'm at it. If I have UART trigger interrupt, but UART interrupt is disabled in NVIC, will it fire after I enable interrupt in NVIC?

Also yes.

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

View solution in original post

7 REPLIES 7

Top line question, yes.

It will also keep firing if your handler doesn't fill the TDR to clear the TXE​

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

which means once the interrupt fires I need to make sure TXE is cleared. Either by actually sending something (to TDR) or by clearing TXE manually via clear flag. Correct?

TDK
Guru

> which means once the interrupt fires I need to make sure TXE is cleared

Yes, you need to clear the interrupt or disable it.

You can't clear the TXE flag with a clear flag in UART mode, you can only write to TDR to clear it.

> Also, question 2. Not directly related, but while I'm at it. If I have UART trigger interrupt, but UART interrupt is disabled in NVIC, will it fire after I enable interrupt in NVIC?

Also yes.

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

Oh yes, it says only in SmartCard Mode.

TXE: Transmit data register empty

This bit is set by hardware when the content of the USART_TDR register has been

transferred into the shift register. It is cleared by a write to the USART_TDR register.

The TXE flag can also be cleared by writing 1 to the TXFRQ in the USART_RQR register, in

order to discard the data (only in Smartcard T=0 mode, in case of transmission failure).

Well, not that I was going to discard it anyway.

With UART interrupt it's clear.

How does NVIC remember that UART fired before its interrupt was enabled in NVIC, how does it know that UART interrupt fired? There are no registers in Programming Manual that seem to contain that kind of data. It clearly won't be in pending interrupts because the interrupt is disabled.

They're hardware state machines, it doesn't need to remember anything.

If TXEIE & TXE -> NVIC pending ISR is set.

If NVIC pending ISR set and enabled -> ISR fires.

These statements are executed continuously. (This description is simplified a bit.)

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

Your hardware state machine statement was totally unclear, but everything after that makes perfect sense. I thought interrupt can't become pending if it's not enabled. Now it makes perfect sense. I guess I have all my questions answered. Much appreciated!

kta
Associate II

Hello,

What do you mean by continuously? Do you mean periodically with a set period?
Also, you mention that this description is simplified a bit, do you know where can I get exact description of that?

BR,

kta