(Speziell für das Arduino Uno ...)
Was passiert mit dem Stack, wenn auf einem AVR-Mikrocontroller ein Interrupt auftritt und ich eine Funktion aufrufe? Inline der Compiler den Code? Zwischenspeichert es den Stapel irgendwo und setzt dann den Stapelzeiger zurück? Hat es einen sekundären Stapel nur für Interrupts?
Soweit ich weiß, ist der Vektor für den Interrupt ein direkter GOTO-Befehl in der Assembly. Ich glaube auch nicht, dass der Mikrocontroller automatisch mit dem Stack herumspielen würde, also wird er wahrscheinlich in Ruhe gelassen. Dies erklärt jedoch immer noch nicht, wie Funktionen während eines ISR funktionieren.
arduino
interrupts
compiler
Anonymer Pinguin
quelle
quelle
Antworten:
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:
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.
Jetzt sind wir fertig und wollen vom Interrupt zurückkehren. Zuerst müssen wir die Software bereinigen.
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.
quelle
ISR_NAKED
) deaktivieren können . Auf diese Weise können Sie die Schritte 5, 6, 8, 9 in einem Kontext überspringen, in dem Sie diese Zyklen wirklich benötigen. Der Nachteil ist, dass Sie absolut sicher sein müssen, dass Sie entweder alle relevanten Register beibehalten oder sie ohne Schaden überschreiben können.