fix: refactor wakeup detection logic and improve logging for reset reasons

This commit is contained in:
Arthur Tazhitdinov 2026-01-28 01:15:39 +05:00
parent 75319cb807
commit 5f4de8d6c8
3 changed files with 81 additions and 25 deletions

View File

@ -24,12 +24,13 @@ bool HalGPIO::wasAnyReleased() const { return inputMgr.wasAnyReleased(); }
unsigned long HalGPIO::getHeldTime() const { return inputMgr.getHeldTime(); }
void HalGPIO::startDeepSleep() {
esp_deep_sleep_enable_gpio_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_GPIO_WAKEUP_GPIO_LOW);
// Ensure that the power button has been released to avoid immediately turning back on if you're holding it
while (inputMgr.isPressed(BTN_POWER)) {
delay(50);
inputMgr.update();
}
// Arm the wakeup trigger *after* the button is released
esp_deep_sleep_enable_gpio_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_GPIO_WAKEUP_GPIO_LOW);
// Enter Deep Sleep
esp_deep_sleep_start();
}
@ -44,16 +45,24 @@ bool HalGPIO::isUsbConnected() const {
return digitalRead(UART0_RXD) == HIGH;
}
bool HalGPIO::isWakeupByPowerButton() const {
HalGPIO::WakeupReason HalGPIO::getWakeupReason() const {
const bool usbConnected = isUsbConnected();
const auto wakeupCause = esp_sleep_get_wakeup_cause();
const auto resetReason = esp_reset_reason();
return ((wakeupCause == ESP_SLEEP_WAKEUP_UNDEFINED && resetReason == ESP_RST_POWERON && !usbConnected) ||
(wakeupCause == ESP_SLEEP_WAKEUP_GPIO && resetReason == ESP_RST_DEEPSLEEP && usbConnected));
}
bool HalGPIO::isWakeUpAfterFlash() const {
return esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_UNDEFINED &&
esp_reset_reason() == ESP_RST_UNKNOWN &&
isUsbConnected();
if ((wakeupCause == ESP_SLEEP_WAKEUP_UNDEFINED && resetReason == ESP_RST_POWERON && !usbConnected) ||
(wakeupCause == ESP_SLEEP_WAKEUP_GPIO && resetReason == ESP_RST_DEEPSLEEP && usbConnected)) {
return WakeupReason::PowerButton;
}
if (wakeupCause == ESP_SLEEP_WAKEUP_UNDEFINED &&
resetReason == ESP_RST_UNKNOWN &&
usbConnected) {
return WakeupReason::AfterFlash;
}
if (wakeupCause == ESP_SLEEP_WAKEUP_UNDEFINED &&
resetReason == ESP_RST_POWERON &&
usbConnected) {
return WakeupReason::AfterUSBPower;
}
return WakeupReason::Other;
}

View File

@ -47,11 +47,14 @@ class HalGPIO {
// Check if USB is connected
bool isUsbConnected() const;
// Check if wakeup was caused by power button press
bool isWakeupByPowerButton() const;
enum class WakeupReason {
PowerButton,
AfterFlash,
AfterUSBPower,
Other
};
// Check if wakeup was caused by flashing (hard reset via RTS pin)
bool isWakeUpAfterFlash() const;
WakeupReason getWakeupReason() const;
// Button indices
static constexpr uint8_t BTN_BACK = 0;

View File

@ -294,18 +294,22 @@ void setup() {
SETTINGS.loadFromFile();
KOREADER_STORE.loadFromFile();
if (gpio.isWakeupByPowerButton()) {
switch (gpio.getWakeupReason()) {
case HalGPIO::WakeupReason::PowerButton:
// For normal wakeups, verify power button press duration
Serial.printf("[%lu] [ ] Verifying power button press duration\n", millis());
verifyPowerButtonDuration();
} else if (gpio.isWakeUpAfterFlash()) {
// After flashing, just proceed to boot
Serial.printf("[%lu] [ ] Wake up after flash detected, proceeding to boot\n", millis());
} else {
break;
case HalGPIO::WakeupReason::AfterUSBPower:
// If USB power caused a cold boot, go back to sleep
Serial.printf("[%lu] [ ] No valid wakeup detected, entering deep sleep\n", millis());
Serial.printf("[%lu] [ ] Wakeup reason: After USB Power\n", millis());
gpio.startDeepSleep();
// This should never be hit as `startDeepSleep` calls esp_deep_sleep_start
break;
case HalGPIO::WakeupReason::AfterFlash:
// After flashing, just proceed to boot
case HalGPIO::WakeupReason::Other:
default:
break;
}
// First serial output only here to avoid timing inconsistencies for power button press duration verification
@ -313,6 +317,46 @@ void setup() {
setupDisplayAndFonts();
// log reset reason and wakeup cause
// log enum names as strings for easier reading in logs
// Convert enum values to readable strings for logs
auto resetReasonStr = [resetReason]() {
switch (resetReason) {
case ESP_RST_UNKNOWN: return "UNKNOWN";
case ESP_RST_POWERON: return "POWERON";
case ESP_RST_EXT: return "EXT";
case ESP_RST_SW: return "SW";
case ESP_RST_PANIC: return "PANIC";
case ESP_RST_INT_WDT: return "INT_WDT";
case ESP_RST_TASK_WDT:return "TASK_WDT";
case ESP_RST_WDT: return "WDT";
case ESP_RST_DEEPSLEEP: return "DEEPSLEEP";
case ESP_RST_BROWNOUT: return "BROWNOUT";
case ESP_RST_SDIO: return "SDIO";
default: return "OTHER";
}
}();
auto wakeupCauseStr = [wakeupCause]() {
switch (wakeupCause) {
case ESP_SLEEP_WAKEUP_UNDEFINED: return "UNDEFINED";
case ESP_SLEEP_WAKEUP_EXT0: return "EXT0";
case ESP_SLEEP_WAKEUP_EXT1: return "EXT1";
case ESP_SLEEP_WAKEUP_TIMER: return "TIMER";
case ESP_SLEEP_WAKEUP_TOUCHPAD: return "TOUCHPAD";
case ESP_SLEEP_WAKEUP_ULP: return "ULP";
case ESP_SLEEP_WAKEUP_GPIO: return "GPIO";
case ESP_SLEEP_WAKEUP_UART: return "UART";
default: return "OTHER";
}
}();
const std::string resetInfo =
std::string("Reset: ") + resetReasonStr + " Wakeup: " + wakeupCauseStr + " USB: " + (usbConnected ? "Yes" : "No");
enterNewActivity(
new FullScreenMessageActivity(renderer, mappedInputManager, resetInfo, EpdFontFamily::REGULAR));
delay(10000);
exitActivity();
enterNewActivity(new BootActivity(renderer, mappedInputManager));