Salta al contenuto
Note per Studenti Sottosistema di I-O - polling, interruzioni e DMA

Sottosistema di I-O - polling, interruzioni e DMA

In questa pagina 5
**; le NMI non sono mascherabili. -->

In ogni sistema a microprocessore ci sono ALU, controllo, memoria e periferiche di input-output (Organizzazione del processore - Von Neumann, Harvard, bus, ALU e registriOgni processore ha ALU, memoria e dispositivi di I/O. Nell'organizzazione Von Neumann dati e istruzioni stanno nella stessa memoria e viaggiano su un solo sistema di bus (semplice ed economica, usata nei µC più semplici); nell'organizzazione Harvard memorie e bus sono separati (più accessi per ciclo: tipica di DSP e µC veloci). I bus sono pilotati da porte tri-state; l'ALU lavora su registri (accumulatore o molti registri); il controllo è cablato o microprogrammato; la gerarchia di memoria va dai registri alla RAM interna e a quella esterna.Organizzazione del processore - Von Neumann, Harvard, bus, ALU e registri →). La gestione del sottosistema di I/O può avvenire in modi diversi; il più tipico, nei µC e DSP per controllo real-time, è quello basato sulle interruzioni.

L'interfaccia e i registri

Ogni periferica è collegata al bus tramite un circuito di interfaccia che adatta logicamente (e, se serve, elettricamente) la periferica alla CPU. Poiché ciascuna periferica lavora in modo asincrononon sincronizzato con il clock della CPU rispetto alla CPU, l'interfacciacircuito che collega una periferica al bus e ne adatta i segnali fornisce registri per:

  1. ospitare i dati scambiati con la CPU (DREGData REGister: registro dei dati della periferica);
  2. configurare la periferica (CREGControl REGister: registro di controllo);
  3. tenere traccia dello stato della periferica (SREGStatus REGister: registro di stato). CREG e SREG sono spesso di pochi bit e quindi non sempre separati; il DREG può avere dimensione diversa da quella della parola della CPU (per esempio un ADC a 12 bit). I registri devono poter essere letti e scritti. Due organizzazioni:
  • I/O mappato in memoria (memory mapped I/O): i registri delle periferiche sono trattati come normali locazioni di memoria, senza istruzioni o linee di controllo dedicate. È la tecnica usata nei µC e DSP: basta collegare le periferiche ad alcune linee del bus indirizzi con un decodificatore.
  • I/O isolato: istruzioni apposite e linee di controllo dedicate per selezionare le periferiche; praticamente abbandonato.

Le periferiche tipiche sono: convertitori A/D e talvolta D/A, timer (Timer - prescaler, compare, capture e watchdogUn timer è un contatore binario di periodi di clock: $f_{cont}=f_{clk}/PSC$ ($PSC$ = fattore del prescaler). In modalità compare/match genera un evento (interruzione, reset del conteggio, azione su un pin) quando il conteggio raggiunge il registro di match: per un evento ogni $T$ servono $N=T,f_{clk}/PSC\le2^{16}$ conteggi, e si prende il minimo $PSC$ (massima risoluzione). Con uscita in modo toggle la frequenza dell'onda quadra è metà di quella degli eventi, il duty-cycle 50%. In modalità capture il valore del contatore, salvato a due fronti, dà il periodo: $T=C_2-C_1$ (corretto anche con un overflow), risoluzione $1/f_{clk}$. Il watchdog reinizializza il sistema se non viene azzerato in tempo.Timer - prescaler, compare, capture e watchdog →) e contatori (PWM), moduli di comunicazione (UART, bus di campo), interfacce verso encoder, display (solo µC), gestione della memoria esterna.

Tre modi di sincronizzare

Poiché le periferiche sono asincrone e spesso più lente della CPU, serve sincronizzare lo scambio di dati:

  1. polling (controllo da programma): la CPU interroga periodicamente lo stato della periferica; quando è pronta, esegue le istruzioni necessarie e torna a controllare. Molto inefficiente, perché spreca tempo di CPU;
  2. interruzioni: la CPU fa altro e la periferica la avvisa: è l'approccio di gran lunga più usato;
  3. DMA: un processore di I/O sposta i dati senza coinvolgere la CPU.

Le interruzioni

Quando una periferica ha bisogno della CPU (ha prodotto un dato, ha ricevuto un segnale esterno) invia una richiesta di interruzione (IRQInterrupt ReQuest: richiesta di interruzione). La CPU, di norma, sospende il programma e si occupa della periferica. L'interruzione è un caso particolare del concetto più generale di eccezionequalunque condizione operativa che non corrisponde alla normale esecuzione del codice: reset, guasti, accessi proibiti alla memoria, istruzioni indefinite, watchdog.

Sequenza. (1) la CPU completa l'istruzione corrente; (2) salva il contesto; (3) attiva, se possibile, la routine di servizio (ISRInterrupt Service Routine: sottoprogramma che serve una interruzione); (4) alla fine ripristina il contesto e riprende il programma. Il punto (2) è cruciale: la CPU deve poter tornare allo stato di prima. Si salvano almeno il program counter e il registro di stato; alcuni processori (ARM) hanno un secondo set di registri per tutta la durata dell'interruzione, altri richiedono che il programmatore salvi (per esempio in uno stack) i registri usati dalla ISR. La ISR è un sottoprogramma che gestisce la periferica e termina con un'istruzione speciale (RTI o simile) che riporta la CPU al programma originario.

Problemi con molte periferiche: riconoscere chi ha chiesto l'interruzione; gestire richieste simultanee; gestire interruzioni di una ISR (interruzioni annidate, nestingannidamento: una ISR a priorità più alta interrompe una a priorità più bassa, vedi Sistemi di interruzioni - latenza, nesting e sostenibilitàCon $N$ sorgenti, ciascuna ISR $i$ ha durata $T_{d,i}$ (spesso già comprensiva della latenza intrinseca $T_{LI}$ e dell'istruzione in corso) e periodo minimo $T_{p,i}$. Condizione necessaria: $\sum_iT_{d,i}/T_{p,i}<1$ (la percentuale di impegno della CPU è la somma). Condizione di intervallo per ogni $i$ (priorità 1 = massima): $T_{d,i}+\sum_{k<i}n_k,T_{d,k};[+\max(T_{RC},\max_{j>i}T_{d,j})\text{ senza nesting}]\le T_{p,i}$, con $n_k=\lceil T_{p,i}/T_{p,k}\rceil$. Latenza massima della priorità $n$: con nesting $T_{LI}+\sum_{i<n}T_{ex,i}$; senza nesting si aggiunge $\max_{j>n}T_{ex,j}$.Sistemi di interruzioni - latenza, nesting e sostenibilità →). Soluzioni possibili:

  • gestione da programma: un registro di stato delle interruzioni (ISR register) con un bit per periferica; la routine di servizio ne legge i bit in ordine fisso (così implicitamente si ottiene una priorità), determina la sorgente e chiama la routine giusta. È poco efficiente (la lettura del registro costa tempo) e il programma deve azzerare i bit serviti.
  • interruzioni vettorizzate: più linee IRQ (una per periferica o per un piccolo gruppo) e attivazione automatica della ISR giusta: la CPU esegue una istruzione speciale (push PC, jump alla ISR) la cui locazione è nel vettore delle interruzionitabella in memoria con gli indirizzi (o le istruzioni di salto) delle ISR. Il vettorizzatore può far passare le richieste di priorità più alta (nesting) e deve gestire correttamente le pendenti. Esempi: il vettore delle eccezioni dell'ARM Cortex-M3 prevede fino a 240 interruzioni (IRQn), con salvataggio automatico del contestol'insieme dei registri (PC, registro di stato, altri) che descrive lo stato del programma interrotto; l'ARM7 ha solo 2 posizioni (due sorgenti, niente nesting).
  • daisy-chain: una sola linea IRQ ma le periferiche collegate in catena; quando riceve la richiesta la CPU manda un segnale INTA lungo la catena che si propaga da una periferica alla successiva finché arriva a quella che ha chiesto l'interruzione, che lo blocca, genera IACK e invia un indirizzo (di solito un puntatore alla routine). Introduce implicitamente una priorità (l'ordine nella catena): è una vettorizzazione esterna.

Interruzioni mascherabili e non

Con il segnale di Interrupt Enable (IE) si possono mascheraredisabilitare temporaneamente una sorgente di interruzione le sorgenti in alcuni momenti (anche una per una). Tutti i processori hanno almeno una sorgente non mascherabile (NMINon-Maskable Interrupt: richiesta che non si può disabilitare, usata per le emergenze, per esempio il watchdog o una mancanza di alimentazione). Se un segmento di programma deve essere eseguito in modo rigorosamente sequenziale (temporizzazioni precise) tutte le interruzioni vanno mascherate: altrimenti la durata del segmento varia in modo casuale (jitterpiccola variazione casuale nei tempi di un evento che dovrebbe essere periodico, glitch) con errori non ripetibili difficili da trovare.

Parametri di un sistema di interruzioni: numero di sorgenti (di norma >10>10, fino a un centinaio), gestione delle priorità, velocità di salvataggio del contesto, mascherabilità. Nelle applicazioni real-time la velocità del salvataggio del contesto è critica, così come la possibilità di non interrompere le regioni critiche del codice.

DMA

Il Direct Memory Access è la soluzione più efficiente per interfacciare CPU e periferiche, ma molto costosa (dispositivi ad altissime prestazioni). Un circuito di controllo aggiuntivo, il DMAC, una volta programmato (indirizzo di memoria di partenza e numero di dati da spostare) gestisce le periferiche senza coinvolgere la CPU e genera una interruzione al termine dello spostamento. È l'unico approccio possibile per periferiche con velocità paragonabile a quella della CPU, e utile quando una periferica produce grandi quantità di dati. Il trasferimento può essere singolo (cycle stealingil DMAC ruba un ciclo di bus alla CPU per ogni dato) o a blocchi (bursttrasferimento a blocchi: il DMAC tiene il bus per tutta una sequenza di dati); mentre il DMACcontrollore del DMA: il circuito che sposta i dati al posto della CPU è attivo la CPU non può usare il bus: per questo si usa spesso con una cache. Un DMAC ha di norma più canali (per esempio 6 nel DSP TMS320C4x, che completa un trasferimento per ciclo senza interferire con il processore).

Protocollo: (1) la periferica chiede il trasferimento al DMAC (TransferRequest); (2) il DMAC chiede alla CPU il permesso di usare i bus (DMARequest); (3) la CPU lo concede (DMAGrant): degli switch isolano la CPU dai bus e collegano DMAC e periferica alla memoria; (4) il DMAC imposta l'indirizzo e autorizza la periferica (TransferGrant) a scrivere o leggere il dato.

Errori comuni

  • Credere che le interruzioni siano sempre preferibili al pollinginterrogazione periodica dello stato di una periferica da parte della CPU: per periferiche molto veloci e prevedibili il polling può costare meno dell'overhead di una interruzione, ma in generale si usano le interruzioni.
  • Dimenticare che i registri delle periferiche sono locazioni di memoria nei µC.
  • Confondere interruzione mascherabile e NMI.
  • Dimenticare che la CPU completa l'istruzione in corso prima di servire l'interruzione (il tempo di latenza dipende anche da questo).

Versione ripasso

Esercizi su questo argomento

Teoria collegata