Search code examples
embeddedcpucpu-architectureinterrupthardware

Are hardware interrupts still needed on embedded devices (as opposed to flags)?


In general, ISR for hardware interrupts on embedded devices should be very short: Usually just setting a flag which will be read under the normal course of execution (e.g. in a task loop).

This begs the question: If so, what is the purpose of fullfledged hardware interrupts which interrupt control? Why doesn't the MCU simply set a flag (in a designated register, memory mapped), which can be checked by the task loop just the same? Why go through the expense (in MCU circuitry, in execution disruption, and in complexity) of actually diverting execution if all we're going to do is set a flag?

Background: My goal here is to understand. If the answer is "99% of the time, you're right, but here's 1% of the case where it makes a difference...", that will accomplish my goal.


Solution

  • Your assumption "Usually just setting a flag [...]" is not at all 99% of the use cases, not even near.

    I'm in the world of embedded software since 40+ years, and the interrupt service routines setting flags are in the minority, in my personal subjective experience.

    It's a common rule to keep an interrupt service routine short-running. But this is only correct in relation to the requirements. What is "short" in the context of the target system? Some systems need run-times shorter than a few microseconds, or even less. Others can perfectly live with multiple seconds. Therefore you need to specify the requirements before you can tell how short an interrupt service routine needs to run.

    The vast majority of interrupt service routines I came across or wrote do more than just setting a flag.

    For example, servicing a UART commonly includes fetching the next data to send or buffering the received data. In more than one case these routines additionally preprocess the data.

    In another example of my own projects, the edge-triggered interrupt service routine of an input pin decodes the Manchester coded data stream. It finally queues the decoded bytes. For the main thread it looks like a module providing the byte stream in its buffer.

    A special, but strange example is the "operating system" of the early personal computer ZX81. Granted, this is not really an embedded system, and it is 42 years old. Anyway, it creates its video signal to view on a TV set with a mixture of non-maskable and maskable interrupts. The routine running the longest is the generation of the vertical retrace signal, it takes about 3.5ms. During this time it scans and debounces the complete keyboard matrix, among other tasks.

    Next, think about exceptions. These are also hardware interrupts, detected by hardware for certain conditions, like division by zero, access violation, you name it. You will not want that they just set a flag and return to the triggering instruction.

    Finally (for my answer), a preemptive multitasking system will use its interrupt service routine to switch tasks.

    So, interrupts still make sense, and will keep making sense.


    As a side note, these hardware flags you suggest already exist. Any system I used had interrupt flags that the software can poll. Actually, we built systems without using interrupt service routines just by polling (and resetting) the interrupt flags. We had our reasons.

    You asked in a comment for an example for STM32. Since you did not specify further, I selected the first MCU whose user manual I found in a quick web research: the STM32L0x0.

    Chapter 21.8.8 describes the register USART_ISR, which includes the flag TXE in bit 7:

    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).
    An interrupt is generated if the TXEIE bit =1 in the USART_CR1 register.

    You can poll this bit in software and react accordingly. The implementation is left as an exercise to the reader.