Hallo, Wie das immer so ist bei übernommenen Projekten mit fehlenden Kommentaren - es fehlt ein wenig der Überblick. Aktuell stellt sich das Problem so: Quelltext wurde für den 16F84 geschrieben und jetzt auf den 16F628 umgebaut. Nach Überwindung einiger Fallen war das auch nicht das größte Problem. Jetzt möchte man aber schon den größeren Speicher nutzen, es steht nur ein Block im Weg, der Adresse 300 bis 342 blockiert. Einfach noch oben verschieben? Schön wär's, wenn's so leicht ginge. Wird das gemacht, dann bleibt der Prozessor an der Stelle hängen. Berechnet wird in diesem Bereich ein CRC. Hier der Quelltext: ################################### org 300h crc_1 addlw 30 crc_2: addlw data_crc-300h bsf pclath,0 bsf pclath,1 movwf pcl data_crc: retlw 12h retlw 9 retlw 16h retlw 0bh retlw 17h ... ; viele retlw Zeilen ... retlw 0fh end ################################### Werden nur die Zeilen org 300h und data_crc-300h auf eine andere (höhere) Adresse angepasst, dann hängt Kamerad PIC. Dass der Block tatsächlich nach oben verschoben wird, konnte im Disassembly Listing und im EPROMer bestätigt werden. Direkt (und indirekt zumindest nicht sichtbar) wird an keiner anderen Stelle im Quelltext die 300h adressiert. Hab' ich da jetzt einen generellen Denkfehler drin oder wie ist das Problem lösbar? Liegt es womöglich doch daran, dass irgendwo im Programm nochmal versucht wird in die 300h zu springen? Solange dieser Block da drin steht, kann ich denkbar schlecht den ganzen Speicher nutzen. Bin für Vorschläge dankbar. Gruß, Thomas
Springt er erst gar nicht an diese Adresse? Führt er den Befehl dort nicht aus? Steppe mal durch deinen Code, dann siehst du genau an welcher Adresse/mit welcher Codezeile du Probleme bekommst.
Hallo Carsten, Sorry für die doofe Frage: Wie "steppe" ich in MPLAB durch (View, Project, ...? Thomas
Unter Debugger. Muss halt irgendein Tool ausgewählt sein - also ICD2 oder Simulator, ICE, ect.
Wenn ich mich noch richtig an meine PIC-Zeiten erinnere, gibt es da immer ein Problem, wenn eine Tabelle (=die ganzen retlw) über eine 256-Byte-Grenze im Speicher geht. Da muss man dann mit dem PCLATH tricksen, um die Sprungadresse hinzubekommen, da der PIC ja nur 8 Bit direkt adressieren kann. Der Code hier macht zwar auch etwas mit dem PCL, aber vielleicht geht das ja durch deine Verschieberei schief. Auf jeden Fall muss natürlich das data_crc-300h gegen data_crc-3A0h ersetzt werden, sonst geht schon da die Berechnung des Einsprungs schief.
Richtig, der PCL (Programm Counter Low) hat nur 8 Bit. Wenn eine Tabelle über eine 256 Byte-Grenze geht, muß PCLATH korrigiert werden. Dazu stehen im Datenbuch des PIC Beispiele, aber auch hier: http://www.domnick-elektronik.de/picasm.htm#CompGoto
OK. Danke erst mal für Eure Tipps. Aktuell hindert mich noch etwas am Verständnis: Die Länge der Tabelle verändert sich ja nicht. Was genau ist mit 256 Byte-Grenze gemeint? Bzw. kriegt man daraus eine Adresse errechnet, an die man die Tabelle legen kann (von mir aus auch erst mal testweise, um ausprobieren zu können, ob das der Auslöser ist) ohne den Quellcode zusätzlich ändern zu müssen?
Bei Computed Goto wird der Offset der Tabelle zur aktuellen Adresse des Programm Counters Low-Byte addiert. Das Programm so wie bisher beginnt bei Adresse 300h. Der Befehl 'movwf pcl' ist bei Adresse 304h, die Tabelle beginnt bei 305h. Ein Offset ist z.B. 200d = 0C8h. Die Addition 304h + 0c8h = 3CCh. Die 256 Byte-Grenze wird nicht überschritten; alles ok. Jetzt verschiebst Du das Ganze nach 3A0h. Der Befehl 'movwf pcl' ist jetzt bei Adresse 3A4h, die Tabelle beginnt bei 3A5h. Offset 200d = 0C8h + 3A4h = 46Ch; jetzt wurde die 256 Byte-Grenze überschritten: jetzt steht in PCL 6Ch, was ist bei Adresse 36Ch für ein Befehl, denn niemand hat dem High-Teil des Programm Counters mitgeteilt, daß bitteschön 4xxh gemeint ist. Deshalb vor der Addition des Offset mit dem PCL den PCLATH setzten und testen, ob es eine Überschreitung der 256 Byte gibt und PCLATH evtl. incrementieren. Lies Dich mal im Datenbuch durch.
Das Datenblatt ist nicht wahnsinnig aufschlussreich darüber (6 Zeilen auf S.28 mit einem Kurzverweis auf aie AN556). Gibt's ausser der app. note noch was hilfreiches?
Setz das Org doch auf 0x3fb, dann beginnt die Tabelle auf 0x400 und es gibt keinen Überlauf.
Kann ich jetzt nicht mehr rechnen? Wenn bereits bei 3A0 die 256 Byte Grenze überschritten ist, dann doch bei 3FB erst recht(?) Oder hab ich da mit dem Offset was nicht kapiert? Hab's trotzdem probiert - aber der Kamerad hängt bei 3A0 und 3FB.
Hallo Thomas, der Fallstrick liegt wo ganz anders. Du darfst die Adressberechnung data_crc-300h nicht anpassen, da ja auch die tatsächliche Adresse entsprechend höher liegt. Das mit dem Überlauf stimmt schon, tritt hier aber nicht auf (falls WREG nicht mal einen zu großen Wert enthält).
Hallo Dieter, Danke für den Tipp - aber das kann ich nun so gar nicht glauben, zumal es auch nicht funktioniert. Bin immer noch am Grübeln über dem Quellcode. Es ist ja fast, als wäre die Tabelle bei 300h festzementiert. Verschiebt man Sie um eins oder zwei nach unten (mehr Platz ist gar nicht mehr) und passt data_crc-xxxh an, dann geht's. Verschiebt man sie um eins nach oben (oder mehr), gibt's Ärger. Thomas
Hmmmm, schon komisch, ich würde es dann mal mit 3fc (damit der movwf pcl auf 400 liegt) oder 400 probieren. Wie groß kann der Index maximal werden? Vielleicht ist es auch ganz was anderes?
Wenn in PCLATH 04h eingetragen wird, ist 3FBh völlig ok ! Wieviel 'returns' sind es denn ? 256 - 6 ? Folgendes Programmteil kannst Du ablegen, wo Du möchtest (die Assembler-Beispiele werde ich noch ändern, da es mit dem 'Computed Goto' und längeren Tabellen öfter Probleme gibt:
1 | ; =============================================================== |
2 | ; Binär nach 7-Segment-Code |
3 | ; Eingang: W Binär |
4 | ; Ausgang: W 7-Segment-Code |
5 | ; =============================================================== |
6 | p2BinTo7Segm movwf Temp1 ; Byte retten |
7 | movlw HIGH(Tbl7Segm) |
8 | movwf PCLATH |
9 | movfw Temp1 ; Auf Ueberlauf testen |
10 | addwf PCL,W |
11 | skip_NC ; ... kein Uebertrag |
12 | incf PCLATH ; ... PCH + 1 |
13 | |
14 | addlw 6 ; + 6 Befehle |
15 | skip_NC ; ... kein Uebertrag |
16 | incf PCLATH ; ... PCH + 1 |
17 | |
18 | movfw Temp1 |
19 | Tbl7Segm addwf PCL |
20 | retlw 00111111b ; 0 |
21 | retlw 00000110b ; 1 |
22 | retlw 01011011b ; 2 |
23 | retlw 01001111b ; 3 |
24 | retlw 01100110b ; 4 |
25 | retlw 01101101b ; 5 |
26 | retlw 01111101b ; 6 |
27 | retlw 00000111b ; 7 |
28 | retlw 01111111b ; 8 |
29 | retlw 01101111b ; 9 |
30 | retlw 01110111b ; A |
31 | retlw 01111100b ; b |
32 | retlw 00111001b ; C |
33 | retlw 01011110b ; d |
34 | retlw 01111001b ; E |
35 | retlw 01110001b ; F |
Jetzt läuft's - Wer erklärt mir bitte warum? Original: org 300h crc_1: addlw 30 crc_2: addlw data_crc-300h bsf pclath,0 bsf pclath,1 movwf pcl geändert in: org 700h crc_1: addlw 30 crc_2: addlw data_crc-700h bsf pclath,0 bsf pclath,1 bsf pclath,2 movwf pcl
Hi, ich könnte kurz schreiben: RTFM! Nur leider ist damit keinem geholfen! ;-) Also: der PIC hat nur einen 8-Bit ProgramCounter, kurz PC, das bedeutet, DU kannst nur 256 Word (hier 1 Word zu 14Bit! auf 16Bit-Adressen im HEX-File) ohne weitere Vorkehrungen addressieren! Beispiel: die Funktion, die ursprünglich ab 0x300 startete. Nehmen wir an, sie hat die Länge von 0x80 Word! Sobald Du sie auf 0x3A0 verschiebst, passiert das folgende: ein Teil des Code steht nicht mehr auf Program-Page 0 (0x0-0x3ff), sondern ab 0x400-0x700, also auf Page 1. Nehmen wir also an, Dein Code wird linear durchlaufen, dann würde der Prozessor in dem Moment, wo Du auf den Code an der Adresse 0x400 zugreifst, auf den Code an Adresse 0x0 zugreifen! Ergebnis: Fatal! Um diese Fälle zu handeln, gibt es das PCLATH-Register, das genau den höherwertigen Teil der Adresse enthält, aber nur programmiert verändert werden kann. Deshalb setzt auch jeder C-Compiler unmittelbar vor den Call zu dieser Funktion (soweit ich weiß) die Sequenz zum Beschreiben des PCLATH-Registers. Und deshalb muß auch die Interrupt-Funktion das PCLATH-Register retten! (wenn es nicht gerade den 16F84 betrifft, der ohnehin nur eine Page hat!) hth, schönen Tag noch, Thomas
Hi, wenn man zu schnell tippt: Page 0: 0x0-0x1ff Page 1: 0x200-0x3ff etc. ... D.h. in meinem Beispiel Page 0 und 1 durch 1 und 2 ersetzen! Und der 16F84 hat 2 Pages! Schönen Tag noch, Thomas
Weil die Tabelle wieder innerhalb eines 256-Byte-Blocks liegt? Das Problem mit den 256-Byte-Blöcken ergibt sich aus der 8-Bit-Architektur in Verbindung mit dem "computed goto". Beispiel: Du bist im Code an Adresse 300h. Dein PCL (untere 8 Bit des Adresszählers steht also bei 00h). Wird jetzt ein Sprung von +40h berechnet, so wird 40h in den PCL geladen. PCLATH (die oberen Bits des Adresszählers) wurde schon auf 0b011, also 0x3, gesetzt. Beim Beschreiben des PCL wird PCLATH automatisch hinzugefügt und alles in den internen PC geladen --> Sprung auf 340h. Bist du aber mit deiner Sprunganweisung z.B. an Speicherstelle 3f0h und möchtest jetzt 40h weit springen, so funktioniert obige Rechnung nicht mehr. Der PCL steht jetzt auf f0h, du addierst 40h dazu, Ergebnis ist 30h (nicht 130h, da PCL nur 8 Bit breit ist!). PCLATH wird wie immer mit 0x3 vorgeladen, dann schreibst du 0x30 in PCL --> Sprung auf 330h. Anstatt 40h im Code weiterzuspringen bist du also rückwärts gesprungen! Daher muss bei einem solchen "computed goto" auf dem PIC immer dafür gesorgt werden, dass entweder alles innerhalb eines 256-Byte-Blocks bleibt (also zwischen 100h - 1ffh, 200h - 2ffh usw.), oder dass der PCLATH im Falle eines Überschreitens der Grenze um 1 inkrementiert wird (siehe Beispielcode meines Vorredners). Bei deiner Änderung funktioniert natürlich wieder alles, da o.g. Bedingungen wohl erfüllt sind: Du bleibst innerhalb einer 256-Byte-Page (700h-7ffh) und lädst PCLATH dementsprechend immer mit 0x7.
das ist alles unsauber programmiert geändert in: org 700h crc_1: addlw 30 crc_2: addlw data_crc-700h bsf pclath,0 bsf pclath,1 bsf pclath,2 movwf pcl sollte heissen: org ($+.255)&0xf00h ; nächste 256er grenze crc_1: addlw 30 crc_2: addlw low(data_crc) ; low adresse von data_crc dazu movwf retten ; zusätzlicher speicherplatz movlw high(data_crc) ; high adresse von data_crc movwf pclath ; vormerken movf retten,w ; w wiederherstellen movwf pcl ; sprung zu retlw durchführen retlw...... ; max. 256-7 retlw erlaubt !! jetzt sollte es überall im speicher laufen
> wenn man zu schnell tippt: > > Page 0: 0x0-0x1ff > Page 1: 0x200-0x3ff > etc. ... > > D.h. in meinem Beispiel Page 0 und 1 durch 1 und 2 ersetzen! > > Und der 16F84 hat 2 Pages! Das verwirrt mich immer noch. Das Beispiel org 0x700 und 0x7 in PCLATH ist für mich eher einleuchtend. In benutze ähnliches in einem Programm. Dann wäre aber doch Page 0: 0x0-0xff Page 1: 0x100-0x1ff Page 2: 0x200-0x2ff Page 3: 0x300-0x3ff Page 4: 0x400-0x4ff Page 5: 0x500-0x5ff Page 6: 0x600-0x6ff Page 7: 0x700-0x7ff richtiger? Das wären dann auch 256er Blöcke
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.