Skip to content

Commit cbdf2b2

Browse files
davelee98claude
andauthored
fix(esp32): deinit BLE before esp_restart() to stop reboot boot-loop (#114)
* fix(esp32): deinit BLE before esp_restart() to stop reboot boot-loop reboot() (0x000F) and enterDFUMode() called esp_restart() while NimBLE was still initialized. esp_restart() resets the CPU but NOT the BT controller hardware, so on the next (software-reset) boot BLEDevice::init() (ble_init.cpp:255) tries to enable an already-enabled controller and aborts -> PANIC. The panic is itself a software reset, so the device boot-loops and only recovers on a physical power cycle (POWERON fully resets the controller). Observed on esp32-s3-N16R8 (Seeed reTerminal E1003) after Home Assistant sent 0x000F following a config write: crash logged consistently just after "Device name will be:" and before "Setting BLE MTU", looping until power-cycled. Pre-existing latent bug (old main had the identical reboot()); triggered by issuing a reboot command. Unrelated to the config-read ring-drain change. Fix: add esp32_ble_deinit_before_restart(), mirroring the deep-sleep teardown in enterDeepSleep() (main.cpp) -- stop advertising, delay, BLEDevice::deinit(true) (clearAll disables + releases the controller), esp32_ble_clear_handles() -- and call it before both esp_restart() sites. That clean controller shutdown is why sleep->wake already re-inits fine; reboot now does the same. NRF paths untouched (all new code is under #ifdef TARGET_ESP32). Builds: esp32-s3-N16R8, esp32-c3-N16, nrf52840custom. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(esp32): drop duplicate READ MSD banner in handleReadMSD CMD_READ_MSD logged "=== READ MSD COMMAND (0x0044) ===" twice per command: once at the dispatch case (communication.cpp) and again as the first line of handleReadMSD(). Remove the one inside the handler; the dispatch case still logs it exactly once. Cosmetic (serial log only), no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f29eab2 commit cbdf2b2

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

‎src/communication.cpp‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ void sendResponse(uint8_t* response, uint16_t len) {
259259
}
260260

261261
void handleReadMSD() {
262-
writeSerial("=== READ MSD COMMAND (0x0044) ===", true);
263262
uint8_t response[2 + 16];
264263
uint16_t responseLen = 0;
265264
response[responseLen++] = RESP_ACK;

‎src/device_control.cpp‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ extern "C" void bootloader_util_app_start(uint32_t start_addr);
2121
#include <esp_system.h>
2222
#include "driver/gpio.h"
2323
#include "esp32-hal-gpio.h"
24+
#include "ble_init.h" // BLEDevice/BLEServer/BLEAdvertising aliases + esp32_ble_clear_handles()
25+
extern BLEServer* pServer; // defined in main.cpp
2426
#endif
2527

2628
extern uint8_t rebootFlag;
@@ -108,13 +110,33 @@ void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
108110
resetPipeWriteState(); // clear any pipe transfer + reorder queue on disconnect
109111
}
110112

113+
#ifdef TARGET_ESP32
114+
// Tear NimBLE down before esp_restart(): esp_restart() resets the CPU but NOT the
115+
// BT controller hardware, so on the next (software-reset) boot BLEDevice::init()
116+
// tries to enable an already-enabled controller and aborts -> PANIC boot loop that
117+
// only a physical power cycle clears. Mirrors the deep-sleep teardown in
118+
// enterDeepSleep() (main.cpp), which is why sleep->wake re-inits cleanly.
119+
static void esp32_ble_deinit_before_restart() {
120+
if (pServer != nullptr) {
121+
BLEAdvertising* pAdvertising = pServer->getAdvertising();
122+
if (pAdvertising != nullptr) pAdvertising->stop();
123+
}
124+
delay(200);
125+
BLEDevice::deinit(true); // clearAll: disables + releases the BT controller
126+
esp32_ble_clear_handles();
127+
delay(100);
128+
writeSerial("BLE deinitialized before restart", true);
129+
}
130+
#endif
131+
111132
void reboot(){
112133
writeSerial("=== REBOOT COMMAND (0x000F) ===", true);
113134
delay(100);
114135
#ifdef TARGET_NRF
115136
NVIC_SystemReset();
116137
#endif
117138
#ifdef TARGET_ESP32
139+
esp32_ble_deinit_before_restart();
118140
esp_restart();
119141
#endif
120142
}
@@ -702,6 +724,7 @@ void enterDFUMode() {
702724
#ifdef TARGET_ESP32
703725
writeSerial("ESP32: Rebooting (OTA typically handled via WiFi)", true);
704726
delay(100);
727+
esp32_ble_deinit_before_restart();
705728
esp_restart();
706729
#endif
707730
}

0 commit comments

Comments
 (0)