co-operative multitasking scheduler für avr ohne irq plus framework für TOS Supported AVR CPUs: m328p, m644, ... kompilieren: make flash : make isp Anpassen: CPU und Programmer wird in "makefile" eingestellt Anzahl Tasks werden in "config.h" definiert Das Programm eignet sich gut für mehrere parallele Aufgaben. Er hilft ausufernde state-machines zu vermeiden und eignet sich sehr gut für Kommunikations-funktionen. Der scheduler muss explizit aufgerufen werden, dadurch bewahrt man sich die volle kontrolle über das timing im Programm. Zudem wird das debuggen möglich. Zum Testen am besten einen Arduino verwenden. In config.h wird der PIN für eine LED definiert. Wenn ein anderes Testboard verwendung findet, sollte dies angepasst werden. scheduler: wechseln zwischen den tasks timer2 : millisekunden zähler (bestimmte CPUs!) xitoa : elm-chan version von printf und co. config.h : alle Konfigurationen master : das Demo Programm cpu.h : viele nützliche macros zb: "cfg_lo(D4); cfg_in(D5)" serx.h : zur generierung von code für mehrere serielle ports BUGS: nur wenige AVR CPUs mit einer USART in serx.h unterstützt, timer2 prescaler Berechnung nur eingeschränkt universell THANKS: elm-chan : xitoa (he is the KING) günter greschenz: gos (the scheduler) avr-freaks: id8 - force 8 bit alu operations in gcc atmel : please, create seriel bus without usb nonsense ************************************ you are the best ;-) https://www.mikrocontroller.net ************************************ KEYWORDS: scheduler task tasks arduino avrdude makefile xitoa xatoi printf preemptive framework timer ctc-mode milliseconds wiring avr-libc serial communication state-machine multitasking KISS ;-)
Das Ganz ist ziemlich Quick & Dirty programmiert. Wenn schon bei task_create nicht die Limits, hier NUM_TASKS, abgefragt wird, dann ist das nicht schön und neigt zu Fehlern/Fehlverhalten, wenn man bei der Programmierung vergisst NUM_TASK seinen Bedürfnissen anzupassen. Der TCB sieht etwas mager aus. Da fehlt mir zuviel, Priorität, Mailbox, usw.. Und mal ehrlich, das Beispiel überzeugt nicht wirklich. Das bekomme ich mit weniger Code auch hin. Und ohne Overhead für das bissel Taskwechsel. Multitasking sieht anders aus. Jens H. schrieb: > Das Programm eignet sich gut für mehrere parallele Aufgaben. Wie soll das Deiner Meinung nach funktionieren? Parallel sieht anders aus. Das kann dieser Scheduler nicht leisten. Das ist ein netter Versuch und das macht auch bestimmt Spass sich in die Materie einzuarbeiten. Aber sinnvoll und professionell einsetzbar ist das nicht. Da musst Du noch einiges dafür tun.
Jens H. schrieb: > Das Programm eignet sich gut für mehrere parallele Aufgaben. > Er hilft ausufernde state-machines zu vermeiden und eignet > sich sehr gut für Kommunikations-funktionen. Will nicht meckern aber das sieht irgendwie unordentlich und zusammengekleistert aus. Tasks können nicht ausgetragen bzw. gelöscht werden, wenn ein Task blockiert, sind alle blockiert und vor allem - da sind keine parallelen Aufgaben möglich. Du hast es zwar richtig angeführt - kooperativ, aber kooperativ und parallel gehen eben nicht zusammen und deswegen eignet sich dein Beispiel nicht für irgendwelche Kommunikations-funktionen. P.S. Und mal ehrlich - das Ganze kann genausogut in einem while(1) loop in main() laufen - absolut kein Unterschied...
:
Bearbeitet durch User
Marc V. schrieb: > Tasks können nicht ausgetragen bzw. gelöscht werden, dies ist ein Beispiel, also auf das notwendigste reduziert. Wer in der Lage ist einen scheduler zu benötigen, kann solche Funktionen sicherlich selber hinzufügen. > Task blockiert, sind alle blockiert und vor allem - da sind keine > parallelen Aufgaben möglich. Wie du erkannt hast, kooperativ! > Du hast es zwar richtig angeführt - kooperativ, aber kooperativ und > parallel gehen eben nicht zusammen und deswegen eignet sich dein > Beispiel nicht für irgendwelche Kommunikations-funktionen. Aber sicher doch, oder läuft das Programm bei dir nicht ;-) ? Wenn ein Task blockiert, z.B. mit "while(PIND&1);" kann dir dieser scheduler nicht helfen. Das geht nur mit preemptive multitasking! Wie ich versucht habe, auf ganz einfache weise zu Demonstrieren in master.c:comm(), schreibt man solche Warteschleifen um in "while(PIND&1) schedule();" und schon läuft es. > > P.S. > Und mal ehrlich - das Ganze kann genausogut in einem while(1) loop > in main() laufen - absolut kein Unterschied... Doch ein wesentlicher Unterschied: state-machine. Es ist mir vollkommen klar, das du mit einer State-Machine dieses minimale Beispiel nachprogrammieren kannst, aber es ist nicht das gleiche! Angenommen du hast Peripherie per i2c angebunden und musst ein Protokoll implementieren bei dem jede Aktion wieder in einzelne send/recv Schritte unterteilt ist, dann benötigt jede Function eine eigene State-Machine, die wiederum in einer weiteren State-Machine läuft usw.usf., mit einem scheduler kann jede dieser State-Machines so aussehen wie ich es in master.c:comm() gezeigt haben. Die gleiche Funktionalität, aber einfacher und kürzer in der Implementation. Fazit: jedes aktive warten auf einen Stimulus wird nach dem Muster: "while( nicht_fertig() ) schedule();" geschrieben, anstelle von: switch(state) { case 0: aktion(); state=1; break; case 1: if(nicht_fertig) return; else state=2;" usw.. Gruß, Jens
Jens H. schrieb: > Wer in der Lage ist einen scheduler zu benötigen, kann solche Funktionen > sicherlich selber hinzufügen. Wenn er in der Lage ist solche Funktionen selber hinzuzufügen, dann kann er auch gleich alles neu schreiben und seinen Bedürfnissen anpassen. > Fazit: jedes aktive warten auf einen Stimulus wird nach dem Muster: > "while( nicht_fertig() ) schedule();" geschrieben, anstelle von: > switch(state) { case 0: aktion(); state=1; break; case 1: > if(nicht_fertig) return; else state=2;" usw.. Das sind (in deinem Fall) rein kosmetische Unterschiede. Ausserdem ist Statemachine (in meisten Fällen) weitaus effizienter als dein Scheduler, alleine schon wegen der PUSH/POP Orgie. Auf diese Weise werden andere Tasks zwar nicht blockiert, dafür aber solange einfach hintereinander durchlaufen, bis der blockierende Task wieder weitergeht. Da du nicht mit Timeslices arbeitest, wird z. B. bei 3 blockierenden Tasks (von 4) nur der vierte Task immer wieder durchlaufen aber du (bzw. dein Programm) hat keine Ahnung davon, dass 3 Tasks blockieren. Ehrlich gesagt, ich habe noch nie eine sinnvolle Anwendung mit kooperativem Multitasking ohne Timer gesehen. Selbst eine einfache Ampelsteuerung geht nicht ohne Timer... Schaue mal hier: Beitrag "Wartezeiten effektiv (Scheduler)"
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.