Ändern der Interrupt-Vektortabelle von Atmega32

Ein Projekt, an dem ich arbeite, beinhaltet eine zyklusgenaue Interrupt-Service-Routine. Diese Routine ist in AVR Assembly geschrieben, wo ich gerade geschrieben habe:

.org oc1aadr
rjmp INTRP

(um das IVT einzurichten) Und es hat perfekt funktioniert. Allerdings musste ich für dieses Projekt sowohl C als auch Assembler verwenden, also wechselte ich zu GCC und nachdem ich etwas Dokumentation nachgeschlagen hatte, stellte ich fest, dass ich die Routine nur mit einem Label schreiben musste:

TIMER1_COMPA_vect:

Jetzt funktioniert der Interrupt auch gut, aber die Sache ist, dass es jetzt 3 Zyklen dauert, um in die ISR einzutreten. Beim Nachschlagen des Disassembler-Codes sah ich, dass das IVT so ist:

+00000000:   940C002A    JMP     0x0000002A       Jump
+00000002:   940C0047    JMP     0x00000047       Jump
+00000004:   940C0047    JMP     0x00000047       Jump
+00000006:   940C0047    JMP     0x00000047       Jump
+00000008:   940C0047    JMP     0x00000047       Jump
+0000000A:   940C0047    JMP     0x00000047       Jump
+0000000C:   940C0047    JMP     0x00000047       Jump
+0000000E:   940C0049    JMP     0x00000049       Jump
+00000010:   940C0047    JMP     0x00000047       Jump

Die JMP-Anweisung dauert 3 Zyklen im Gegensatz zu RJMP, die nur 2 dauert. Ich habe versucht zu schreiben:

.org 0x0E
rjmp INTRP

Aber es wird immer noch nicht funktionieren, ich habe auch versucht, (.section .init0) vor .org zu schreiben, aber immer noch keine Wirkung. Gibt es also eine Möglichkeit, die Anweisung in RJMP zu ändern? Hinweis: Nur die Interrupt-Routine ist in Assembler geschrieben.

Für meine zweite Frage: Gibt es einen Unterschied in den Taktzyklen, die von einer Anweisung benötigt werden, wenn verschiedene Compiler/Assembler verwendet werden? Meine gesamte Routine benötigt mit GCC im Vergleich zu AVR Assembler 3 Taktzyklen weniger. Ich weiß nicht, ob GCC von AVR Assembler abhängt oder nicht, aber besteht die Möglichkeit, dass dies passiert? (Ich frage dies basierend auf der Ausgabe des AVR-Simulators).

Antworten (1)

Die Antwort befindet sich in Zeile 228 von avr/interrupt.h , die sich für die Verwendung jmpauf ATMEGA und rjmpauf anderen Micros entscheidet. Vermutlich könnten Sie es wieder auf überschreiben, rjmpsolange Sie sicherstellen, dass die Adresse Ihres ISR innerhalb des zulässigen Bereichs für liegt rjmp.

Die Dokumentation für avr/interrupt.h, wie in einer anderen Antwort erwähnt, erklärt, wie die ISR als nackt markiert wird, um den Overhead für die Einrichtung/Abbau von Funktionen zu vermeiden. Sie könnten die Funktion sogar mit Inline-Assembler schreiben, aber Sie können wahrscheinlich auch genau die Anweisungen von C erhalten, die Sie wollen.

Das habe ich versucht, aber keine Wirkung. Wie auch immer, ich habe die 1-Takt-Verzögerung an anderer Stelle angepasst, das Problem besteht nicht mehr. Vielen Dank für Ihre Hilfe.
Interessante Frage "Wie generiert GCC die Interrupt-Vektortabelle"; Ich habe auf jeden Fall etwas gelernt. Sie haben Recht, der erste Teil meiner Antwort war falsch, dieser Teil von interrupt.h definiert nur einen veralteten ISR-Aliasing-Mechanismus.