T&T - PIC

 

Ancora su BANK0 e simili

 


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:

  1. 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.

  1. 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.

  1. 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.

  1. 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:


 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 29/03/18.