www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR: Programmcounter einlesen


Autor: Rolli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

um beim AVR-Controller switch-case Listen effektiv programmieren zu
können müsste ich am Kopf der Verzweigung den aktuellen Stand des
Programmcounters auslesen und mittels indirekter Adressierung den
jeweils gewünschten case-Fall aufrufen. Wie lese ich den aktuellen
PC-Stand aus? Gibt es eine andere effektive Möglichkeit für eine
direkte programmgesteuerte Verzweigung?

Gruß Rolli

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wozu interessiert Dich der PC ?

Springe einfach dahin, wo Du weitermachen willst.

Bei bis 10 Werten ist je ein Vergleich am effektivsten.
Sind es mehr und aufeinanderfolgend, kann man IJMP verwenden.


Peter

Autor: Rolli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Hinweis!

Habe, wie ich meine, alle Möglichkeiten schon durchprobiert, ohne
Erfolg:

Beim direkten Sprung RJMP muß ich jeweils eine konstante Verschiebung
bzw. ein Label angebeben. Adressierung über Register nicht möglich.

Beim indirekten Sprung IJMP muß ich das Z-Register (R31:R30) mit der
Basisadresse laden. Hierfür brauche ich den aktuellen PC. In der Doku
finde ich keinen Hinweis auf die Register, in denen der PC abgelegt
ist.

Weiter habe ich versucht, den Sprungverteiler per .org-Anweisung auf
eine feste Basisadresse zu legen: akzeptiert der Imagecraft-C-Compiler
nicht in Inline-Assemblermodulen.

Da ich den Sprungverteiler im zeitkritischen Assemblermodul eines
Reglers benötige, brauche ich eine sehr schnelle Variante.

Gruß Rolli

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beim IJMP brauchst Du nur die Zieladresse, die lädst Du ins
Z-Registerpaar.

Sieh Dir einfach an, wie ein Compiler das macht.

Autor: Rolli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein ICC-Compiler macht aus der "einfachen" switch-case-Anweisung eine
recht aufwändige Assembler-Routine mit zahlreichen "cpi"-Abfragen und
darauffolgenden "breq"/"rjmp"-Sprüngen: pro Sprungziel eine
Abfrage, eine Verzweigung und ggf. ein Programmsprung. Für mich ist das
bei einer Vielzahl von Sprungzielen unbrauchbar.

Soweit ich das verstanden habe, muß ich beim "ijmp"-Befehl die
absolute Sprungadresse im Z-Registerpaar ablegen, d.h. vorher mit Hilfe
des aktuellen PC bestimmen. Wenn der Controller zu "PC+Z" springen
würde wäre das ja okay, aber er springt direkt zu "Z".

Verstehe ich da was falsch?

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein Compiler macht aus komplizierten switch-Anweisungen sehr wohl
eine Sprungtabelle. ;-)

Ja, Du mußt eine absolute Adresse dafür haben, aber warum zum
Geier[tm] brauchst Du denn dafür den aktuellen PC?  Die Absolutadresse
läßt man sich üblicherweise vom Linker eintragen, indem man in der
Sprungtabelle ein Symbol für das Sprungziel hinlegt -- so macht es
jedenfalls der GCC.

.org ist ohnehin tabu, diese Pseudo-Op hat nur für Absolutassemb-
lierung Sinn (wenn also kein Linker im Spiel ist), bei verschieblichen
Objekten bestimmt ja stets erst der Linker, wohin was kommt.  Das war
schon zu CP/M-Zeiten so...

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.
.
.
pc_adress:
     ldi r30,low(pc_adress)
     ldi r31,high(pc_adress)
.
.
Durch diesen Code hättest Du den aktuellen PC im Z-Register.
Wieviele Sprungziele hast Du denn?
Ich habe so etwas ähnliches mit einer Tabelle realisiert. In der
Tabelle stehen die Sprungadressen. Einfach die entsprechende Adresse
aus der Tabelle lesen, ins Z-Register und per ijmp springen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Durch diesen Code hättest Du den aktuellen PC im Z-Register."

Ja aber wozu ist das nütze ???

Der AVR kennt keinen BranchBackward Befehl.


Peter

Autor: Profi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mache es mit der Tabelle und ijmp.
Du musst die verschiedenen Startadressen in die Tabelle bringen.

Für Branches (relativ) brauchst Du den aktuellen PC.
Da der hier verwendete Befehl ein Jump (absolut) ist, braucht Dich der
aktuelle PC nicht interessieren.

Alle Adressberechnungen macht der Linker für Dich (wenn Du es ihm
richtig sagst).

Wenn es schnell gehen soll, als Notlösung:
Mache es mit einer Sprungtabelle:
LABEL_A:
JMP LABEL0
JMP LABEL1
JMP LABEL2
JMP LABEL3
JMP LABEL4
JMP LABEL5
...

Da jetzt alle JMPs gleichviele Bytes belegen (hoffentlich wird nichts
wegoptimiert), kannst Du mit
JMP LABELA+n*m (m ist die Zahl der Bytes, die ein JMP belegt)
zum LABELn springen.

Schafft das Dein Compiler?

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter: Der Nutzen entzieht sich mir ebenfalls - aber die Frage ist
beantwortet ;)

Autor: Rolli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hinweise!

So gehts natürlich ganz einfach.

Gruß Rolli

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.