Forum: Mikrocontroller und Digitale Elektronik Präemptives Multitasking auf ARM9


von Guest (Gast)


Lesenswert?

Hallo,
ich habe hier einen AT91SAM9XE512. Das ist ein ARM926EJ-S Prozessor. Ich 
wollte mir jetzt aus Interesse mal Multitasking anschauen. Dafür habe 
ich mir einen Thread Scheduler überlegt. Der sollte Folgendes tun:
- PC auf den Stack kopieren
- SP in Threadliste sichern
- nächsten SP aus der Threadliste laden
- "return", wobei der neue PC vom Stack geholt wird

Mein Problem ist nun, so glaube ich, dass der Scheduler Interrupt (ein 
Periodic Interval Timer) logischerweise im Interrupt-Mode ausgeführt 
wird, deshalb einen eigenen Stack hat und das ganze System ins Wasser 
fällt. Ich habe versucht den Interrupt-Startup-Code (also das ASM 
Programm) umzuschreiben, aber dabei habe ich irgendwie versagt.
Gibt es eine Standardprozedur für das Context Switching? Ich habe nach 
Multithreading auf ARM gegoogelt aber nichts gefunden.

Das hier ist mein Code: http://pastebin.com/JZfG10V6
Aber wie gesagt, ich weiß nicht wie ich den InterruptHandler schreiben 
muss. Der original-Handler von Atmel sieht so aus: 
http://pastebin.com/5cMt6pWa

Ich bin für jede Hilfe dankbar.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

FreeRTOS läuft auf AT91/ARM9:
http://www.freertos.org/
Musst ja nicht gleich das ganze OS installieren, aber der Source Code 
könnte interssant sein.

von Guest (Gast)


Lesenswert?

> http://www.freertos.org/
Habe ich mir nun mal angeschaut. So wie ich das sehe machen die es 
genauso wie ich es mir vorgestellt habe. Nur, der richtige 
Einstiegspunkt für den Interrupt, den habe ich nicht gefunden. 
Allerdings habe ich auch nur ein ARM7 Verzeichnis gesehen, keins für 
ARM9.

von (prx) A. K. (prx)


Lesenswert?

Guest schrieb:

> Mein Problem ist nun, so glaube ich, dass der Scheduler Interrupt (ein
> Periodic Interval Timer) logischerweise im Interrupt-Mode ausgeführt
> wird, deshalb einen eigenen Stack hat und das ganze System ins Wasser
> fällt.

Du bist hier schon auf dem richtigen Weg. Allerdings musst du natürlich 
die Register der unterbrochenen Task im Task-Kontext sichern, also auf 
dem Task-Stack oder in einem Task-State-Record. Auf dem IRQ-Stack nützen 
sie dir nichts.

Weshalb der IRQ Handler natürlich entsprechend umgeschrieben werden 
muss. Beispiele dafür gibts in jedem von den dutzenden RTOS-Kernels, die 
sich im Netz finden.

Dafür gibts zwei Varianten: Die eine sichert den Kontext im Interrupt 
immer schon so, dass die Tast drin gewechselt werden kann. Nachteil: Es 
wird mehr gesichert als unbedingt nötig, die Latenz wächst. Die andere 
Variante fragt am Ende des IRQ-Dispatchers (irqHandler) ein Flag ab, ob 
die Task gewechselt wurde, und zieht den Kontext-Save/Restore separat 
durch. Bei IRQs ohne Taskswitch ist das billiger, mit Task-Switch 
teurer.

von Guest (Gast)


Lesenswert?

>Du bist hier schon auf dem richtigen Weg. Allerdings musst du natürlich
>die Register der unterbrochenen Task im Task-Kontext sichern, also auf
>dem Task-Stack oder in einem Task-State-Record. Auf dem IRQ-Stack nützen
>sie dir nichts.
Ja genau. Das habe ich versucht. Es ist jetzt erstmal nur der PIT 
Interrupt aktiv, die anderen kümmern nicht. Ich habe es also mal so 
versucht: http://pastebin.com/1PUnKyrk
Allerdings gibt das nur komisches Verhalten. Ich starte das Debugging, 
und egal wie lange ich warte, wenn ich auf Pause drücke ist der ARM ganz 
am Anfang dieses Interrupt Handlers. Dann kann ich mich 
instruktionsweise durchsteppen, lande dann im SchedulerInterrupt, wenn 
ich dann auf Play drücke springt er in den ersten Thread und führt den 
aus. Leider wird der Scheduler Interrupt nie wieder ausgeführt.

von (prx) A. K. (prx)


Lesenswert?

Guest schrieb:

> Ja genau. Das habe ich versucht. Es ist jetzt erstmal nur der PIT
> Interrupt aktiv, die anderen kümmern nicht. Ich habe es also mal so
> versucht: http://pastebin.com/1PUnKyrk

Du sicherst die Register im SVC-Stack. Sie müssen aber in den 
Task-Stack, also den Stack vom USR/SYS-Kontext, oder in ein 
Task-State-Record, aber eben nicht in den als IRQ-Stack verwendeten 
SVC-Stack.

Der SVC-Kontext hat ein eigenes LR. Das LR im IRQ-Kontext wird bei dir 
also nicht gesichert und der Return vom Handler springt zu dem was im LR 
vom SVC zufällig drin stand.

Es könnte nicht schaden, wenn du mal in Beispielcode reinschaust, oder 
in entsprechende Doku. So enthält auch das ARM ARM erklärten 
Beispielcode für einen Task-Switch.

Du könntest dir anfangs das Leben auch etwas erleichtern, indem du nicht 
zwei Probleme gleichzeitig angehst, nämlich Taskswitching und nested 
IRQs. Ohne nested IRQs ist die komplizierte Umschaltung in den 
SVC-Kontext unnötig, was die Sache deutlich erleichtert.

von Guest (Gast)


Lesenswert?

>Du sicherst die Register im SVC-Stack. Sie müssen aber in den
>Task-Stack, also den Stack vom USR/SYS-Kontext, oder in ein
>Task-State-Record, aber eben nicht in den als IRQ-Stack verwendeten
>SVC-Stack.
Ich dachte das normale Programm läuft auch im SVC-Mode :/. Denn in der 
Entry-Funktion schaltet er ganz am schluss auf SVC-Mode um und geht dann 
in die low-level-init Funktion, und dann nach main(). Schaltet der 
Compiler da in den Usermode?

>Der SVC-Kontext hat ein eigenes LR. Das LR im IRQ-Kontext wird bei dir
>also nicht gesichert und der Return vom Handler springt zu dem was im LR
>vom SVC zufällig drin stand.
Ja, DAS ist mir natürlich nicht eingefallen. Wie sicher ich denn das 
LR_irq? In den SVC Mode, alle Register sichern, in den IRQ Mode, LR in 
ein unge-banktes Register laden, wieder in den SVC Mode, Register 
sichern? Das klingt zu kompliziert.

>Es könnte nicht schaden, wenn du mal in Beispielcode reinschaust, oder
>in entsprechende Doku. So enthält auch das ARM ARM erklärten
>Beispielcode für einen Task-Switch.
Bin schon auf der Suche!

>Du könntest dir anfangs das Leben auch etwas erleichtern, indem du nicht
>zwei Probleme gleichzeitig angehst, nämlich Taskswitching und nested
>IRQs. Ohne nested IRQs ist die komplizierte Umschaltung in den
>SVC-Kontext unnötig, was die Sache deutlich erleichtert.
Das war nun aber eher unfreiwillig^^ Wollte ja in den SVC Mode weil die 
Tasks auch SVC sind. Dachte ich.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.