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:
1 | void __attribute__ ((interrupt("IRQ"))) timer1_isr(void)
|
2 | {
|
3 | T1IR = 0xff; // clear all interrupt of Timer1
|
4 | asm volatile(
|
5 | "STMDB SP!, {R0} \n\t" // Alle Register der Userapp sichern
|
6 | "STMDB SP!, {R1} \n\t" // Alle Register der Userapp sichern
|
7 | "STMDB SP!, {R2} \n\t" // Alle Register der Userapp sichern
|
8 | "STMDB SP!, {R3} \n\t" // Alle Register der Userapp sichern
|
9 | "STMDB SP!, {R4} \n\t" // Alle Register der Userapp sichern
|
10 | "STMDB SP!, {R5} \n\t" // Alle Register der Userapp sichern
|
11 | "STMDB SP!, {R6} \n\t" // Alle Register der Userapp sichern
|
12 | "STMDB SP!, {R7} \n\t" // Alle Register der Userapp sichern
|
13 | "STMDB SP!, {R8} \n\t" // Alle Register der Userapp sichern
|
14 | "STMDB SP!, {R9} \n\t" // Alle Register der Userapp sichern
|
15 | "STMDB SP!, {R10} \n\t" // Alle Register der Userapp sichern
|
16 | "STMDB SP!, {R11} \n\t" // Alle Register der Userapp sichern
|
17 | "STMDB SP!, {R12} \n\t" // Alle Register der Userapp sichern
|
18 | "STMDB SP!, {LR} \n\t" // Alle Register der Userapp sichern
|
19 | "MOV R0, #2 \n\t" // Unterbrechen der Userapp mit Status=2 kennzeichnen
|
20 | "STR R0, sheduler_back \n\t"
|
21 | "STR R13, userapp_sp \n\t" // Stackpointer sichern
|
22 | "LDR R14, scheduler_main \n\t" // Rücksprungadresse nach R14
|
23 | "LDR R0, scheduler_main_sr \n\t"// Statusregister zurücksichern
|
24 | "MSR SPSR, R0 \n\t"
|
25 | ); // 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