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*)¶ms0, /* 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*)¶ms1, /* 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);
}
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..