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.
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.
> 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.
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.
>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.
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.
>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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.