Der AVR ist eine RISC-Architektur, daher verfügt er über eine ziemlich grundlegende Hardware-Behandlung von Interrupts. Die meisten Prozessoren spielen während Interrupts mit dem Stack, obwohl es einige gibt, insbesondere ARM und PowerPC, die unterschiedliche Methoden verwenden.
In jedem Fall macht der AVR Folgendes für Interrupts:
Wenn ein Interrupt auftritt, führt die Prozessorhardware die folgenden Schritte aus, die nicht nur ein einfaches GOTO sind:
- Beenden Sie die aktuelle Anweisung.
- Deaktivieren Sie das globale Interrupt-Flag.
- Schieben Sie die Adresse der nächsten Anweisung auf den Stapel.
- Kopieren Sie die Adresse im richtigen Interrupt-Vektor (entsprechend dem aufgetretenen Interrupt) in den Programmzähler.
Zu diesem Zeitpunkt hat die Hardware alles getan, was sie tun wird. Die Software muss korrekt geschrieben sein, damit nichts kaputt geht. In der Regel erfolgen die nächsten Schritte in diese Richtung.
Schieben Sie das Statusregister auf den Stapel. (Dies muss zuerst erfolgen, bevor es geändert wird).
Schieben Sie alle CPU-Register, die geändert werden (oder werden könnten), auf den Stapel. Welche Register auf diese Weise gespeichert werden müssen, wird vom Programmiermodell festgelegt. Das Programmiermodell wird vom Compiler definiert.
Jetzt kann der Arbeitsinterrupt-Code ausgeführt werden. Um den Fall in der Frage des Aufrufs einer Funktion zu beantworten, tut sie einfach das, was sie immer tut, drückt den Rückgabewert auf den Stapel und legt ihn dann zurück, wenn sie fertig ist. Dies hat keinen Einfluss auf diese vorherigen Werte, die wir bisher auf dem Stapel gespeichert haben.
- Führen Sie den ISR-Arbeitscode aus.
Jetzt sind wir fertig und wollen vom Interrupt zurückkehren. Zuerst müssen wir die Software bereinigen.
- Pop die CPU-Register, die wir in Schritt 6 verschoben haben.
- Fügen Sie den gespeicherten Statuswert wieder in das Statusregister ein. Danach müssen wir darauf achten, keine Anweisung auszuführen, die das Statusregister ändern könnte.
Führen Sie den RTI-Befehl aus. Die Hardware führt die folgenden Schritte für diese Anweisung aus:
ein. Aktivieren Sie das globale Interrupt-Flag. (Beachten Sie, dass mindestens ein Befehl ausgeführt werden muss, bevor der nächste Interrupt berücksichtigt wird. Dadurch wird verhindert, dass schwere Interrupts die Hintergrundarbeit vollständig blockieren.)
b. Geben Sie die gespeicherte Absenderadresse in den PC ein.
Jetzt kehren wir zum normalen Code zurück.
Beachten Sie, dass es einige Punkte gibt, an denen wir sehr vorsichtig sein müssen, insbesondere in Bezug auf das Statusregister und die Speicherregister, die geändert werden könnten. Wenn Sie einen C-Compiler verwenden, wird dies alles zum Glück unter der Decke erledigt.
Außerdem müssen Sie auf Ihre Stapeltiefe achten. Zu jedem Zeitpunkt, an dem Interrupts aktiviert sind, kann ein ISR mehr vom Stapel verwenden, als anhand des lokalen Codes ersichtlich ist. Natürlich kommt dies nicht viel auf, es sei denn, Sie bringen Ihr Gedächtnis an seine Grenzen.
Hier ist ein Link, der diesen Prozess beschreibt, wenn Sie eine Referenz wünschen.