Polling and interrupt-driven systems
There is a class of embedded systems that run without any operating systems. The program running on CPU receives inputs from one or more IO devices, processes them as required by the system functionality and transmits outputs to one or more IO devices. The system is classified as a polling system or an interrupt driven system based on how the program interacts with the IO devices.
Polling system
The program needs to know if there are any IO activities in the system. An IO activity could be data received from an input device or data transmission completed to an output device. In a polling system, the program running on the CPU actively checks for any IO activities and if so, it takes action accordingly.
{
wait until input is received <-- polling
read the input data
process the input data and generate output data
wait till previous output is transmitted <-- polling
write the output data
}
The activities in a polling system are sequential: the CPU reads the inputs, processes them and generates outputs. Hence, such programs are relatively straight-forward to write and verify. However, there are two shortcomings of the polling systems:
1. The CPU actively polls for the IO activities. This means the CPU runs continuously and consumes power while waiting. This could mean significant waste of power, esp. for the systems where IO activities are infrequent. If the system runs on a battery, polling would consume the battery even when the system is on standby mode.
Take a TV remote control, for an example. When we press a button, CPU reads the button that was pressed and transmits the corresponding code to TV. This whole activity could take a few milliseconds. For the remaining time, the system remains idle. If we implement this as a polling system, then the CPU would be running even when we are not using the remote, resulting into battery getting drained out quickly.
2. An IO device can communicate to the CPU only when the CPU initiates the communication. If CPU gets busy doing something else, an IO device would have to wait until CPU completes its activity. If the input is from a high speed device, then the system may lose the inputs received when CPU is running other parts of the program.
For example, take a voice recorder. The system would receive voice samples every fraction of a millisecond. After receiving samples, CPU would run a compression algorithm and store the samples in the memory. Compression algorithm could take a few milliseconds (depending on CPU speed and complexity of compression algorithm). Any samples received during this period would be lost, resulting into intermittent breaks in audio.
Interrupt driven systems take care of these two shortcomings.
Interrupt driven system
The limitations in a polling system comes from the fact that it is always the CPU that initiates an IO activity. An IO device, even if it is ready to communicate to the CPU, cannot initiate a communication with the CPU. To overcome this, the hardware provides a facility called interrupts.
Here, an IO device sends a signal (called an interrupt request, IRQ for short) to the CPU whenever there is an IO activity that requires CPU's attention. When the CPU receives IRQ signal, it temporarily stops whatever code it is running and jumps to a routine called interrupt handler. The interrupt handler, also known as an interrupt service routine (ISR) interacts with the interrupting device to receive the input or begin transmission of the next output. Once ISR completes its job, it returns and the processor resumes running the program it has stopped on the arrival of the interrupt.
Unlike in a polling system, here an IO device can initiate communication by sending IRQ signal. The CPU reacts immediately to the IRQ by stopping whatever code it is running and jumping to the ISR. As a result, the system does not miss any IO activity even when CPU is busy with computing activities.
Let us revisit the earlier example of a voice recorder implemented as a polling system, which was losing samples when the CPU was compressing the samples. If we implement the same as an interrupt driven system, then we can write an ISR that gets triggered whenever input sample is available. The ISR simply reads the sample from the input device and copies it into memory. When the required number of samples are received, the CPU can start running the compression algorithm. While the CPU is running the compression algorithm, the input device continues to send IRQ signals to the CPU. On receiving the IRQ signal, the CPU momentarily stops running the compression algorithm and jumps to the ISR. ISR, which is a function written by us, can read the sample from the input device, copy the same into memory and return. When ISR returns, the CPU can continue running the compression algorithm. In this way, the samples which were simply lost in a polling system are now copied by the ISR into memory which can later be used as required.
The flip side of using an interrupt driven system is that the code is not sequential. Interrupts can occur at any time, stopping the main code and running the ISR. Such a code is relatively more difficult to test and debug compared to the same in a polling system.
Additionally, whenever an interrupt occurs, we need to save the registers which could be used by the main code before jumping to the ISR and restore the registers before returning to the main code. As a result, there is a small overhead associated with the interrupts.
How does an interrupt driven system address the power consumption limitation in polling? Many processor implementations provide a "wake-up on interrupt" feature. When there are no activities on the system, the program can place CPU in a sleep mode, where most of the CPU except a small wake-up circuit is placed into a low power state. When any IO device needs to wake up the processor, it can send an IRQ signal. The wake up circuit wakes up the CPU, which can then interact with the device and take the required action.
Comments
Post a Comment