Per trovare un amico bisogna chiudere un occhio; per tenerselo, due
MICROPROCESSORI E MICROCONTROLLORI
… studiare, studiare ed ancora studiare,
è il solo modo di capire quanto possa
essere grande sia la propria ignoranza!
ARCHITETTURA DEI MICROPROCESSORI
L’architettura interna di un microprocessore può essere, in
base all’organizzazione della memoria, di due tipi:
• classica di von Neumann;
• Harvard.
Nell’architettura classica di von Neumann i dati e il programma sono residenti in un’unica
memoria mentre nell’architettura Harvard i dati e il programma sono localizzati in memorie
differenti e con bus differenti.
Nella versione odierna, per architettura Harvard si intende una CPU con una sola memoria
principale e due cache separate: una per i dati e una per il programma.
L’architettura Harvard è utilizzata prevalentemente nei microcontrollori, ovvero nei micro-
-processori embedded.
L’architettura interna di una CPU è caratterizzata anche dal suo set di istruzioni e in
particolare dal metodo di memorizzazione degli operandi; può essere di tre tipi:
•
ad accumulatore;
•
a stack;
•
a registri generali.
Nell’architettura ad accumulatore tutte le istruzioni aritmetiche, logiche e di confronto
hanno un operando in un registro particolare, chiamato registro accumulatore, e gli
altri operandi sono localizzati in memoria.
Il prelevamento di un dato dalla memoria costituisce un vero e proprio collo di bottiglia
(bottleneck) per il microprocessore.
Si tratta di un modello arcaico e poco efficiente in quanto tutte le istruzioni devono
indirizzare un dato in memoria.
La programmazione è sintetica.
Esempio 1
Somma di due operandi X e Y nel caso di architettura ad accumulatore: .
Nell’architettura a stack non esistono registri generali e registro accumulatore, ma
un registro particolare chiamato Stack Pointer, che punta alla testa di una pila, chiamata
pila di sistema.
L’area stack può essere interna al microprocessore o interna alla memoria centrale.
Gli operandi sono localizzati in testa alla pila.
Gli operandi sono inseriti nella pila tramite l’istruzione PUSH e i risultati sono prelevati
tramite l’istruzione POP.
Si tratta di un modello arcaico e di scarsa efficienza, specialmente se la pila si trova in
memoria centrale.
La programmazione è prolissa.
Esempio 2
Somma di due operandi A e B nel caso di architettura a stack:
Nella soprastante figura è riportato un altro esempio di esecuzione di una espressione
algebrica in un microprocessore con struttura a pila.
In un microprocessore a registri generali gli operandi sono tutti espliciti e localizzati
in un set di registri , utilizzabili in modo assolutamente
generico.
Gli operandi possono essere indirizzati con vari metodi di indirizzamento.
Si possono implementare tre tipi di microprocessori a registri generali:
•
registro/registro; tutti gli operandi sono localizzati nei registri; esempi di microproces-
-sori di questo tipo sono i RISC (SPARC, MIPS, PowerPC);
•
memoria/registro; alcuni operandi in memoria e altri in registri; esempi di queste CPU
sono Intel x86 e Motorola 68000;
•
memoria/memoria; operandi tutti in memoria e risultato in memoria; non esistono in
commercio CPU di questo tipo.
Architettura classica di von Neumann
L’architettura più semplice, comune a tutti i microprocessori, è chiamata a singolo bus e
prevede un solo bus dati ed un registro particolare chiamato accumulatore.
Questa architettura tradizionale è nota anche come tipo SISD (Single Instruction
Single Data) perché con una singola istruzione elabora un singolo dato.
Le CPU tradizionali sono note per essere processori di tipo scalare perché eseguono sugli
operandi una istruzione alla volta.
I componenti fondamentali che costituiscono un microprocessore sono i seguenti:
• l’unità aritmetico-logica ALU;
• l’unità di controllo;
• registri di uso generale (general purpose);
• registri dedicati
Nella figura i cui sopra, è stato evidenziato il data bus interno; questo ha quasi sempre le
stesse dimensioni di quello esterno.
L’ALU è l’elemento funzionale del microprocessore in quanto esegue operazioni (program-
-mate dall’unità di controllo) logiche (AND, OR, NOT, shift ecc.) e aritmetiche (addizione,
sottrazione, incremento e decremento) su uno o due operandi.
Gli operandi vengono memorizzati in appositi registri, tra questi l’accumulatore svolge un
ruolo centrale.
L’unità di controllo
L’unità di controllo (CU, Control Unit) è l’elemento che sovrintende all’elaborazione del
programma.
Essa genera i segnali utili a programmare l’ALU al fine di svolgere le operazioni descritte
da ogni istruzione, gestisce lo scambio dei dati tra i vari registri interni al microprocessore,
gestisce lo scambio dei dati tra la CPU e la memoria e tra la CPU e i dispositivi di I/O.
La CU genera inoltre i segnali per una corretta sincronizzazione del funzionamento di tutti i
blocchi interni al microprocessore.
Tutta l’attività della CU è scandita da un segnale di clock generato da un oscillatore al
quarzo, in alcuni casi esterno e in altri interno al microprocessore.
L’esecuzione di un’istruzione si concretizza nell’assunzione da parte della CU di una suc-
-cessione ben definita di stati logici, comunemente chiamata microprogramma.
L’insieme dei microprogrammi è noto come firmware del microprocessore ed è memo-
-rizzato in un PLD interno alla CU.
I registri
L’accumulatore è il registro principale di ogni microprocessore.
Esso ha un rapporto preferenziale con la ALU poiché è utilizzato per contenere uno dei due
operandi, oppure l’unico operando, e il risultato delle operazioni.
L’accumulatore è inoltre il registro che il microprocessore utilizza per scambiare dati con la
memoria e i dispositivi di I/O.
I registri presenti in un microprocessore possono essere divisi in due categorie: quelli di
uso generale, che costituiscono il livello di memoria più veloce e servono a immagazzinare
temporaneamente dati, indirizzi e risultati intermedi delle operazioni, e quelli dedicati.
Il numero e le funzioni svolte dai registri determinano le caratteristiche dei vari micropro-
-cessori esistenti in commercio.
I registri di uso generale (General Purpose Register) sono registri che servono a memo-
-rizzare i dati, consentendo così di aumentare la velocità di esecuzione delle istruzioni
riducendosi notevolmente il numero di accessi alla memoria esterna al microprocessore.
Questi registri possono essere utilizzati anche in coppia o in banchi per contenere
informazioni a uno o più byte.
Nel registro di stato (SR, Status Register) l’ALU annota delle informazioni relative alle
caratteristiche del risultato di operazioni aritmetiche o logiche: segno, parità, segnalazione
di risultato nullo ecc.
I bit dello Status Register, noti come flag di stato, hanno un significato individuale e non
complessivo.
La maggior parte delle istruzioni di un microprocessore altera lo stato di alcuni o di tutti i
flag, che possono essere testati per condizionare l’evoluzione del programma.
I registri dedicati sono: IR, PC e SP.
Nel registro istruzioni (IR, Instruction Register) viene posto il codice operativo di ogni
istruzione, prelevata dalla locazione di memoria puntata dal registro PC.
Il contenuto dell’IR è letto e decodificato dall’unità di controllo che provvede a generare gli
opportuni segnali necessari per l’esecuzione dell’istruzione stessa.
Il contatore di programma (PC, Program Counter) è un registro delle stesse dimensioni
dell’address bus che contiene l’indirizzo dell’istruzione da prelevare dalla memoria.
È incrementato automaticamente in ordine sequenziale ogni qualvolta si acquisisce una
nuova istruzione.
Il puntatore allo stack (SP, Stack Pointer) è un registro che punta la prima locazione libera
dell’area stack.
L’area stack è una zona di RAM in cui vengono memorizzati temporaneamente degli
indirizzi o dei dati.
Lo stack è una struttura di tipo LIFO (Last In First Out): l’ultimo dato immesso è il
primo a uscire, mentre il primo dato
immagazzinato è l’ultimo a uscire.
In definitiva lo stack è paragonabile ad
una pila di piatti.
Nella figura a lato sono illustrate l’area
stack e le modalità di accesso.
L’area stack viene gestita sia autonoma-
-mente dalla CPU che dall’utente con le
istruzioni opportune.
Per inserire un dato nello stack si esegue
un’istruzione PUSH, per estrarlo invece è
necessaria un’istruzione POP il primo dato
prelevato è quello che si trova in cima
all’area, ossia l’ultimo inserito nella pila
Il funzionamento dei registri PC e SP è il
seguente.
All’avviamento o dopo un impulso di reset, il
PC del microprocessore viene caricato con
l’indirizzo della locazione di memoria contene-
-nte la prima istruzione del programma;
supponiamo ad esempio che tale indirizzo sia
0000H.
L’unità di controllo preleva e decodifica l’istruzione contenuta nella locazione con indirizzo
0000H, ma prima di eseguirla, provvede a incrementare il PC, il cui contenuto è ora
l’indirizzo 0001H.
Prelevata e decodificata l’istruzione relativa all’indirizzo 0001H, il PC viene aggiornato con
l’indirizzo successivo, ovvero 0002H. Supponiamo che l’istruzione dell’indirizzo
0001H, attualmente in fase di esecuzione, imponga un salto ad un altro segmento di
programma che ha inizio da 0A00H e termina a 0A10H.
Dopo aver eseguito il sottoprogramma, il microprocessore deve rientrare nel programma
principale all’indirizzo 0002H.
La sequenza delle operazioni eseguite dalla CPU è la seguente:
•
carica il Program Counter con l’indirizzo 0A00H;
•
provvede a salvare 0002H nell’area stack, puntata dallo Stack Pointer;
•
eseguito il sottoprogramma, richiama nel Program Counter l’indirizzo 0002H;
•
l’esecuzione del programma principale viene ripresa dal punto in cui era stata mome-
-ntaneamente sospesa.
Il dato da salvare, nel nostro caso l’indirizzo 0002H, è depositato mediante un’operazione
di push; il dato va ad occpare la prima locazione libera corrispondente all’indirizzo
più elevato.
Se la RAM è da 32 K × 8, l’ultimo indirizzo è
7FFFH, ma viene occupato anche 7FFEH
poiché servono 2 byte per memorizzare un
indirizzo (vedi figura (a) a lato).
L’ultima istruzione del sottoprogramma
ordina al microprocessore il rientro
nel programma principale.
Mediante un’operazione di pop viene ripristinato
nel PC l’indirizzo 0002H perché a questo indirizzo era stata sospesa l’esecuzione del
programma principale.
Se in una istruzione del sottoprogramma (ad esempio quella con indirizzo 0A05H) è an-
-nidato un altro sottoprogramma, inizio 0B20H e fine 0B35H, è necessario salvare nello
stack anche l’indirizzo 0A06H (figura (b)).
L’indirizzo 0A06H viene salvato nello stack sempre con il byte più significativo sul fondo e
quello meno significativo in superficie: il registro SP continua a essere incrementato e a
puntare la locazione libera 7FFBH.
essere incrementato e a puntare la locazione libera 7FFBH.
Al rientro dal secondo sottoprogramma il PC viene aggiornato con l’indirizzo 0A06H per
consentire il ritorno al punto di provenienza, ovvero il primo sottoprogramma.
Con la stessa tecnica, al termine dell’elaborazione del primo sottoprogramma si rientra nel
programma principale all’indirizzo 0002H.
Salvataggio dell’indirizzo nell’area stack (a);
salvataggio di più indirizzi nello stack (b).
Il registro indirizzi di memoria (MAR, Memory Address Register) è il registro direttamente
interfacciato con l’address bus del microprocessore.
Durante la fase di prelevamento di un’istruzione dalla memoria, questo registro genera
sull’address bus il relativo indirizzo attingendolo dal PC.
Se l’istruzione in corso di esecuzione prevede un trasferimento di dati alla memoria o ai
dispositivi di I/O, nel MAR viene posto l’indirizzo relativo a quel componente.
Il registro dati di memoria (MDR, Memory Data Register) è un registro bidirezionale
interfacciato direttamente con il data bus esterno.
La sua funzione principale è quella di provvedere allo scambio dei dati tra la CPU e la
memoria o i dispositivi di I/O.
Se il dato è un operando viene inviato in uno dei registri interni, mentre se si tratta del
codice operativo di una istruzione viene inviato al registro IR.
Esecuzione di un’istruzione
L’esecuzione di ogni istruzione si articola in due fasi distinte:
•
fase di fetch o di prelievo dell’istruzione dalla memoria;
•
fase di execute o di decodifica ed esecuzione vera e propria dell’istruzione.
L’esecuzione completa di un’istruzione di un microprocessore a 8 bit si articola nelle
seguenti fasi.
All’attivazione del sistema o comunque dopo un impulso di reset, il PC viene inizializzato
con l’indirizzo di partenza, che potrebbe essere 0000H, dove si trova la prima istruzione
del programma,
per esempio LD A,5B. Questa è una tipica istruzione di tutti i microprocessori il cui
significato è: carica l’accumulatore con il dato esadecimale 5B.
Ogni istruzione è costituita da uno o più byte, nel caso in esame da due byte: il primo
è l’op code (codice operativo) dell’istruzione, il secondo è il dato (5BH).
A destra è illustrata la memoria con i dati contenuti.
Le due fasi in cui si articola l’attività della CU sono la fetch e la
execute.
•
Fase di fetch:
– il contento del PC viene trasferito nel registro MAR;
– il MAR pilota l’address bus mentre la CU genera i segnali opportuni
per predisporre la memoria alla lettura;
– la memoria pone il contenuto della locazione 0000H (3EH) sul data bus;
– il primo byte (3EH) viene depositato nel registro MDR;
– essendo 3EH un codice operativo, viene inviato nel registro IR.
•
Fase di execute:
– il contenuto del registro IR viene letto internamente dalla CU tramite una PLA;
– la CU riconosce il tipo di istruzione e la sua lunghezza e pertanto si predispone a
leggere un altro byte (il dato) dalla memoria, quello con indirizzo 0001H;
– la CU tramite il registro MAR pilota l’address bus con l’indirizzo 0001H;
– la CU invia alla memoria un segnale di richiesta per una lettura (RD);
– la memoria pone sul data bus il dato richiesto, nel nostro caso 5BH;
– il dato posto sul data bus entra nel registro MDR;
– il contenuto di MDR viene trasferito nell’accumulatore.
Prima che abbia inizio la vera e propria fase di esecuzione dell’istruzione, la CU aggiorna
il contenuto del PC in modo tale da predisporsi al prelievo della successiva istruzione del
programma.
Il PC viene pertanto aggiornato con l’indirizzo 0002H.
L’esecuzione dell’istruzione viene così completata e il microprocessore è già pronto per
una nuova fase di fetch.
Polling e interrupt
Lo scambio di dati tra la CPU e la memoria non esige particolari procedure, infatti se
in un qualsiasi istante la CPU attiva gli ingressi di abilitazione, la memoria si dichiara
immediatamente disponibile: lo scambio dei dati può avvenire.
I dispositivi periferici sono caratterizzati da un funzionamento asincrono quindi lo
scambio di informazioni non avviene sempre ma solo in un alcuni istanti, ovvero quando
gli organi periferici segnalano la loro disponibilità.
Ad esempio, un processo industriale potrebbe in un certo istante non avere la necessità
(o la possibilità) di trasmettere (o ricevere) dati alla (o dalla) CPU;
un altro esempio potrebbe essere costituito da una stampante che non può accettare
altri dati dalla CPU perché la sua memoria è satura.
Pertanto, prima di dar luogo alla procedura di scambio dei dati, il microprocessore deve
accertare la disponibilità della periferica alla comunicazione.
In genere sono due le tecniche di comunicazione tra la CPU e una periferica: il polling e
l’interrupt.
Il polling consiste nella scansione ciclica, da parte della CPU, di tutte le periferiche per
verificare la disponibilità o meno alla comunicazione.
La tecnica del polling ha l’indubbio vantaggio di una semplicità hardware, infatti ogni
periferica è dotata di un registro di stato su cui annota la propria situazione.
Pertanto la CPU, tramite comandi software, verifica lo stato del registro e assume le
decisioni opportune.
Gli inconvenienti di questo tipo di tecnica sono:
•
la CPU è impegnata per la quasi totalità del suo tempo in operazioni di verifica dei
registri di stato dei dispositivi di I/O;
•
la comunicazione vera e propria occupa un tempo notevolmente inferiore rispetto al
tempo speso per l’interrogazione sequenziale di tutti i dispositivi;
•
una richiesta di dialogo con carattere di urgenza, avanzata da una periferica alla CPU,
non può essere soddisfatta immediatamente perché il microprocessore è impegnato
nella scansione delle altre periferiche;
•
la comunicazione potrebbe avvenire con un ritardo intollerabile per il processo
industriale da controllare.
La tecnica dell’interrupt (interruzione) consiste nella richiesta di dialogo avanzata
dalla periferica alla CPU mentre questa è impegnata nello svolgimento di altri compiti.
Il microprocessore è infatti provvisto di un ingresso per la richiesta d’interruzione,
INTRQ (Interrupt Request), che viene attivato dal registro di stato della periferica.
La CPU, alla fine dell’esecuzione dell’istruzione in corso di elaborazione e prima della
fase di fetch dell’istruzione successiva, risponde al dispositivo, che ha avanzato la
richiesta, con un segnale di riconoscimento dell’interruzione, INTA (Interrupt
Acknowledge) e svolge la routine di servizio dell’interrupt, cioè esegue un segmento di
programma, già memorizzato in precedenza nel sistema, atto a soddisfare l’esigenza
del dispositivo richiedente l’interruzione.
Dopo aver svolto la routine di servizio, il microprocessore torna al programma prece-
-dente esattamente al punto in cui aveva sospeso l’esecuzione.
Con questa tecnica la CPU dedica alle periferiche il tempo strettamente necessario allo
scambio dei dati, mentre la sua attività principale è rivolta allo svolgimento di altre
mansioni.
Temporizzazioni
Tutte le attività di un microprocessore sono scandite da un segnale di clock, generato
da un oscillatore al quarzo perché l’oscillazione deve essere quanto più possibile stabile
con la temperatura e con l’invecchiamento dei componenti.
L’esecuzione di un’istruzione ha una durata complessiva che viene chiamata ciclo
d’istruzione.
Si definisce invece ciclo macchina il tempo che il microprocessore impiega a eseguire
un’operazione elementare.
Le operazioni elementari più comuni sono:
•
Internal Operation (operazione interna alla CPU stessa);
•
Fetch Operation (operazione di prelievo dell’istruzione);
•
Memory Write (operazione di scrittura in memoria);
•
Memory Read (operazione di lettura in memoria);
•
I/O Write (operazione di scrittura in un dispositivo di I/O);
•
I/O Read (operazione di lettura in un dispositivo di I/O);
•
Interrupt Acknowledge (riconoscimento di interruzione).
Ogni ciclo macchina è costituito da più cicli di clock, dove per ciclo di clock (o stato
macchina) si intende il periodo del segnale di clock.
Il ciclo di clock rappresenta per la CPU il passo più piccolo dell’attività di esecuzione di
un’istruzione.
Ogni ciclo istruzione è composto quindi da un certo numero di cicli macchina.
Normalmente una fase di fetch è costituita da un ciclo macchina mentre la durata di
una fase di execute è variabile.
Ciclo di clock
In alcuni microprocessori il segnale di clock viene diviso
in due segnali isofrequenziali sfasati di 90°, come indicato
nella figura a lato.
Combinando i due segnali si ottiene un nuovo clock avente
frequenza doppia.
Ad ogni ciclo di clock corrisponde un passo della esecuzione dell’istruzione, ad ogni
ciclo del nuovo clock, chiamato sottociclo, corrisponde un sottopasso eseguito dal
microprocessore.
Esempio
Nella sottostante figura è illustrato il ciclo istruzione dell’esempio studiato nel paragrafo
precedente: LD A,5B.
Dalla figura si nota che il primo ciclo macchina M1, quello relativo alla fase di fetch, è
costituito da 4 colpi di clock mentre il secondo ciclo macchina M2 è formato da tre cicli.
In totale l’istruzione LD A,5B necessita di 7 cicli di clock.
L’operazione di lettura dalla memoria è una delle operazioni fondamentali del micropro-
-cessore, questa operazione è presente sempre nella fase di fetch e molto spesso anche
in quella di execute per prelevare operandi o indirizzi dalla memoria.
Quando la memoria è caratterizzata da un comportamento temporale lento, vengono
generati dalla CPU degli stati di attesa Tw (wait time) per sincronizzare le operazioni,
pertanto il ciclo macchina si allunga in misura direttamente proporzionale alla lentezza
della memoria.