Tutorials - PIC

 

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:

  1. solo i 9 bit meno significativi della destinazione possono entrare a far parte della codifica dell' istruzione (1000110000 000110000)
  2. 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:

  1. solo gli 8 bit meno significativi della destinazione entrano a far parte della codifica (0100110000 00110000)
  2. 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:

  1. Se il programma si estende solo nelle prime 256 locazioni, tutte le istruzioni possono essere eseguite senza problema.
      
  2. 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.
      
  3. 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:

  1. 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.
     
  2. Al reset (POR) il o i bit PAx sono posti per default a 0, quindi si accede direttamente alla Pagina 0

 


 

 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 08/05/13.