環境
- VSCode
- ESP-IDF(VSCodeプラグイン)v5.4
- ESP32-WROOM-32E
発生したエラー
E (20414) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (20414) task_wdt: - IDLE1 (CPU 1)
E (20414) task_wdt: Tasks currently running:
E (20414) task_wdt: CPU 0: IDLE0
E (20414) task_wdt: CPU 1: liftoff_task
E (20414) task_wdt: Print CPU 1 backtrace
コードで行っていたこと
-
マルチコア利用
CPU0 と CPU1 にそれぞれタスクを割り振り、並列処理を実現しています -
高頻度ループ:
CPU1 上の liftoff_detection_task では、センサーの高速サンプリング(1000Hz)を行うため、高頻度でループする処理を実装していました -
ウォッチドッグのリセット
各タスク内で esp_task_wdt_reset() を呼び出し、ウォッチドッグにフィードを送るようにしていましたが、CPU1 の特定タスクが常に実行状態となっていたため、システム自動生成のアイドルタスク(IDLE1)に実行機会が与えられず、結果的にウォッチドッグがタイムアウトしていました
エラーの原因
ESP-IDF では、各 CPU に以下のようなタスクが自動的に生成されます。
IDLE タスク
CPU0 → IDLE0
CPU1 → IDLE1
これらは、システム上で実行可能なユーザタスクが存在しないときや、全タスクがブロック状態の場合に自動的に実行される低優先度タスクです。
問題となった点は、CPU1 上で高頻度のループ処理を実行するタスク(liftoff_detection_task)が常に CPU を占有してしまい、低優先度の IDLE1 に実行機会が与えられなかったことです。
その結果、IDLE1 はウォッチドッグに定期的なリセット(フィード)を送ることができず、WDT がタイムアウトしエラーを出力しました。
解決方法
1. ループ処理に適切な遅延処理を入れる
高頻度ループにvTaskDelay()
やtaskYIELD()
を入れ、CPUを他のタスクに譲るようにします。
while(1) {
// 処理
vTaskDelay(pdMS_TO_TICKS(1));
}
2. アイドルタスクのウォッチドック監視を無効にする
ESP-IDFの設定で、アイドルタスクに対するウォッチドック監視を無効にします。
sdkconfig
ファイルの
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
の値を変更します。
VSCodeのプラグインの場合、SDK Configuration Editor
から設定を変更することが可能です。
写真の、
- Watch CPU0 Idle Task
- Watch CPU1 Idle Task
のチェックを外し、Save
ボタンを押せば設定を変更できます。
おわりに
公式ドキュメントを読んでもピンとこなかったので、ChatGPT o3-mini-highに聞いたら教えてくれました...
助かりました...
参考サイト