You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 19:57:01