Added enterDeepSleep() for NRF52 and shutdownPeripherals() for ESP32

This commit is contained in:
Kevin Le committed 2026-09-19 18:37:03 +07:00
1 parent 166fd6a941
commit d9c42964eb
41 files changed
+120 -115

No files matched your search

+1
View File
@@ -62,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.
+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
+2 -1
View File
@@ -64,8 +64,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
+23
View File
@@ -383,6 +383,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
@@ -52,6 +52,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;
@@ -43,11 +43,11 @@ public:
}
#endif
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
uint32_t button_pin = PIN_BUTTON1;
nrf_gpio_cfg_input(button_pin, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(button_pin, NRF_GPIO_PIN_SENSE_LOW);
NRF52Board::powerOff();
}
};
@@ -43,11 +43,11 @@ public:
}
#endif
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
uint32_t button_pin = PIN_BUTTON1;
nrf_gpio_cfg_input(button_pin, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(button_pin, NRF_GPIO_PIN_SENSE_LOW);
NRF52Board::powerOff();
}
};
@@ -43,11 +43,11 @@ public:
}
#endif
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
uint32_t button_pin = PIN_BUTTON1;
nrf_gpio_cfg_input(button_pin, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(button_pin, NRF_GPIO_PIN_SENSE_LOW);
NRF52Board::powerOff();
}
};
@@ -34,11 +34,11 @@ public:
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
uint32_t button_pin = PIN_BUTTON1;
nrf_gpio_cfg_input(button_pin, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(button_pin, NRF_GPIO_PIN_SENSE_LOW);
NRF52Board::powerOff();
}
};
-4
View File
@@ -31,10 +31,6 @@ void HeltecRC32Board::begin() {
}
}
void HeltecRC32Board::powerOff() {
enterDeepSleep(0);
}
void HeltecRC32Board::onBeforeTransmit() {
digitalWrite(P_LORA_TX_LED, HIGH);
}
-1
View File
@@ -21,7 +21,6 @@ public:
void begin();
void onBeforeTransmit() override;
void onAfterTransmit() override;
void powerOff() override;
uint16_t getBattMilliVolts() override;
bool setAdcMultiplier(float multiplier) override;
float getAdcMultiplier() const override { return adc_mult; }
+3 -2
View File
@@ -111,10 +111,11 @@ void T096Board::variant_shutdown() {
nrf_gpio_cfg_default(PIN_GPS_TX);
}
void T096Board::powerOff() {
void T096Board::shutdownPeripherals() {
NRF52Board::shutdownPeripherals();
loRaFEMControl.setSleepModeEnable();
nrf_gpio_cfg_default(PIN_GPS_EN); // 363uA down to 39uA
NRF52Board::powerOff();
}
const char* T096Board::getManufacturerName() const {
+1 -1
View File
@@ -24,7 +24,7 @@ public:
void onAfterTransmit(void) override;
uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override ;
void powerOff() override;
void shutdownPeripherals() override;
bool setLoRaFemLnaEnabled(bool enable) override;
bool canControlLoRaFemLna() const override;
bool isLoRaFemLnaEnabled() const override;
+3 -2
View File
@@ -97,9 +97,10 @@ void T1Board::variant_shutdown() {
digitalWrite(PIN_BAT_CTL, !ADC_CTRL_ENABLED);
}
void T1Board::powerOff() {
void T1Board::shutdownPeripherals() {
NRF52Board::shutdownPeripherals();
variant_shutdown();
NRF52Board::powerOff();
}
const char* T1Board::getManufacturerName() const {
+1 -1
View File
@@ -22,5 +22,5 @@ public:
void onAfterTransmit() override;
uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override;
void powerOff() override;
void shutdownPeripherals() override;
};
+3 -3
View File
@@ -46,11 +46,11 @@ public:
return "Heltec T114";
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
#ifdef LED_PIN
digitalWrite(LED_PIN, HIGH);
#endif
NRF52Board::powerOff();
}
};
@@ -88,7 +88,9 @@ const char* HeltecTowerV2Board::getManufacturerName() const {
return "Heltec Tower V2";
}
void HeltecTowerV2Board::powerOff() {
void HeltecTowerV2Board::shutdownPeripherals() {
NRF52Board::shutdownPeripherals();
pinMode(PIN_GPS_EN, OUTPUT);
digitalWrite(PIN_GPS_EN, !PIN_GPS_EN_ACTIVE);
pinMode(PIN_GPS_STANDBY, OUTPUT);
@@ -99,5 +101,4 @@ void HeltecTowerV2Board::powerOff() {
pinMode(PIN_BAT_CTL, OUTPUT);
digitalWrite(PIN_BAT_CTL, LOW);
variant_shutdown();
sd_power_system_off();
}
}
@@ -20,5 +20,5 @@ public:
void onAfterTransmit() override;
uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override;
void powerOff() override;
void shutdownPeripherals() override;
};
@@ -35,12 +35,12 @@ void HeltecTrackerV2Board::begin() {
loRaFEMControl.setRxModeEnable();
}
void HeltecTrackerV2Board::powerOff() {
void HeltecTrackerV2Board::shutdownPeripherals() {
ESP32Board::shutdownPeripherals();
// Turn off PA
digitalWrite(P_LORA_PA_POWER, LOW);
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
ESP32Board::powerOff();
}
uint16_t HeltecTrackerV2Board::getBattMilliVolts() {
@@ -16,7 +16,7 @@ public:
void begin();
void onBeforeTransmit(void) override;
void onAfterTransmit(void) override;
void powerOff() override;
void shutdownPeripherals() override;
uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override ;
bool setLoRaFemLnaEnabled(bool enable) override;
+3 -3
View File
@@ -32,12 +32,12 @@ void HeltecV4Board::begin() {
loRaFEMControl.setRxModeEnable();
}
void HeltecV4Board::powerOff() {
void HeltecV4Board::shutdownPeripherals() {
ESP32Board::shutdownPeripherals();
// Turn off PA
digitalWrite(P_LORA_PA_POWER, LOW);
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
ESP32Board::powerOff();
}
uint16_t HeltecV4Board::getBattMilliVolts() {
+1 -1
View File
@@ -22,7 +22,7 @@ public:
void begin();
void onBeforeTransmit(void) override;
void onAfterTransmit(void) override;
void powerOff() override;
void shutdownPeripherals() override;
bool setLoRaFemLnaEnabled(bool enable) override;
bool canControlLoRaFemLna() const override;
bool isLoRaFemLnaEnabled() const override;
+3 -23
View File
@@ -39,30 +39,10 @@ void HeltecV4R8Board::onAfterTransmit(void) {
loRaFEMControl.setRxModeEnable();
}
void HeltecV4R8Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
void HeltecV4R8Board::shutdownPeripherals() {
ESP32Board::shutdownPeripherals();
loRaFEMControl.setRxModeEnableWhenMCUSleep();
if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH);
} else {
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH);
}
if (secs > 0) {
esp_sleep_enable_timer_wakeup(secs * 1000000);
}
esp_deep_sleep_start();
}
void HeltecV4R8Board::powerOff() {
enterDeepSleep(0);
}
uint16_t HeltecV4R8Board::getBattMilliVolts() {
+1 -2
View File
@@ -23,8 +23,7 @@ public:
void begin();
void onBeforeTransmit(void) override;
void onAfterTransmit(void) override;
void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1);
void powerOff() override;
void shutdownPeripherals() override;
uint16_t getBattMilliVolts() override;
bool setAdcMultiplier(float multiplier) override {
if (multiplier == 0.0f) {
+3 -3
View File
@@ -47,7 +47,9 @@ const char* TBeam1WBoard::getManufacturerName() const {
return "LilyGo T-Beam 1W";
}
void TBeam1WBoard::powerOff() {
void TBeam1WBoard::shutdownPeripherals() {
ESP32Board::shutdownPeripherals();
// Turn off radio LNA (CTRL pin must be LOW when not receiving)
digitalWrite(SX126X_RXEN, LOW);
@@ -58,8 +60,6 @@ void TBeam1WBoard::powerOff() {
// Turn off LED and fan
digitalWrite(LED_PIN, LOW);
digitalWrite(FAN_CTRL_PIN, LOW);
ESP32Board::powerOff();
}
void TBeam1WBoard::setFanEnabled(bool enabled) {
+1 -1
View File
@@ -37,7 +37,7 @@ public:
void onAfterTransmit() override;
uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override;
void powerOff() override;
void shutdownPeripherals() override;
// Fan control methods
void setFanEnabled(bool enabled);
+2 -4
View File
@@ -34,7 +34,8 @@ public:
void reboot() override { NVIC_SystemReset(); }
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
#ifdef PIN_USER_BTN
while (digitalRead(PIN_USER_BTN) == LOW) {
@@ -59,8 +60,5 @@ public:
#ifdef PIN_USER_BTN
nrf_gpio_cfg_sense_input(g_ADigitalPinMap[PIN_USER_BTN], NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
#endif
NRF52Board::powerOff();
}
};
+3 -3
View File
@@ -46,7 +46,9 @@ public:
return 0;
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
#ifdef HAS_GPS
digitalWrite(GPS_VRTC_EN, LOW);
digitalWrite(GPS_RESET, LOW);
@@ -81,7 +83,5 @@ public:
#ifdef BUTTON_PIN
nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);
#endif
sd_power_system_off();
}
};
@@ -45,7 +45,9 @@ public:
return "Minewsemi";
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
#ifdef HAS_GPS
digitalWrite(GPS_VRTC_EN, LOW);
digitalWrite(GPS_RESET, LOW);
@@ -65,7 +67,6 @@ public:
#ifdef BUTTON_PIN
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(BUTTON_PIN), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
#endif
NRF52Board::powerOff();
}
#if defined(P_LORA_TX_LED)
+2
View File
@@ -20,6 +20,8 @@ public:
#ifdef NRF52_POWER_MANAGEMENT
void powerOff() override {
shutdownPeripherals();
initiateShutdown(SHUTDOWN_REASON_USER);
}
#endif
+3 -3
View File
@@ -43,7 +43,9 @@ public:
const char *getManufacturerName() const override { return "Nano G2 Ultra"; }
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
// put GPS chip to sleep
digitalWrite(PIN_GPS_STANDBY, LOW);
// TODO: unset buzzer to prevent notification circuit activating on hibernate
@@ -51,7 +53,5 @@ public:
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(PIN_USER_BTN), NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_SENSE_LOW);
NRF52Board::powerOff();
}
};
@@ -40,7 +40,9 @@ public:
return "RAK WisMesh Tag";
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
#ifdef BUZZER_EN
digitalWrite(BUZZER_EN, LOW);
#endif
@@ -68,7 +70,5 @@ public:
// configure button press to wake up when in powered off state
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(BUTTON_PIN), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
#endif
NRF52Board::powerOff();
}
};
+7 -1
View File
@@ -37,7 +37,9 @@ public:
return "Seeed SenseCap Solar";
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
digitalWrite(LED_WHITE, LOW);
digitalWrite(LED_BLUE, LOW);
@@ -50,6 +52,10 @@ public:
// Keep pull-up enabled in system-off so the wake line doesn't float low.
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(g_ADigitalPinMap[PIN_BUTTON1]), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
#endif
}
void powerOff() override {
shutdownPeripherals();
#ifdef NRF52_POWER_MANAGEMENT
initiateShutdown(SHUTDOWN_REASON_USER);
+3 -3
View File
@@ -1,6 +1,8 @@
#include "StationG3Board.h"
void StationG3Board::powerOff() {
void StationG3Board::shutdownPeripherals() {
ESP32Board::shutdownPeripherals();
loRaFEMControl.setSleepModeEnable();
#ifdef P_PA1_EN
rtc_gpio_hold_en((gpio_num_t)P_PA1_EN);
@@ -9,8 +11,6 @@ void StationG3Board::powerOff() {
#ifdef P_PRIMARY_LNA_EN
rtc_gpio_hold_en((gpio_num_t)P_PRIMARY_LNA_EN);
#endif
ESP32Board::powerOff();
}
bool StationG3Board::setLoRaFemLnaEnabled(bool enable) {
+1 -1
View File
@@ -50,7 +50,7 @@ public:
bool canControlLoRaFemPaGain() const override;
bool isLoRaFemPaGainEnabled() const override;
void powerOff() override;
void shutdownPeripherals() override;
uint16_t getBattMilliVolts() override {
return 0;
+3 -3
View File
@@ -49,7 +49,9 @@ public:
return 0;
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
#ifdef HAS_GPS
digitalWrite(GPS_VRTC_EN, LOW);
digitalWrite(GPS_RESET, LOW);
@@ -87,7 +89,5 @@ public:
#ifdef BUTTON_PIN
nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);
#endif
NRF52Board::powerOff();
}
};
+2 -4
View File
@@ -32,14 +32,12 @@ public:
return "Elecrow ThinkNode-M1";
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
// turn off all leds, sd_power_system_off will not do this for us
#ifdef P_LORA_TX_LED
digitalWrite(P_LORA_TX_LED, LOW);
#endif
// power off board
NRF52Board::powerOff();
}
};
+3 -4
View File
@@ -42,13 +42,12 @@ public:
return 0;
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
// turn off all leds, sd_power_system_off will not do this for us
digitalWrite(PIN_LED_BLUE, !LED_STATE_ON);
digitalWrite(PIN_LED_GREEN, !LED_STATE_ON);
digitalWrite(PIN_LED_RED, !LED_STATE_ON);
// power off board
NRF52Board::powerOff();
}
};
+2 -4
View File
@@ -36,14 +36,12 @@ public:
return "Elecrow ThinkNode M6";
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
// turn off all leds, sd_power_system_off will not do this for us
#ifdef P_LORA_TX_LED
digitalWrite(P_LORA_TX_LED, LOW);
#endif
// power off board
NRF52Board::powerOff();
}
};
@@ -33,8 +33,4 @@ public:
const char* getManufacturerName() const override {
return "Seeed Wio Tracker L1";
}
void powerOff() override {
NRF52Board::powerOff();
}
};
+3 -3
View File
@@ -35,7 +35,9 @@ public:
return "Seeed Xiao-nrf52";
}
void powerOff() override {
void shutdownPeripherals() override {
NRF52Board::shutdownPeripherals();
// set led on and wait for button release before poweroff
digitalWrite(PIN_LED, LOW);
#ifdef PIN_USER_BTN
@@ -49,8 +51,6 @@ public:
// configure button press to wake up when in powered off state
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(g_ADigitalPinMap[PIN_USER_BTN]), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
#endif
NRF52Board::powerOff();
}
};