乐鑫技术交流
直播中

闷~~

9年用户 759经验值
擅长:可编程逻辑
私信 关注
[问答]

vTaskDelete()删除正在打印日志的任务导致esp32卡死无法恢复要怎么处理?

实际的应用场景是录音的时候创建了一个任务去读i2s数据,放到一个ringbuf里,然后主任务从ringbuf里取数据进行降噪编码处理。
长跑测试发现设备在执行录音时偶然会发生死机现象,排查发现是读i2s数据的任务在结束前会调用ESP_LOG接口打印任务结束的日志,如果子任务正在打印日志时,被主任务调用vTaskDelete()销毁,会导致esp32卡死,且没有打印报错信息
在一段时间后(几十分钟甚至几个小时后),报错“ assert failed: vTaskPriorityDisinheritAftertimeout”,然后设备重启
关键部分的代码类似下面这段Code: Select all
#include #include "sdkconfig.h"#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "esp_system.h"#include "esp_spi_flash.h"#include "esp_log.h"static const char *TAG = "main";static void test_task(void *args){    while (1)    {        ESP_LOGI(TAG, "test_task working");    }        vTaskDelete(NULL);}void app_main(void){    while (1)    {        ESP_LOGI(TAG, "main task running");        TaskHandle_t test_task_handle = NULL;        xTaskCreate(test_task, "test_task", 1024 * 5, NULL, 10, &test_task_handle);        vTaskDelay(10);        vTaskDelete(test_task_handle);        vTaskDelay(100);    }            fflush(stdout);    esp_restart();}

                              

回帖(1)

晴兮晴兮

2024-6-17 17:49:42
在您描述的情况下,问题可能出在使用 `vTaskDelete()` 函数时,任务正在执行打印日志的操作。这可能导致ESP32的调度器无法正常工作,最终导致设备死机。为了解决这个问题,我们可以采取以下措施:

1. **使用互斥锁**:在执行打印日志操作之前,使用互斥锁(例如 `xSemaphoreCreateMutex()`)来确保在打印日志时,其他任务(如主任务)不能调用 `vTaskDelete()`。这样可以避免在打印日志时删除任务。

2. **异步日志系统**:考虑实现一个异步日志系统,将日志消息发送到一个队列中,然后由另一个低优先级的任务来处理这些日志消息。这样可以避免在关键任务中直接打印日志。

3. **延迟删除任务**:在 `vTaskDelete()` 调用之前,可以设置一个延迟,等待当前任务完成打印日志操作。例如,可以使用 `vTaskDelay()` 函数来实现这个延迟。

4. **检查任务状态**:在调用 `vTaskDelete()` 之前,可以使用 `eTaskGetState()` 函数来检查任务的状态。如果任务正在执行打印日志操作,可以等待任务状态变为非运行状态后再进行删除。

5. **使用断言**:在调用 `vTaskDelete()` 之前,使用断言来检查任务是否正在执行打印日志操作。如果正在执行,可以暂时不删除任务,等待合适的时机再进行删除。

6. **优化日志系统**:考虑优化您的日志系统,以减少在关键任务中打印日志的频率和复杂性。例如,可以使用更高效的日志记录方法,或者在非关键任务中处理日志。

7. **监控和调试**:使用ESP-IDF提供的调试工具,如GDB,来监控和调试您的应用程序。这可以帮助您更好地了解问题发生的原因和时机。

8. **更新ESP-IDF版本**:确保您使用的ESP-IDF版本是最新的,因为新版本可能修复了一些已知的问题和bug。

通过采取这些措施,您应该能够解决在使用 `vTaskDelete()` 时导致ESP32卡死的问题。同时,这也有助于提高您的应用程序的稳定性和可靠性。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分