[Projekt] Polytasking (kooperativ)

Hi.
Das Thema (kooperatives) Multitasking wird immer wieder gerne genommen. Für größere µC mit viel ram und Speicherverwaltung dürfte Multitasking wie unter FreeRTOS häufig eine sinnvolle Option sein, aber ich hab mal versucht ein nano-os auf einem tiny4313 unterzubringen und bin dabei auf Polytasking, d.h. jeder Prozess nutzt eine dynamisch zugewiesene (gleiche) Speicherbank, gestoßen. Vom Prinzip ähnlich wie Soundkarten früher Klänge erzeugt haben oder bspw. beim C64 aus einem Pool von 8 Sprites dynamisch zugewiesen wurde.

Grundsätzliche Einschränkung bei dem Prinzip:

  • alle PolyTask müssen im gleichen Segment arbeiten d.h. bei APL/C und ähnlichen Sprachen in einer Funktion
  • die Variablen müssen über die zugewiesene Bank adressiert werden. Vereinfachung über Macro.
    kurz: für einfache Anwendungen nicht unbedingt dramatisch.

Schwierig ist es eine passende Syntax zu finden für Programme die praktisch in einer Funktion laufen, aber wie Programme unter Windows/Linux/etc. d.h. mit

  • Autostart
  • 1++- Instanzen
  • Prozess-Id
    gestartet und beendet werden.

Der (aktuelle) Werkzeugkasten:

  • poly_var definiert Anzahl der Slots und verfügbare Variablen
  • poly_init <=> autoexec.bat /init-script
  • poly_schedule 'umrahmt' den Block mit allen Polys (und 'scheduled')
  • startPoly(id,name,para) ... startet ein Poly
  • stopPoly(id) wenn die ID bekannt ist, dann lässt sich ein Poly auch beenden
  • POLY(name) Kopf eines Poly/Task/Progrämmchen
  • poly_ end/rep/to(name) ...Fuß eines Poly
  • **P_(var) ** für den Zugriff auf die Poly-Variablen
  • zum warten: P_Wait(cond) P_Wait_cs(cs)
    (Zeit in centi-sekunden passt mMn. besser für solche Polys)
void do_Poly (uint16_t centis) {
   poly_var(8,int A,B,C);                     // 8 Slots vars:A,B,C
   poly_init{ startPoly(1,blink,50);  } // 1 Hz
   poly_schedule{
      POLY(blink){
         led(on );  P_Wait_cs( P_(para));
         led(off );  P_Wait_cs( P_(para));
     poly_rep;}
   end_(schedule);}
   if (btn1) stopPoly (1);
   if (btn2) startPoly (1,blink,25);      // 2 Hz
end_(do_poly);}
// ... do_Poly (time_in_cs); .... 

ein bisschen sieht das nach basic aus. Als wir früher mit 8-bit CPU gebastelt haben hatten wir ironischer weise auch eine einfache Sprache (basic) für die eigentlichen Programme und haben C bzw. ASM für zeitkritische Routinen/Treiber genutzt (C64). So deutlich wie damals lässt sich das heutzutage sicherlich nicht realisieren, aber ich glaub, dass eine zweite Sprache durchaus 'automatisch' helfen kann.

Genug der Theorie!
Demo-Board

polytask.h (3,1 KB)

P.S.: die Idee eine Programmiersprache mit Makros zu erweitern stammt eigentlich aus dem Buchdruck. TeX ist schon bei Version 3.141592653

Die gibt es teilweise schon, in den Task Makros nach Knuth (TeX?), implementiert von mir oder Combie. Eine Suche im Forum nach "Task Makros" zeigt etliche zugehörige Diskussionen auf.

Deine Beschreibung mit Segment, Bank und Slots ist wenig hilfreich, wenn ein Controller sowas nicht unterstützt und damit den (Arduino-) Benutzern nicht klar ist, was das soll.

genau dort wurde auch bemängelt, dass taskBegin taskEnd mitten in einer Funktion völlig unverständlich sind und besser TASK(name) als Header benutzt werden sollte.

Das ist Software. Jeder Controller der unter C programmiert werden kann unterstützt die Segmentierung von C, Arrays/Banks.

Kannst bitte noch ein paar Worte schreiben was der Sketch machen soll?
Weil aktuell schauts für mich nach geblinke mit 225 Zeilen Code aus. Das überzeugt mich noch nicht.

imho kann das zu einem Fehler beim rollover führen:

if(millis()>=millis_upd)
  {  millis_upd=millis()+20; pin_update();}
 if(millis()>=millis_upd)
  {  millis_upd=millis()+20; pin_update();}

Hier handelst du dir einen Überlauf ein, welcher dafür sorgt, dass die if Bedingung mehrfach nacheinander wahr wird. Das Timing läuft dir so aus dem Ruder.

Ansonsten, schaue ich da wie ein Schwein ins Uhrwerk.

Hallo
Wofür braucht man(n) sowas ?

Kooperatives Multitasking ist die Glückseligkeit, der Nutzer von kleinen µC.

Ich machs mir (mittlerweile) allerdings etwas anders!
(siehe Anhang)
CooperativeTask.zip (11,0 KB)

1 Like

Wirklich zwingend braucht man sowas nicht, aber poly- oder multi-tasking ist halt sehr praktisch wenn viele Abläufe bspw. Lichteffekte in interaktiven Installationen verständlich organisiert werden oder zur (vergl. protothreads- ebenfalls mit scheduler) IP Protokoll Auswertung.
Viele machen es sich halt anders und bemerken eher, dass millis() nach 40 Tagen aus dem Ruder läuft.

Auslöser für den Arduino-Port ist übrigens ein populäres Elektronik-Forum in dem keiner erklären kann wie man Lichteffekte mit einem AVR 32 CH PWM Board programmieren kann.

Tut es das bei Dir? Dann machst Du was falsch.

Gruß Tommy

was hat der IP-Protokol-Stack mit Task-Scheduling und Task-Dispating zu tun?

Bei Combie läuft das Timing nach 40 Tagen aus dem Ruder, weil die If Bedingung um den Zeitpunkt einmal 9 ms früher erfüllt ist.

Dunkels verwendet seine protothreads auch in 2 IP-Stacks.
Die single-task Lösungen, bei denen für jeden weiteren 'Task' ein Aufruf in der main bzw. loop notwendig ist, scheiden da praktisch aus.

Bist du bereit, diese Aussage zu belegen?

Wie alt bist du wenn du schon nach 3 Stunden deine Beiträge vergisst?

Jetzt wirds absurd....

... die Stelle die du bemängelt hast stammt übrigens aus deinen (single)TaskMakros.

und ?

ist halt Ironie wenn ältere Menschen einen Vorstellungs-Thread zum Thema Polytasking kapern müssen und dabei über ihre Jugendsünde mekkern (ich hab versucht die 40 Tage Problematik im Combie Makro zu verharmlosen, konnte dabei allerdings nicht über den Rest hinwegsehen)

@asmandfriends
Ich habe das als Hinweis von combie über deinen fehlerhaften Code interpretiert.

Wer auf einem "echten" Arduino (d.h. einem Gerät das mit minimalem RAM faszinierende Sachen hinkriegt) kooperatives Multitasking mithilfe komplexer Objekte und Strukturen realisiert, hat eben Spaß an unsinnigen Ansätzen, den ich jedem gönne.
Brauchen tut das keiner und die beste Lösung (nach welchen Kriterien auch immer) wird es wohl auch nicht. Wenn es drum geht, viele Sachen gleichzeitig zu machen, ist die Frage nach den vorhandenen Ressourcen wichtig. Da sehe ich bisher keinen Hinweis.

Nach #14 und #18 hätte ich allerdings diesen Thread auf "nicht mal ignorieren" setzen sollen.
Tschüß

und ich hab den "fehlerhaften" Code von Combie

zu den vorhanden Ressourcen musst du in das Datenblatt eines µC schauen, um Hinweise zu entdecken.
Um Speicher/Zeitverbrauch zu entdecken müsstest du die Anzahl der Slots mit Größe eines Variablensatzes multiplizieren und 10 byte dazu rechnen.

Sozialhilfeempfänger schaffen sowas nicht.