ESP32 Arduino环境下类中FreeRTOS任务传参错误问题求助
问题:ESP32类中向FreeRTOS任务传递参数输出始终为0.00
使用ESP32开发板与Arduino IDE,尝试在类中向FreeRTOS任务传递浮点参数,但任务中输出结果始终为0.00。以下是代码示例:
class testClass { public: testClass(/*parameters*/){ //Do some stuff... } private: TaskHandle_t testTask; static void testTaskFunction (void * pvParameters) { float *number = (float *) pvParameters; String stringifiedNumber; stringifiedNumber = String(*number); Serial.println(stringifiedNumber); // Output 2 Serial.println(*number); // Output 3 vTaskDelete(NULL); // Must be there, otherwise there will be an error because the function is finished but the task still exists. Here the task is deleted and the function is aborted. } public: void testFunction (float number) { Serial.println(number); // Output 1 xTaskCreatePinnedToCore( testTaskFunction, // Function to implement the task "testTask", // Name of the task 10000, // Stack size in words (void *) &number, // Task input parameter 2, // Priority of the task &testTask, // Task handle. 0); // Core where the task should run } }; testClass testInstance1; testClass testInstance2; void setup() { // put your setup code here, to run once: Serial.begin(115200); } void loop() { // put your main code here, to run repeatedly: for (float i = -20; i < 30; i += 0.1) { testInstance1.testFunction(i); delay(1000); testInstance2.testFunction(i + 21); delay(1000); } }
输出结果(不含注释):
ets Jun 8 2016 00:22:57 rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0030,len:1416 load:0x40078000,len:14804 load:0x40080400,len:4 load:0x40080404,len:3356 entry 0x4008059c -20.00 // Output 1 (testInstance1) 0.00 // Output 2 (testInstance1) 0.00 // Output 3 (testInstance1) 1.00 // Output 1 (testInstance2) 0.00 // Output 2 (testInstance2) 0.00 // Output 3 (testInstance2) -19.90 // ... 0.00 0.00 1.10 0.00 0.00 -19.80 0.00 0.00 1.20 0.00 0.00 -19.70 0.00 0.00 1.30 0.00 0.00 -19.60 0.00 0.00 1.40 0.00 0.00 -19.50 0.00 0.00 1.50 0.00 0.00 -19.40 0.00 0.00 1.60 0.00 0.00 -19.30 0.00 0.00 1.70 0.00 0.00
已尝试的方法:
- 移除另一个类实例后功能恢复正常,但这并非可行方案
- 调整delay的时长也没有效果
解答
问题核心是传递了局部变量的地址:
在testFunction中,number是函数的局部参数,存储在栈内存中。当testFunction执行完毕返回后,该局部变量的内存空间会被释放或被后续代码覆盖。而FreeRTOS任务创建后不一定立即执行,等到任务运行时,&number指向的内存已经失效,读取到的就是随机值或0.00。移除一个类实例后偶尔正常,只是内存覆盖的概率降低,并非可靠解决办法。
提供两种修复方案:
方案1:直接传递值(适合单个基础类型)
ESP32中float和void*的内存大小均为4字节,可以直接把浮点值转换为指针类型传递,任务中再转换回浮点值:
修改testFunction的参数传递:
xTaskCreatePinnedToCore( testTaskFunction, "testTask", 10000, (void *) number, // 直接传递值而非地址 2, &testTask, 0);
修改任务函数:
static void testTaskFunction (void * pvParameters) { float number = (float) pvParameters; // 将指针转换回浮点值 String stringifiedNumber = String(number); Serial.println(stringifiedNumber); Serial.println(number); vTaskDelete(NULL); }
方案2:动态分配内存(适合复杂类型/多参数)
通过malloc分配堆内存存储参数,任务使用完成后释放内存,避免局部变量失效问题:
修改testFunction:
void testFunction (float number) { Serial.println(number); float* param = (float*)malloc(sizeof(float)); *param = number; xTaskCreatePinnedToCore( testTaskFunction, "testTask", 10000, param, // 传递动态分配的内存地址 2, &testTask, 0); }
修改任务函数,使用后释放内存:
static void testTaskFunction (void * pvParameters) { float *number = (float *) pvParameters; String stringifiedNumber = String(*number); Serial.println(stringifiedNumber); Serial.println(*number); free(number); // 释放动态分配的内存,避免泄漏 vTaskDelete(NULL); }
额外注意事项
- 任务名称建议唯一,可添加实例标识避免冲突
- 栈大小可根据实际需求调整,10000 words对于简单任务过大,可改为2048左右
内容的提问来源于stack exchange,提问作者Pr77Pr77
相关产品推荐
相关产品推荐

