From df369d718b78efaee4655d8134f5b9b5b5693b35 Mon Sep 17 00:00:00 2001 From: Todd Herbert Date: Mon, 1 Apr 2024 06:39:55 +1300 Subject: [PATCH 1/5] Change wakeup source from EXT0 to GPIO --- src/sleep.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/sleep.cpp b/src/sleep.cpp index 2f4bd09e14..0a62b49626 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -312,13 +312,10 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r // assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK); #endif #ifdef BUTTON_PIN -#if SOC_PM_SUPPORT_EXT_WAKEUP - esp_sleep_enable_ext0_wakeup((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN), - LOW); // when user presses, this button goes low -#else + // The enableLoraInterrupt() method is using ext0_wakeup, so we are forced to use GPIO wakeup + gpio_num_t pin = (gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); + gpio_wakeup_enable(pin, GPIO_INTR_LOW_LEVEL); esp_sleep_enable_gpio_wakeup(); - gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); -#endif #endif enableLoraInterrupt(); #ifdef PMU_IRQ From e3f6fa74f2d4694bda8902811d46e4fd9c6cc3ba Mon Sep 17 00:00:00 2001 From: Todd Herbert Date: Mon, 1 Apr 2024 06:45:36 +1300 Subject: [PATCH 2/5] Avoid ISR issue on wake --- src/sleep.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sleep.cpp b/src/sleep.cpp index 0a62b49626..b9af65a497 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -314,6 +314,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r #ifdef BUTTON_PIN // The enableLoraInterrupt() method is using ext0_wakeup, so we are forced to use GPIO wakeup gpio_num_t pin = (gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); + gpio_intr_disable(pin); gpio_wakeup_enable(pin, GPIO_INTR_LOW_LEVEL); esp_sleep_enable_gpio_wakeup(); #endif @@ -339,6 +340,10 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r } assert(res == ESP_OK); + gpio_wakeup_disable(pin); + // Would have thought that need gpio_intr_enable() here, but nope.. + // Works fine without it; crashes with it. + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); #ifdef BUTTON_PIN if (cause == ESP_SLEEP_WAKEUP_GPIO) { From 2e9379336c53363dda3d961a2605232e468e3057 Mon Sep 17 00:00:00 2001 From: Todd Herbert Date: Mon, 1 Apr 2024 06:59:02 +1300 Subject: [PATCH 3/5] Detect press from wake reason, instead of digitalRead --- src/PowerFSM.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index b6e267e285..2a9da28890 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -102,23 +102,18 @@ static void lsIdle() powerFSM.trigger(EVENT_SERIAL_CONNECTED); break; + case ESP_SLEEP_WAKEUP_GPIO: + // GPIO wakeup is now used for all ESP32 devices during light sleep + powerFSM.trigger(EVENT_PRESS); + break; + default: - // We woke for some other reason (button press, device interrupt) - // uint64_t status = esp_sleep_get_ext1_wakeup_status(); + // We woke for some other reason (device interrupt?) LOG_INFO("wakeCause2 %d\n", wakeCause2); -#ifdef BUTTON_PIN - bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); -#else - bool pressed = false; -#endif - if (pressed) { // If we woke because of press, instead generate a PRESS event. - powerFSM.trigger(EVENT_PRESS); - } else { - // Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc) - // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code - powerFSM.trigger(EVENT_WAKE_TIMER); - } + // Let the NB state handle the IRQ (and that state will handle stuff like IRQs etc) + // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code + powerFSM.trigger(EVENT_WAKE_TIMER); break; } } else { From c5c52684af07d301b29dd1d5a89833fa96f8fc66 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Mon, 1 Apr 2024 08:07:12 +1300 Subject: [PATCH 4/5] Missing #ifdef Risky phone-typed commit --- src/sleep.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sleep.cpp b/src/sleep.cpp index b9af65a497..e91bda7827 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -340,9 +340,11 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r } assert(res == ESP_OK); +#ifdef BUTTON_PIN gpio_wakeup_disable(pin); // Would have thought that need gpio_intr_enable() here, but nope.. // Works fine without it; crashes with it. +#endif esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); #ifdef BUTTON_PIN @@ -408,4 +410,4 @@ void enableLoraInterrupt() gpio_wakeup_enable((gpio_num_t)RF95_IRQ, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high #endif } -#endif \ No newline at end of file +#endif From a26cb31cf823f2fe97f0f512a30632f11f62fecb Mon Sep 17 00:00:00 2001 From: Todd Herbert Date: Mon, 1 Apr 2024 15:31:25 +1300 Subject: [PATCH 5/5] Fix PowerFSM timed transition preventing light sleep Addresses https://github.com/meshtastic/firmware/issues/3517 --- src/PowerFSM.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 2a9da28890..0002a62b4f 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -343,9 +343,6 @@ void PowerFSM_setup() powerFSM.add_timed_transition(&statePOWER, &stateDARK, Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, "Screen-on timeout"); - powerFSM.add_timed_transition(&stateDARK, &stateDARK, - Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, - "Screen-on timeout"); // We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally) #ifdef ARCH_ESP32 @@ -356,11 +353,24 @@ void PowerFSM_setup() powerFSM.add_timed_transition(&stateNB, &stateLS, Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, "Min wake timeout"); + + // If ESP32 and using power-saving, timer mover from DARK to light-sleep + // Also serves purpose of the old DARK to DARK transition(?) See https://github.com/meshtastic/firmware/issues/3517 powerFSM.add_timed_transition( &stateDARK, &stateLS, Default::getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, "Bluetooth timeout"); + } else { + // If ESP32, but not using power-saving, check periodically if config has drifted out of stateDark + powerFSM.add_timed_transition(&stateDARK, &stateDARK, + Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), + NULL, "Screen-on timeout"); } +#else + // If not ESP32, light-sleep not used. Check periodically if config has drifted out of stateDark + powerFSM.add_timed_transition(&stateDARK, &stateDARK, + Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, + "Screen-on timeout"); #endif powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state