µC AT90S2313 Program Counter (PC)

Hallo,

hat jemand ne Ahnung wie man den Programm Counter auslesen kann. Im Elektor Buch "AVR-Mikrocontroller-Praxis" von den Volpe's steht auf Seite 12 im Kapitel 2.2 AVR-Architektur das sich dieser im I/O - Adreßbereich befinden soll. Habe alle Datenblätter der Basic Line durchforstet kann aber nirgendwo finden, wie man den PC (Programm Counter) auslesen kann.

Kennt von euch jemand da vielleicht einen Trick ?

Bis dann Bernd_Stein

Reply to
Bernd Stein
Loading thread data ...

Wozu? Der ändert sich ja sowieso ständig.

In Programmen verwendet man Labels, um den Wert des PC an einer bestimmten Stelle des Programms zu bestimmen.

Ein JSR (heißt ein Subroutinenaufruf bei den AVRs so?) legt den PC auf den Stack. Da kannst du ihn dann mit POP abholen.

XL

Reply to
Axel Schwenke

Wieso willst du den auslesen? Das Programm weiss doch, wo es gerade ist ;-)

I/O Adressbereich ist der Adressbereich, wo man die Ports und die Special-Function Register findet. Sollte kein Problem sein. Ansonsten per Call die Adresse auf den Stack schreiben und vom Stack zurücklesen. Aber wie oben bereits beschrieben: Der PC hat den Wert der Adresse, an der sich das Programm gerade befindet...

Gruß

Stefan DF9BI

Reply to
Stefan Brröring

Und nach Möglichkeit mit PUSH wiederherstellen. Es sei denn, ein kreatives GOTO ist gewünscht ;-)

Falk

Reply to
Falk Willberg

Kann schon sinnvoll sein, z.B. wenn man positionsunabhängigen Code braucht, ohne aber jetzt noch eine Relozierungsfunktion schreiben zu wollen, der z.B. auch Daten enthält und man keinen relativen Lesebefehl hat. Ok, etwas viele wenn's, vielleicht doch nicht so sinnvoll, aber am C64 habe ich das auch schonmal für dynamisches Linken in Assembler verwendet :-)

Also hier:

formatting link

kann man ein RCALL finden, sodaß es dann die Kombination

rcall label label: pop

das gewünschte Ergebnis im Rd-Register liefern sollte. Der Assembler kümmert sich dann darum, daß die Anweisung "rcall label" in irgendwas wie "rcall 1" oder "rcall 3" oder so umgesetzt wird.

--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Reply to
Frank Buss

Da wurde wahrscheinlich was mit dem Stack Pointer verwechselt, der ist als I/O und natuerlich Memory-mapped erreichbar. Der PC direkt nicht.

Mache ein RCALL und lass die Subroutine den Wert des PC vom Stack lesen.

Micha

Reply to
Michael Baeuerle

Das ist die Basis für viele schöne Dinge, die weit über jedes simple C++ vtable hinausgehen und bei späteren Softwareentwicklern, die das dann warten müssen, für Freude sorgt :-)

--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Reply to
Frank Buss

Klar. Aber dann verwendet man ein Label. Typisches Stück Code vom C64:

ldy #npages ldx #0 loop: lda quelle,x sta ziel,x inx bne loop inc loop+2 inc loop+5 dey bne loop

XL

Reply to
Axel Schwenke

Oh Graus, selbstmodifizierender Code! Sowas macht man sauber über indirekte Adressierung mit der Zeropage :-) (die üblichen Bereiche von $FB bis $FE, wenn der Kernel noch was machen soll)

Ich sehe aber nicht, was dein Code sonst mit relativer Adressierung und dynamischen Linking zu tun hat, also zur Laufzeit z.B. ein Scrolltext-Modul von der Floppy reinladen, danach ein Sound-Modul, initialisieren, starten, wieder entladen, neue Module reinladen usw., also was man bei größeren Demos alles so gebraucht hat.

--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Reply to
Frank Buss

Stefan Brröring schrieb:

Also,

ich überprüfe Zahlenwerte von 1 bis 3. Und falls ein anderer Wert vorliegt habe ich irgendwo ein Programmfehler gemacht und möchte deshalb wissen wo dieser ungefähr ist.

Gruß Bernd_Stein

Reply to
Bernd Stein

Nö. Das wäre ja langsamer :) Außerdem ist die Zeropage sowieso *immer* schon voll. Und "4 Bytes Zeropage gescrubt" ist ein häßlicher Seiteneffekt. Ein richtiger H4> Ich sehe aber nicht, was dein Code sonst mit relativer Adressierung und

Es adressiert die Daten relativ. Egal, wohin der obige Code assembliert wird, er läuft immer. Und wenn die Entwicklungsumgebung einen Linker hat, dann wird das 'loop' Symbol erst beim Linken festgelegt.

Es ist kein position independent code, falls du das meintest. Der müßte dann tatsächlich zur Laufzeit den PC auslesen und die beiden INCs fixieren. Ich wüßte bloß nicht, warum man das machen sollte. Dynamische Libs ergeben weder auf dem C64 noch auf dem AVR einen Sinn.

XL

Reply to
Axel Schwenke

Wir haben es hier mit einer Harvard-Architektur zu tuen. Da würde positionsunabhängiger oder relozierbarer Code allenfalls für einen Bootloader eine Rolle spielen, der variable Module von einem Host nachlädt.

Der braucht aber sowieso eben diesen Host als Gegenstück. Wenn also überhaupt irgendwas, würde der das sinnvollerweise erledigen. Und er bräuchte dazu natürlich nicht den PC auslesen, sondern den Code einfach nur ab übermittelter Basisadresse kompilieren.

Aber viel Sinn würde die Sache eh' nicht machen, weil der Flash bei intensivem Modulgetausche eh' nach relativ kurzer Zeit hinüber wäre.

Reply to
Heiko Nocon

Also,

ich überprüfe Zahlenwerte von 1 bis 3. Und falls ein anderer Wert vorliegt habe ich irgendwo ein Programmfehler gemacht und möchte deshalb wissen wo dieser ungefähr ist, da ich an mehreren Stellen im Programm solche Überprüfungen vornehme.

Bei Motorolas MC68HC11 gibt es einen Illegal Opcode Interrupt und den benutzte ich damals um auf einem LCD die Adresse auszugeben wo dieser auftrat. So etwas möchte mit den AVR auch machen.

Ich glaube mit dem "rcall" (relativ) leg ich mich evtl. selber rein.

.... breq drei ;Verzweige bei Übereinstummung... rcall error ;...ansonsten Fehler im Programm. error: pop temph ;High-Byte... pop templ ;...und Low-Byte der Programmadresse vom... ;..Stack holen. rcall Lcd_out ;Programmadresse auf dem LCD ausgeben. ende: rjmp ende ;Endlosschleife

und dann fällt mir ein - alles irgendwie Mist. Wie wird die Rücksprungadresse auf dem Stack gelegt ? Erst Low-Byte dann High-Byte ? Der Stack arbeitet auf jedenfall nach dem LIFO Prinzip. Last In -> First Out. Falls ich im Simulator alles richtig verstanden habe, stimmt das Programm zufälligerweise so weit.

Gruß Bernd_Stein

Reply to
Bernd Stein

Man kann sich auch ein kreatives GOTO basteln indem man erst per PUSH sich einen Programmzaehler auf den Stack schreibt und dann RTS aufruft. Das freut den, der diesen Code mal warten muss spaeter ungemein.

Gerrit

Reply to
Gerrit Heitsch

Gerrit Heitsch schrieb:

Naja, so unüblich ist das nicht. Zumindest jeder, der mal präemptives Multitasking bzw federgewichtige Threads selbst implementiert hat, hat sowas schonmal gesehen.

Viele Grüße, Johannes

--
"Meine Gegenklage gegen dich lautet dann auf bewusste Verlogenheit,
verlästerung von Gott, Bibel und mir und bewusster Blasphemie."
         -- Prophet und Visionär Hans Joss aka HJP in de.sci.physik
Reply to
Johannes Bauer

Für sowas hilft nur RTFM :-) Ich finde das aber generell nicht besonders sinnvoll. Wieso nicht einfach eine feste Nummer laden und die dann ausgeben? So musst du ja das Listing-File des Assemblers erst laden, dann dort nachschauen, was an der Adresse steht und danach ggf. wieder im Sourcecode dieselbe Stelle suchen, wenn du was ändern willst. Bei genügend Speicher, besseren Macrofähigkeiten und Textdisplay oder seriellem Port, könnte man bestimmt auch sowas programmieren:

assert(Rd=3, "Rd ungleich 3 bei Stelle Foobar")

--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Reply to
Frank Buss

Ist mir trotzdem noch nicht ganz klar, wie das funktionieren soll, und wie du die Fehlerposition bestimmen willst.

Denkbar wäre, dass im Fehlerfall ein INT ausgelöst wird. In der INT-Routine könnte man dann mit Pop die Rücksprungadresse auslesen. Wenn man die dann wieder zurückpusht, dann kann das Programm sogar direkt weiterlaufen.

Beispiel für AVR Assembler kann ich leider nicht liefern, weil ich den nur in GCC programmiere

Als Alternative kann man an den betreffenden Stellen auch einfach eine entsprechende Fehlernummer ausgeben.

Gruß

Stefan DF9BI

Reply to
Stefan

So einen Interrupt koennen AVRs nicht erzeugen. Laut Atmel:

formatting link
werden Illegal Opcodes einfach als NOP ausgefuehrt.

Um die Integritaet des Flash zu pruefen (AVR kann wegen Harvard Architektur keine Befehle aus dem RAM ausfuehren) kannst du eine Checksumme mit hinein brennen und den AVR die neu berechnen und vergleichen lassen.

Der 2313 hat halt kein CALL (absolut) weil die relative Adressierung sein komplettes Flash abdecken kann. Die Adresse auf dem Stack waere in beiden Faellen die des naechsten Befehls.

Ich wuerde sagen ja. Die ausgelesene Adresse ist die von "pop temph", alse dem Label "error".

Frank meint eine Loesung in der Art:

---------------------------------------------------------------------- .... breq drei ;Verzweige bei Übereinstummung... E1: ldi temph, 'E' ;Fehlermeldung laden ldi templ, '1' rcall Lcd_out ;Fehlermeldung auf dem LCD ausgeben. rjmp ende ;Endlosschleife

---------------------------------------------------------------------- Das Display zeigt an "E1" und man kann einfach nach der Stelle im Source suchen.

Micha

Reply to
Michael Baeuerle

Und wenn man unbedingt eine Adresse haben will:

breq drei ;Verzweige bei Übereinstummung... E1: ldi temph, hi8(E1) ;lade Adresse von E1 nach temp ldi templ, lo8(E1) rcall Lcd_out ;Fehlermeldung auf dem LCD ausgeben. rjmp ende ;Endlosschleife

XL

Reply to
Axel Schwenke

Zumindest einige AVRs können sowas ähnliches. Die, denen Atmel die BREAK-Instruktion spendiert hat. Man braucht allerdings natürlich einen entsprechenden Debugger, um sie nutzen zu können.

Das wäre sie auch im Falle eines absoluten CALLs. Ich sehe da kein Problem.

Reply to
Heiko Nocon

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.