Page 1 of 1

Help with ESP32 and RTOS

Posted: Thu Apr 07, 2022 9:27 am
by protttoy
Hi, I don't understand how the vTaskResume and vTaskSuspend commands work in this following code:

Code: Select all


static TaskHandle_t handle_task1 = NULL;
static TaskHandle_t handle_task2 = NULL;
static TaskHandle_t handle_task3 = NULL;


void setup()
{
    Serial.begin(115200);
    delay(2000);
    
    // create tasks
    xTaskCreate(task1, "task1", 1024, NULL, 2, &handle_task1);
    xTaskCreate(task2, "task2", 1024, NULL, 2, &handle_task2);
    xTaskCreate(task3, "task3", 1024, NULL, 2, &handle_task3);
}

void loop()
{
    // nothing to do here
    vTaskDelete(NULL);
}


void task1(void *params)
{
    TickType_t xLastWakeUpTime = xTaskGetTickCount();
    const TickType_t xDelay10000ms = pdMS_TO_TICKS(10000);

    while(1)
    {   xLastWakeUpTime = xTaskGetTickCount();

        if (handle_task2)
        vTaskSuspend(handle_task2);
        if (handle_task3)
        vTaskSuspend(handle_task3);
        Serial.println("in Task 1");
        vTaskResume(handle_task2);
        vTaskResume(handle_task3);
        
        vTaskDelayUntil(&xLastWakeUpTime , xDelay10000ms );
    }
}

void task2(void *params)
{
    TickType_t xLastWakeUpTime = xTaskGetTickCount();
    const TickType_t xDelay5000ms = pdMS_TO_TICKS(5000);

    while(1)
    {
        xLastWakeUpTime = xTaskGetTickCount();

        if (handle_task1)
        vTaskSuspend(handle_task1);
        if (handle_task3)
        vTaskSuspend(handle_task3);
        Serial.println("in Task 2");
        vTaskResume(handle_task1);
        vTaskResume(handle_task3);

        vTaskDelayUntil(&xLastWakeUpTime , xDelay5000ms );
    }
}

void task3(void *params)
{
    TickType_t xLastWakeUpTime = xTaskGetTickCount();
    const TickType_t xDelay1000ms = pdMS_TO_TICKS(1000);
    while(1)
    {
        xLastWakeUpTime = xTaskGetTickCount();

        if (handle_task2)
        vTaskSuspend(handle_task2);
        if (handle_task1)
        vTaskSuspend(handle_task1);

        Serial.println("in Task 3");
        vTaskResume(handle_task2);
        vTaskResume(handle_task1);
        
        vTaskDelayUntil(&xLastWakeUpTime , xDelay1000ms );    
    }
}

What I am trying to achieve: The task1 should run every 10 seconds but when it is running the other two tasks should not run. Similarly task2 should run every 5 seconds and task3 every second.

But the output is like this: data of 20 seconds
Timestamp --> Serial output
15:20:56:596 --> in Task 1in Task 2
15:20:56:596 -->
15:20:56:596 --> in Task 3
15:20:57:539 --> in Task 3
15:20:57:539 --> in Task 2
15:20:57:540 --> in Task 1
15:20:58:539 --> in Task 3
15:20:58:540 --> in Task 2
15:20:58:541 --> in Task 1
15:20:59:539 --> in Task 3
15:20:59:540 --> in Task 2
15:20:59:541 --> in Task 1
15:21:00:539 --> in Task 3
15:21:00:540 --> in Task 2
15:21:00:541 --> in Task 1
15:21:01:538 --> in Task 3
15:21:01:540 --> in Task 2
15:21:01:541 --> in Task 1
15:21:02:538 --> in Task 3
15:21:02:540 --> in Task 2
15:21:02:541 --> in Task 1
15:21:03:538 --> in Task 3
15:21:03:539 --> in Task 2
15:21:03:540 --> in Task 1
15:21:04:538 --> in Task 3
15:21:04:539 --> in Task 2
15:21:04:540 --> in Task 1
15:21:05:538 --> in Task 3
15:21:05:539 --> in Task 2
15:21:05:540 --> in Task 1
15:21:06:538 --> in Task 3
15:21:06:539 --> in Task 2
15:21:06:540 --> in Task 1
15:21:07:538 --> in Task 3
15:21:07:539 --> in Task 2
15:21:07:541 --> in Task 1
15:21:08:538 --> in Task 3
15:21:08:540 --> in Task 2
15:21:08:541 --> in Task 1
15:21:09:538 --> in Task 3
15:21:09:539 --> in Task 2
15:21:09:540 --> in Task 1
15:21:10:538 --> in Task 3
15:21:10:539 --> in Task 2
15:21:10:540 --> in Task 1
15:21:11:538 --> in Task 3
15:21:11:539 --> in Task 2
15:21:11:540 --> in Task 1
15:21:12:538 --> in Task 3
15:21:12:539 --> in Task 2
15:21:12:540 --> in Task 1
15:21:13:538 --> in Task 3
15:21:13:539 --> in Task 2
15:21:13:540 --> in Task 1
15:21:14:538 --> in Task 3
15:21:14:539 --> in Task 2
15:21:14:540 --> in Task 1
15:21:15:537 --> in Task 3
15:21:15:538 --> in Task 2
15:21:15:539 --> in Task 1
15:21:16:537 --> in Task 3
15:21:16:538 --> in Task 2
15:21:16:539 --> in Task 1
15:21:17:538 --> in Task 3
15:21:17:538 --> in Task 2
15:21:17:539 --> in Task 1
Please can anyone explain what is happening ? I am using Arduino IDE and ESP core 2.0.3-RC1

Re: Help with ESP32 and RTOS

Posted: Thu Apr 07, 2022 6:21 pm
by lbernstone
I know it is not the answer you are looking for, but I think what you really want here is a mutex with a 10 (or maybe 9) second timeout, rather than suspending the processes. That way, you could just have the three functions on timers, and if Task1 timer is defined first, it will consistently run first, take the mutex, and the other two processes will have to wait for it to release the lock.

Re: Help with ESP32 and RTOS

Posted: Thu Apr 07, 2022 11:53 pm
by ESP_Sprite
That is one mess of code. What may be happening is that as soon as you wake up a task, it gets to work and suspends the task that woke it up. (This could even happen between the vTaskDelayUntil and GetTickCount, making your task sleep for longer than intended.)

Re: Help with ESP32 and RTOS

Posted: Fri Apr 08, 2022 1:56 am
by protttoy
with the vTaskResume the task should resume from the moment it was suspended, right ? Why is the vTaskDelayUntill not working in this case ? Please see the output, the tasks are printing things without executing the delay.

Re: Help with ESP32 and RTOS

Posted: Fri Apr 08, 2022 8:19 am
by ESP_Sprite
Ah, that is potentially because a delay already suspends the task. Likely the resume also resumes it if the task is suspended because of that.

Re: Help with ESP32 and RTOS

Posted: Sat Apr 16, 2022 7:58 am
by sfoulk526
lbernstone wrote:
Thu Apr 07, 2022 6:21 pm
I know it is not the answer you are looking for, but I think what you really want here is a mutex with a 10 (or maybe 9) second timeout, rather than suspending the processes. That way, you could just have the three functions on timers, and if Task1 timer is defined first, it will consistently run first, take the mutex, and the other two processes will have to wait for it to release the lock.
Just what I was thinking, this is definitely job for the mutex.