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

ESP32连续读取光度数据时Task Watchdog触发问题求助

ESP32 ESP-IDF 5.2 连续读取光度数据触发Task Watchdog问题解决建议

问题描述

基于ESP-IDF 5.2开发ESP32项目,需在连续循环中读取TSL2591光度数据,但始终触发Task Watchdog,提示IDLE0未及时复位。代码虽能继续运行,但实际执行时间远长于计时结果。延长看门狗超时至20秒仅临时有效,测量次数增至200000次时问题复现;添加10ms以上延迟可避免触发,但低于10ms会因默认tick周期导致无限循环。

错误日志

I (15255) MONIDAT: Measurement 86800: Luminosity: 3
I (15265) MONIDAT: Measurement 86900: Luminosity: 3
I (15285) MONIDAT: Measurement 87000: Luminosity: 3
I (15305) MONIDAT: Measurement 87100: Luminosity: 3
E (15305) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (15305) task_wdt:  - IDLE0 (CPU 0)
E (15305) task_wdt: Tasks currently running:
E (15305) task_wdt: CPU 0: main
E (15305) task_wdt: CPU 1: IDLE1
E (15305) task_wdt: Print CPU 0 (current core) backtrace

Backtrace: 0x4200D673:0x3FC93300 0x4200DA90:0x3FC93320 0x40377175:0x3FC93350 0x4200AF31:0x3FC99090 0x4200B10C:0x3FC990C0 0x4200B1D3:0x3FC99100 0x4200BE12:0x3FC99130 0x42008436:0x3FC991D0 0x4200849B:0x3FC99200 0x420085E9:0x3FC99240 0x4201B877:0x3FC992A0 0x4037A9E1:0x3FC992D0
0x4200d673: task_wdt_timeout_handling at C:/ESP/components/esp_system/task_wdt/task_wdt.c:441
0x4200da90: task_wdt_isr at C:/ESP/components/esp_system/task_wdt/task_wdt.c:515
0x40377175: _xt_lowint1 at C:/ESP/components/xtensa/xtensa_vectors.S:1240
0x4200af31: s_i2c_send_commands at C:/ESP/components/driver/i2c/i2c_master.c:433 (discriminator 1)
0x4200b10c: s_i2c_transaction_start at C:/ESP/components/driver/i2c/i2c_master.c:509
0x4200b1d3: s_i2c_synchronous_transaction at C:/ESP/components/driver/i2c/i2c_master.c:780
0x4200be12: i2c_master_transmit_receive at C:/ESP/components/driver/i2c/i2c_master.c:995
0x42008436: tsl2591_read_register at C:/ESP/examples/get-started/lisi_monidat/main/lisi_monidat.c:34
0x4200849b: measure_task at C:/ESP/examples/get-started/lisi_monidat/main/lisi_monidat.c:55
0x420085e9: app_main at C:/ESP/examples/get-started/lisi_monidat/main/lisi_monidat.c:98
0x4201b877: main_task at C:/ESP/components/freertos/app_startup.c:208
0x4037a9e1: vPortTaskWrapper at C:/ESP/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134        

I (15375) MONIDAT: Measurement 87200: Luminosity: 3
I (15385) MONIDAT: Measurement 87300: Luminosity: 3
I (15405) MONIDAT: Measurement 87400: Luminosity: 3
I (15425) MONIDAT: Measurement 87500: Luminosity: 3

核心代码片段

void measure_task(i2c_master_dev_handle_t dev_handle)
{
    uint8_t data[2];
    int num_measurements = 100000;
    int64_t start_time = esp_timer_get_time();

    for (int i = 0; i < num_measurements; i++)
    {
        ESP_ERROR_CHECK(tsl2591_read_register(TSL2591_REGISTER_CHAN0_LOW, data, 2,dev_handle));
        uint16_t luminosity = (data[1] << 8) | data[0];
        // Optionally log every 1000th measurement to avoid overwhelming the log
        if (i % 100 == 0) {
        ESP_LOGI(TAG, "Measurement %d: Luminosity: %d", i, luminosity);
        }
    }

    int64_t end_time = esp_timer_get_time();
    float elapsed_time_sec = (end_time - start_time) / 1000000.0;
    ESP_LOGI(TAG, "Completed %d measurements in %.2f seconds good job", num_measurements, elapsed_time_sec);

}

已尝试方案

  • 创建tskIDLE_PRIORITY任务,无效
  • 延长看门狗超时至20秒,仅临时解决,增加测量次数后复现
  • 添加10ms以上延迟可避免触发,但低于10ms会导致无限循环
  • 将任务绑定到核心1,无效
  • 提高任务优先级,无效

解决方案建议

1. 主动让出CPU,给IDLE任务运行机会

Task Watchdog触发的核心原因是IDLE0任务长时间无法获得CPU时间复位看门狗。在循环中加入任务切换指令,让IDLE任务有执行窗口:

for (int i = 0; i < num_measurements; i++)
{
    ESP_ERROR_CHECK(tsl2591_read_register(...));
    // ... 光度数据处理 ...
    // 每N次读取后主动让出CPU
    if (i % 100 == 0) {
        taskYIELD(); // 无延迟切换,适合高频采样
        // 或 vTaskDelay(0); 效果与taskYIELD()一致
    }
}

2. 配置I2C传输超时,避免无限阻塞

从backtrace看,I2C同步传输是阻塞式的,若总线异常会导致任务长时间占用CPU。初始化I2C时设置超时:

i2c_master_dev_config_t dev_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = TSL2591_ADDR,
    .scl_speed_hz = 400000,
    .timeout_ms = 100, // 设置传输超时时间
};
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_handle, &dev_cfg, &dev_handle));

3. 拆分长循环为批次处理

将大循环拆分为多个小批次,每批次执行完后让出CPU,平衡采样效率与系统稳定性:

void measure_task(i2c_master_dev_handle_t dev_handle)
{
    uint8_t data[2];
    int total_measurements = 200000;
    int batch_size = 1000; // 每批次处理1000次
    int64_t start_time = esp_timer_get_time();

    for (int i = 0; i < total_measurements; i++)
    {
        ESP_ERROR_CHECK(tsl2591_read_register(TSL2591_REGISTER_CHAN0_LOW, data, 2, dev_handle));
        uint16_t luminosity = (data[1] << 8) | data[0];
        if (i % 100 == 0) {
            ESP_LOGI(TAG, "Measurement %d: Luminosity: %d", i, luminosity);
        }
        // 每批次结束后让出CPU
        if ((i + 1) % batch_size == 0) {
            taskYIELD();
        }
    }

    int64_t end_time = esp_timer_get_time();
    float elapsed_time_sec = (end_time - start_time) / 1000000.0;
    ESP_LOGI(TAG, "Completed %d measurements in %.2f seconds", total_measurements, elapsed_time_sec);
}

4. 调整TSL2591采样配置

通过传感器自身配置降低读取频率,减少CPU占用:

// 设置积分时间为100ms,低增益(根据实际场景调整)
tsl2591_set_integration_time(dev_handle, TSL2591_INTEGRATIONTIME_100MS);
tsl2591_set_gain(dev_handle, TSL2591_GAIN_LOW);

5. 临时禁用IDLE0看门狗(不推荐生产环境)

仅用于调试,禁用CPU0的IDLE任务看门狗监控:

task_wdt_config_t twdt_config = {
    .timeout_ms = 20000,
    .idle_core_mask = (1 << 1), // 仅监控CPU1的IDLE任务
    .trigger_panic = false,
};
task_wdt_init(&twdt_config);

内容的提问来源于stack exchange,提问作者Harith 75

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:39:50