Forum: Mikrocontroller und Digitale Elektronik PIC-Problem: BSR und Bankregister


von Be T. (wilhelmt)


Lesenswert?

Ich habe ein kleines Programm für einen PIC in Maschinen-Code 
geschrieben, das funktioniert, aber ich weiß nicht – warum! Der PIC ist 
ein 18F14K22, die MPLAB X-Version ist 3.55, genutzt wird das PICkit3 und 
eine Basiplatine dafür. Es geht letztlich um einen bestimmten Opcode, 
bzw. um die Begriffe  „BSR („Bank Select Register“), bzw. schlicht um 
den aktuellen Platz/ die Bank  im Daten-Memory.
Als Beispiele nehme ich zwei Befehle aus dem Instruction-Set.
movf file,0,1        oder auch
movf EEDATA,0,0

Beide Befehle bewegen den Inhalt eines Files, beim zweiten geht es um 
das Auslesen des EEPROMs. Der jeweils erste Opcode (intern mit „d“ 
bezeichnet) , bestimmt, dass bei „0“ das WREG das Ziel ist, bei „1“ 
würde in das Register zurück gespeichert. Der zweite Opcode ist der 
Stolperstein, das ist der intern mit „a“ bezeichnete. Bei „0“ ist die 
„Access Bank“ ausgewählt, bei „1“ die „GPR“-Bank, und letzteres per 
default.

Lesen kann ich, aber nix verstehen. Vermutlich geht es um die bei PICs 
berühmte Speicher-Akrobatik. Aber woher erkenne ich nun, welche Bank da 
anzuwählen ist? Im Simulator gibt’s ja ganz oben in der Mitte ein 
kleines Fensterchen mit diversen Anzeigen, u.a. auch dem Bank-Register.
Bei movf EEDATA,0,1 wird der Eeprom-Inhalt mit FFh ausgegeben,
bei movf EEDATA,0,0 gibt’s den „richtigen“ Inhalt.
Muss und kann ich da  beim „Simulieren“ reinschauen, in welcher Bank 
gerade rumprozessiert wird? Muss man das ausrechnen, oder was ist zu 
tun? Mit try-and-error hab ich die Funktion des Progs ja rausgefunden, 
aber verstehen würde ich es auch gerne.
Grüße, wilhelmT

: Bearbeitet durch User
von Ottmar K. (wil1)


Lesenswert?

Hallo!

Verwende doch ganz einfach "Banksel" und der Assembler/Compiler 
verwendet automatisch die richtige Bank.

Beispiel:
Banksel  LATB   ;Latchregister
movlw    0x00   ;clear PORTB Output Latches
movwf    LATB
Banksel  TRISB  ;Datenrichtungsregister
movlw    0x00   ;set RB7:RB0 as autputs
BANKSEL  0     ,zurück zu Bank 0

Das kannst Du bei allen SFR's so anwenden.

Banksel   EECON1
bsf       EECON1,EEPGD
Banksel   0

mfG Ottmar

von Be T. (wilhelmt)


Lesenswert?

Danke für deine Anregung!
Erst hattest du mich in Verlegenheit gebracht, weil der "normale" 
Befehlssatz des PIC18F14K22 solche Befehle nicht vorhält. Nur einer der 
Befehle hantiert direkt mit dem BSR: movlb k , da wird eine 8-bit-Zahl 
in das untere Nibbel des BSR geschrieben.
Der Assembler scheint "deinen" Befehl aber zu kennen, die Auswirkung 
hatte ich allerdings noch nicht getestet. Im Prinzip weiche ich damit 
meinem Ziel auch wieder aus, ich wollte ja gerne verstehen, in welcher 
Bank das Programm so gerade Bits schaufelt, und vor allem: wo gibt es 
einen Anzeige für die momentane Bank? Ist das die schon angesprochene 
Info in dem Mini-Fensterchen rechts oben im Simulator?
Grüße, wilhelmT

von Thomas E. (picalic)


Lesenswert?

Be T. schrieb:
> Lesen kann ich, aber nix verstehen. Vermutlich geht es um die bei PICs
> berühmte Speicher-Akrobatik.

Hallo Wilhelm,

der Hintergrund ist, daß im Opcode des Befehls nur Platz für eine 8-Bit 
breite Adresse ist, also maximal 0 bis 255. Da der PIC aber mehr 
Register (GPR und SFR) hat, als 256, werden die Register in Bänke 
eingeteilt. Die Adresse, auf die man dann mit dem Befehl zugreift, 
ergibt sich aus der Banknummer im BSR-Register und der Adresse (0..255) 
im Opcode, so kann man dann auf bis zu 16 Bänke * 256 Adressen = 4096 
Register zugreifen, wenn das "A"-Bit im Opcode 1 ist.
Damit man nicht für jeden Zugriff auf eine häufig benutzte Variable oder 
ein SFR immer erst das Bankselect-Register mit der richtigen Banknummer 
laden muss, kann man durch A=0 im Opcode das BSR-Register ignorieren, 
allerdings kann man so eben auch nur 256 Register adressieren. Diese 
sind dann fest vorgegeben: Für Adressen 0 bis 0x5F werden die 
entsprechenden GPRs in Bank 0 angesprochen (es ist also klug, viel 
benutze Variablen in diesen Bereich zu legen, um sich die 
Bankumschaltung zu sparen), für Adressen 0x60..0xFF wird mit A=0 auf die 
SFRs (in Bank 15) zugegriffen. Die SFRs sind also immer ohne 
Bankumschaltung erreichbar.

Gruß,

Thomas

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Be T. schrieb:
> Der zweite Opcode ist der
> Stolperstein, das ist der intern mit „a“ bezeichnete. Bei „0“ ist die
> „Access Bank“ ausgewählt, bei „1“ die „GPR“-Bank, und letzteres per
> default.

Das mit den Defaults stimmt so nicht, obwohl es im Datenblatt steht.
Der Assembler "weiß", wenn eine Variable im ACCESS Ram steht und 
verwendet dann nicht banked. (außer du erzwingst es mit der Angabe des 
Parameters a)

: Bearbeitet durch User
von Be T. (wilhelmt)


Lesenswert?

Danke sehr für eure Erklärungen! Wenn die Hilfen hier weiter gehen, 
werde ich das irgendwann verstehen, aber noch ist es nicht soweit.
Ein Prob ist inzwischen geklärt, die von mir vermisste Anzeige der 
Speicher ist gefunden. Im Simulator- is klar – liegen ja in dem linken, 
unteren Fenster, dem „Dashboard“,  u.a. zwei hübsch gefärbte Balken. Oft 
gesehen, aber nicht wirklich hingeschaut. Da gibt’s also als 
Balkenanzeige und in Zahlen zunächst den vom Prog benutzten 
Datenspeicher-Platz. Der macht bei meinem Prog genau 15 Bytes aus, und 
dass in dem Prog 15 Variable definiert sind, ist eher kein Zufall. Da 
drunter der Balken für den Programm-Speicher, der benötigte Platz peilt 
z.Z. bei 365 Bytes.

Trotzdem ist mir nicht klar, wo und in welchem Speicher und welcher Bank 
denn nun diese vermaledeite EEprom-Variable  EEDATA liegt. Laut 
Datenblatt verstehe ich das so, dass dieses EEDATA im Datenspeicher 
liegt und dort fest verankert „ganz oben“ im Bereich der SFRs, im „Acces 
RAM High“, im Bereich 60h bis Ffh (und dieser SFR-Bereich taucht dann 
auch noch im Bereich F60h bis FFFh auf ???? !!!)

Wenn dieses EEDATA im SFR-Bereich liegt und dort fest verankert ist, 
müsste doch diese Bank-Zuweisung quasi immer gelten. Oder kann ich etwa 
dieses EEDATA zusätzlich in meine Variablen-Liste aufnehmen, um so zu 
erreichen, dass diese Variable „ganz vorne“ und in der Bank 0 liegt?

Oder ist es doch ganz anders, und wichtig für die Bankzuordnung ist die 
Stelle, an welcher im Programmspeicher diese vermaledeite Variable 
EEDATA gerade plaziert ist? Grundlagenwissen, schön, wenn man es hätte.
Grüße, wilhelmT

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Be T. schrieb:
> Trotzdem ist mir nicht klar, wo und in welchem Speicher und welcher Bank
> denn nun diese vermaledeite EEprom-Variable  EEDATA liegt.

Also EEDATA liegt laut Datenblatt an der Adresse 0xFA8. Das ist absolut 
fix und in keiner Weise änderbar. 0xFA8 liegt automatisch im ACCESS 
Bereich und auch das ist in keiner Weise änderbar.

Wenn du mit Gewalt banked auf EEDATA zugreifen willst, kannst du die 
Adresse FA8 aufteilen in die Adresse der Bank (F) und in die Adresse in 
der Bank (A8). Beim einem Befehl zur Verarbeitung von EEDATA wird das F 
(außer bei movff) sowieso ignoriert. Anstatt dessen wird der Inhalt von 
BSR verwendet und nur das A8 ausgewertet.
Also falls du aus welchen Gründen auch immer "banked" auf EEDATA 
zugreifen willst, dann muss vorher VON DIR BSR auf 0x0F gesetzt worden 
sein.

Beim access Zugriff wird das F auch ignoriert, aber weil die 
verbleibende Adresse xA8 >= x60 ist, wird quasi im Hintergrund ein F 
wieder ergänzt und die Adresse wird zu 0xFA8. (Was im BSR steht wird 
beim access Zugriff ignoriert.)
Bei Adressen kleiner 0x_wasauchimmer_60 wird beim access Zugriff das 
wasauchimmer ignoriert und eine Null ergänzt. Die Adresse wird zu 
0x000..0x05F.


Deine Variablen sollten die Adressen 0x000..0x00E belegen, falls du die 
in einer UDATA_ACS Section untergebracht hast. Das kann man z.B. im 
Debugger sehen...

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.