ESP32 FreeRTOS class method to start and delete tasks does not work
Posted: Thu Sep 02, 2021 9:02 am
Hello. I am learning about Freertos and I have stumbled upon the error that my program hangs on vTaskDelete when trying to delete current running task and start another one. The full project can be downloaded and tested on ESP32 dev board: https://github.com/krupis/ESP32
My controller.cpp
controller.h
The logic of this program is very simple. In my main.c I create class object and call begin method. During begin method state_change_handle(TASK2) is called and the task2 is started sucesfully. After the counter reaches 10, state_change_handle(TASK1) is called from within task2 and that SHOULD delete task2 and start task1, however, when counte reaches 10 and state_change_handle method is called, the program just hangs after vTaskDelete. Serial monitor output:
Please could someone help me understand what is the issue here?
I am concerned with this part of the code:
Is this correct?
Could there be some issues with the way I create this pointer to the controller object and then use it to call class method?
I have tried to print the task name before deleting the task and it returned the correct name which probably means the task handle and object is correct:
serial monitor:
My controller.cpp
Code: Select all
#include "Controller.h"
Controller::Controller(){
printf("Thermostat object created \n");
}
void Controller::begin(){
this->test1 = 0;
this->old_state = INITIAL;
this->new_state = INITIAL;
this->main_task_handle = NULL;
printf("Start the task1 \n");
this->State_change_handle(TASK2);
}
void Controller::State_change_handle(e_thermostat_state state)
{
this-> new_state = state;
if(this-> old_state != this-> new_state ){ // if the new state is different than current state, delete the task
printf("different state, delete the previous task \n");
if (this ->main_task_handle != NULL){
vTaskDelete(this ->main_task_handle);
}
printf("PROGRAM STUCK \n");
}
else
{
printf("same task \n"); // the same task is set, dont do anything
return;
}
switch(this->new_state)
{
case TASK1:
printf("NEW STATE = MODE1 \n");
this-> old_state = TASK1;
xTaskCreate(task1,"MODE1",10000,this,1,&this->main_task_handle); // receiving commands from main uart
break;
case TASK2:
printf("NEW STATE = MODE2\n");
this-> old_state = TASK2;
xTaskCreate(task2,"MODE2",10000,this,1,&this->main_task_handle); // receiving commands from main uart
break;
default:
printf("state not recognised \n");
}
}
Code: Select all
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include "stdint.h"
#include "stdio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
enum e_thermostat_state
{
INITIAL,
TASK1,
TASK2,
TASK3,
MAX_STATES
};
class Controller
{
private://only accesible for class
int test1;
e_thermostat_state new_state;
e_thermostat_state old_state;
TaskHandle_t main_task_handle;
TaskHandle_t secondary_task_handle;
public:
//accesible outside class
Controller(); // INIT OBJECT
void begin();
void State_change_handle(e_thermostat_state state);
static void task1(void* parameters)
{
Controller* controller = (Controller*)parameters;
for(;;)
{
printf("test 1 =%i\n",controller->test1);
printf("hello from task 1\n");
vTaskDelay(1000/portTICK_RATE_MS);
}
}
static void task2(void* parameters)
{
Controller* controller = (Controller*)parameters;
for(;;)
{
printf("hello from task 2\n");
controller->test1 ++;
printf("test 1 inside task2 = %i \n",controller->test1);
vTaskDelay(1000/portTICK_RATE_MS);
if(controller->test1 >= 10){
controller->test1 = 0;
controller->State_change_handle(TASK1);
}
}
}
//static void normal_operation_task(void *argument); // DECLARE DEFAULT THERMOSTAT STATES AND VARS
};
#endif
The logic of this program is very simple. In my main.c I create class object and call begin method. During begin method state_change_handle(TASK2) is called and the task2 is started sucesfully. After the counter reaches 10, state_change_handle(TASK1) is called from within task2 and that SHOULD delete task2 and start task1, however, when counte reaches 10 and state_change_handle method is called, the program just hangs after vTaskDelete. Serial monitor output:
Code: Select all
Start the task1
different state, delete the previous task
PROGRAM STUCK
NEW STATE = MODE2
hello from task 2
test 1 inside task2 = 1
hello from task 2
test 1 inside task2 = 2
hello from task 2
test 1 inside task2 = 3
hello from task 2
test 1 inside task2 = 4
hello from task 2
test 1 inside task2 = 5
hello from task 2
test 1 inside task2 = 6
hello from task 2
test 1 inside task2 = 7
hello from task 2
test 1 inside task2 = 8
hello from task 2
test 1 inside task2 = 9
hello from task 2
test 1 inside task2 = 10
different state, delete the previous task
I am concerned with this part of the code:
Code: Select all
static void task2(void* parameters)
{
Controller* controller = (Controller*)parameters;
for(;;)
{
printf("hello from task 2\n");
controller->test1 ++;
printf("test 1 inside task2 = %i \n",controller->test1);
vTaskDelay(1000/portTICK_RATE_MS);
if(controller->test1 >= 10){
controller->test1 = 0;
controller->State_change_handle(TASK1);
}
}
}
Is this correct?
Code: Select all
Controller* controller = (Controller*)parameters;
I have tried to print the task name before deleting the task and it returned the correct name which probably means the task handle and object is correct:
Code: Select all
if(object->old_state != object->new_state ){ // if the new state is different than current state, delete the task
if (object->main_task_handle != NULL){
printf("different state, delete the previous task \n");
printf(" deleting task with name = %s \n",pcTaskGetTaskName(object->main_task_handle));
vTaskDelete(object->main_task_handle);
}
printf("PROGRAM STUCK \n");
}
Code: Select all
test 1 inside task2 = 10
object test 1 = 10
different state, delete the previous task
deleting task with name = MODE2