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
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
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
Beim IJMP brauchst Du nur die Zieladresse, die lädst Du ins Z-Registerpaar. Sieh Dir einfach an, wie ein Compiler das macht.
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?
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...
. . . 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.
"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
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?
@Peter: Der Nutzen entzieht sich mir ebenfalls - aber die Frage ist beantwortet ;)
Danke für die Hinweise! So gehts natürlich ganz einfach. Gruß Rolli
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.