From d9e7fd129be30c9062386f21909f1f24e8a6b2cb Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 11 Nov 2024 06:06:23 -0600 Subject: [PATCH] Don't attempt to save NodeDB on low-batt shutdown to prevent FS corruption --- src/Power.cpp | 2 +- src/PowerFSM.cpp | 20 ++++++++++++------- src/modules/PositionModule.cpp | 2 +- src/modules/PowerStressModule.cpp | 2 +- .../Telemetry/EnvironmentTelemetry.cpp | 2 +- src/modules/Telemetry/HealthTelemetry.cpp | 2 +- src/modules/Telemetry/PowerTelemetry.cpp | 2 +- src/sleep.cpp | 6 ++++-- src/sleep.h | 2 +- 9 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/Power.cpp b/src/Power.cpp index ab09cd08c5..4e5cf0f2cd 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -614,7 +614,7 @@ void Power::shutdown() #ifdef PIN_LED3 ledOff(PIN_LED3); #endif - doDeepSleep(DELAY_FOREVER, false); + doDeepSleep(DELAY_FOREVER, false, false); #endif } diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 7aa454d344..00dd6c942b 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -55,9 +55,14 @@ static void sdsEnter() { LOG_DEBUG("State: SDS"); // FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw - doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false); + doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, false); } +static void lowBattSDSEnter() +{ + LOG_DEBUG("State: Lower batt SDS"); + doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, true); +} extern Power *power; static void shutdownEnter() @@ -247,6 +252,7 @@ static void bootEnter() State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN"); State stateSDS(sdsEnter, NULL, NULL, "SDS"); +State stateLowBattSDS(lowBattSDSEnter, NULL, NULL, "SDS"); State stateLS(lsEnter, lsIdle, lsExit, "LS"); State stateNB(nbEnter, NULL, NULL, "NB"); State stateDARK(darkEnter, NULL, NULL, "DARK"); @@ -291,12 +297,12 @@ void PowerFSM_setup() "Press"); // Allow button to work while in serial API // Handle critically low power battery by forcing deep sleep - powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); - powerFSM.add_transition(&stateLS, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); - powerFSM.add_transition(&stateNB, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); - powerFSM.add_transition(&stateDARK, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); - powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); - powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); + powerFSM.add_transition(&stateBOOT, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); + powerFSM.add_transition(&stateLS, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); + powerFSM.add_transition(&stateNB, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); + powerFSM.add_transition(&stateDARK, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); + powerFSM.add_transition(&stateON, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); + powerFSM.add_transition(&stateSERIAL, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); // Handle being told to power off powerFSM.add_transition(&stateBOOT, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown"); diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index f80d3eb679..fc15aabb62 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -364,7 +364,7 @@ int32_t PositionModule::runOnce() sleepOnNextExecution = false; uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(config.position.position_broadcast_secs); LOG_DEBUG("Sleep for %ims, then awaking to send position again", nightyNightMs); - doDeepSleep(nightyNightMs, false); + doDeepSleep(nightyNightMs, false, false); } meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum()); diff --git a/src/modules/PowerStressModule.cpp b/src/modules/PowerStressModule.cpp index 80b14c756c..d487fe6fce 100644 --- a/src/modules/PowerStressModule.cpp +++ b/src/modules/PowerStressModule.cpp @@ -111,7 +111,7 @@ int32_t PowerStressModule::runOnce() setBluetoothEnable(true); break; case meshtastic_PowerStressMessage_Opcode_CPU_DEEPSLEEP: - doDeepSleep(sleep_msec, true); + doDeepSleep(sleep_msec, true, true); break; case meshtastic_PowerStressMessage_Opcode_CPU_FULLON: { uint32_t start_msec = millis(); diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index c18944ebd5..4ef68d4b7c 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -74,7 +74,7 @@ int32_t EnvironmentTelemetryModule::runOnce() uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval, default_telemetry_broadcast_interval_secs); LOG_DEBUG("Sleep for %ims, then awake to send metrics again", nightyNightMs); - doDeepSleep(nightyNightMs, true); + doDeepSleep(nightyNightMs, true, false); } uint32_t result = UINT32_MAX; diff --git a/src/modules/Telemetry/HealthTelemetry.cpp b/src/modules/Telemetry/HealthTelemetry.cpp index 7cacdc6c17..22534e9f53 100644 --- a/src/modules/Telemetry/HealthTelemetry.cpp +++ b/src/modules/Telemetry/HealthTelemetry.cpp @@ -40,7 +40,7 @@ int32_t HealthTelemetryModule::runOnce() uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.health_update_interval, default_telemetry_broadcast_interval_secs); LOG_DEBUG("Sleep for %ims, then awake to send metrics again", nightyNightMs); - doDeepSleep(nightyNightMs, true); + doDeepSleep(nightyNightMs, true, false); } uint32_t result = UINT32_MAX; diff --git a/src/modules/Telemetry/PowerTelemetry.cpp b/src/modules/Telemetry/PowerTelemetry.cpp index 409585f446..3676438498 100644 --- a/src/modules/Telemetry/PowerTelemetry.cpp +++ b/src/modules/Telemetry/PowerTelemetry.cpp @@ -28,7 +28,7 @@ int32_t PowerTelemetryModule::runOnce() uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.power_update_interval, default_telemetry_broadcast_interval_secs); LOG_DEBUG("Sleep for %ims, then awake to send metrics again", nightyNightMs); - doDeepSleep(nightyNightMs, true); + doDeepSleep(nightyNightMs, true, false); } uint32_t result = UINT32_MAX; diff --git a/src/sleep.cpp b/src/sleep.cpp index a50f7aac34..05597cdfa7 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -187,7 +187,7 @@ static void waitEnterSleep(bool skipPreflight = false) notifySleep.notifyObservers(NULL); } -void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) +void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveNodeDb = false) { if (INCLUDE_vTaskSuspend && (msecToWake == portMAX_DELAY)) { LOG_INFO("Enter deep sleep forever"); @@ -219,7 +219,9 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) screen->doDeepSleep(); // datasheet says this will draw only 10ua - nodeDB->saveToDisk(); + if (!skipSaveNodeDb) { + nodeDB->saveToDisk(); + } #ifdef PIN_POWER_EN pinMode(PIN_POWER_EN, INPUT); // power off peripherals diff --git a/src/sleep.h b/src/sleep.h index 6ac4207695..8d3cb17e8a 100644 --- a/src/sleep.h +++ b/src/sleep.h @@ -4,7 +4,7 @@ #include "Observer.h" #include "configuration.h" -void doDeepSleep(uint32_t msecToWake, bool skipPreflight), cpuDeepSleep(uint32_t msecToWake); +void doDeepSleep(uint32_t msecToWake, bool skipPreflight, bool skipSaveNodeDb), cpuDeepSleep(uint32_t msecToWake); #ifdef ARCH_ESP32 #include "esp_sleep.h"