How does multitasking really work with loop()?



  • Got two tasks, both on separate core, loop only has a delay(500) in it
    all arrays are initialized to 0 on setup and loop looks like this:
    what happens is the m5 freeze after the first completed task 2

    void Oscillo()
    {
    //copy ADC samples to oscillo buffer
    for (int i = 0; i < SAMPLES; i++)
    oscilloBuffer[i] = vSample[i];

    for (int i = 0; i < SAMPLES; i++)
    {
    	oscilloBuffer[i] = vSample[i];
    	if (i == 0)
    	{
    		M5.Lcd.drawPixel(i, 128 - oldOscilloBuffer[i] * .01, BLACK);  //clear
    		M5.Lcd.drawPixel(i, 128 - oscilloBuffer[i] * .01, RED);
    	}
    	else
    	{
    		M5.Lcd.drawLine(i - 1, 128 - oldOscilloBuffer[i - 1] * .01, i, 128 - oldOscilloBuffer[i] * .01, BLACK); //clear
    		M5.Lcd.drawLine(i - 1, 128 - oscilloBuffer[i - 1] * .01, i, 128 - oscilloBuffer[i] * .01, RED);
    		//M5.Lcd.drawFastVLine (i, 128 - min(oldOscilloBuffer[i - 1], oldOscilloBuffer[i]) * .01, max(1,abs(oldOscilloBuffer[i]- oldOscilloBuffer[i-1])) * .01, BLACK);
    		//M5.Lcd.drawFastVLine(i, 128 - min(oscilloBuffer[i - 1], oscilloBuffer[i]) * .01, max(1,abs(oscilloBuffer[i] - oscilloBuffer[i - 1])) * .01, RED);
    	}
    }
    
    //copy to back buffer
    for (int i = 0; i < SAMPLES; i++)
    	oldOscilloBuffer[i] = oscilloBuffer[i];
    

    }

    (by the way, how do I get the auto code parse in this forum to work? it's always missing the start of the method)



  • I’m probably not the best resource to answer this, because I’m just getting started with programming in general... but from the little experience I have so far, delay is a blocking function. So nothing else will run until it completes the task. Something like mills or simpleTimer looks to be better.

    https://canvas.instructure.com/courses/1054116/pages/arduino-millis-and-simpletimer-instead-of-delay-and-blocking

    Also to get the code text formatted properly, I wrap it in three back ticks (before and after the code): ```



  • "loop()" is located inside a task:
    void loopTask(void *pvParameters)
    {
    setup();
    for(;;) {
    micros(); //update overflow
    loop();
    }
    }
    normal functions that run inside loop can't do multitasking.
    For multitasking you have to use RTOS xTaskCreatePinnedToCore... to create a separate task
    check out the signal generator functions on my oscilloscope project to see an example of running tasks on different core.
    Oscilloscope run's inside loop, on core 1
    Signal generators run on core 0



  • the tasks are started the task way from setup
    loop only contains delay because without delay the program freezes



  • You can use something like

    TaskHandle_t taskHandle;
    void setup()
    {
    //some init functions
    }
    void loop()
    {
    if (taskHandle == NULL)
    {
    xTaskCreatePinnedToCore(
    yourTask, /* Task function. /
    "yourTask", /
    name of the task, a name just for humans /
    xxxx, /
    Stack size of task */
    (void )&pvParameter, / parameter of the task /
    y, /
    priority of the task /
    &taskHandle, /
    Task handle to keep track of the created task */
    z); /cpu core number where the task is assigned/
    }
    }

    inside the loop to create a task from loop
    This way you keep the loop busy too with the if statement :)



  • @calin hahaha... wait, seriously?
    But I am not trying to replace the delay with something else. I'm trying to understand why the m5 freezes up under certain conditions when using tasks. Oh and if I lower delay below 500 it will freeze much faster.



  • it freezes because of the watchdog get triggered if the loop is empty or if you use a task on core 0 and you don't handle the IDLE task on that core.
    You might even get some message about that in serial console.
    Something like
    "Task watchdog got triggered. The following tasks did not reset the watchdog in time:

    • IDLE (CPU 0)"


  • @calin freeze with no serial message.
    What is the IDLE task and how do I control all this?