Woher weiß der Controller, wann er zur ISR springen muss?

Ich spreche von Dingen auf der Kernebene.

Soweit ich weiß, führt der Controller-Kern nur Anweisungen aus, die aus dem Speicher abgerufen werden (Fetch - Decode - Execute). Wenn ein Interrupt eintrifft, wie entscheidet der Kern/die ALU, zum ISR zu springen?

Weil wir oder der Compiler keine Anweisung zum Abfragen des Interrupt-Status hinzufügen - woher weiß er dann, dass ein Interrupt bedient werden muss?

Antworten (4)

Was Sie vermissen, ist, dass der Kern mehr tut , als nur Opcodes auszuführen, die aus dem Speicher abgerufen werden. Es enthält eine spezifische Logik, um Interrupts zu implementieren.

Wenn die Interrupt-Erkennungshardware das Signal aktiviert, das besagt, dass es an der Zeit ist, einen Interrupt zu nehmen, wird normalerweise eine spezielle Anweisung in den Kern gesteckt, die nie aus dem Speicher abgerufen wurde. In den meisten Fällen ist dies ein CALL-Befehl an die Interrupt-Vektoradresse. Dies verwendet den vorhandenen Befehlsausführungsmechanismus, um den aktuellen PC auf dem Aufrufstapel zu speichern und ihn in die Interrupt-Vektoradresse zu ändern. Es befasst sich auch mit dem Verwerfen vorab abgerufener Anweisungen und dergleichen.

Die spezielle Interrupt-Annahmelogik muss Interrupts auch so sperren, dass dieselbe Interrupt-Bedingung im nächsten Zyklus keinen weiteren Aufruf an die Interrupt-Vektoradresse verursacht. Unterschiedliche Prozessoren handhaben dies unterschiedlich. Am einfachsten ist es, Interrupts global zu deaktivieren, sodass die Software sie am Ende der Interrupt-Serviceroutine wieder aktivieren muss. Andere Prozessoren haben eine Interrupt-Prioritätsstufe. Dieser Pegel wird angehoben, so dass nur Interrupt-Bedingungen höherer Priorität einen neuen Interrupt verursachen können. Die Unterbrechungspriorität wird dann automatisch zusammen mit der CALL-Rückkehradresse gespeichert und wiederhergestellt, wenn der Code von der Unterbrechung zurückkehrt.

Oft handelt es sich nicht um eine gewöhnliche CALLAnweisung, da Interrupts anders beendet werden (vgl. RETvs. RETI).
Kann ich mit Sicherheit davon ausgehen, dass, wenn diese Interrupt-Erkennungshardware das Signal aktiviert, die CPU anstelle des Speichers Anweisungen zum Springen von woanders erhält ... Wie ein Schalter vielleicht ... Wenn der Schalter ausgeschaltet ist, holen Sie die Anweisung aus dem Speicher und wenn der Schalter eingeschaltet ist , Diese Anweisung ausführen?

Üblicherweise gibt es in modernen Mikrocontrollern eine dedizierte Interrupt Controller (IC)-Einheit, die für die Verwaltung von Interrupts zuständig ist. Zusätzlich hat jede periphere Komponente einen oder mehrere Interrupt-Ausgänge, die von 0zu 1(oder umgekehrt) gehen, wenn eine Bedingung zutrifft (zum Beispiel hat diese Peripherie etwas Arbeit erledigt). Dieser Ausgang ist mit dem Interrupt-Controller verbunden. Die CoreCPU kann dem IC mitteilen, diesen bestimmten Interrupt entweder zu ignorieren (maskieren) oder die MCU zu benachrichtigen, wenn dies geschieht, indem sie bestimmte Signale auslöst, 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 zum entsprechenden Behandlungscode zu springen.

Es gibt Hardware im Computerkern, die einen neuen Wert in den Programmzähler staut, der dem bestimmten ausgelösten Interrupt entspricht. Um sich daran zu erinnern, wohin nach Abschluss der Unterbrechungsroutine zurückzukehren ist, wird der aktuelle Wert im Programmzähler in den Stapel geschoben, bevor die Hardware die Unterbrechungsadresse in den Programmzähler staut. Wenn die Interrupt-Routine abgeschlossen ist, wird der ursprüngliche Wert des Programmzählers aus dem Stapel wiederhergestellt.

Die Werte, die zum Interrupt-Zeitpunkt in den Programmzähler eingeklemmt werden sollen, werden normalerweise durch eines von zwei Schemata bestimmt. Ein Ansatz klemmt eine feste Adresse für jeden Unterbrechungstyp in den Programmzähler und der Computerkern beginnt dann mit der Ausführung von dieser festen Stelle. Der Platz an der festen Stelle ist oft in der Größe begrenzt, so dass es üblich ist, einen Sprungbefehl an den festen Adressen zu codieren, die zu der tatsächlichen Unterbrechungsdienststelle übergehen. Das andere Schema verwendet etwas, das als Unterbrechungsvektortabelle bezeichnet wird. Hier erzeugt die Hardware basierend auf dem Interrupt-Typ einen festen Adress-Offset in die Vektortabelle. Die Hardware zieht dann den Inhalt an dieser Tabellenposition heraus und verwendet diesen Wert als eine Adresse, um in den Programmzähler zu stauen.

Der Controller hat ein Register für den Programmzähler , der die Adresse verfolgt, wo der als nächstes auszuführende Befehl gespeichert ist. (Dieses Register wird auch geschrieben, wenn ein Sprung ausgeführt wird.)

Der Controller hat einen Interrupt-Vektor (oder manchmal mehr als einen, abhängig von der Art des Interrupts), bei dem es sich um die Adresse handelt, an der die ISR gespeichert ist. Diese Adresse ist immer gleich - sie ist wie der Reset-Vektor, wo das Programm startet.

(Oft ist an diesem Vektor eine Sprunganweisung gespeichert, die zum eigentlich auszuführenden Code springt, da der Platz am Vektor nicht ausreicht, um die gesamte Prozedur zu speichern. Wichtig ist jedoch, dass sich die ISR immer an der gleichen Stelle befindet Position.)

Wenn ein Interrupt auftritt, gibt es eine dedizierte Hardware in der Steuerung, die den Programmzähler mit dem Interrupt-Vektor schreibt. Wenn der Controller dann den nächsten Befehlszyklus erreicht, ruft er den Befehl von der Adresse ab, auf die der Programmzähler (also der Unterbrechungsvektor) zeigt.

(In einem Befehlszyklus des Controllers führt er verschiedene Aufgaben aus: Er holt den nächsten Befehl von der Adresse, auf die der Programmzähler zeigt; er erhöht den Programmzähler; er dekodiert den Befehl und führt ihn aus.)