ESP32のマルチタスクを使う時に無限ループしない場合はvTaskDelete(NULL)が必要
これで1時間溶かしたので怒りのメモです。
環境はArduino core for the ESP32。
メインループをブロッキングしたくない場合、xTaskCreatePinnedToCoreを使ってタスクに処理を逃がすことができる
しかしこのコードは実行時にCore 0 panic'ed (IllegalInstruction). Exception was unhandled.と言われパニックで落ちる
スタックトレースをデコードして見てみても原因がさっぱり分からない
code: arduino
void blinkLED(){
xTaskCreatePinnedToCore(blinkLEDTask, "blinkLEDTask", 4096, NULL, 2, NULL, 0);
}
void blinkLEDTask(void* param){
M5.dis.drawpix(0, 0x000000);
delay(100);
M5.dis.drawpix(0, color);
delay(100);
M5.dis.drawpix(0, 0x000000);
delay(100);
M5.dis.drawpix(0, color);
}
タスクの終了時にvTaskDeleteを呼び出してタスクを閉じる必要がある
つまりこう
code: arduino
void blinkLEDTask(void* param){
M5.dis.drawpix(0, 0x000000);
delay(100);
M5.dis.drawpix(0, color);
delay(100);
M5.dis.drawpix(0, 0x000000);
delay(100);
M5.dis.drawpix(0, color);
vTaskDelete(NULL);
}
というのがxTaskCreatePinnedToCoreを使っている記事に載っていなかった
どこの記事でもタスク内でwhite(true)の無限ループをしていて、使い捨てしているものが無かった
xTaskCreatePinnedToCore 終了でググったらこのツイートが出てきて、vTaskDelete(null)を最後に呼び出すようにしたら解決した
vTaskDeleteで終了させることができる。
Create時点の引数でTaskHandle_t型の変数の参照を渡してハンドルを取得し、Delete時にハンドルを渡せばよい。
なるほど。
改めてEspressifの公式ドキュメントを見てみたら書いてあった
FreeRTOS task function has returned. In FreeRTOS, if a task function needs to terminate, it should call vTaskDelete() and delete itself, instead of returning.
自分の愚かさを確認したというのが今回のオチです。公式ドキュメントをちゃんと読みましょう。