Ich muss ein Programm schreiben auf dem zwei oder drei Task scheinbar zur selben Zeit ausgeführt werden. Lösungsansatz: - erster Task wird nach 10ms per Interrupt unterbrochen - derzeitige Stelle im Task1 "merken" - Wechel zum zweiten Task - zweiter Task wird nach Ablauf von 10ms wieder unterbrochen - derzeitige Stelle im Task2 "merken" - Wechsel zum ersten Task - Ausführung an gemerkter Stelle fort führen Das Ganze soll in C programmiert werden. Der Interrupt dient dabei zur Zeitgenerierung (Prozessor-Zeit für den jeweiligen Task). Mein Problem ist, wie bekomme ich es hin, dass ich den jeweiligen Task wieder an der gleichen Stelle fortsetze?
Ja, okay. Hatte ich auch schon dran gedacht. Aber wie stelle ich dann beim Weitermachen den richtigen Stackpointer wieder ein?
task1 wird unterbrochen: > sp vom task1sichern > register vom task1 sichern task2 wird zurückgeholt > sp vom task2 zurückschreiben > register vom task2 zurückschreiben task2 wird unterprochen > sp vom task2 sichern > register sichern task1 wird geladen > sp vom task1 zürückschreiben ...
Was sind denn das für Tasks ? Am einfachsten geht es, wenn die Tasks selber zur Mainloop zurückkehren, z.B. an Stellen, an denen sie auf irgendwas warten müssen. Aber so mal eben schnell ein Multitasking in C hinzaubern: Vergiß es !!! Peter
hab mir auch mal nen kleines Task OS aufgebaut allerdings für nen M16C Jeder Task braucht nen eigenen Stack beim Taskwechsel/ Interrupt durch timer wird ja auch beim 8051 die rücksprungaddr. im Stack abgelegt. Durch das tauschen der stack ist auf jedenfall schon mal der rucksprung gesichert. Desweitern muss aber noch mehr gespeichert werden: die register (entweder aufm stack am besten aber register bänke verwenden) -> PSW, acc, b und dptr würd ich alles auf den stack legen so jetzt zum taskwechsel alles wie oben besprochen sichern auf Stack stack austauschen alles vom neuen stack wieder runterholen reti ich würde sagen dass man den taskwechsel in asm programmiert jeder task muss natürlich am anfang entsprechen initialisiert werden damit er beim erstenmal aufrufen auch an die richtige stelle hüpft hilfreich sind hier structures gruß jochen leichte fehler vorbehalten :) da ich mehr mit m16c auskenne hab zwar mit 8051 was gemacht aber ...
Okay, danke erst einmal! Werde mal am Wochenende etwas rum spielen. Zum Hinweis das die Task alleine zum Mainprog zurückkehren: Leider geht das für mindestens einen Task nicht. Dieser soll nach Möglichkeit vom restlichen Geschehen nichts mitbekommen.
#asm ;save registers PUSH ACC ; PUSH PSW ; PUSH DPL ; PUSH DPH PUSH 00 ;push R0 from bank 0 PUSH 01 ;push R1 from bank 0 PUSH 02 ;push R1 from bank 0 PUSH 03 ;push R1 from bank 0 PUSH 04 ;push R4 from bank 0 PUSH 05 ;push R5 from bank 0 PUSH 06 ;push R5 from bank 0 PUSH 07 ;push R5 from bank 0 . . Dein Code . .OUT: POP 07 ;pop reg 5 from bank 0 POP 06 ;pop reg 5 from bank 0 POP 05 ;pop reg 5 from bank 0 POP 04 ;pop reg 4 from bank 0 POP 03 ;pop reg 1 from bank 0 POP 02 ;pop reg 1 from bank 0 POP 01 ;pop reg 1 from bank 0 POP 00 ;pop reg 0 from bank 0 POP DPH POP DPL POP PSW POP ACC RETI #endasm Abgesehen davon würde ich das "ohne Stack" retten ganz einfach als quasi Multitasking System in C programmieren. Geht doch viel einfacher. Aber dazu müsstest du doch noch ein paar Infos mehr rauslassen ...
>Jeder Task braucht nen eigenen Stack >Desweitern muss aber noch >mehr gespeichert werden: die register (entweder aufm stack am besten >aber register bänke verwenden) Korrekt. Das ganze nennt man einen "context switch". Wer so was proggen will, sollte sich aber klarmachen, daß er sich damit bereits voll auf dem Gebiet des Betriebssystem-Baus bewegt. Die context switches und das task scheduling sind dabei nur ein kleiner Teil der Angelegenheit. Die Prozesse wollen/müssen ja im allgemeinen auch untereinander kommunizieren, und da fängt die Geschichte dann an, ganz und gar nicht mehr einfach zu sein (Stichworte Critical Sections, Semaphore, Mutexe...). Deshalb an alle, die sich "mal eben schnell" daran versuchen wollen, ein gutgemeinter Rat: Bitte unterschätzt die Sache nicht - ein (funktionierendes) Betriebssystem zu schreiben ist eine sehr anspruchsvolle Aufgabe.
Peter, ein einfaches kooperatives Multitasking ist mit Hilfe von setjmp/longjmp keine große Sache: http://www.mikrocontroller.net/forum/read-4-157859.html#159124
@Andreas, "Peter, ein einfaches kooperatives Multitasking ist mit Hilfe von setjmp/longjmp keine große Sache:" So wie ich das verstanden habe, soll aber eine Task nicht kooperativ sein. Dafür ginge dann folgende Lösung: Die nicht kooperative Task läuft im Main uneingeschränkt bzw. braucht auch nie dahin zurück kehren. Alle anderen kooperativen Tasks laufen dann einfach in einer Schleife im Timerinterrupt. Für die Nichtkenner des 8051 sei gesagt, daß er üblicher Weise nur 128 Byte SRAM hat und das deshalb der Compiler lokale Variablen direkt im RAM per Overlaying ablegt. Auch sind die Bibliotheksfunktionen nicht reentrant geschrieben. Was also auf dem ARM keine große Sache ist, ist aber bestimmt eine auf dem 8051. Peter
Ich werde mal die gestellte Aufgabe genauer beschreiben. Das Ganze soll eine Art Monitor-Programm sein. Auf dem Mikrocontroller (MSC1211 von TI - mit 8051 Kern) soll ein User-Programm laufen. Während das User-Programm läuft sollen gelegentlich Register ausgelesen und evtl. manipuliert werden können (z.B. um Einstellungen des AD- bzw. DA-Wandler im Betrieb zu ändern). Das User-Programm soll von der Main-Funktion gestartet werden und kehrt danach eigentlich nie wieder zur Main-Funktion zurück.
das stimmt natürlich was Bolle schreibt, der taskswitch ist nicht das aufwendige jedoch denke ich das Dirk auf Semaphore verzichten kann, da sein Multitasking bestimmt nicht vorsieht task schlafen zu legen meiner ansicht will er eher ein einfaches roundroubin mit festen taskzeiten keine prioritäten hier muss er nur drauf achten nicht "gleichzeitig" auf resourcen zu zugreifen und hier ein beispiel es wird eine resource z.B. das LCD von mehreren genutzt das Problem befindet sich ein Task gerade in der LCD Ausgabe oder sonst einer LCD Operation und wird unterbrochen bevor er fertig ist muss aufjedenfall unterbunden werden dass ein weiter task jetzt aufs LCD zugreift denn sonst weiß das LCD gar nicht mehr wo es lang geht. Lösung hier: die angesprochenen Mutexe dieser würde ein weiteren zurgriff unterbinden und ein Taskswitch durchführen
Hi Ich habe neulich mal etwas in die Richtung implementiert (nur als Test auf meinem PC), wenn mich nicht alles täuscht nennt sich das kooperatives Mulitasking. Das sieht etwa so aus: Eine Tabelle speichert Funktionspointer zu allen Tasks, die abzuarbeiten sind, sowie deren Prioritäten und was sonst noch so sein muss (je nach Anwendung halt). Die von mir genannten Tasks sind Funktionen, welche ihre Aufgabe oder einen Teil davon in möglichst kurzer Zeit erfüllen und sich danach wieder beenden. Der Rückgabewert sagt aus, ob noch mehr Durchläufe der Funktion notwendig sind oder nicht. Ein Taskmanager geht dann die Tabelle durch und arbeitet die Tasks je nach Priorität öfter oder weniger oft ab und verweilt je nach Rückgabewert bei einem Task oder kümmert sich zuerst um wichtigeres. Ich finde diese Lösung einfach, ressourcensparend und flexibel. Du kannst mir ja mal eine Mail schreiben, wenn du den Prototypen (PC-Version) haben willst. Gruss & HTH Tom
In dem erwähnten Zeitraster von 10ms ist kooperatives Multitasking problemlos machbar, nur muss man natürlich darauf achten, dass alle(!) Warteschleifen oft genug den Scheduler aufrufen. Präemptives Multitasking wird beispielsweise dann nötig, wenn Tasks kurzfristig auf Interrupts reagieren müssen. Mann muss dann zwar in Warteschleifen nicht immer auf den Scheduler achten, dafür kämpft man dann mit Semaphoren, Deadlocks, Timern. Bei einfachem kooperativem Multitasking kann man auf Semaphoren verzichten. Auch sind in der Beschreibung oben keine komplexen Timerstrukturen zu erkennen. Also wird ein simpler setjmp-basierender Scheduler ausreichen. Auch interessant, und ein deutlich anderer Ansatz als klassisches kooperatives Multitasking, besonders geeignet für kleine Devices mit wenig Raum für Stacks: Protothreads => http://www.sics.se/~adam/pt/. Kommt ohne Stack-Switch aus, beim 8051 beispielsweise klar von Vorteil.
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.