10
\$\begingroup\$

I know that the RX interrupt is obviously used to save polling, but why the TX one too?

\$\endgroup\$
4
  • 3
    \$\begingroup\$ Same reason. You're often sending a long message a character at a time. \$\endgroup\$
    – user16324
    Nov 21, 2016 at 21:32
  • 1
    \$\begingroup\$ Code that needs to do very little else can block on the actual transmission. More efficient code can drain a software buffer in the interrupt. Yet more sophisticated code on hardware that supports it can set up a DMA engine to pump the transfer without distracting the CPU from more important work, though as serial baud rates are often fairly slow in MCU terms that may not always be important. \$\endgroup\$ Nov 21, 2016 at 21:48
  • 3
    \$\begingroup\$ If you are asking about a UART TX interrupt on a particular type of device, then please post a link to its datasheet. \$\endgroup\$ Nov 21, 2016 at 21:54
  • \$\begingroup\$ The interrupt that others have mentioned signals that there is buffer space available in the uart for more transmit data. The buffer may be one or more bytes in length depending on the uart hardware. There is often a different "transfer complete" interrupt that signals that all bits have been shifted out of the uart. This may be used used for other purposes such as switching a transceiver from transmit to receive. \$\endgroup\$
    – Tut
    Nov 21, 2016 at 21:59

5 Answers 5

9
\$\begingroup\$

The main goal of the TX interrupt (really an END OF TX) is to send the content of a buffer (multiple bytes) automatically. When implemented in a proper way:

  1. Enable the TX interrupt.
  2. The user code starts transmission by sending only the first byte in the buffer.
  3. At the end of TX (of the first byte), an interrupt will be generated.
  4. In the TX ISR (Interrupt Service Routine), the code must send the next byte in the buffer and update the buffer index.
  5. At the end of this transmission, a new interrupt occurs, and so on, until the entire content of buffer is sent "automatically".
  6. Disable the TX interrupt.

The exact behavior depends on the microcontroller. That is a general description.

\$\endgroup\$
2
  • 4
    \$\begingroup\$ An easy simplification on many platforms is to have the user code merely be responsible for putting data in the buffer and enabling the interrupt; the ISR disables the interrupt if it fires when the buffer is dry. \$\endgroup\$
    – supercat
    Nov 21, 2016 at 22:29
  • 1
    \$\begingroup\$ This answer is quite misleading - UART tx interrupts usually indicate the holding register is empty (or FIFO low), independently of whether there's still data being shifted out of the shift register. (Hence the common driver approach that enables the tx interrupt without having written any tx data, which will immediately generate an interrupt - such that all tx data is written by the ISR, with no special handling for the first character.) 'End of tx' is a distinct condition discussed in other answers here. \$\endgroup\$
    – Jeremy
    Feb 2, 2021 at 11:15
8
\$\begingroup\$

The TX interrupt is mainly for longer datagrams. You can initiate the transfer for a buffer of known length (bytecount). Now you can push your buffer pointer as often as there are bytes to send, when the TX interrupt occurs. This ensures the "as quick as possible" transfer of your buffer, without the need to poll any "TransferComplete"-Flag/Statusbit.

\$\endgroup\$
2
\$\begingroup\$

Some UARTS have an internal buffer that is larger than one, the 16xxx series for one.

The procedure here was

  1. Set a transmit window mask, for example to 4 remaining.
  2. fill buffer positions until the UART said full or no more data need to be send
  3. do other stuff
  4. when only 4 buffer positions are left unsend, set TX interrupt
  5. wait for the interrupt to be serviced
  6. if more data needs to be send go to 2.

This decreases the CPU load by offloading some processing to the UART thus enabling slower CPU's to keep up and service other task instead of getting interrupted all the time.

\$\endgroup\$
2
\$\begingroup\$

The TX interrupt fires when there is space in the transmit buffer.

For devices that don't have a transmit buffer (i.e. where you write one byte, which is transferred immediately), the interrupt is asserted when the transmit register can be written with the next byte.

For devices with a buffer, the interrupt is asserted at an implementation-defined time. For some, it is when the buffer is half empty, for some it is when transmission of the last byte has started and the buffer is completely empty.

\$\endgroup\$
0
\$\begingroup\$

Another use case is when you connect the UART to another communication interface like RS485. The controller has to release the bus driver as soon as the last bit has been shifted out of the TX buffer. This is easy to handle in the TX interrupt, but would be cumbersome to implement without, since you would have to wait an exact time after writing the last byte to the output buffer which would also vary with baud rate.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ The RS485 usage works best if there's a transmit-complete interrupt available rather than just transmit-buffer-available. Especially on devices with big buffers, the only way to get an interrupt after the last useful byte is sent is to feed the UART unwanted additional bytes and hope one can disable the transmission before they go out. \$\endgroup\$
    – supercat
    Nov 21, 2016 at 22:27
  • \$\begingroup\$ @supercat: You are indeed right to point out that this would require a Tx complete interrupt. But i think this still relates to the question. \$\endgroup\$
    – Rev
    Nov 22, 2016 at 8:36
  • \$\begingroup\$ It's often possible to get by with just a buffer-available interrupt, but the tx complete interrupt is often better; I had been thinking that it might be helpful to amplify why some UARTs have separate interrupts for buffer-ready and transmit complete. \$\endgroup\$
    – supercat
    Nov 22, 2016 at 15:15
  • \$\begingroup\$ I'm mystified why so many UART designs lack a 'tx complete' interrupt. They almost always have a status bit representing this (or equivalent) condition, but including it in interrupt generation seems to be the exception rather than the norm. Especially unforgivable in microcontroller peripherals. \$\endgroup\$
    – Jeremy
    Feb 2, 2021 at 11:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.