Die Überschrift ist etwas unverständlich, aber mir ist nichts besseres
einfallen. Daher erkläre ich mal mein Problem. Ich verwende den
Microchip MPASM-Assembler und programmiere einen PIC18F24K20.
Sprungmarken werden vom Assembler beim assemblieren ja in Zahlenwerte
(21bit breit) für call, goto, bra etc. umgesetzt. Es ist für jede Marke
bekannt welche Adresse im Flash sie bezeichnet. Wenn man
1
movlw Sprungmarke
sagt, wird daraus zb.
1
movlw 0x56
im Maschinencode, wobei 0x56 das unterste Byte der 21bit-Adresse
"Sprungmarke" ist. Wie kann ich dem Assembler beibringen, dass er das
mittlere bzw. oberste Byte der 21bit-Flashadresse nehmen soll? Ich habe
die low, high und upper-Operatoren in der Hilfe gefunden, aber diese
funktionieren wohl nur in Relocatable Code.
?? movlw <Sprungaddress> , wirklich, das sollte man vermeiden für den
oberen Bereich, ein bit im höheren Bereich ist ok, mehr sollte aber
nicht sein. Ansonsten lgoto oder lcall ist dein Freund, wobei dies
pseudo Befehle
sind, man kann diese nicht mit skip überspringen.
Ich will movlw Sprungadresse benutzen um mit den Tablepointer-SFRs eine
Datentabelle zu adressieren, die evtl. länger wird als 256 Bytes. Wären
es weniger, könnte ich die oberen Adressbytes festlegen.
Sascha schrieb:> Sprungmarken werden vom Assembler beim assemblieren ja in Zahlenwerte> (21bit breit) für call, goto, bra etc.
Nur um Verwirrung zu vermeiden. Es sind natürlich 12Bit. ;)
Lies mal Dabla ab Seite 79.
An die oberen Bits kommt man über ein SFR u. FSR.
Allerdings ist mir schleierhaft, was du wirklich bezwecken willst.
Lade dir mal die MICROCHIP App.Note AN556 runter.
Ist zwar für PIC16 geschrieben, aber die prinzipielle Vorgangsweise bei
Tableaccess über Seitengrenzen hinweg ist dort gut beschrieben und lässt
sich sicher für PIC18 anpassen.
Nein, der Flash hat 21bits Adressbreite (2Mbyte maximal), der RAM hat
12bit Adressbreite (4kbyte maximal)
Ich will als db-Tabellen im Flash abgelegte Strings konstanter Länge auf
ein LCD schreiben. Damit das vom Hauptprogramm aus möglichst einfach
ist, wollte ich mit 2x movlw Sprungadresse TBLPTRL und TBLPTRH mit der
Startadresse des gewollten Strings laden und dann ein Unterprogramm den
Rest machen lassen. Falls das mit dem Low- und Highbyte nicht
funktioniert, werd ich wohl die Strings "durchnummerieren" müssen und
anhand dieser Nummer die Startadresse berechnen müssen.
Ok, dies geht nur bis 64K, darüber geht es nicht mehr, bzw kann auch der
Chip nur 2 bits implementieren, dies wären dann 13bit oder 8K.
Genaueres steht im datenblatt.
Hier ein Beispiel
movlf high(addresse),PCLATH
addlw low(addresse) ; hier nur ein Beispiel bei unaligned Table.
skpnc
incf PCLATH
movlw PCL
Trotzdem ist der PC 21bit breit ;-)
Chris: Dein Codeschnipsel setzt imho voraus, dass ich für jeden String
dessen obere/untere Startadresse manuell eintippe, damit er PCLATH/PCL
berechnen kann. Damit könnte ich doch auch direkt PCLATH/PCL
beschreiben. Ich wollte nur das Label eintippen und der Assembler
ermittelt selber Highbyte/Lowbyte der Startadresse. Das Auslesen des
Flashs ist bei den PIC18 wesentlich komfortabler als bei den PIC16.
Wraparound an 256Byte-Grenzen gibts mit TBLPTR nicht.
Ich verstehe immer noch nicht, was das Problem ist.
Es gibt mehrere Möglichkeiten für Strings im Flash.
1.
Du plazierst einfach vor jeden String ein Label und wählst sie per Label
aus.
2.
Du plazierst ein Label (Startadresse) vor eine Liste von Strings mit
konstanter Länge und wählst sie per Startadresse + Index * Länge aus.
3.
Du plazierst vor jeden String ein Label und an anderer Stelle eine
Tabelle der Labels. Das Auswahl erfolgt dann mit Table_Start + Index *
Labelsize.
Labelsize dürfte 2 Byte (14 Bit Adresse) sein.
4.
Eine sehr elegante Methode habe ich zu meinen Assemmblerzeiten beim
8051/AVR benutzt.
Der String steht einfach direkt im Code hinter dem Aufruf der
Ausgaberoutine und vor dem nächsten Befehl.
Die Ausgaberoutine holt sich die Stringadresse vom Stack, gibt bis zum
0-Byte aus und springt dann hinter das 0-Byte zurück.
Das geht natürlich nur bei Architekturen, die die Befehle PUSH/POP
kennen (PIC18 und höher).
Sascha schrieb:> Sprungmarken werden vom Assembler beim assemblieren ja in Zahlenwerte> (21bit breit) für call, goto, bra etc. umgesetzt. Es ist für jede Marke> bekannt welche Adresse im Flash sie bezeichnet.
Der Programmcounter kann über drei Register manipuliert werden: PCL,
PCLATH and PCLATU.
PCLATU wird beim dem PIC18F24K20 nicht gebraucht, da nur 16KB Flash.
Peda schlägt mit den Labels eine gute und einfache Lösung für die
Adressierung von Strings
Gruss Picfan
Sascha schrieb:> Nein, der Flash hat 21bits Adressbreite (2Mbyte maximal), der RAM> hat> 12bit Adressbreite (4kbyte maximal)
Stimmt nicht, ist aber egal
>> Ich will als db-Tabellen im Flash abgelegte Strings konstanter Länge auf> ein LCD schreiben. Damit das vom Hauptprogramm aus möglichst einfach> ist, wollte ich mit 2x movlw Sprungadresse TBLPTRL und TBLPTRH mit der> Startadresse des gewollten Strings laden und dann ein Unterprogramm den> Rest machen lassen. Falls das mit dem Low- und Highbyte nicht> funktioniert, werd ich wohl die Strings "durchnummerieren" müssen und> anhand dieser Nummer die Startadresse berechnen müssen.
Wenn man TBLPTRX benutzt, wieso dann computed gotos verwenden ?
Sascha schrieb:> Trotzdem ist der PC 21bit breit ;-)>> Chris: Dein Codeschnipsel setzt imho voraus, dass ich für jeden String> dessen obere/untere Startadresse manuell eintippe, damit er PCLATH/PCL> berechnen kann.
klar
> Damit könnte ich doch auch direkt PCLATH/PCL> beschreiben.
Stimmt aber nur für den Stringanfang.
> Ich wollte nur das Label eintippen und der Assembler> ermittelt selber Highbyte/Lowbyte der Startadresse.
angenommen man hat eine puts funktion welche strings ausgibt, und eine
putch funktion, welche Zeichen ausgibt, dann übergibt man der puts
Funktion das Label des Strings, dieser addiert aber einen Index für
einzelne Zeichen dazu, und da muss man dann PCLATH abhängig vom Index
incrementieren, genau dies macht der gepostete Beispielcode.
> Das Auslesen des> Flashs ist bei den PIC18 wesentlich komfortabler als bei den PIC16.> Wraparound an 256Byte-Grenzen gibts mit TBLPTR nicht.
Wie gesagt, wenn man TBLPTR verwendet, wieso dannn computed goto ?
Wenn du z.B. fixe 16Zeichen String machst, dann ist es einfacher ein
.org $ + ($&0xf)
zu verwenden, denn dann sind die Strings aligned.
Ein Beispiel eines codes mit TBLPTR
;******************************************************************
;
; PutStr - print in-line string via Stack and TBLPTR
;
; string must be terminated with a 0 byte and does not need
; to be word aligned
;
PutStr
movff TOSL,TBLPTRL ; copy return address into TBLPTR
movff TOSH,TBLPTRH ;
clrf TBLPTRU ; assume PIC with < 64-KB
PutNext
tblrd *+ ; get in-line string character
movf TABLAT,W ; last character (00)?
bz PutExit ; yes, exit, else
rcall Put232 ; print character
bra PutNext ; and do another
PutExit
btfsc TBLPTRL,0 ; odd address?
tblrd *+ ; yes, make it even (fix PC)
movf TBLPTRH,W ; setup new return address
movwf TOSH ;
movf TBLPTRL,W ;
movwf TOSL ;
return ; return to address after string
;
nochmals, wozu computed goto wenn du TBLPTR verwenden willst ?