Zur Übung würde ich gerne ein sehr kleines Multitasking System bauen. Es soll nichts weiter tun, außer zwischen 3 Tasks im Millisekundentakt wechseln. Wie kann man in einer Timer ISR den Kontext-Switch realisieren?
Klar geht das... Jeder Task bekommt seinen eigenen Stack und dann gehts los: 1. Alle Register in zu Anfang der ISR auf den Stack sichern: SREG, R0-R31 2. Dann den Stackpointer sichern 3. Den Stackpointer auf den nächsten Task ändern 4. Alle Register zurücksichern 5. Rücksprung mit reti Schau dir mal den FreeRTOS-Port an, da solltest du fündig werden. MfG Marius
Eine Möglichkeit wäre z.B. folgendes: Du hast eine Sturktur, in der Platz für alle 32 Register, SP und PC ist. Diese stellt den Zustand eines Threds dar. Dann gibt es eine Liste von Zeigern auf diese Sturkturen, mit in deinem Fall 3 elementen, so wie einen Index, der immer auf das momentan verwendete Element zeigt. In der ISR liest du den Index aus und speicherst alle Register, SP und PC in den aktuellen Eintrag. Dann wird der Index erhöht (FIFO-Prinzip) und zeigt auf den nächsten auszuführenden Thread. es werden dann alle Register aus der Sturktur gelesen, der SP gesetz sowie der gespicherte PC als letzes auf den Stack gelegt. Mit einem reti wird dann "zurück" in den nächste Task gesprungen. usw... Jeder Thread muss natürlich einen eigenen Stack haben. MfG Mark
Wieviel Multitasking solls denn sein? Alle 1ms umschalten, da langweilt der µC sich ziemlich. Da in dieser Zeit jede Menge Befehle abgearbeitet werden können, reicht vielleicht auch so ein 'Multitasking für arme'. Gibt's einige Vorschläge hier im Forum.
chris schrieb: > Zur Übung würde ich gerne ein sehr kleines Multitasking System bauen. Es > soll nichts weiter tun, außer zwischen 3 Tasks im Millisekundentakt > wechseln. > > Wie kann man in einer Timer ISR den Kontext-Switch realisieren? Multitasking heisst noch lange nicht Kontext-Switch. Kooperation ist nicht nur im Leben sondern auch bei kleinen uCs besser, siehe Artikel Multitasking
Vielen Dank erst mal für eure Antworten.
>Jeder Task bekommt seinen eigenen Stack und dann gehts los:
1 | // neuen Stack erzeugen
|
2 | // aber wie?
|
3 | |
4 | task1(); // task1 mit neuen Stack starten |
5 | |
6 | |
7 | void task1() |
8 | {
|
9 | while(1) |
10 | {
|
11 | tuewas(); |
12 | }
|
13 | }
|
Bei machen C-Kompilern gibt es einen Parameter und einen Call-Stack.
Hallo, in einer älteren c't (vor zwei Jahren?) wurde das Thema schön erläutert mit Beispielen .
Hallo Chris, ich habe damit gearbeitet http://www.cocoos.net/ Anregungen sollten für dich zu finden sein. Sehr elegant ist das Beitrag "Wartezeiten effektiv (Scheduler)" von Peter Dannegger. Wenn man das Beisiel verstanden hat, eröffnet sich eine andere Sicht einer Problemlösung.
Danke für die Links. Leider bin ich mit der Beantwortung der Frage, wie man vor dem Call einer Funktion einen neuen Stack-Bereich anlegen kann, nicht weitergekommen. Vielleicht weiß von euch jemand, wie man so etwas macht.
Es wird z.B. im Sourcecode von FreeRTOS und auch uc/OS-II gut gezeigt. Es wird in den anderen vielen kleineren RTOS sicher auch zum "Nachlesen" drinstehen. Einfach nur versuchen das nachzuvollziehen. Hier im Thread wurden auch schon Lösungen gezeigt. Ach ja, ohne Assembler wird es nicht gehen.
>Hier im Thread wurden auch schon Lösungen gezeigt.
Wo wurde hier im Thread gezeigt, wie man einen neuen Stack-Bereich für
einen Task erzeugt?
chris schrieb: >>Hier im Thread wurden auch schon Lösungen gezeigt. > > Wo wurde hier im Thread gezeigt, wie man einen neuen Stack-Bereich für > einen Task erzeugt? Hier: Beitrag "Re: Multitasking mit AVR" Beitrag "Re: Multitasking mit AVR" Wie gesagt, etwas (oder pur) Assemblercode ist nötig.
Chris, dieser Beitrag Beitrag "Re: Multitasking mit AVR" ist bestimmt direkt gemeint und alle aufgezeigten Taskswitscher liegen im Quellcode vor, da müsste man dann auch hinein schauen. Die Frage ist nur_ wir kompliziert und bzgl. Speicherverbrauch, Task-Verhalten muss es für eine Problemlösung sein ?
Bei FreeRTOS findest du das erzeugen des Stacks in der Datei port.c in einem AVR-Port directory. Z.B: FreeRTOS\Source\portabe\GCC\ATMegaxxx\port.c pxPortInitialiseStack heißt die Funktion, die z.B. von xTaskGenericCreate() in tasks.c aufgerufen wird. Der Context-Switch selber findet in vPortYieldFromTick() in port.c statt.
>Z.B: FreeRTOS\Source\portabe\GCC\ATMegaxxx\port.c
Danke, das scheint genau die Stelle zu sein, die man braucht. Ich hänge
die Datei mal als Referenz zur weiteren Diskussion an den Thread.
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.