Forum: Mikrocontroller und Digitale Elektronik PIC628: ORG und ab ins Nirwana ...


von Thomas M. (tm112)


Lesenswert?

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

von Carsten (Gast)


Lesenswert?

An welche Adresse hast du denn den Block hingelegt?

von Thomas M. (tm112)


Lesenswert?

Zuerst mal Probeweise an 3A0h.

von Carsten (Gast)


Lesenswert?

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.

von Thomas M. (tm112)


Lesenswert?

Hallo Carsten,

Sorry für die doofe Frage: Wie "steppe" ich in MPLAB durch (View,
Project, ...?

Thomas

von Carsten (Gast)


Lesenswert?

Unter Debugger.
Muss halt irgendein Tool ausgewählt sein - also ICD2 oder Simulator,
ICE, ect.

von Qwerty (Gast)


Lesenswert?

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.

von Karl-heinz D. (kalledom)


Lesenswert?

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

von Thomas M. (tm112)


Lesenswert?

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?

von Karl-heinz D. (kalledom)


Lesenswert?

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.

von Thomas M. (tm112)


Lesenswert?

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?

von Profi (Gast)


Lesenswert?

Setz das Org doch auf 0x3fb, dann beginnt die Tabelle auf 0x400 und es
gibt keinen Überlauf.

von Thomas M. (tm112)


Lesenswert?

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.

von Dieter Werner (Gast)


Lesenswert?

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

von Thomas M. (tm112)


Lesenswert?

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

von Profi (Gast)


Lesenswert?

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?

von Karl-heinz D. (kalledom)


Lesenswert?

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

von Thomas M. (tm112)


Lesenswert?

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

von tom (Gast)


Lesenswert?

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

von tom (Gast)


Lesenswert?

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

von Qwerty (Gast)


Lesenswert?

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.

von Qwerty (Gast)


Lesenswert?

Ups, tom war schneller....

von PLCP (Gast)


Lesenswert?

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

von Dominik (Gast)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.