ELEMANIA
Z80 - Polling e interrupt
Polling e interrupt

Nei semplici esempi considerati nelle lezioni precedenti il µP era impegnato permanentemente nel compito di gestire una periferica. Con ciò intendiamo dire che il µP doveva interrogare ciclicamente lo stato della periferica per sapere se questa era pronta al trasferimento di un dato. Questa tecnica di gestione delle periferica si chiama polling e, come abbiamo già osservato, non sfrutta in modo molto efficiente il tempo di calcolo del µP. Si consideri a titolo di esempio il programma per la gestione del segnale di strobe visto nella precedente lezione:

  LD A,00h  ; inizializza A con zero
  OUT (41h), A ; azzera il segnale di strobe
  LD HL,1234h ; inizializza un contatore in memoria
  ... ; il programma prosegue con altre istruzioni
inizio: LD A,(HL) ; carica in A un valore dalla memoria
  INC HL ; incrementa il contatore
  OUT (40h), A ; invia il dato al registro uno
  LD A, 10h ; prepara in A l'attivazione dello strobe
  OUT  (41h), A ; attiva lo strobe
  CALL RITARDO ; chiama un sottoprogramma di ritardo
  LD A,00h ; azzera A
  OUT (41h), A ; azzera lo strobe
  JP inizio ; ripete dall'inizio
           

Osserviamo come il µP sia impegnato costantemente nell'esecuzione di un ciclo infinito per la gestione della periferica e dunque non possa essere utilizzato per svolgere altre operazioni.

Inoltre nei semplici esempi considerati finora il µP doveva gestire un'unica periferica. In una situazione più realistica ci saranno invece più periferiche collegate col µP e dunque sarà necessario gestirle tutte. Usando una soluzione a polling con più periferiche, il µP deve interrogare ciclicamente lo stato di tutte le periferiche per accertarsi se ve ne sia una che è pronta per trasmettere o ricevere dati. Usando l'handshake bidirezionale il µP in pratica deve testare il bit busy di ogni periferica collegata in modo ciclico. Questa soluzione è piuttosto semplice dal punto di vista hardware e del software di gestione, ma, come già detto, tiene inutilmente impegnato il µP nell'interrogazione ciclica delle periferiche.

Una tecnica più efficiente è quella ad interrupt (interruzione). In una gestione ad interrupt la periferica può interrompere il normale flusso di esecuzione del µP per richiedere un particolare servizio (ad esempio di leggere un dato). In questo modo il µP non è impegnato continuamente a testare lo stato delle periferiche, poiché sono queste ad attivare un interrupt quando ne hanno bisogno.

Per fare un semplice esempio, se in una corsia di ospedale gli infermieri devono controllare lo stato dei pazienti con una tecnica a polling, essi dovranno continuare a percorrere il reparto verificando ogni paziente ad uno ad uno. Viceversa con una gestione ad interrupt è il paziente stesso a richiedere l'attenzione dell'infermiere per esempio suonando un campanello.

Evidentemente l'interrupt risulta più efficiente del polling nell'uso delle risorse del sistema, tuttavia esso è anche più complesso da gestire, sia dal punto di vista del software che da quello dell'hardware necessari.

Routine di gestione dell'interrupt

Nel momento in cui arriva al µP una segnalazione di interruzione da parte di una periferica, viene interrotta la normale sequenza di esecuzione delle istruzioni e, con una sorta di salto speciale a sottoprogramma, viene eseguita una routine di interruzione o routine di servizio dell'interruzione. Quest'ultima è un sottoprogramma che si occupa di gestire la richiesta di interruzione eseguendo le opportune istruzioni, come vedremo meglio nel seguito.

Al termine dell'esecuzione della routine di interruzione, la normale esecuzione del programma prima interrotto verrà poi ripresa, come se fosse stata eseguita un'istruzione RET da un sottoprogramma (in effetti l'interrupt usa lo stack per salvare l'indirizzo di ritorno, esattamente come accade nella normale chiamata a un sottoprogramma).

Occorre prestare attenzione al fatto che tuttavia questo particolare sottoprogramma non è stato attivato da una istruzione CALL, ma da un evento hardware, che per sua natura può avvenire in qualunque momento (si dice che la routine di interruzione è eseguita “in modo asincrono”).

La routine di interruzione per prima cosa deve salvare nello stack il contenuto dei registri interni che utilizza, in modo che possa essere ripristinato, a fine interruzione, il loro contenuto. L’uso delle PUSH e delle POP nella routine di servizio delle interruzioni è reso obbligatorio dal fatto che la routine viene eseguita in modo del tutto asincrono rispetto al programma interrotto, per cui è necessario provvedere affinché questo, alla sua ripresa, ritrovi nei registri interni al processore esattamente i contenuti che vi aveva lasciato. Si dice che la routine di interruzione deve lasciare inalterato lo stato del µP.

Un'altra possibilità per salvare lo stato del microprocessore consiste nell'utilizzare i cosiddetti registri ombra (shadow registers) A'...F', che rappresentano delle copie interne dei registri dello Z80. Ci sono due istruzioni di scambio che effettuano lo scambio fra i registri principali e le loro copie ombra:

EX AF,AF'     ; scambia AF con A' e F'
EXX            ; scambia tutti gli altri registri con le copie ombra

La ragione per cui i registri AF sono trattati con un'istruzione separata è che spesso A e F sono usati per scambiare dati con la routine di servizio dell'interrupt e dunque non si desidera ripristinarne i valori originali.

Se nel sistema è presente un solo dispositivo in grado di interrompere il processore, a questo punto la routine di servizio assolve al compito richiesto, direttamente. Nel caso più generale di presenza di più dispositivi, la routine di servizio dovrà effettuare l'individuazione di quello che ha richiesto servizio, eseguendo un test su tutti i dispositivi che possono avere avanzato la richiesta (si parla di Polling Post Interrupt).

Riconosciuto il dispositivo, sarà eseguita la parte di codice ad esso relativa. La routine di servizio dovrà testare in ordine di priorità i vari dispositivi, in modo da eseguire, in caso di richieste contemporanee, il codice relativo al dispositivo più prioritario.

In ultimo, prima di terminare, la routine di servizio dell'interrupt dovrà ripristinare il contenuto di tutti i registri interni del µP che sono stati alterati dalla routine stessa, in modo tale che il programma precedentemente interrotto possa riprendere l'esecuzione come se nulla fosse successo.

Tutte queste istruzioni da eseguire nella routine di interrupt sono a carico del programmatore, cioè non vengono eseguite in automatico ma devono essere scritte da chi programma la routine. Un diagramma di flusso abbastanza generico e generale di una routine di interrupt è il seguente:

L'abilitazione degli interrupt è necessaria per le routine di gestione degli interrupt mascherabili in quanto tali interrupt vengono disabilitati automaticamente dallo Z80 al momento dell'accettazione della richiesta di interruzione (per evitare la generazione di una sequenza di interruzioni).

 

precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it