An interrupt is a request to the processor to temporarily suspend the currently executing code to handle the event that caused it. If the processor accepts the request, it saves its state and executes an interrupt handler, also known as an interrupt service routine (ISR). Interrupts are usually signalled by peripheral devices when they have data to process. Often, peripherals do not send an interrupt signal directly to the processor; instead, the interrupt controller collects requests from various peripherals in the system. The interrupt controller prioritises the peripherals to ensure that the more important requests are handled first.
From a hardware perspective, an interrupt can be signalled by a change in the signal state.
The interrupt signal arrives asynchronously, meaning it can occur during instruction execution. Usually, the processor finishes this instruction and then calls the interrupt handler. To handle interrupts, the processor must store the address of the next instruction to be executed in the interrupted code. Some implementations use the stack, while others use a special register to store the return address. The latter approach requires software support if interrupts can be nested (i.e., if an interrupt can be accepted while already in another ISR).
After finishing the interrupt subroutine, the processor uses the return address to restore program control to the interrupted code.
The figure 1 illustrates how interrupts work and their stack usage. The processor executes the program. When an interrupt comes, it saves the return address on the stack. Next jumps to the interrupt handler. With return instruction, the processor returns to the program, taking the address of an instruction to execute from the stack.
To properly handle interrupts, the processor must recognise the interrupt source. Different code should be executed when a network controller signals the interrupt, and different code if the interrupt is from a timer. The information on the interrupt source is provided to the processor by the interrupt controller or directly by the peripheral. We can distinguish three main methods of calling a proper ISR for incoming interrupts.
In modern processors, interrupts can be signalled with the Message Signalled Interrupt mechanism. While the hardware needs to indicate the interrupt, it exchanges special messages through the chipset to a previously assigned memory address.
Interrupts can be enabled or disabled. Disabling interrupts is often used for time-critical code to ensure the shortest possible execution time. Interrupts which can be turned off are named maskable interrupts. They can be disabled with the corresponding flag in the control register. In microcontrollers, there are separate bits for different interrupts.
If an interrupt cannot be disabled, it is called a non-maskable interrupt. Such interrupts are implemented for critical situations:
In microprocessors, there is a separate non-maskable interrupt input (NMI).
In some processors, it is possible to signal the interrupt by executing special instructions. They are named software interrupts and can be used to test interrupt handlers. In some operating systems, software interrupts are used to implement the mechanism of calling system functions.
Another group of interrupts, signalled by the processor itself, is the internal interrupt group. Special instructions don't signal them; rather, they occur in specific situations during normal program execution. They are called exceptions and can be divided into three groups.
Faults are not real errors. The operating system often uses them to perform normal operations, such as handling paging.