我正在开发一个 ESP32 项目,我需要连续循环读取亮度数据。 尽管遵循了各种建议,包括使用 tskIDLE_PRIORITY 创建任务和增加看门狗超时,但我仍然面临任务看门狗被触发的问题。下面是我的问题、代码以及我迄今为止所采取的步骤的详细描述。
ESP IDF 版本:5.2
运行我的代码时,任务看门狗会被触发并显示以下消息:
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
但是代码继续运行,看起来 WDT 没有阻塞。 例如,在菜单配置中将 WD 设置为 6 秒, 每 6 秒我就会有一个 WDT。 所以我的函数的实际执行时间为 +-22 秒,但按已用时间计时为 17 秒。
我尝试按照建议此处创建具有 tskIDLE_PRIORITY 的任务,但它没有解决问题。
然后我在 menuConfig 中将看门狗超时值从 6 秒增加到 20 秒,这暂时有效,因为我的循环需要 17.21 秒。然而,当测量次数增加到 200,000 次时,循环时间超过 20 秒,导致看门狗再次触发。
添加延迟(例如 10 毫秒)可以避免触发看门狗,但由于默认滴答周期为 10 毫秒,任何低于 10 毫秒的延迟都会导致无限循环。
代码片段:
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);
}
采取的步骤:
任何帮助或建议将不胜感激。谢谢!
这和Linux下编程不一样。 freeRTOS 默认没有循环调度。您的任务不会将控制权传递给调度程序(直到它结束),并且您不会重置看门狗 - 因此看门狗开始。你让 freeRTOS 陷入僵局
在循环中添加
vTaskDelay(1);
或 taskYIELD();
以让其他任务运行。