10 Stimmen

Ändern des Kontexts innerhalb eines ISR auf Cortex-M

Ich versuche, einen einfachen Round-Robin-Scheduler für den Cortex-M mit dem CodeSourcery GCC-Toolchain zu schreiben. Mein Scheduler verwendet den SysTick, um nach Ablauf eines Zeitscheibens einen Interrupt auszulösen, und der Kontextwechsel findet im ISR statt. Um die Dinge einfach zu halten, verwende ich nur den Haupt-Stack-Zeiger (MSP) für alles.

Ich stecke fest bei der Bestimmung, wie das Laden des neuen Kontexts auf dem Cortex-M3 gehandhabt werden soll. Laut dem Cortex-M3 Technical Reference Manual (TRM) drückt der Prozess die PC, LR und Statusregister beim Eintritt in das ISR auf den aktuellen Stapel.

Wenn ich den Rest der Register drücke, um den Kontext der aktuellen Aufgabe zu speichern und einen neuen SP-Wert aus dem Steuerblock der nächsten Aufgabe zu laden, wie würde ich den Rest ihres Kontextes wiederherstellen?

Nach meinem Verständnis muss ich die Register, die ich drücke (sagen wir {r4-r11}), wieder herausnehmen und der Prozessor wird den Rest automatisch herausdrücken (einschließlich der Rückgabeadresse der neuen Aufgabe (LR) und Statusregister), wenn das ISR zurückkehrt. Ich nehme also an, dass ich nach Abschluss der Aufgabe einfach ein BX ausführen muss, um die Aufgaben zu wechseln?

Hier steht, was im TRM steht:

Ausnahmerückgaben erfolgen, wenn eine der folgenden Anweisungen einen Wert von 0xFFFFFFFX in den PC lädt, wenn 1) POP/LDM, das das Laden des PC umfasst 2) LDR mit dem PC als Ziel 3) BX mit einem beliebigen Register.

Wie gehe ich vor, um den EXC_RETURN-Wert zu laden? Sollte ich ihn einfach auf den Stapel drücken (wie es angeblich hier macht)? Angenommen, ich habe die Register, die ich über Software gedrückt habe, wieder herausgenommen, wie geht der Cortex dann vor, um die Register, die er gespeichert hat, herauszudrücken? Im Allgemeinen, wie stellt man den Kontext einer Aufgabe wieder her?

Ich habe versucht, das TRM und andere ARM-Referenzen zu lesen, aber sie scheinen unklar zu sein.

22voto

K.Mulier Punkte 7550

Es ist wirklich ziemlich kompliziert. Ich schreibe ein Buch über das Betriebssystem FreeRTOS, das auf Cortex-M-Kernen läuft. Ich habe bereits ein Kapitel darüber verfasst. Ich glaube, dass dir dieses Kapitel beim Lesen deiner Frage helfen wird:

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

2voto

Shrikant Giridhar Punkte 379

Nachdem ich ein wenig mehr gelesen und Hilfe im #ARM IRC-Kanal erhalten hatte, konnte ich später den Mechanismus für die Rückgabe von Ausnahmen verstehen. Hier ist, was ich verstehe.

Wie im CM3 TRM erwähnt, schiebt der Kern die Register r0-r3, r12 zusammen mit dem Status, LR und PC auf den aktuellen Prozess-Stack, wenn eine Ausnahme registriert wird. Somit enthält der Stack beim Eintritt einer Ausnahme 8 Wörter, die den LR enthalten, der die Adresse zum Zurückkehren enthält. Der Hardware-Pop-Mechanismus kehrt im Wesentlichen dieselbe Aktion um, d.h. er poppt die letzten 8 Wörter aus, während er den LR in den PC lädt, um zur unterbrochenen Funktion zurückzukehren.

Daher kann der Kontext einfach gewechselt werden, indem der Stackzeiger an eine geeignete Stelle verschoben wird, sodass der aktuelle Stackframe dem Stackframe einer gerade unterbrochenen Aufgabe ähnelt, d.h. die genauen Wörter in derselben Reihenfolge enthält.

Beim Eintritt einer Ausnahme und nach dem Speichern der Register auf dem Stack wird der LR mit dem EXC_RETURN-Wert geladen. Dieser Wert enthält spezielle Statusflaggen, um Rückkehrbedingungen anzuzeigen. Dies wird auch verwendet, um das Ende des Interrupts anzuzeigen. Das heißt, wenn der ISR zu einer Aufgabe zurückkehren und den Stackzeiger vom aktuellen (MSP) auf den PSP wechseln muss, kann er den LR mit dem entsprechenden EXC-Wert laden (wie im TRM angegeben) und einfach ein BX LR ausführen, um den Zustand zu wechseln.

2voto

Freddie Chopin Punkte 7970

Hier ist ein Codefragment, das genau das macht, was du brauchst - https://github.com/DISTORTEC/distortos/blob/master/source/architecture/ARM/ARMv7-M/ARMv7-M-PendSV_Handler.cpp - es funktioniert wie von dir beschrieben:

  • Ausnahme-Eintritt stapelt automatisch einige Register,
  • du stapelst manuell die verbleibenden Register,
  • du wechselst den SP,
  • du entstapelst "verbleibende" Register,
  • Ausnahmerückkehr entstapelt den Rest der Register.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X