Il PC nei Baseline: banchi e pagine_0
|
La memoria programma : PAGINE
Prendiamo ad esempio un PIC minimale come 10F200. La sua mappa di memoria
programma è questa:
|
La memoria programma è ampia solo 256 elementi, quindi va dall'
indirizzo 00h all' indirizzo FFh.
Per quanto abbiamo detto
prima, le istruzioni di salto
goto e
call possono
indirizzare qualsiasi punto di questa area.
Ad esempio, se all'indirizzo 000h
inserisco una istruzione goto
0FFh sarà eseguita correttamente.
Il meccanismo di esecuzione di queste istruzioni comprende il fatto
che i bit di indirizzo contenuti nella codifica vengono passati al
Program Counter, in questo caso ampio 9 bit.
Dato che il PC e l' indirizzo in codifica hanno la stessa ampiezza,
si potrà indirizzare tutta l' area disponibile (9 bit = da 000h
a 1FFh).
|
Per quanto riguarda l' istruzione call
la situazione è leggermente diversa:
|
Dal diagramma notiamo che per call
il bit 8 del PC è sempre e comunque posto a 0.
Questo
limita l' indirizzamento a 8 bit (2^8 = 256 , 0FFh).
La limitazione relativa a call
nel caso di questo PIC con solo 256 posizioni di memoria non ha alcuna influenza, dato che l' ampiezza massima
della memoria programma è proprio 256.
|
Per riassumere:
Opcode |
Program
Counter |
Valori
Possibili |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
CALL k |
0 |
k
dall' istruzione |
da 000h a 0FFh |
GOTO k |
k
dall' istruzione |
da 000h a 1FFh |
Va tenuta sempre presente una cosa fondamentale:
Lo stack
dei Baseline è costituito solamente da due livelli. Quindi è
possibile chiamare una subroutine 1 che a sua volta chiami una subroutine
2, ma quest' ultima NON può chiamare una terza subroutine dato
che i due livelli dello stack sono già pieni. Non essendo disponibile
un meccanismo di verifica dell' overflow, un errore sullo stack manda
in crash il programma. |
Cosa succede, però, in PIC10F204 ?
|
La memoria programma disponibile è il doppio della precedente,
ovvero si estende da 000h a 1FFh. L' istruzione di salto goto
dispone di 9 bit per l' indirizzo e con
questi può coprire tutta l' estensione della memoria, da 000h
a 1FFh.
Quindi, scrivendo all' indirizzo 000h
l' istruzione goto
1FFh questa
sarà eseguita correttamente.
Il problema sorge con la calll, che dispone solamente di 8 bit per
l' indirizzo. Ne risulta che l' istruzione call
0FFh, scritta a 00h
sarà eseguita correttamente, ma se scriverò call
130h, dato che il
bit 9 è sempre a 0, raggiungerò non 130h
ma 030h.
E, per la stessa ragione, se all' indirizzo 100h
scrivessi call 1FFh
raggiungerei comunque solo 0FFh.
Ovvero, nei Baseline, la call
può indirizzarsi esclusivamente a locazioni
comprese nei primi 256 bytes.
La massima estensione di memoria programma che viene
coperta direttamente dai bit forniti nell' istruzione goto
si
chiama "pagina".
Nei Baseline la pagina è
ampia 512 locazioni.
Lo spazio da 000h a 1FFh
si chiama pagina 0. |
|
In PIC10F200 la memoria programma disponibile è ampia mezza pagina.
In PIC10F204 la memoria programma disponibile è ampia una pagina.
Per altri PIC con risorse maggiori, la questione si complica ulteriormente:
|
Per esempio, in PIC12F509, la memoria programma disponibile
è ampia 1024 bytes (che sarebbe meglio chiamare words
in quanto sono ampie ciascuna 12 bit e non 8), ovvero 1 k.
Se indichiamo con "pagina" uno spazio ampio 512 words,
qui abbiamo due pagine, che prendono il nome di:
- pagina 0, da 000h a 1FFh
- pagina 1, da 200h a 3FFh
Abbiamo visto che i 9 bit del goto potranno raggiungere uno spazio da 000h a
1FFh.
Per definire tutta
l' area da 1k (2^10 = 1024) occorrono 10 bit.
Quindi se a 000h scriviamo goto
1FFh, questo sarà eseguito
correttamente; ma se scriviamo goto
2AAh si otterrà un salto a 0AAh,
dato che nella codifica manca il decimo bit.
|
Si rende necessario un sistema per passare da una pagina alla seguente
aggiungendo il bit mancante.
|
Questo decimo bit è derivato dal bit PA0 dello
STATUS. Il bit
verrà aggiunto come più significativo a quelli forniti nella codifica dell'
istruzione, permettendo così di indirizzare da 000h
a 3FFh.
Per accedere alle due pagine il metodo è questo:
- PA0 = 0 -> primi 512 words
, Pagina 0 (000h-1FFh)
- PA0 = 1 -> successivi 512 words, Pagina 1 (200h-3FFh)
Opcode |
Program
Counter |
Valori
Possibili |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
GOTO k |
PA0 |
k
dall' istruzione |
PA0=0 da 000h a 1FFh
PA0=1 da 200h a 3FFh |
|
Ad esempio, se con il PC a 0040h si
inserisce l'istruzione goto 080h
essa viene
eseguita correttamente.
Se si agisce portando PA0=1, si passa nella
seconda pagina (pagina 1)
Opcode |
Codifica
|
Note |
1 |
0 |
1 |
k
|
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
GOTO 080h |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
Solo
9 bit della destinazione entrano a far parte della codifica (0010000000
→ 01000000) |
|
PA0
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
|
|
0/1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
PA0=0 destinazione PC →
080h (80h in pagina 0)
PA0=1 destinazione PC → 280h (80h in
pagina 1)
|
|
Program
Counter |
|
Nella stesa situazione, goto 230h (1000110000) non viene
eseguita correttamente, dato che:
- solo i 9 bit meno significativi della destinazione possono entrare a far parte della codifica
dell' istruzione (1000110000 → 000110000)
- l' indirizzo di destinazione è nella
pagina 1
Se la partenza è in pagina 0, essendo impostato dai default PA0=0,
l' indirizzo di destinazione reale del salto sarà ancora nelle pagina
0,
a 030h.
Occorrerà prima portare PA0=1 in modo da
aggiungere questo 1 all' indirizzo di destinazione.
Opcode |
Codifica
|
Note |
1 |
0 |
1 |
k
|
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
GOTO 230h |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
Solo
9 bit della destinazione entrano a far parte della codifica (1000110000
→ 000110000) |
|
PA0
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
|
|
0/1 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
PA0=0 destinazione PC →
030h (30h in pagina 0)
PA0=1 destinazione PC → 230h (30h in
pagina 1)
|
|
Program
Counter |
|
La sequenza di istruzioni necessaria sarà:
bsf STATUS, PA0
goto 230h
Il salto viene eseguito correttamente, avendo portato lo switch delle
pagine PA0=1,
che ora punta alla pagina 1. Per quanto riguarda call
la situazione è analoga, con la limitazione che l' indirizzamento si estende
solo ai primi 256 words della pagina in cui ci si trova.
|
La situazione è analoga a quella vista per goto, con il fatto
che il bit 8 è in ogni caso settato a 0.
Questo genera la limitazione ai primi
256 indirizzi di ogni pagina:
- PA0 = 0 -> primi 256 bytes
di Pagina 0 (000h-0FFh)
- PA0 = 1 -> primi 256
bytes di Pagina 1 (200h-2FFh)
|
Con il bit 8 del PC, sempre e comunque posto a 0, e k che varia tra 00000000 e
11111111, si ha:
Opcode |
Program
Counter |
Valori
Possibili |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
CALL k |
PA0 |
0
|
k
dall' istruzione |
PA0=0 da 000h a 0FFh
PA0=1 da 200h a 2FFh |
Ad esempio, se con il PC a 0040h si
inserisce l'istruzione call 080h
essa viene
eseguita correttamente.
Se si agisce portando PA0=1, si passa nella seconda pagina (pagina 1) e si
chiamerà l' indirizzo 280h.
Opcode |
Codifica
|
Note |
1 |
0 |
0 |
1
|
k
|
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
CALL 080h |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
Solo 8 bit della destinazione entrano a far parte della codifica
(0010000000 →
1000000) |
|
PA0
↓ |
0
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
|
|
0/1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
PA0=0 destinazione PC →
080h (80h in pagina 0)
PA0=1 destinazione PC → 280h (80h in
pagina 1)
|
|
Program
Counter |
|
Invece, nella stesa situazione, call
130h (0100110000) non viene
eseguita correttamente, dato che:
- solo gli 8 bit meno significativi della destinazione entrano a far parte
della codifica (0100110000 →
00110000)
- il bit 8 è sempre fissato a 0
Se dai default PA0=0, l' indirizzo di destinazione reale della
chiamata sarà ancora nelle pagina 0, ma 030h.
Se si porta PA0=1 in modo da aggiungere
questo 1 all' indirizzo di destinazione, la chiamata sarà indirizzata a 230h.
Opcode |
Codifica
|
Note |
1 |
0 |
0 |
1
|
k
|
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
CALL 230h |
1 |
0 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
Solo 8 bit della destinazione entrano a far parte della codifica
(01001100000 →
00110000) |
|
PA0
↓ |
0
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
↓ |
|
|
0/1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
PA0=0 destinazione PC →
030h (30h in pagina 0)
PA0=1 destinazione PC → 230h (30h in
pagina 1)
|
|
Program
Counter |
|
Peraltro, è evidente che se la riga della call
si trova OLTRE i primi 256 indirizzi, potrà rimandare solamente ad indirizzi ENTRO
i primi 256. Quindi, una riga call
130h posta all' indirizzo 100h
rimanderà comunque all' indirizzo 030h.
Quindi possiamo riassumere il problema della paginazione della memoria
programma nei seguenti tre casi, indipendentemente dalla quantità di
memoria disponibile:
- Se il programma si estende solo nelle prime 256 locazioni, tutte
le istruzioni possono essere eseguite senza problema.
- Se il programma supera i 256 bytes, ma resta all' interno
dei primi 512 (pagina 0), tutte le istruzioni possono essere eseguite, esclusa la
call, che consente acceso soli a indirizzi compresi nei primi 256
bytes.
- Se il programma si estende oltre i primi 512 bytes, per accedere
con alle pagine successive alla pagina 0 occorre azionare i bit di switch
relativi alla pagina voluta.
call agirà
comunque esclusivamente entro i primi 256 indirizzi di qualsiasi pagina
|
Da notare un punto importante:
Una volta effettuata la sequenza:
bsf STATUS, PA0
il PC si troverà in pagina 1 e il puntatore PA0 indicherà questa
pagina, aggiungendo 1 come bit 10 dell' indirizzo contenuto nell' istruzione, fino
a che non viene cambiato dal programma (o azzerato al reset).
Se occorre eseguire istruzioni in un' altra
pagina, sarà necessario manovrare ancora gli switches di pagina.
|
Ovvero:
100h bsf STATUS, PA0
; commuta su pagina 1
goto 230h
; salta a 230h
....
230h goto
100h ;
questo invia a 200h, dato che PA0 = 1 |
invece:
100h bsf STATUS, PA0
; commuta su pagina 1
goto 230h
; salta a 230h
....
230h bcf STATUS, PA0 ;
commuta su pagina 0
goto
100h ;
questo invia a 100h, dato che PA0 = 0 |
Il Macro Assembler MPASM dispone di una direttiva specifica, PAGESEL
che effettua la selezione della pagina in funzione della label
indicata. Così:
100h base bsf STATUS, PA0
; commuta su pagina 1
goto target
; salta a 230h
....
230h target bcf
STATUS, PA0 ; commuta su pagina 0
goto base ;
questo invia a 100h, dato che PA0 = 0 |
è sostituibile a:
100h base PAGESEL target
; commuta su pagina 1
goto target ;
salta a 230h
....
230h target PAGESEL
base ; commuta su pagina
0
goto base ;
questo invia a 100h, dato che PA0 = 0 |
La direttiva ha il vantaggio di poter utilizzare label invece di
assoluti, cosa fondamentale in una buona programmazione Assembly.
Esistono PIC Baseline con memoria programma maggiore di 1k.
|
Ad esempio, 16F57 dispone di 2k words di memoria programma, da 000h a
4FFh, che quindi risultano divisi in 4
pagine da 512k ciascuna.
Per coprire questo spazio occorrono 11 bit di indirizzo (2^11 = 2k).
I bit mancanti all' opcode sono forniti dallo STATUS con i bit Pa1:0.
- PA<1:0> = 00 -> Pagina
0, primi 512 bytes, 000h-1FFh
- PA<1:0> = 01 -> Pagina
1, successivi 512
bytes, 200h-2FFh
- PA<1:0> = 10 -> Pagina
2, successivi 512 bytes, 300h-3FFh
- PA<1:0> = 11 -> Pagina
3, successivi 512
bytes, 400h-4FFh
|
Quindi occorre commutare i due bit per accedere ai vari banchi. Ad esempio:
bsf STATUS, PA0
; commuta su pagina 4
bsf STATUS, PA1
....
bsf STATUS, PA0
; commuta su pagina 1
bcf STATUS, PA1 |
che equivalgono a:
PAGESEL 4
; commuta su pagina 4
....
PAGESEL 1
; commuta su pagina 1 |
Alcune note importanti:
- L' istruzione di rientro da subroutine, retlw per i Baseline (return
per gli altri PIC), non necessita di indirizzo nella codifica,
dato che lo preleva dal top dello stack, dove sono contenuti tutti i
12 bit necessari, e lo copia direttamente nel PC.
- Al reset (POR) il o i bit PAx sono
posti per default a 0, quindi si accede direttamente alla Pagina 0
|
|