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 <noreply@anthropic.com>
This commit is contained in:
jpirnay
2026-03-31 11:00:20 +02:00
co-authored by Claude Sonnet 4.6
parent 0496969dc8
commit 6c9f497d2b
2 changed files with 6 additions and 0 deletions
+5
View File
@@ -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();
+1
View File
@@ -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()) {