Hallo,
ich experimentiere hier gerade etwas mit einem LPC2148 herum und möchte
einen EInfachen Taskswitch programmieren. Dazu wollte ich folgendes
machen:
1. Taskswitch im Timerinterrupt durchführen und dazu:
2. Alle Register auf den Stack sichern
3. Stackpointer und Programmcounter sichern
4. Statusregister sichern
5. Statusregister des nächsten Tasks zurückschreiben
6. Programcounter des nächsten Tasks zurückschreiben
Dabei sollen in diesem einfachen Experiment erstmal nur ein Task
unterbrochen werden und dann in eine fest definierte Funktion gesprungen
werden, nach abarbeiten dieser soll der unterbrochene Tasks fortgesetzt
werden.
Folgendes (nichtmal kompilierendes) Fragment wollte ich für das
Unterbrechen des Tasks nutzen:
);// Interrupt wird abgeschlossen und r14 und CPSR wiederhergestellt
26
VICVectAddr=0;//Dummy write to signal end of interrupt
27
}
Leider steige ich noch nicht ganz durch die Sntax des Arm Assemblers
durch.
Meine Hauptsächliche frage ist allerdings, was genau beim Aufruf eines
Interrupts passiert? Wenn ich das richtig verstanden habe, bleibt der
Stack völlig unangetastet und der Arm sicher Statusregister und
Programmcounter in Schattenregister. Ändert der gcc an diesem Verhalten
etwas?
Kann mein oben skizziertes Vorhaben so funktionieren, oder habe ich
etwas grundlegendes nicht bedacht?
Vielen Dank für Eure Hilfe,
Stefan
> Wenn ich das richtig verstanden habe, bleibt der Stack völlig> unangetastet und der Arm sicher Statusregister und Programmcounter in> Schattenregister.
Ja.
> Ändert der gcc an diesem Verhalten etwas?
Daran wird er wohl nichts ändern, aber er kann auf die Idee kommen, z.B.
andere Register zu sichern, bevor deine asm-Routine aufgerufen wird.
Deshalb definiere die Funktion mit __attribute__((naked)). Dann macht er
da garantiert überhaupt nichts.
> Kann mein oben skizziertes Vorhaben so funktionieren, oder habe ich> etwas grundlegendes nicht bedacht?
Du kannst mal in den Scheduler-Code von FreeRTOS reinschauen und ihn
verstehen. Deine Register werden z.B. im IRQ-Stack gespeichert und nicht
im Task-Stack, wo es sinnvoller wäre.
Danke für Deine Antwort.
Das jeder Task einen eigenen Stack bekommt möchte ich erst als zweiten
Schritt implementieren. Bisher soll nur der eine (der im Beispiel
unterbrochene) Task einen Stack haben und der zweite Task bei jedem
Aufruf einen neuen Stack aufbauen. Ich möchte bevor ich weitermache
erstmal den Taskswitch genau verstehen. Allerdings habe ich irgendwie
Probleme mit der Syntax vom Inline-Assembler und vertstehe deshalb den
Code von FreeRTOS (danke für den Hinweis) auch nicht so ganz...
Obiger Code liefert beim kompilieren immer nur den Fehler:
\LOCALS~1\Temp/ccS8aaaa.s OFFSET_IMM) not fixed up
Grüße, Stefan
> Das jeder Task einen eigenen Stack bekommt möchte ich erst als zweiten> Schritt implementieren.
Es geht mir eher darum, daß auch die ISR einen eigenen Stack hat.
Übrigens: Wo wird eigentlich dein Task-Stackpointer gesichert?
> Allerdings habe ich irgendwie Probleme mit der Syntax vom> Inline-Assembler
Du wirst nicht darum herumkommen, dich damit zu beschäftigen.
Insbesondere auch damit, wie man Parameter an den Assembler übergibt.
> und vertstehe deshalb den Code von FreeRTOS (danke für den Hinweis)> auch nicht so ganz...
Wenn du den verstehst, verstehst du auch, wie du einen Taskwechsel
machen mußt. ;-)
> Obiger Code liefert beim kompilieren immer nur den Fehler:>> \LOCALS~1\Temp/ccS8aaaa.s OFFSET_IMM) not fixed up
In welcher Zeile?
PS:
Du mußt daran denken, daß so Dinge wie z.B.
1
T1IR=0xff;// clear all interrupt of Timer1
Register benutzen, die also vorher gesichert werden müssen.