Fix Task WDT crashes: LVGL priority starvation + BLE WDT false positives

Two root causes for frequent device reboots:

1. LVGL task (priority 2) starved loopTask (priority 1) on core 1.
   During heavy screen rendering, loopTask couldn't run for 30+ seconds,
   triggering the Task WDT. Fixed by lowering LVGL to priority 1 so
   FreeRTOS round-robins both tasks fairly.

2. BLE task was registered with the 30s Task WDT, but blocking NimBLE
   GATT operations (connect + service discovery + subscribe + read) can
   legitimately take 30-60s total. Removed BLE task from WDT since
   NimBLE has its own internal ~30s timeouts per GATT operation.

Also added ble_hs_synced() guards to write(), read(), notify(),
writeCharacteristic(), discoverServices(), and enableNotifications()
to prevent use-after-free on stale NimBLE client pointers during
host resets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
torlando-tech
2026-03-04 13:44:08 -05:00
parent d9411fb4bb
commit c80e63dee9
3 changed files with 50 additions and 17 deletions
+5 -5
View File
@@ -10,7 +10,6 @@
#ifdef ARDUINO
#include <Arduino.h>
#include <esp_heap_caps.h>
#include <esp_task_wdt.h>
#endif
using namespace RNS;
@@ -1136,12 +1135,13 @@ void BLEInterface::ble_task(void* param) {
BLEInterface* self = static_cast<BLEInterface*>(param);
Serial.printf("BLE task started on core %d\n", xPortGetCoreID());
// Subscribe BLE task to Task Watchdog — detects BLE deadlocks
esp_task_wdt_add(NULL);
// NOTE: BLE task is intentionally NOT subscribed to the FreeRTOS Task WDT.
// Blocking NimBLE GATT operations (service discovery, subscribe, read, write)
// each have ~30s internal timeouts. A full connect chain (connect + discover +
// enable notifications + identity read) can legitimately block 30-60s total,
// which exceeds the 30s WDT. NimBLE's own timeouts provide recovery.
while (true) {
esp_task_wdt_reset();
// Run the BLE loop (already has internal mutex protection)
self->loop();