From 1ac4f9111d6bdf0b9dfbb10f154119edf0c00f92 Mon Sep 17 00:00:00 2001 From: mark9064 <30447455+mark9064@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:48:12 +0000 Subject: [PATCH] Persist time and steps across reboots --- src/components/motion/MotionController.cpp | 9 ++++++ src/components/motion/MotionController.h | 3 ++ src/components/persistence/RebootPersist.h | 36 ++++++++++++++++++++++ src/main.cpp | 17 +++++----- src/systemtask/SystemTask.cpp | 6 +++- src/systemtask/SystemTask.h | 3 +- 6 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 src/components/persistence/RebootPersist.h diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index ce959f0efb..fb8066b256 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -38,12 +38,15 @@ namespace { void MotionController::AdvanceDay() { --nbSteps; // Higher index = further in the past SetSteps(Days::Today, 0); + carrySteps = 0; if (service != nullptr) { service->OnNewStepCountValue(NbSteps(Days::Today)); } } void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) { + // Offset the sensor value by whatever we are carrying forward + nbSteps += carrySteps; uint32_t oldSteps = NbSteps(Days::Today); if (oldSteps != nbSteps && service != nullptr) { service->OnNewStepCountValue(nbSteps); @@ -160,3 +163,9 @@ void MotionController::Init(Pinetime::Drivers::Bma421::DeviceTypes types) { break; } } + +void MotionController::Restore(uint32_t carrySteps, uint32_t carryTripSteps) { + this->carrySteps = carrySteps; + SetSteps(Days::Today, carrySteps); + currentTripSteps = carryTripSteps; +} diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index ed6cbbd144..4814e85907 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -66,6 +66,8 @@ namespace Pinetime { void Init(Pinetime::Drivers::Bma421::DeviceTypes types); + void Restore(uint32_t carrySteps, uint32_t carryTripSteps); + void SetService(Pinetime::Controllers::MotionService* service) { this->service = service; } @@ -76,6 +78,7 @@ namespace Pinetime { private: Utility::CircularBuffer nbSteps = {0}; + uint32_t carrySteps = 0; uint32_t currentTripSteps = 0; void SetSteps(Days day, uint32_t steps) { diff --git a/src/components/persistence/RebootPersist.h b/src/components/persistence/RebootPersist.h new file mode 100644 index 0000000000..aec8ec440a --- /dev/null +++ b/src/components/persistence/RebootPersist.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +namespace Pinetime { + namespace Components { + class RebootPersist { + public: + [[nodiscard]] bool IsValid() const volatile { + return canary == magic; + } + + void SetValid() volatile { + canary = magic; + } + + // layout of time point is implementation defined + // instead store milliseconds since epoch + uint64_t timeMillis; + uint32_t steps; + uint32_t tripSteps; + + private: + // The canary determines whether memory has been kept or not after a reset, + // since the NRF52832 doesn't guarantee RAM retention + // See https://docs.nordicsemi.com/bundle/ps_nrf52832/page/power.html#d935e523 + // If the magic value is still in the canary when booting, + // we assume that memory is intact from the previous boot + + // Increment magic upon changing members of this class + // Otherwise garbage values will be loaded after DFU + static constexpr uint32_t magic = 0xDEAD0001; + uint32_t canary; + }; + } +} diff --git a/src/main.cpp b/src/main.cpp index d0ab3e4887..53b8ebe2ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,7 @@ #include "components/datetime/DateTimeController.h" #include "components/heartrate/HeartRateController.h" #include "components/stopwatch/StopWatchController.h" +#include "components/persistence/RebootPersist.h" #include "components/fs/FS.h" #include "drivers/Spi.h" #include "drivers/SpiMaster.h" @@ -161,14 +162,10 @@ void vApplicationStackOverflowHook(TaskHandle_t /*xTask*/, char* /*pcTaskName*/) stackOverflowCount++; } } -/* Variable Declarations for variables in noinit SRAM - Increment NoInit_MagicValue upon adding variables to this area -*/ +// Variable Declarations for variables in noinit SRAM extern uint32_t __start_noinit_data; extern uint32_t __stop_noinit_data; -static constexpr uint32_t NoInit_MagicValue = 0xDEAD0000; -uint32_t NoInit_MagicWord __attribute__((section(".noinit"))); -std::chrono::time_point NoInit_BackUpTime __attribute__((section(".noinit"))); +volatile Pinetime::Components::RebootPersist NoInit_Persistence __attribute__((section(".noinit"))); void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { if (pin == Pinetime::PinMap::Cst816sIrq) { @@ -352,12 +349,14 @@ int main() { // retrieve version stored by bootloader Pinetime::BootloaderVersion::SetVersion(NRF_TIMER2->CC[0]); - if (NoInit_MagicWord == NoInit_MagicValue) { - dateTimeController.SetCurrentTime(NoInit_BackUpTime); + if (NoInit_Persistence.IsValid()) { + dateTimeController.SetCurrentTime( + std::chrono::time_point(std::chrono::milliseconds(NoInit_Persistence.timeMillis))); + motionController.Restore(NoInit_Persistence.steps, NoInit_Persistence.tripSteps); } else { // Clear Memory to known state memset(&__start_noinit_data, 0, (uintptr_t) &__stop_noinit_data - (uintptr_t) &__start_noinit_data); - NoInit_MagicWord = NoInit_MagicValue; + NoInit_Persistence.SetValid(); } systemTask.Start(); diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 56bf9273e1..9ec6eb5c64 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -391,7 +391,11 @@ void SystemTask::Work() { } } monitor.Process(); - NoInit_BackUpTime = dateTimeController.CurrentDateTime(); + + NoInit_Persistence.steps = motionController.NbSteps(); + NoInit_Persistence.tripSteps = motionController.GetTripSteps(); + NoInit_Persistence.timeMillis = + std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()).count(); if (nrf_gpio_pin_read(PinMap::Button) == 0) { watchdog.Reload(); } diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 606ddd3492..f1f2b0491f 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -18,6 +18,7 @@ #include "components/stopwatch/StopWatchController.h" #include "components/alarm/AlarmController.h" #include "components/fs/FS.h" +#include "components/persistence/RebootPersist.h" #include "touchhandler/TouchHandler.h" #include "buttonhandler/ButtonHandler.h" #include "buttonhandler/ButtonActions.h" @@ -32,7 +33,7 @@ #include "drivers/Watchdog.h" #include "systemtask/Messages.h" -extern std::chrono::time_point NoInit_BackUpTime; +extern volatile Pinetime::Components::RebootPersist NoInit_Persistence; namespace Pinetime { namespace Drivers {