Interrupts: Basics

An interrupt is a signal to the processor emitted by hardware or software calling attention to an event that needs immediate attention. When an interrupt occurs, the processor temporarily halts the execution of the code, calling an interrupt handler function, also known as an interrupt service routine (ISR), to take care of the event. Once the processor handles the event, the processor resumes execution of the code, continuing from where the execution had previously stopped. To make an analogy, this is similar to working on a coding project, receiving a text from your friend (an interrupt), unlocking your phone to respond to the text (the ISR), and then going back to working on your project. 

Interrupts have three states: inactive, pending, and active. When an interrupt is inactive, the conditions to generate the interrupt haven’t been met, so nothing special is happening. When an interrupt is pending, the conditions have been met, but the ISR has not been called. Finally, when an interrupt is active, the ISR is servicing the interrupt. When the event has been handled, the interrupt status returns to inactive.


The hardware and design behind interrupts consist of multiple components. The interrupt controller is a peripheral that helps the processor manage the interrupts. An interrupt source is any peripheral that can interrupt the processor, such as the ADC, timer, GPIO, UART, etc. By contrast, an interrupt trigger is a hardware event that generates the interrupt via an electrical signal. For example, a GPIO can be an interrupt source. We can then program the GPIO such that when the GPIO input goes from 0 to 1, the GPIO generates an interrupt. In such a case, the event of the GPIO input going from 0 to 1 is considered the interrupt trigger.

The interrupt controller also makes use of flags, which are signals used by software functions or hardware modules, often to indicate the status of a process. Designers use flags to show that something of importance has occurred. One flag that the interrupt controller uses is called interrupt enable. The programmer can set or reset the interrupt enable. The processor uses this flag to decide whether to acknowledge and service interrupts or ignore them. Another flag used is the interrupt flag, which indicates that an interrupt trigger has occurred, and an interrupt is pending. 

ISRs play a key role in handling interrupts, but they also have a few nuances. ISRs are software functions, just like other functions. In that sense, the programmer implements the ISR as a set of instructions that should execute when the respective interrupt occurs. However, ISRs cannot take any input arguments, nor can they return anything. As such, ISRs can only interact with the rest of the code by using global variables, which can be used by any function within the program. Additionally, a well-developed ISR should clear the interrupt flag that called it. This act prevents the ISR from being perpetually called (thus putting your code into an infinite loop) and also allows other interrupts from the same trigger to be serviced.  

Just as with functions, ISRs have addresses, too. The address of an ISR is called its interrupt vector. Each interrupt source has its own vector (e.g. ADC has its own vector, timers have their own vectors, each GPIO has its own vector, etc.). These interrupt vectors are commonly indexed in a data structure known as an interrupt vector table (IVT), which associates each ISR with an interrupt source. IVTs provide a quick way for the processor to find the corresponding ISR when an interrupt is generated. However, keep in mind that IVTs can differ across multiple architectures.


Interrupts can also be prioritized by number. Priority is used to determine which interrupt should be serviced if more than one interrupt is pending. In some designs, interrupts with a higher number have a higher priority, thus having precedence in being serviced compared to lower number/lower priority interrupts. Additionally, a higher priority interrupt will stop the execution of an ISR of a lower priority interrupt.