ESP32平台FreeRTOS跨任务删除任务时子任务无法销毁问题排查
ESP32 FreeRTOS跨任务删除功能异常排查
场景说明
正在学习FreeRTOS的任务创建、管理以及跨任务删除功能,为ESP32微控制器编写了测试程序:后台常驻serial_message_receive任务监听串口消息,收到对应指令后创建对应FreeRTOS任务:
- "task1":启动task1
- "task2":启动task2
源代码
controller.cpp
#include "Controller.h" Controller controller_obj; //static void Thermostat::normal_operation_task2(Thermostat* thermostat_obj); Controller::Controller(){ printf("Thermostat object created \n"); } void Controller::begin(){ this-> old_state = INITIAL; this->main_task_handle = NULL; this->secondary_task_handle = NULL; printf("Initialise the object with the default values \n"); //xTaskCreate(task1,"thermostat normal operation task",10000,this,1,NULL); //receiving commands from main uart } 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); } } else{ printf("same task \n"); // the same task is set, dont do anything return; } switch(this->new_state) { case MODE1: printf("NEW STATE = MODE1 \n"); this-> old_state = MODE1; xTaskCreate(task1,"MODE1",10000,this,1,&this->main_task_handle); // receiving commands from main uart break; case MODE2: printf("NEW STATE = MODE2\n"); this-> old_state = MODE2; xTaskCreate(task2,"MODE2",10000,this,1,&this->main_task_handle); // receiving commands from main uart break; default: printf("state not recognised \n"); } }
controller.h
#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, MODE1, MODE2, MODE3, 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_obj = *((Controller*)parameters); //CHECK IF TASK3 IS ACTIVE. IF IT IS ACTIVE, ALWAYS DELETE IT WHEN TASK1 IS STARTED if(controller_obj.secondary_task_handle != NULL){ printf("task3 is active, delete it"); vTaskDelete(controller_obj.secondary_task_handle); } for(;;) { printf("hello from task 1\n"); vTaskDelay(1000/portTICK_RATE_MS); } } static void task2(void* parameters) { Controller controller_obj = *((Controller*)parameters); for(;;) { printf("hello from task 2\n"); if(controller_obj.secondary_task_handle ==NULL){ printf("task3 started from task2"); xTaskCreate(task3,"MODE2",10000,&controller_obj,1,&controller_obj.secondary_task_handle); } vTaskDelay(1000/portTICK_RATE_MS); } } static void task3(void* parameters) { Controller controller_obj = *((Controller*)parameters); for(;;) { printf("hello from task 3 which is created from task 2\n"); vTaskDelay(1000/portTICK_RATE_MS); } } //static void normal_operation_task(void *argument); // DECLARE DEFAULT THERMOSTAT STATES AND VARS }; #endif
逻辑说明
调用类的begin方法时完成初始化:
void Controller::begin(){ this-> old_state = INITIAL; this->main_task_handle = NULL; this->secondary_task_handle = NULL; printf("Initialise the object with the default values \n"); //xTaskCreate(task1,"thermostat normal operation task",10000,this,1,NULL); //receiving commands from main uart }
初始化了两个任务句柄:
main_task_handle:用于管理主任务,即收到串口消息后创建的任务secondary_task_handle:用于管理副任务,即task2内部创建的task3
通过串口消息切换task1和task2时会调用State_change_handle方法,删除旧的主任务后创建新任务,该功能测试正常。
异常现象
task3出现异常:task3由task2创建,创建时传入secondary_task_handle存储句柄,task2和task3可正常运行;但切换回task1时,判断secondary_task_handle非空就删除task3的逻辑始终不执行,task3仍持续运行,串口日志如下:
Initialise the object with the default values task1 selected different state, delete the previous task NEW STATE = MODE1 hello from task 1 hello from task 1 hello from task 1 hello from task 1 task2 selected different state, delete the previous task NEW STATE = MODE2 hello from task 2 task3 started from task2hello from task 3 which is created from task 2 hello from task 3 which is created from task 2 hello from task 2 hello from task 2 hello from task 3 which is created from task 2 hello from task 3 which is created from task 2 hello from task 2 task1 selected different state, delete the previous task NEW STATE = MODE1 hello from task 1 hello from task 3 which is created from task 2 hello from task 1 hello from task 3 which is created from task 2 hello from task 1 hello from task 3 which is created from task 2 hello from task 1 hello from task 3 which is created from task 2 hello from task 1 hello from task 3 which is created from task 2
根因与解决方案
问题根源:任务内部将void参数转为类对象时,最初使用了值拷贝写法*Controller controller_obj = *((Controller*)parameters);,修改的是临时对象的secondary_task_handle,原类对象的句柄始终为NULL,导致判断逻辑失效。
修改为指针引用写法Controller* controller_obj = (Controller*)parameters;后,直接操作原类对象的成员变量,功能恢复正常。
内容的提问来源于stack exchange,提问作者TheBestPlayer
相关产品推荐
相关产品推荐

