Vai al contenuto
Sistemi di Elaborazione

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:

  1. salva il PC e lo stato;
  2. salta alla routine di servizio (ISR) associata a quella interruzione, il cui indirizzo è in una tabella dei vettori;
  3. esegue la routine, che legge o scrive i registri del dispositivo;
  4. ripristina lo stato e riprende il programma esattamente da dove si era fermato.
Gestione di un'interruzione nel tempo
Il programma principale è in esecuzione quando arriva la richiesta d’interruzione. Dopo un breve tempo per salvare lo stato (la latenza), il processore esegue la routine di servizio; alla fine ripristina lo stato e riprende il programma dal punto in cui era stato interrotto.

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

BusUso tipicoCaratteristiche
I²Csensori, memorie piccole2 fili, fino a qualche Mbit/s, molti dispositivi con indirizzo
SPIdisplay, convertitori, memorie flash4 fili, decine di Mbit/s, semplice e veloce
UARTconsole, moduli radio, GPS2 fili, asincrono, fino a qualche Mbit/s
CANautomobili, industria2 fili differenziali, robusto ai disturbi, priorità dei messaggi
USBperiferiche dei computerda 12 Mbit/s a decine di Gbit/s, alimentazione inclusa
PCI Expressschede grafiche, SSD, reticollegamenti 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).

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x
()
x