Browse Source
Merge pull request #1562 from oltaco/nrf52-sleep-repeater
Add Low-Power Sleep for nRF52 Boards
pull/1597/head
ripplebiz
4 months ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with
33 additions and
3 deletions
-
examples/simple_repeater/main.cpp
-
src/helpers/NRF52Board.cpp
-
src/helpers/NRF52Board.h
|
|
|
@ -127,14 +127,17 @@ void loop() { |
|
|
|
#endif |
|
|
|
rtc_clock.tick(); |
|
|
|
|
|
|
|
if (the_mesh.getNodePrefs()->powersaving_enabled && // To check if power saving is enabled
|
|
|
|
the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep
|
|
|
|
if (!the_mesh.hasPendingWork()) { // No pending work. Safe to sleep
|
|
|
|
if (the_mesh.getNodePrefs()->powersaving_enabled && !the_mesh.hasPendingWork()) { |
|
|
|
#if defined(NRF52_PLATFORM) |
|
|
|
board.sleep(1800); // nrf ignores seconds param, sleeps whenever possible
|
|
|
|
#else |
|
|
|
if (the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep
|
|
|
|
board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet
|
|
|
|
lastActive = millis(); |
|
|
|
nextSleepinSecs = 5; // Default: To work for 5s and sleep again
|
|
|
|
} else { |
|
|
|
nextSleepinSecs += 5; // When there is pending work, to work another 5s
|
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -251,6 +251,32 @@ void NRF52BoardDCDC::begin() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void NRF52Board::sleep(uint32_t secs) { |
|
|
|
// 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 |
|
|
|
|
|
|
|
// On nRF52, we use event-driven sleep instead of timed sleep
|
|
|
|
// The 'secs' parameter is ignored - we wake on any interrupt
|
|
|
|
uint8_t sd_enabled = 0; |
|
|
|
sd_softdevice_is_enabled(&sd_enabled); |
|
|
|
|
|
|
|
if (sd_enabled) { |
|
|
|
// first call processes pending softdevice events, second call sleeps.
|
|
|
|
sd_app_evt_wait(); |
|
|
|
sd_app_evt_wait(); |
|
|
|
} else { |
|
|
|
// softdevice is disabled, use raw WFE
|
|
|
|
__SEV(); |
|
|
|
__WFE(); |
|
|
|
__WFE(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Temperature from NRF52 MCU
|
|
|
|
float NRF52Board::getMCUTemperature() { |
|
|
|
NRF_TEMP->TASKS_START = 1; // Start temperature measurement
|
|
|
|
|
|
|
|
@ -51,6 +51,7 @@ public: |
|
|
|
virtual float getMCUTemperature() override; |
|
|
|
virtual void reboot() override { NVIC_SystemReset(); } |
|
|
|
virtual bool startOTAUpdate(const char *id, char reply[]) override; |
|
|
|
virtual void sleep(uint32_t secs) override; |
|
|
|
|
|
|
|
#ifdef NRF52_POWER_MANAGEMENT |
|
|
|
bool isExternalPowered() override; |
|
|
|
|