FreeRTOS C++: passing arguments to a task in a class

2.3k views Asked by At

My question is similar to this one but I need to pass arguments to the task.

I want to run 2 parallel instances of a task on an ESP32. So I create the task inside a class and a wrapper to prevent the

error: invalid use of non-static member function

Here is the task creation:

// Create parallel tasks
    xTaskCreatePinnedToCore(
      this->startForwardTask,              /* Function to implement the task */
      "Forward0",               /* Name of the task */
      1000,                     /* Stack size in words */
      this,
  /*    (void*)&params0,          /* Task input parameter */
      20,                       /* Priority of the task */
      NULL,                     /* Task handle */
      0);                       /* Core where the task runs */

    xTaskCreatePinnedToCore(
      this->startForwardTask,             /* Function to implement the task */
      "Forward1",              /* Name of the task */
      1000,                    /* Stack size in words */
      this,
  /*    (void*)&params1,         /* Task input parameter */
      20,                      /* Priority of the task */
      NULL,                    /* Task handle */
      1);                      /* Core where the task runs */

Then the task is :

void MLP::startForwardTask(void* _this) {
 (MLP*)_this->forwardTask();
}

void MLP::forwardTask (void * parameters) {
  argsStruct myArgs = *((argsStruct*)parameters);

 // whatever

  SemaphoreHandle_t barrierSemaphore = myArgs.semaphore;
  xSemaphoreGive(barrierSemaphore);
  vTaskDelete(NULL);
}

params0 and params1 are structs where I put the parameters I want to pass to the tasks.

    // Create semaphore for tasks synchronization
    SemaphoreHandle_t barrierSemaphore = xSemaphoreCreateCounting( 2, 0 );
    // Arguments for the tasks
    argsStruct params0 = {1, med, l, barrierSemaphore};
    argsStruct params1 = {med + 1, end, l, barrierSemaphore};

I get the following error:

C:---\Arduino\libraries\MLP\MLP.cpp: In static member function 'static void MLP::startForwardTask(void*)':

C:---\Arduino\libraries\MLP\MLP.cpp:887:14: error: 'void*' is not a pointer-to-object type

(MLP*)_this->forwardTask();

          ^

exit status 1

In order to use the wrapper function, I had to pass the 'this' argument to the wrapping task. How can I pass the params0 and params1 arguments to the 'real' task (forwardTask) when I declare the tasks?

One other question: I create a counting semaphore to synchronize the 2 tasks and continue after both have ended. I passed the semaphore as an argument to both tasks (inside a struct). How can the method that created the tasks monitor this semaphore? Is this correct?

    for (int i = 0; i < 2; i++) {
      xSemaphoreTake(barrierSemaphore, portMAX_DELAY);
    }
1

There are 1 answers

0
HS2 On

According to C++ operator precedence you need to properly cast _this before calling a method like this ((MLP*)_this)->forwardTask();

See https://en.cppreference.com/w/cpp/language/operator_precedence

I guess you want to wait for both tasks exit with the barrierSemaphore and I think it should work. Although dynamically creating/destroying tasks is usually not the preferred pattern in embedded systems..