Input and output: polling, interrupts, DMA and buses
Memory-mapped registers with a C example, polling, interrupts and service routines, latency and cost, DMA, I²C, SPI, UART, CAN, USB and PCI Express buses.
A processor that does not communicate with the outside world is useless: it must read sensors, keyboards and networks, and drive motors, screens and disks. Input and output devices are slow and unpredictable compared with the CPU, and the problem is how to exchange data with them without wasting time. In this lesson we see how the processor sees devices, the three transfer techniques (polling, interrupts, DMA) and the most common buses.
Talking to a device
Each device has registers: data (the byte received, the one to transmit), status (ready, busy, error), control (speed, mode). In modern systems they are memory-mapped: they occupy reserved addresses, and are read and written with ordinary load and store instructions. In C they are accessed through a volatile pointer, which stops the compiler from removing or reordering the accesses:
#define UART_STATUS (*(volatile uint32_t *)0x40011000)
#define UART_DATA (*(volatile uint32_t *)0x40011004)
#define TX_EMPTY (1u << 7)
void send(char c) {
while (!(UART_STATUS & TX_EMPTY)) { } /* wait until the transmitter is free */
UART_DATA = c;
}
This is polling: the CPU checks the status register continuously.
Polling
It is simple and has minimal latency, but it wastes the CPU: while waiting it does nothing else. It is fine when the wait is very short or the CPU has nothing else to do; it is unacceptable for rare, unpredictable events such as a key press, or when many devices must be handled.
Interrupts
With interrupts it is the device that alerts the CPU, by asserting a request line (IRQ). At the end of the current instruction the processor:
- saves the PC and the state;
- jumps to the interrupt service routine (ISR) associated with that interrupt, whose address is in a vector table;
- runs the routine, which reads or writes the device registers;
- restores the state and resumes the program exactly where it stopped.

Interrupts have priorities: a more important one can interrupt the routine of a less important one. The time between the request and the start of the routine is the latency; in real-time systems (motor control, airbags) it must be guaranteed, and in microcontrollers it is measured in tens or hundreds of nanoseconds.
Rules for service routines. They must be short: they do the bare minimum (read the data, flag the event) and leave the rest to the main program, because while they run, interrupts of equal or lower priority wait. Variables shared between routine and program must be declared volatile and accessed carefully, because the routine can arrive at any moment, even in the middle of an operation.
The cost. Each interrupt costs saving and restoring state, a few hundred nanoseconds, or a few microseconds with an operating system. A 10 Gbit/s network card receives over a million packets per second: at 2 µs per interrupt it would need 2 seconds of CPU every second, impossible. So interrupts are coalesced (one every many packets) and DMA is used.
DMA
With direct memory access (DMA) a dedicated controller transfers blocks of data between the device and memory without the CPU. The processor programs the transfer (start address, amount, direction) and carries on with other work; the DMA controller uses the bus on its own and, at the end, raises a single interrupt. This is how disks, network cards, high-speed analogue-to-digital converters and audio are read.
There is a delicate detail: DMA writes to memory, but the CPU may hold an old copy of that data in its cache. Architectures solve this with cache coherence towards devices, or software must flush or invalidate the cache before and after the transfer.
Buses
| Bus | Typical use | Characteristics |
|---|---|---|
| I²C | sensors, small memories | 2 wires, up to a few Mbit/s, many addressed devices |
| SPI | displays, converters, flash memories | 4 wires, tens of Mbit/s, simple and fast |
| UART | console, radio modules, GPS | 2 wires, asynchronous, up to a few Mbit/s |
| CAN | cars, industry | 2 differential wires, robust to noise, message priorities |
| USB | computer peripherals | from 12 Mbit/s to tens of Gbit/s, power included |
| PCI Express | graphics cards, SSDs, networking | point-to-point serial links, up to tens of GB/s with several lanes |
The trend is clear: parallel buses with many wires have been replaced almost everywhere by fast serial links, because at high frequencies it is impossible to keep dozens of signals aligned with each other (Electromagnetic Fields lesson on transmission lines).





