Go Down

Topic: ESP32 xTaskCreatePinnedToCore usage in a class (Read 427 times) previous topic - next topic

taz00

Hi there, straight to the point.

I'm trying to use wificlientsecure to make some https requests, I want these requests to run on the esp32's second core, so they're not blocking the main thread.

But I've run into some problems trying to put the following sketch into a class.

I've removed anything not directly related to my problem, so theres no http requests being done here. It will do some work on the second core, write the result in a shared variable, and set a flag indicating it's done. Main loop thread checks the indicator and reads the result variable when its complete. To hopefully make it thread safe.

ESP32CoreTaskTest.ino
Code: [Select]


//Global Variables shared between cores
bool taskFinished = false;
int count = 0;

void setup() {
    //Start Serial Output
    Serial.begin(115200);
    Serial.println("");

    xTaskCreatePinnedToCore(
                task,       //Function to implement the task
                "taskname", //Name of the task
                6000,       //Stack size in words
                NULL,       //Task input parameter
                0,          //Priority of the task
                NULL,       //Task handle.
                1);         //Core where the task should run
}


void loop() {
  // put your main code here, to run repeatedly:
  if(taskFinished){
    Serial.print("Task#: ");
    Serial.println(count);
  }else{
    Serial.println("Busy");
  }
  delay(100);
}

void task( void* ){
  while(1){
    taskFinished = false;
    count++;      //do some work
    delay(250);   //do some work
    taskFinished = true;
    delay(250);   //Pretend task is done, and not really looping. We should be able to read the task result after the task has finished
  }
}





This works perfectly, they share memory and wait for tasks to be finished before reading the result.
But I cannot figure out how implement it as a class. So I can use it like this.

Code: [Select]

Task task = Task();
task.startTask();

while(!task.taskFinished)
{
   //busy
}

int result = task.count;

//Dispose the task, keep the result



Obviously the code works, so it must be turned into c++ at some point, but I dont know what that would look like.

My attempt at the code looks like this:

ESP32CoreTaskTest_Class.ino

Code: [Select]

#include "Task.h"

Task task;

void setup() {
    //Start Serial Output
    Serial.begin(115200);
    Serial.println("");

    task = Task();
    task.startTask();
}

void loop() {
  // put your main code here, to run repeatedly:
  if(task.taskFinished){
    Serial.print("Task#: ");
    Serial.println(task.count);
  }else{
    Serial.println("Busy");
  }
  delay(100);
}


Task.cpp

Code: [Select]

#include "Task.h"

//Constructor
Task::Task(){
 
}

//Member
void Task::startTask(){

  xTaskCreatePinnedToCore(
            this->worktask, //Function to implement the task
            "taskname",     //Name of the task
            6000,           //Stack size in words
            NULL,           //Task input parameter
            0,              //Priority of the task
            NULL,           //Task handle.
            1);             //Core where the task should run
}

//Task to run
void Task::worktask(void* _this){
  while(1){
    taskFinished = false;
    count++;      //do some work
    delay(250);   //do some work
    taskFinished = true;
    delay(250);   //Pretend task is done, and not really looping. We should be able to read the task result after the task has finished
  }
}



Task.h

Code: [Select]

#ifndef Task_h
#define Task_h

#include "Arduino.h"

class Task {
  public:
    Task(void);
    void startTask(void);
    bool taskFinished = false;
    int count = 0;
  private:
    static void worktask( void* ); 
   
   
};



#endif


This throws "invalid use of member 'Task::taskFinished' in static member function" as described in the link below.

As its not quite as simple as just making it a static member. :/

https://esp32.com/viewtopic.php?t=5027 that I cant quite decipher.

And I did try what was suggested, but I ran into some different compile errors, so I thought I'd go back to my orignal question to myself, and post it here.

What would my original sketch look like, if it was plain c++?



taz00

#1
Jan 11, 2020, 06:32 pm Last Edit: Jan 11, 2020, 06:35 pm by taz00
Well, I've figured it out it seems.

Key clue to getting it working was here https://esp32.com/viewtopic.php?t=2085

Here's a working example of using xTaskCreatePinnedToCore inside a class. There's still some work left to do, fx adding proper callbacks and replacing the "work" with an actual https request.

Code: [Select]

class AsyncHTTPSRequest {

  public:
    int testVar = 0;
    char request[100] = "";
    volatile bool taskFinished = true;
  private:
    const int taskCore = 0;
    const int taskPriority = 1;
    TaskHandle_t Task1;
 
  public:  AsyncHTTPSRequest(void){
   
  }
 
  public: void Start(void)
  {     
    taskFinished = false;
    //Start Task with input parameter set to "this" class
    xTaskCreatePinnedToCore(
      this->httpsTask,        //Function to implement the task
      "httpsTask",            //Name of the task
      5000,                   //Stack size in words
      this,                   //Task input parameter
      taskPriority,           //Priority of the task
      &Task1,                 //Task handle.
      taskCore);              //Core where the task should run
  }
 
 
  private: static void httpsTask(void *pvParameters)
  {   
    AsyncHTTPSRequest *l_pThis = (AsyncHTTPSRequest *) pvParameters;   
    // Handle the request here

    delay(1000); //Pretend work
   
    l_pThis->testVar = 1;

    l_pThis->taskFinished = true;
    delay(50); //Wait a little before killing task
    vTaskDelete( NULL );
  }
     
};

AsyncHTTPSRequest req;

void setup() {
  // put your setup code here, to run once:
  //Start Serial Output
  Serial.begin(115200);
  Serial.println("");
   
  req.Start();
}

void loop() {
  // put your main code here, to run repeatedly:
  if(req.taskFinished){
    Serial.print("Done :");Serial.println(req.testVar);   //Task finished, read result variable
    while(1){delay(10);}
  }
  else
  {
    Serial.println("Busy");
  }

  delay(10);
}

Go Up