Ingresso e uscita: polling, interruzioni, DMA e bus
Registri mappati in memoria con esempio in C, polling, interruzioni e routine di servizio, latenza e costo, DMA, bus I²C, SPI, UART, CAN, USB e PCI Express.
Un processore che non comunica con l’esterno non serve a niente: deve leggere sensori, tastiere e reti, comandare motori, schermi e dischi. I dispositivi di ingresso e uscita sono lenti e imprevedibili rispetto alla CPU, e il problema è come scambiare dati con loro senza sprecare tempo. In questa lezione vediamo come il processore vede i dispositivi, le tre tecniche di trasferimento (polling, interruzioni, DMA) e i bus più comuni.
Come si parla con un dispositivo
Ogni dispositivo ha dei registri: di dati (il byte ricevuto, quello da trasmettere), di stato (pronto, occupato, errore), di controllo (velocità, modalità). Nei sistemi moderni sono mappati in memoria: occupano indirizzi riservati, e si leggono e scrivono con le normali istruzioni di caricamento e memorizzazione. In C si accede con un puntatore volatile, che impedisce al compilatore di eliminare o riordinare gli accessi:
#define UART_STATO (*(volatile uint32_t *)0x40011000)
#define UART_DATO (*(volatile uint32_t *)0x40011004)
#define TX_VUOTO (1u << 7)
void invia(char c) {
while (!(UART_STATO & TX_VUOTO)) { } /* aspetta che il trasmettitore sia libero */
UART_DATO = c;
}
Questo è il polling (interrogazione ciclica): la CPU controlla di continuo il registro di stato.
Polling
È semplice e ha una latenza minima, ma spreca la CPU: mentre aspetta non fa altro. Va bene quando l’attesa è brevissima o quando la CPU non ha altro da fare; è inaccettabile per eventi rari e imprevedibili, come la pressione di un tasto, o quando bisogna gestire molti dispositivi.
Le interruzioni
Con le interruzioni è il dispositivo ad avvisare la CPU, attivando una linea di richiesta (IRQ). Alla fine dell’istruzione in corso il processore:
- salva il PC e lo stato;
- salta alla routine di servizio (ISR) associata a quella interruzione, il cui indirizzo è in una tabella dei vettori;
- esegue la routine, che legge o scrive i registri del dispositivo;
- ripristina lo stato e riprende il programma esattamente da dove si era fermato.

Le interruzioni hanno priorità: una più importante può interrompere la routine di una meno importante. Il tempo tra la richiesta e l’inizio della routine è la latenza; nei sistemi in tempo reale (il controllo di un motore, l’airbag) deve essere garantita, e si misura in decine o centinaia di nanosecondi nei microcontrollori.
Regole per le routine di servizio. Devono essere brevi: fanno il minimo indispensabile (leggere il dato, segnalare l’evento) e lasciano il resto al programma principale, perché mentre girano le interruzioni di priorità uguale o minore aspettano. Le variabili condivise tra routine e programma vanno dichiarate volatile e accedute con attenzione, perché la routine può arrivare in qualsiasi momento, anche a metà di un’operazione.
Il costo. Ogni interruzione costa salvataggio e ripristino dello stato, qualche centinaio di nanosecondi o qualche microsecondo con un sistema operativo. Una scheda di rete a 10 Gbit/s riceve oltre un milione di pacchetti al secondo: con 2 µs per interruzione servirebbero 2 secondi di CPU ogni secondo, impossibile. Si raggruppano allora le interruzioni (una ogni tanti pacchetti) e si usa il DMA.
DMA
Con l’accesso diretto alla memoria (DMA) un controllore dedicato trasferisce blocchi di dati tra il dispositivo e la memoria senza la CPU. Il processore programma il trasferimento (indirizzo di partenza, quantità, verso) e continua con altro; il controllore DMA usa il bus per conto suo e, alla fine, genera una sola interruzione. Così si leggono i dischi, le schede di rete, i convertitori analogico-digitali che campionano a velocità elevata, l’audio.
C’è un dettaglio delicato: il DMA scrive in memoria, ma la CPU potrebbe avere in cache una copia vecchia di quei dati. Le architetture risolvono il problema con la coerenza della cache verso i dispositivi, oppure il software deve svuotare o invalidare la cache prima e dopo il trasferimento.
I bus
| Bus | Uso tipico | Caratteristiche |
|---|---|---|
| I²C | sensori, memorie piccole | 2 fili, fino a qualche Mbit/s, molti dispositivi con indirizzo |
| SPI | display, convertitori, memorie flash | 4 fili, decine di Mbit/s, semplice e veloce |
| UART | console, moduli radio, GPS | 2 fili, asincrono, fino a qualche Mbit/s |
| CAN | automobili, industria | 2 fili differenziali, robusto ai disturbi, priorità dei messaggi |
| USB | periferiche dei computer | da 12 Mbit/s a decine di Gbit/s, alimentazione inclusa |
| PCI Express | schede grafiche, SSD, reti | collegamenti seriali punto a punto, fino a decine di GB/s con più corsie |
La tendenza è chiara: i bus paralleli con molti fili sono stati sostituiti quasi ovunque da collegamenti seriali veloci, perché a frequenze alte è impossibile mantenere allineati tra loro decine di segnali (lezione sulle linee di trasmissione di Campi elettromagnetici).





