Improved sleep() and added enterDeepSleep()

This commit is contained in:
Kevin Le committed 2026-10-17 23:08:46 +07:00
1 parent 3301a022d7
commit 552599fb34
5 files changed
+62 -9

No files matched your search

+11
View File
@@ -37,6 +37,15 @@
#define BRIDGE_DEBUG_PRINTLN(...) {}
#endif
#if POWERSAVING_DEBUG && ARDUINO
#include <Arduino.h>
#define POWERSAVING_DEBUG_PRINT(F, ...) Serial.printf("POWERSAVING: " F, ##__VA_ARGS__)
#define POWERSAVING_DEBUG_PRINTLN(F, ...) Serial.printf("POWERSAVING: " F "\n", ##__VA_ARGS__)
#else
#define POWERSAVING_DEBUG_PRINT(...) {}
#define POWERSAVING_DEBUG_PRINTLN(...) {}
#endif
namespace mesh {
#define BD_STARTUP_NORMAL 0 // getStartupReason() codes
@@ -53,6 +62,7 @@ public:
virtual void onAfterTransmit() { }
virtual void reboot() = 0;
virtual void powerOff() { /* no op */ }
virtual void enterDeepSleep(uint32_t secs) { /* no op */ }
// Called by example setup() functions to signal that boot is complete.
// Boards may override to stop a boot-indicator LED sequence or similar.
// Default no-op: boards that don't care need not implement anything.
@@ -90,6 +100,7 @@ public:
// Called from the example main loops. Lets a board feed its watchdog and
// run periodic housekeeping. Default no-op.
virtual void loop() { /* no op */ }
inline static uint32_t n_cad_busy = 0;
};
/**
+9 -5
View File
@@ -45,11 +45,7 @@ bool ESP32Board::startOTAUpdate(const char* id, char reply[]) {
}
#endif
void ESP32Board::powerOff() {
enterDeepSleep(0); // Do not wakeup
}
void ESP32Board::enterDeepSleep(uint32_t secs) {
void ESP32Board::shutdownPeripherals() {
// Power off the display if any
#ifdef DISPLAY_CLASS
display.turnOff();
@@ -74,6 +70,14 @@ void ESP32Board::enterDeepSleep(uint32_t secs) {
// Flush serial buffers
Serial.flush();
delay(100);
}
void ESP32Board::powerOff() {
enterDeepSleep(0); // Do not wakeup
}
void ESP32Board::enterDeepSleep(uint32_t secs) {
shutdownPeripherals();
// Clear stale wakeup sources to avoid ghost wakeup
// This is required when Power Management and automatic lightsleep are enabled
+18 -4
View File
@@ -21,6 +21,7 @@ class ESP32Board : public mesh::MainBoard {
protected:
uint8_t startup_reason;
bool inhibit_sleep = false;
uint32_t inhibit_sleep_until = 0;
static inline portMUX_TYPE sleepMux = portMUX_INITIALIZER_UNLOCKED;
public:
@@ -66,8 +67,9 @@ public:
return raw / 4;
}
virtual void shutdownPeripherals();
virtual void powerOff() override;
void enterDeepSleep(uint32_t secs);
virtual void enterDeepSleep(uint32_t secs) override;
uint32_t getIRQGpio() override {
return P_LORA_DIO_1; // default for SX1262
@@ -75,13 +77,13 @@ public:
void sleep(uint32_t secs) override {
// Skip if not allow to sleep
if (inhibit_sleep) {
if (inhibit_sleep || (int32_t)(inhibit_sleep_until - millis()) > 0) {
delay(1); // Give MCU to OTA to run
return;
}
// Set GPIO wakeup
gpio_num_t wakeupPin = (gpio_num_t)getIRQGpio();
gpio_num_t wakeupPin = (gpio_num_t)getIRQGpio();
// Configure timer wakeup
if (secs > 0) {
@@ -100,7 +102,10 @@ public:
// Configure GPIO wakeup
esp_sleep_enable_gpio_wakeup();
gpio_wakeup_enable((gpio_num_t)wakeupPin, GPIO_INTR_HIGH_LEVEL); // Wake up when receiving a LoRa packet
gpio_wakeup_enable(wakeupPin, GPIO_INTR_HIGH_LEVEL); // Wake up when receiving a LoRa packet
#if defined(PIN_USER_BTN) && (PIN_USER_BTN >= 0)
gpio_wakeup_enable((gpio_num_t)PIN_USER_BTN, GPIO_INTR_LOW_LEVEL); // Wakeup when pressing button
#endif
// MCU enters light sleep
esp_light_sleep_start();
@@ -108,6 +113,15 @@ public:
// Avoid ISR flood during wakeup due to HIGH LEVEL interrupt
gpio_wakeup_disable(wakeupPin);
gpio_set_intr_type(wakeupPin, GPIO_INTR_POSEDGE);
#if defined(PIN_USER_BTN) && (PIN_USER_BTN >= 0)
gpio_wakeup_disable((gpio_num_t)PIN_USER_BTN);
gpio_set_intr_type((gpio_num_t)PIN_USER_BTN, GPIO_INTR_POSEDGE);
// Check if waken up by PIN_USER_BTN
if (gpio_get_level((gpio_num_t)PIN_USER_BTN) == LOW) {
inhibit_sleep_until = millis() + 30000; // Do not sleep in the next 30s. Should be longer than OLED timeout
}
#endif
// Enable CPU interrupt servicing
portEXIT_CRITICAL(&sleepMux);
+23
View File
@@ -390,6 +390,29 @@ void NRF52Board::powerOff() {
}
}
void NRF52Board::enterDeepSleep(uint32_t secs) {
if (secs == 0) {
powerOff(); // Not wake up
} else {
shutdownPeripherals();
// Clear FPU interrupt flags to avoid insomnia
// see errata 87 for details
// https://docs.nordicsemi.com/bundle/errata_nRF52840_Rev3/page/ERR/nRF52840/Rev3/latest/anomaly_840_87.html
#if (__FPU_USED == 1)
__set_FPSCR(__get_FPSCR() & ~(0x0000009F));
(void)__get_FPSCR();
NVIC_ClearPendingIRQ(FPU_IRQn);
#endif
// Attemp to sleep
vTaskDelay(pdMS_TO_TICKS(secs * 1000));
// Reboot for a fresh recovery
reboot();
}
}
bool NRF52Board::getBootloaderVersion(char* out, size_t max_len) {
static const char BOOTLOADER_MARKER[] = "UF2 Bootloader ";
const uint8_t* flash = (const uint8_t*)0x000FB000; // earliest known info.txt location is 0xFB90B, latest is 0xFCC4B
+1
View File
@@ -54,6 +54,7 @@ public:
virtual void reboot() override { NVIC_SystemReset(); }
virtual void shutdownPeripherals();
virtual void powerOff() override;
virtual void enterDeepSleep(uint32_t secs) override;
virtual bool getBootloaderVersion(char* version, size_t max_len) override;
virtual bool startOTAUpdate(const char *id, char reply[]) override;
virtual void sleep(uint32_t secs) override;