BLE stability: desync connect cooldown prevents crash-on-connect

Add 30-second cooldown after NimBLE host desync recovery before
allowing new connection attempts. During desync, client->connect()
blocks waiting for a host-task completion event that never arrives,
causing WDT crashes. The cooldown skips connection attempts while
the host is desynced or recently recovered.

Also adds ESP reset reason logging at boot to diagnose crash types
(WDT, panic, brownout, etc.) in soak test logs.

Soak test results: Run 3 (before) had 17 reboots in ~4 hours with
a 12-crash-in-14-minutes loop. Run 4 (after) has 1 early reboot
then 19+ hours of continuous uptime with the same desync frequency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
torlando-tech
2026-03-03 18:34:40 -05:00
co-authored by Claude Opus 4.6
parent 74d832fb63
commit 2cc9441f0a
3 changed files with 34 additions and 0 deletions
@@ -859,6 +859,7 @@ bool NimBLEPlatform::startScan(uint16_t duration_ms) {
(reset_reason != 0 ? " (nimble_reason=" + std::to_string(reset_reason) + ")" : ""));
_host_desync_since = 0;
_host_reset_attempts = 0;
_last_desync_recovery = millis(); // Start cooldown before allowing connections
}
// Log GAP hardware state before checking
@@ -1014,6 +1015,14 @@ bool NimBLEPlatform::isScanning() const {
bool NimBLEPlatform::connect(const BLEAddress& address, uint16_t timeout_ms) {
NimBLEAddress nimAddr = toNimBLE(address);
// Skip connections during desync cooldown — connecting while the NimBLE
// stack is recovering from a desync can hang client->connect() (the host
// task can't process the completion event), leading to WDT crashes.
if (_host_desync_since != 0 || (_last_desync_recovery > 0 && millis() - _last_desync_recovery < DESYNC_CONNECT_COOLDOWN_MS)) {
DEBUG("NimBLEPlatform: Skipping connect during desync cooldown");
return false;
}
// Rate limit connections to avoid overwhelming the BLE stack
// Non-blocking: return false if too soon, caller can retry later
static unsigned long last_connect_time = 0;