Your new topic does not fit any of the above??? Check first. Then post here. Thanks.

Moderator: igrr

User avatar
By Kaisha
#69530 I'm working on a small web server/light controller, using the adafruit huzzah with a lcd and sainsmart relay controlled by an mcp23017. I have the hardware up and running nicely (while I'm good at programming, I'm a noob at electronics, so I'm happy it worked so well) and would like some sort of cooperative multitasking framework to manage the thing.

I really liked https://github.com/anmaped/esp8266-scheduler but I can't get it working. Even while playing around with the Arduino linker parameters I've had no luck. I looked at a few other libraries, but I think I can roll my own using <cont.h>. The documentation is a bit sparse...

I was wondering that happens when a function spawned by cont_run() finishes normally (ie. doesn't exit with yeild) and if there is anyway to detect whether a function exited normally, or via yield?

Anyone else played with <cont.h>? Any thoughts on cooperative multitasking libraries?
User avatar
By HelWeb
#84809 How to use <cont.h> in Arduino-IDE ?

1)
Code: Select all// This is the base of task switching from espressif:
extern "C" {
#include <cont.h>
}



2) Declare contexts. Each context has a stack space of (cont.h) 4096 Bytes.
My tests show: without WiFi 1024 Bytes are enough
Code: Select all    cont_t A, B, C;


3) then you have to prepare the contexts once:
Code: Select all    cont_init( & A);                            // prepare an own stack for TaskA
    cont_init( & B);
    cont_init( & C);


4) In a loop call your Tasks:
Code: Select all    cont_run( & A, TaskA);                      // start TaskA from beginning or last cont_yield
    cont_run( & B, TaskB);                      // start TaskB
    cont_run( & C, TaskC);                      // start TaskC


First call cont_run will start the functions from the beginning.
next calls to cont_run(&context) will not start at the beginniing of the function, but where they left with cont_yield

I build a hole multitasking system around it and showed the building in 7 Lessons.

Here is Lesson-1, which shows the principles:
Code: Select all// Esp8266 Wemos D1 R1     and    Esp8266-12F Wemos D1 mini

/*
   ESP8266_CoopOS_Stack_Lesson1

   (C) 2019 Helmut Weber Dph.HelmutWeber.123@gmail.com

   Arduino IDE, Esp8266 Wemos D1 R1

   The simplest form of Multitasking:  (tick time is 1s)

   All tasks are called every second from loop

      >cont_init( &context ):
      reserve a context with a stackspace of 4096 bytes (defined in cont.h)

      >cont_run( &context, functionpointer):
      switch all registers and PC to the named context - then run the function
      1) first time: start the function
      2) next times: got to the point of the last cont_yield in the function

      >cont_yield( &context):
      save context with PC and registers, switch context to caller(where cont_run occured) and return
 */



// This is the base of task switching from espressif:
extern "C" {
#include <cont.h>
}



cont_t A, B, C;

void TaskA() {
    static unsigned long cnt;
    Serial.println("Start TaskA");
    while(1) {
        cnt++;
        Serial.print("TaskA-1 ");
        Serial.println(cnt);
        cont_yield(&A);
        Serial.print("TaskA-2 ");
        Serial.println(cnt);
        cont_yield(&A);                             // save PC and all registers
        // get old PC, stack (==loop)
    }
}


void TaskB() {
    static unsigned long cnt;
    Serial.println("Start TaskB");
    while(1) {
        cnt++;
        Serial.print("TaskB-1 ");
        Serial.println(cnt);
        cont_yield(&B);
        Serial.print("TaskB-2 ");
        Serial.println(cnt);
        cont_yield(&B);
    }
}


void TaskC() {                                // toggle internal LED
    static unsigned long cnt;
    Serial.println("Start TaskC");
    while(1) {
        digitalWrite(2,!digitalRead(2));
        cont_yield(&C);
    }
}



void setup() {
    Serial.begin(500000);
    pinMode(2,OUTPUT);

    cont_init( & A);                            // prepare an own stack for TaskA
    cont_init( & B);
    cont_init( & C);
    Serial.print("Setup End");
}

void loop() {
    Serial.println("   loop");

    cont_run( & A, TaskA);                      // start TaskA from beginning or last cont_yield
    cont_run( & B, TaskB);                      // start TaskB
    cont_run( & C, TaskC);                      // start TaskC


    delay(1000);
}



Lesson 7 does 170.000 taskswitches per second, has external interrupts and 100.000 timer interrupts/s
I will publish it at github.

Just now you may look at

https://github.com/MacLeod-D/ESP8266-Multitasking-CoopOS

which is a CoopOS (based on cont.h) with a webserver.


have fun :D
User avatar
By HelWeb
#84810 But you may have multitasking without <cont.>
Here is a Tutorial for ALL CPUs you may use with Arduino-IDE (including ESP8266):

https://github.com/MacLeod-D/CoopOS-Lessons-English

It has 60 pages of documentation and Lesson-8 (used with ESP8266) shows:

>500.000 Scheduler calls/s
100.000 Timer Interrupts/s
From Timer Interrupt to schedule Task 6: <5µs
External Interrupts

7 Tasks running
2 Interrupt Routines
24% of program space
41% of dynamic memory