Il Set di istruzioni dei PIC18
|
Introduzione
I microcontroller PIC appartengono alla categoria dei RISC, ovvero
dispongono di un set limitato di istruzioni . Queste istruzioni sono , però,
basilari sia come funzionalità che come rapidità di esecuzione; il
programmatore potrà creare, se ritiene necessario, altre istruzioni più
complesse associando più istruzioni fondamentali attraverso la tecnica della
macro istruzione.
Per i PIC più semplici si ha un set ridotto con 31 istruzioni a 12bit. Per
i mid-range, la famiglia 16Fxxx, il set di istruzioni è composto da circa 35
elementi a 14 bit.
Per i PIC18Fxxx il set è espanso a 77 istruzioni, più altre speciali, per
un totale di 83 possibili opcodes, in un formato a 16 bit.
Struttura degli opcodes
Prima di iniziare a vedere in dettaglio il set di
istruzioni, occorre fare una precisazione importante.
Nei PIC la sequenza di bit che codifica le istruzioni contiene sia il codice
specifico dell' istruzione, sia l' indirizzo di destinazione (se previsto) e
le eventuali opzioni o specifiche dell' istruzione stessa. Questo riduce il
numero dei bit disponibili per l' indirizzamento sia nell' area di memoria
utente che nella memoria programma e nei registri interni, richiedendo una
suddivisone in banchi (registri, memoria dati) o pagine (memoria programma).
Occorre per prima cosa tenere ben presente che, quando si dice che i PIC16F e
18F sono a "8 bit" , si identifica con questo la lunghezza del byte
dati (ovvero sono trattabili elementi numerici da 0 a FFh, 255 decimale).
Invece, le istruzioni sono lunghe "2 bytes", ovvero 1 word composta
da 12, 14 o 16 bit a seconda della famiglia.
Nel set a 14 bit (PIC16F), 1 word del codice dell' istruzione è
composto da due bytes di cui il basso è dei canonici 8 bit, ma quello alto è
di soli 6 bit (per un totale di 14 bit, appunto).
Nei PIC18F, i due "bytes" sono entrambi a 8 bit, dando così un
codice istruzione a 16 bit; oltre a questo, sono disponibili alcune istruzioni
che occupano 2 word, ovvero 4 bytes.
Quindi, per riassumere, i PIC18F dispongono di dati su un bus a 8 bit e di
istruzioni su un bus a 16 bit.
Con 16 bit, se fossero tutti usati per l' indirizzamento,
si potrebbe coprire un' area di memoria da 0 a 65 k (FFFFh), mentre con 14 bit
si arriverebbe solo a 3FFFh (16 k).
Se questo è classico con microprocessori che utilizzano un bus per indirizzi
e un bus per dati separati tra di loro, ricordiamo che nei PIC la struttura è
differente : alcuni bit dell' opcode sono impegnati per definire l' istruzione
altri i dati relativi, altri l' indirizzo.
Questo approccio è solo parzialmente limitativo, perchè non tutte le
istruzioni hanno come scopo di toccare locazioni di memoria o registri, mentre
l' impacchettamento di tutti gli elementi in una unica word assicura una
esecuzione più efficiente e rapida, tanto che gran parte degli opcodes è
completata in un solo ciclo macchina.
Ad esempio, l' istruzione per sommare al registro di
lavoro W un numero fisso k (ADDLW - ADD Literal to W) viene
codificata con la seguente stringa binaria :
11 111x kkkk
kkkk per il set a 14 bit
0000 1111 kkkk kkkk
per il set a 16 bit
dove l' istruzione in sè è indicata dai primi bit (11111
o 0000 1111), mentre il numero
k è indicato dagli 8 bit più bassi (x è un bit non utilizzato
nel codice 16F). Questo compattamento di bit permette un notevole risparmio di
risorse ed un certo vantaggio nell' esecuzione dei codici, ma si scontra con
la necessità di disporre di istruzioni che vadano a lavorare in memoria e sui
registri interni diversi dall' accumulatore in modo altrettanto efficace.
Certamente esistono istruzioni "intrinseche" che non hanno
bisogno nè di indirizzo, nè di oggetto, in quanto svolgono una funzione ben
determinata ed unica. Ad esempio la sequenza :
00 0001 0xxx
xxxx per il set a 14 bit
0000 0000 0000 0011
per il set a 16 bit
indica al processore di passare in modalità attesa a basso consumo (SLEEP)
: nel set a 14 bit solo i primi 7 bit del codice sono significativi, mentre
gli altri restano inutilizzati. Questo è possibile perchè esiste un solo
modo per mandare il processore in Sleep e non è necessario un vero e proprio
oggetto e relativo indirizzo.
Se, però, vogliamo, ad esempio, azzerare un qualsiasi registro, sarà
necessario specificarne l' indirizzo preciso, visto che ce ne sono molti. La
serie di bit :
00
0001 1fff ffff per
il set a 14 bit
0110 101a
ffff ffff per il set a 16 bit
comunica al processore di azzerare (clear) il file f
(CLRF). Ora, si nota come 7 bit della word sono usati per codificare l'
istruzione (0000011 a 14 bit e 0110101
per il 16 bit), mentre ne restano solo 7 per definire l'indirizzo del
registro f nell' opcode a 14 bit e 8 nell'
opcode a 16 bit. Con 7 bit il massimo numero binario esprimibile è 111 1111
ovvero 3Fh, cioè 127 decimale. Questo vuol dire che questa istruzione può
azzerare locazioni di memoria da 0 a 127, ma non oltre; per raggiungere la
locazione 128 o 240 sarà necessario utilizzare un qualche altro sistema, come
vedremo. Per contro, con 8 bit si arriva a 1111 1111, ovvero FFh, cioè 255
decimale, raddoppiando l'area indirizzabile, ma comunque, per raggiungere
destinazioni più lontane, occorre implementare un qualche sistema ausiliario
esterno. (Nel codice a 16 bit il bit a è legato
a questi meccanismi e serve a specificare una particolare modalità di
indirizzamento).
Con tutte le istruzioni che vanno a toccare i registri si presenta questa
situazione. Ad esempio :
01 10bb
bfff ffff per il
set a 14 bit
1011 bbba ffff ffff
per il set a 16 bit
permette di saltare l' istruzione successiva se il bit indicato da b nel
file f è = 0 (BTSSC - Bit TeSt on file, Skip
next instruction if Clear), quindi con la possibilità di specificare 1 bit su
8. In entrambi i set, il codice dell' istruzione occupa 4 bit (0110
per il 14 e 1011 per
il 16), mentre, come nell' esempio precedente, 7 bit indirizzano il file f
a 14 bit e 8 a 16, dando rispettivamente un' area indirizzabile di 127 e 255 .
I tre bit b determinano quale degli 8 bit
di f va testato, mentre il bit a presente
nel set a 16 bit serve come sopra per definire una modalità particolare di
indirizzamento.
Un primo punto da considerare, quindi, è quello che l' area di azione nella
memori dati di buona parte delle istruzioni è limitata ad una area di 128 bit
per il set a 14 e di 256 per quello a 16. Inoltre, questa ampiezza è definita
da un numero di bit inferiore a quello di due word : nel PIC abbiamo visto che
c'è una "differenza" tra larghezza del "byte" per gli
indirizzi e del "byte" per i dati e che, nei "byte" di
istruzione, i bit dedicati all' indirizzamento sono solo una parte.
Però questa caratteristica non è costante in tutte le istruzioni del set
a 14 bit. Nell' accesso alla memoria programma, l' area indirizzabile è
maggiore. Ad esempio, il codice :
10 0kkk
kkkk kkkk per il set a 14 bit
contiene i primi tre bit (100)
che indicano al processore di saltare ad una subroutine (CALL subroutine), la
posizione della quale è definita dagli altri 11 bit k.
Con 11 bit si può arrivare da 0 a 3FFh, ovvero 1024 (1k) locazioni di
memoria, coprendo uno spazio diverso dai casi precedenti; d' altronde le
istruzioni BTFSSC e CRLF operano sui registri della memoria dati, mentre la
CALL opera sulla memoria programma, che ha dimensioni maggiori. In ogni caso,
se la memoria programma da indirizzare supera la possibilità degli 11 bit,
occorre anche qui utilizzare un qualche marchingeno addizionale.
Da osservare che la stessa istruzione CALL, nel caso della famiglia 18F, si
sviluppa su due word, per un totale di 32 bit, di cui ben 20 (k)
sono utilizzati per l' indirizzamento :
1110 110s
kkkk kkkk
1111 kkkk kkkk
kkkk
Si nota quindi una primaria differenza tra il set a 14 bit e
quello a 16 : la maggiore ampiezza dell' area indirizzabile da quest' ultimo.
Per inciso, il bit s specifica una modalità
detta Fast.
In effetti il tutto è legato alla struttura della memoria dei
PIC :
Memoria |
16F |
18F |
Note |
pagine |
bytes |
pagine |
bytes |
Programma |
da 1
a 3 |
fino a 2 k |
1 |
fino a
128 k |
Nella famiglia 16F la memoria programma è segmentata in più pagine
raggiungibili modificando degli switches in un apposito registro (PCLATH).
Questo è uno dei punti dolenti dei PIC, perchè richiede particolare
attenzione da parte dell' utente se la lunghezza del programma eccede
una pagina .
Nella famiglia 18F, la memoria programma è organizzata in una sola
pagina, raggiungibile grazie alla maggior estensione dell'
indirizzamento : non esiste più il problema della paginazione del
programma (sospiro di sollievo) |
Dati |
banchi |
bytes |
banchi |
bytes |
Nella famiglia 16F la memoria dati è frammentata in
banchi (da 1 a 4) raggiungibile modificando gli switches RP1:0 dello
STATUS.
I registri general purpose e quelli speciali sono suddivisi sui vari
banchi e questo è un altro dei punti dolenti dei PIC : per pasare da
un registro all' altro occorre agire sugli switches dei banchi.
Nella famiglia 18F la memoria dati è (purtroppo) ancora frammentata
in banchi, fino a 16, anche qui raggiungibili modificando degli
switches. I banchi, però, hanno ampiezza doppia, dato che le
istruzioni a 16 bit permettono di indirizzare 256 bytes e i registri
stanno tutti in uno stesso banco, il che rende le cose meno
antipatiche. Inoltre esistono modalità diverse di indirizzamento ed
istruzioni dedicate alla commutazione dei banchi. |
da 1
a 3 |
127
cad |
fino a 16 |
256
cad |
Vedremo più avanti di chiarire come funziona l'
indirizzamento della memoria.
|