Ich spreche von Dingen auf der Kernebene.
Soweit ich weiß, führt der Controller-Core nur Befehle aus, die aus dem Speicher abgerufen werden (Fetch - Decode - Execute). Wie entscheidet sich der Kern / die ALU, wenn ein Interrupt eintrifft, zum ISR zu springen?
Da wir oder der Compiler keine Anweisung zum Abfragen des Interruptstatus hinzufügen - woher weiß er dann, dass ein Interrupt bedient werden muss?
quelle
CALL
Anweisung, da Interrupts auf andere Weise beendet werden (vgl.RET
Vs.RETI
).In modernen Mikrocontrollern gibt es üblicherweise eine eigene Interrupt-Controller-Einheit (IC), die für die Verwaltung von Interrupts zuständig ist. Zusätzlich hat jede Peripheriekomponente einen oder mehrere Interrupt-Ausgänge, die von
0
nach1
(oder umgekehrt) gehen, wenn eine Bedingung zutrifft (z. B. hat dieses Peripheriegerät einige Arbeiten abgeschlossen). Dieser Ausgang ist mit dem Interrupt-Controller verbunden. DieCore
CPU kann dem IC anweisen, diesen bestimmten Interrupt zu ignorieren (zu maskieren) oder die MCU zu benachrichtigen, wenn dies durch Auslösen bestimmter Signale geschieht, und dann entscheidet die MCU, was damit zu tun ist. Der übliche Weg ist, dass der IC der MCU mitteilt, welcher Interrupt aufgetreten ist, und zu dem entsprechenden Bearbeitungscode springt.quelle
Es gibt Hardware im Computerkern, die einen neuen Wert in den Programmzähler staut, der dem bestimmten ausgelösten Interrupt entspricht. Um sich zu merken, wohin Sie nach Beendigung der Interruptroutine zurückkehren müssen, wird der aktuelle Wert des Programmzählers in den Stapel geschrieben, bevor die Hardware die Interruptadresse in den Programmzähler schreibt. Nach Beendigung der Interruptroutine wird der ursprüngliche Wert des Programmzählers wieder aus dem Stapel entfernt.
Die Werte, die zur Unterbrechungszeit in den Programmzähler eingespeist werden sollen, werden normalerweise durch eines von zwei Schemata bestimmt. Ein Ansatz staut eine feste Adresse für jeden Interrupt-Typ in den Programmzähler, und der Computerkern startet dann die Ausführung an diesem festen Ort. Der Platz an dem festen Ort ist häufig in der Größe begrenzt, so dass es üblich ist, einen Sprungbefehl an den festen Adressen zu codieren, die zu dem tatsächlichen Unterbrechungsdienstort übergehen. Das andere Schema verwendet eine sogenannte Interrupt-Vektortabelle. Hier generiert die Hardware einen festen Adressoffset in der Vektortabelle basierend auf dem Interrupttyp. Die Hardware holt dann den Inhalt an dieser Tabellenposition heraus und verwendet diesen Wert als Adresse, um in den Programmzähler einzugreifen.
quelle
Die Steuerung hat ein Register für den Programmzähler , das die Adresse verfolgt, an der der nächste auszuführende Befehl gespeichert ist. (Dieses Register wird auch geschrieben, wenn ein Sprung ausgeführt wird.)
Die Steuerung hat einen Interrupt-Vektor (oder manchmal mehr als einen, abhängig von der Art des Interrupts), der die Adresse ist, an der der ISR gespeichert ist. Diese Adresse ist immer gleich - es ist wie beim Reset-Vektor, bei dem das Programm startet.
(Häufig ist in diesem Vektor ein Sprungbefehl gespeichert, der zum eigentlichen auszuführenden Code springt, da der Speicherplatz im Vektor nicht ausreicht, um die gesamte Prozedur zu speichern. Wichtig ist jedoch, dass sich der ISR immer am selben Ort befindet Position.)
Wenn ein Interrupt auftritt, befindet sich eine dedizierte Hardware in der Steuerung, die den Programmzähler mit dem Interrupt-Vektor schreibt. Wenn die Steuerung dann den nächsten Befehlszyklus erreicht, ruft sie den Befehl von der Adresse ab, auf die der Programmzähler (also der Interrupt-Vektor) zeigt.
(In einem Befehlszyklus der Steuerung werden verschiedene Aufgaben ausgeführt: Es ruft den nächsten Befehl von der Adresse ab, auf die der Programmzähler zeigt. Es erhöht den Programmzähler. Es decodiert den Befehl und führt ihn aus.)
quelle