vTaskResume throws GetLastError () 87

Hello. I created 3 tasks and the idea is to run the first task for a while then to suspend it and the second task to start running until it gets suspended too. The third task starts and when the execution is finished, I want to resume the second task. When the second task is finished, I want to resume the first task.
The problem is when the third task tries to resume the second task. I get error() 87.
Can you help me?
My code:

/* Standard includes. */
#include <stdio.h>
#include <conio.h>

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"

static TimerHandle_t xTimer = NULL;
static TaskHandle_t xHandle = NULL;
static TaskHandle_t xHandle2 = NULL;
static TaskHandle_t xHandle3 = NULL;

void Task1(void* pvParameters)
{
    int i = 0;
    printf("Task1");
    TickType_t xStartTime = xTaskGetTickCount();
    for (i = 0; i < 10000; i++)
    {
        if (i == 5000)
            vTaskSuspend(xHandle);
    }
    TickType_t xLastTime = xTaskGetTickCount();
    printf("Execution time = %d ", (xLastTime-xStartTime));
    
   
}

void Task2(void* pvParameters)
{
    int i = 0;
    printf("Task2");
    for (i = 0; i < 10000; i++)
    {
        if (i == 5000)
            vTaskSuspend(xHandle2);
    }
    vTaskResume(xHandle);
    vTaskSuspend(xHandle2);
    
}

void Task3(void* pvParameters)
{
    int i = 0;
    for (i = 0; i < 10000; i++)
    {
        printf("Task3");
    }
    printf("Task3asdasdsad");
    vTaskResume(xHandle2);
    vTaskSuspend(xHandle3);
}

void my_main(void)
{
    
    xTaskCreate(Task1, "Task1", 1000, xHandle, 3, NULL);
    xTaskCreate(Task2, "Task2", 1000, xHandle2, 3, NULL);
    xTaskCreate(Task3, "Task3", 1000, xHandle3, 3, NULL);
    vTaskStartScheduler();
    return 0;
}

Hello @BogdanColhon, thank you for your post.

Did you provide the printf() function? Are you sure that it is “re-entrant”? Normally it isn’t.

What platform are you using? WinSim? If so, you should not call the standard Windows API’s like printf() or any other function that may block.

A FreeRTOS task must never return and all your tasks return which is wrong. If you do not need a task anymore, delete it by calling vTaskDelete. Suspend/Resume is not a good idea - can you not use semaphores or task notifications to achieve the synchronization? The following pseudo code shows the idea:

static SemaphoreHandle_t runTask1, runTask2, runTask3;

void Task1( void * params )
{
    for( ;; )
    {
        /* Do work. */
        xSemaphoreGive( runTask2 ); /* Signal Task 2. */
        xSemaphoreTake( runTask1, portMAX_DELAY ); /* Wait for signal from Task 2. */
    }
}

void Task2( void * params )
{
    for( ;; )
    {
        xSemaphoreTake( runTask2, portMAX_DELAY ); /* Wait for signal from Task 1. */
        /* Do work. */
        xSemaphoreGive( runTask3 ); /* Signal Task 3. */
        xSemaphoreTake( runTask2, portMAX_DELAY ); /* Wait for signal from Task 3. */
        /* Do work. */
        xSemaphoreGive( runTask1 ); /* Signal Task 1. */
    }
}

void Task3( void * params )
{
    for( ;; )
    {
        xSemaphoreTake( runTask3, portMAX_DELAY ); /* Wait for signal from task2. */
        /* Do work. */
        xSemaphoreGive( runTask2 ); /* Signal Task 2. */
    }
}

Why do you want to do such synchronization though? What is the problem that you are trying to solve?

Hi @BogdanColhon,
Can you help to check your configuration about configUSE_TIME_SLICING?

Tasks might share time slots with same priority when this configuration is enabled.
It means when task1 might be not suspended when task2 tries to resume it. And so does other case.

I agree with @aggarg opinion that using suspend/resume is not a good idea. I’d suggest you to use xTaskNotify() and xTaskNotifyWait() to do this kind of synchronization.

Thanks.
BR,
Actory

1 Like

Hi @BogdanColhon, were the responses helpful, did they help to solve the problem?