Personal computer/Architettura/IO

Indice del libro

I dispositivi di Input/Output (I/O) permettono la comunicazione tra la CPU e l'esterno, sia con l'uomo ( monitor, tastiera, ... ) che con la macchina stessa ( hard disk ). Il corretto funzionamento dei dispositivi di I/O è assicurato dalle interfacce che, oltre a permettere il corretto utilizzo dei dispositivi periferici, effettuano l'adattamento elettrico tra unità e calcolatore.

Una interfaccia schematicamente è composta da:

  • registri per appoggiare i dati in transito
  • registri per appoggiare i comandi
  • registri per tenere traccia dello stato della periferica e segnalare eventuali errori

I registri dell'interfaccia devono essere accessibili alla CPU, per questo motivo, analogamente alle memorie, appartengono ad uno spazio di indirizzamento che può essere

  • Memory mapped ovvero in una porziona precisa della memoria principale
  • Isolato, separato dalla memoria

I sistemi di I/O più lenti richiedono una sincronizzazione con la CPU che può essere effettuata tramite:

  • Controllo del programma, polling
  • Interruzioni
  • Accesso diretto (DMA)

Controllo del programma, Polling

modifica

La gestione delle interfacce tramite software è la più semplice da realizzare. Pensiamo di voler gestire una stampante che se indirizzata (tramite un segnale di comando) legge dal bus dati una sequenza di word e le stampa. Il software non dovrà far altro che indirizzare la stampante e copiare le word nei registri interni alla stampante.

Con questa realizzazione la CPU svolge un programma, detto routine di servizio ogni volta che accede ad una periferica e deve attendere che il trasferimento di dati tra CPU e dispositivo sia completo prima di poter passare all'istruzione successiva, questo tempo di attesa è quasi totalmente sprecato.

Per approfondire la gestione a polling delle interfacce guardane un esempio di routine di servizio per le architetture 8088

Interruzioni

modifica

Il sistema di interruzioni o interrupt è decisamente più performante rispetto al controllo del programma. L'accesso alla periferica è gestito sempre tramite software, ma nel tempo di attesa la CPU torna a svolgere il programma che eseguiva prima dell'inizio della routine di servizio, una volta che la periferica è di nuovo pronta ad accettare dati emette un interrupt che genera nella CPU il passaggio dal programma principale alla routine di servizio.

La routine di servizio oltre a comandare il trasferimento di dati tra CPU e il dispositivo periferico deve anche salvare tutti i registri della CPU che possono essere modificati dalla routine (soprattutto i registri di stato) per poterli ripristinare al termine dell'esecuzione.

Le interruzioni possono essere mascherabili, ovvero la CPU può continuare a lavorare come se non sia stato ancora ricevuto il segnale di interruzione. In alcuni processori (8088 compreso) esiste un pin per le interruzioni non mascherabili (NMI) da usare ad esempio con periferiche che segnalano il calo di tensione di alimentazione per richiamare nella CPU un programma che permetta di salvare lo stato della macchina.

Quando i dispositivi periferici sono più di uno è necessario un sistema di gestione degli interrupt che permetta di capire quale dispositivo chiama l'interruzione e gestire la priorità in caso vi siano più interruzioni contemporaneamente. La soluzione è la vettorizzazione delle interruzioni che può avvenire

  • internamente alla CPU, soluzione che richiede più linee di interrupt e registri di Interrupt Status per gestire lo stato delle interruzioni
  • esternamente tramite un controllore di interruzioni esterno alla CPU.

La vettorizzazione esterna delle interruzioni richiede che quando la CPU segnala di essere in grado di eseguire un'interruzione (con un segnale INTA), la logica esterna di controllo selezioni la periferica da servire e invii sul bus dati l'informazione che permette alla CPU di passare all'esecuzione della routine di servizio. Il controllore presenta quindi sul bus dati il selettore di interruzione. Nelle CPU 8088 il selettore di interruzioni è un numero che identifica il vector type o tipo di interruzione che viene usato come puntatore al vettore di interruzioni che contiene l'indirizzo della routine. Ogni elemento vettore è di 4 byte (32 bit) che corrispondono alla dimensione dell'Instruction Pointer. La posizione dell'elemento è in memoria e viene ottenuta moltiplicando per 4 il vector type. In tutte le CPU Intel precedenti l'80286 il vettore delle interruzioni è situato nei primi 1024 byte dello spazio di memoria permettendo 256 interruzioni, dal 80286 in poi la posizione all'interno della memoria non è più predefinita.

La logica esterna di controllo delle interruzioni può essere ottenuta con una catena di controllori, detta Daisy Chain Logic. Ogni elemento della catena è denominato DCL e si interpone tra CPU e interfaccia. Una logica così strutturata richiede che vi siano più blocchi DCL tra di loro collegati secondo uno schema di priorità, quello con priorità maggiore è direttamente collegato alla CPU, gli altri sono in cascata.

In una daisy chain logic asincrona la CPU emette INTA che viene letto dal primo blocco DCL, quello a priorità maggiore, se questo blocco ha precedentemente emesso una interruzione (avrà un registro di stato a questo scopo) segnala, con un IACK, all'interfaccia di poter pilotare il bus dati emettendo il selettore di interruzioni. Se la DCL non aveva emesso una interruzione propaga il segnale INTA della CPU al blocco successivo. Per evitare le sovrapposizioni è necessaria una rete che blocca la propagazione degli interrupt tra interfaccia e DCL se quest'ultima ha già propagato INTA.

Una daisy chain logic può essere realizzata anche con un unico integrato dotato di più porte di ingresso per gli interrupt e di una logica interna per la gestione delle priorità. È il caso della CPU 8088 che utilizza un controllore di interruzioni programmabili detto PIC 8259, Programmable Interrupt Controller.

Accesso diretto DMA

modifica

Entrambi i metodi di controllo precedenti richiedono il controllo via software delle interfacce, soluzione che si rivela svantaggiosa quando la periferica è molto veloce, si può verificare il caso di ricezione di interrupt talmente veloce da non consentire alla CPU di eseguire il programma di servizio, è il caso degli hard disk, per i quali le velocità di accesso sono confrontabili con quelle di esecuzione di un'istruzione della CPU.

Per ovviare a questo problema introduco un controller hardware che gestisce il trasferimento di dati tra dispositivi periferici e memoria centrale indipendentemente dalla CPU. Questo hardware è il DMAC (Direct Memory Access Controller).

In un trasferimento tra I/O e memoria è il DMAC a controllare il bus con i seguenti passaggi:

  1. la periferica indica, al DMAC che è pronta a fornire dei dati (DMREQ)
  2. il DMAC segnala alla CPU la volontà di entrare in controllo del bus (BUSREQ)
  3. la CPU cede il controllo del bus (BUSACK)
  4. il DMACK segnala alla periferica attraverso DMACK e un segnale di comando (IOR per la lettura in I/O o IOW per la scrittura) di poter iniziare il trasferimento
  5. il DMACK inserisce sul bus indirizzi la posizione di memoria in cui leggere o scrivere (MR lettura o MW scrittura). Dei quattro segnali di comando sono possibili solo le combinazioni IOR-MW e IOW-MR
  6. al termine del trasferimento il DMAC segnala alla CPU di riprendere il controllo del bus disattivando BUSREQ

Il DMAC deve avere un contatore del numero di word da trasferire con un puntatore alla posizione in cui leggere o scrivere i dati ed un registro di comando ad indicare il tipo di trasferimento che può essere

  • singolo o cycle stealing; in questa modalità viene eseguito un solo trasferimento dopo di che il DMAC libera il bus dati e decrementa di uno il valore del contatore interno. Se ci sono altre word da trasferire richiede nuovamente il controllo del bus alla CPU e attende che questa gle lo ceda.
  • a blocchi o burst; la CPU viene isolata fintanto che non viene azzerato il contatore del numero di word da trasferire.

In entrambe le modalità di trasferimento la CPU intanto non rimane inattiva ma esegue le operazioni che non richiedono il bus dati.