avr co-operative scheduler/multitasking

OP #4951544
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 ;-)
Angehängte Dateien:
Gast
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.
(Firma: Vescomp)
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...
OP
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
(Firma: Vescomp)
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)"

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.