From 6c9f497d2b2e871ad0894697c2805de708111c3b Mon Sep 17 00:00:00 2001 From: jpirnay Date: Tue, 31 Mar 2026 11:00:20 +0200 Subject: [PATCH] fix: release GPIO13 hold before re-entering deep sleep gpio_hold_en(GPIO13) called in startDeepSleep() persists after wake when keepClockAlive=true. A subsequent startDeepSleep() call (e.g. failed button verification) would silently fail to change GPIO13's level, leaving the MOSFET latched and trapping the device in a sleep/wake loop requiring a hardware reset. Release the individual and global holds at the top of startDeepSleep() so each sleep entry configures GPIO13 from a clean state. Also call gpio_deep_sleep_hold_dis() immediately after wake in setup() as a defensive measure. Co-Authored-By: Claude Sonnet 4.6 --- lib/hal/HalPowerManager.cpp | 5 +++++ src/main.cpp | 1 + 2 files changed, 6 insertions(+) diff --git a/lib/hal/HalPowerManager.cpp b/lib/hal/HalPowerManager.cpp index 989376ab..b30a7ff4 100644 --- a/lib/hal/HalPowerManager.cpp +++ b/lib/hal/HalPowerManager.cpp @@ -65,6 +65,11 @@ void HalPowerManager::startDeepSleep(HalGPIO& gpio, bool keepClockAlive) const { // at ~3-4 mA so the LP timer keeps running and RTC memory is preserved. // This allows HalClock to accurately compute elapsed sleep time on wake. constexpr gpio_num_t GPIO_SPIWP = GPIO_NUM_13; + // Release any GPIO hold from a previous sleep cycle (keepClockAlive=true leaves GPIO13 held after wake). + // Without this, gpio_set_level() below silently fails and GPIO13 is stuck in its prior state, + // causing the device to enter a sleep/wake loop that requires a hardware reset to escape. + gpio_hold_dis(GPIO_SPIWP); + gpio_deep_sleep_hold_dis(); gpio_set_direction(GPIO_SPIWP, GPIO_MODE_OUTPUT); gpio_set_level(GPIO_SPIWP, keepClockAlive ? 1 : 0); esp_sleep_config_gpio_isolate(); diff --git a/src/main.cpp b/src/main.cpp index e8a00a1a..6906af2f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -236,6 +236,7 @@ void setup() { HalSystem::begin(); gpio.begin(); powerManager.begin(); + gpio_deep_sleep_hold_dis(); // Release deep sleep GPIO hold state from previous sleep cycle // Only start serial if USB connected if (gpio.isUsbConnected()) {