Occorre ancora spendere qualche riga su una questione che continua ad
intossicare i sorgenti assembly.
Si tratta delle macro BANKx.
Per facilitare il passaggio tra i banchi, che con i PIC Midrange è
effettuato attraverso due bit delle STATUS,
in un (remoto) passato erano state scritte due macro:
BANK0
macro
BCF STATUS, RP0
endm
BANK1
macro
BSF STATUS, RP0
endm
Oppure, meno chiaramente, sotto
forma di definizioni:
#define
BANK0 BCF STATUS, RP0
#define
BANK1 BSF STATUS, RP0
Non ci si può stancare di dire che questo modo di programmare è
sicuramente scorretto.
Le motivazioni, a chiunque abbia un poco di esperienza con i PIC, sono
evidenti, ma esiste ancora una larga fascia di persone che si avvicinano alla
programmazione assembly con il solo ausilio di esempi eccessivamente datati o,
peggio, di più recenti copie insensate degli stessi.
BANK0 e compagnia NON servono: eliminatele!
Il macro assembler MPASM non richiede queste macro, che vanno
eliminate dai sorgenti e sostituite dalla direttiva banksel.
Questa semplice sostituzione non è solo formale, ma permette di evitare di
trovarsi in situazioni dalle quali, in mancanza di sufficienti conoscenze, è
difficile venire fuori.
In primo luogo, le due macro indicate sopra sono funzionali solamente ed
esclusivamente per i PIC Midrange con soli due banchi.
|
Per un chip come 12F629,
ad esempi, sono disponibili due banchi di memoria RAM,
il
cui switch è il bit RP0 della STATUS:
|
In questo caso, le macro BANK0 e BANK1 funzionano, ma se
portiamo il sorgente su un 16F690, ad esempio, ci saranno certamente problemi,
in quanto i banchi disponibili non sono due, ma quattro:
il che richiede una azione su DUE switch di banco, ovvero RP0
e RP1, sempre nello STATUS:
Sono da osservare due cose:
- da parte di Microchip, è sempre presente la filosofia di posizionare i
registri fondamentali nelle stesse posizioni di memoria: Notiamo che STATUS,
PCL, FSR, ecc sono accessibili agli stessi indirizzi
indipendentemente dai banchi, ma anche PIR, PIE,
TMRx, ecc sono posizionati nelle stesse locazioni/banchi.
Però è evidente che all'aumentare delle funzioni integrate, molti SFR
vengo sopstati nei banchi più alti. Così, se è possibile agire sul
TIMER1 in Banco0 e su IOC sul Banco1, la gestione della EEPROM si sposta
dal banco 1 ai banchi 2 e 3.
Ne risulta che si renderebbe necessario un diverso set di macro, che
comprendano anche BANK2 d BANK3 e che, sopratutto, non si limitino ad
agire sul solo RP0, ma interessino anche RP1:
BANK0
macro
bcf STATUS,
RP0
bcf
STATUS, RP1
endm
BANK1
macro
bsf STATUS, RP0
bcf STATUS, RP1
endm
BANK2 macro
bcf STATUS, RP0
bsf
STATUS, RP1
endm
BANK3
macro
bsf STATUS, RP0
bsf STATUS, RP1
endm
Se non introducessimo questo accorgimento, la macro BANK0 precedente, che
agisce solo su RP0, non potrebbe portare al Banco0 partendo dal Banco2 o 3 e
così via, dato che modifica un solo RP.
- lo scambio dei banchi attraverso i bit dello STATUS vale solo ed
esclusivamente per i Midrange.
Per gli Enhanced Midrange e i PIC18F la gestione dei banchi ha un
approccio del tutto differente.
In particolare, passando da Midrange ad Enhanced Midrange occorre sapere
che il numero dei banchi disponibili in questi ultimi processori è di ben
32, il che richiede 5 bit per lo switch.
Questi bit, ovviamente, non trovano posto nello STATUS, ma sono collocati
in un registro BSR (Bank Select Register) e dispongono di una specifica
istruzione di gestione: movlb.
Di conseguenza, una "macro" per i banchi dovrebbe assumere la
forma:
BANK0
macro
movlb 0
endm
Ma la cosa perde immediatamente di senso se consideriamo quanto indicato al
punto 1, ovvero il fatto che gli SFR, in processori diversi, possono essere
posti in banchi diversi e che, a meno di avere costantemente sottocchio la
mappa di memoria, non è comunemente possibile avere a mente questi dati.
Il problema, però, non esiste: basta abbandonare l'inutile pacchetto di
macro per banchi ed usare banksel: il macro
assembler MPASM compilerà la riga in modo adeguato al processore
usato, in modo automatico, riconoscendo, poi, sempre automaticamente, dove si
trova il registro interessato:
banchi
disponibili |
riga |
compilato
come:
|
Midrange 2
banchi
|
banksel TRISIO
|
bsf STATUS,RP0
|
Midrange
a 4 banchi
|
banksel TRISA
|
bsf STATUS,RP0
bcf
STATUS,RP1
|
Enhanced Midrange |
banksel TRISA |
movlb 1 |
Quindi, semplicemente:
eliminiamo le macro o definizioni di comando dei banchi e sostituiamole
con:
banksel
nomeSFR
e il sorgente sarà chiaro,
semplice da scrivere e portabile.
Due note.
- MPASM non accetta una label sulla riga del banksel. Questo è dovuto al
fatto che la riga origina una o due istruzioni. Quindi:
choice
banksel EEADR
originerà un errore. Occorrerà scrivere:
choice:
banksel
EEADR
Il : dopo la label non è obbligatorio, ma è
"tradizionale" in quanto è stato necessario in passato in molte
versioni di assemblatori ormai datati.
- Va considerato che nel caso di processori a 4 banchi, banksell
origina due istruzioni. Quindi non è corretto:
btfss tester
banksel PORTA
testHi...
in quanto verrebbe
compilato come:
btfss tester
bcf
STATUS,RP0
bcf
STATUS,RP1
testHi...
generando un salto errato nel caso in cui il test su bit fosse positivo.
Da notare che nel caso degli Enhaced Midrange, qualsiasi passaggio di banco
richiede una unica istruzione.
Altre informazioni:
|