From b476403001fc3cb4e22d14f32b663b3cd16b4ec9 Mon Sep 17 00:00:00 2001 From: Balazs Racz Date: Fri, 1 Jan 2021 22:24:17 +0100 Subject: [PATCH] Support eeprom update notification. (#499) Adds a weak callback to the eepromemulation driver, triggered after each write is completed. Shows with an example how to use this to automatically apply changes that happened from JMRI configuration UI. --- .../freertos.armv7m.ek-tm4c123gxl/main.cxx | 34 +++++++++++++++++++ boards/ti-ek-tm4c123gxl-launchpad/HwInit.cxx | 9 +++++ .../common/EEPROMEmulation.cxx | 2 ++ .../common/EEPROMEmulation.hxx | 6 ++++ .../common/EEPROMEmulation_weak.cxx | 8 +++++ 5 files changed, 59 insertions(+) diff --git a/applications/io_board/targets/freertos.armv7m.ek-tm4c123gxl/main.cxx b/applications/io_board/targets/freertos.armv7m.ek-tm4c123gxl/main.cxx index 03cd6e908..a514e76d1 100644 --- a/applications/io_board/targets/freertos.armv7m.ek-tm4c123gxl/main.cxx +++ b/applications/io_board/targets/freertos.armv7m.ek-tm4c123gxl/main.cxx @@ -127,6 +127,40 @@ openlcb::ConfiguredProducer producer_sw2( openlcb::RefreshLoop loop( stack.node(), {producer_sw1.polling(), producer_sw2.polling()}); +/// This timer checks the eeprom once a second and if the user has written +/// something, executes a reload of the configuration via the OpenLCB config +/// service. +class AutoUpdateTimer : public ::Timer +{ +public: + AutoUpdateTimer() + : ::Timer(stack.executor()->active_timers()) + { + start(SEC_TO_NSEC(1)); + } + + long long timeout() override + { + extern uint8_t eeprom_updated; + if (eeprom_updated) + { + needUpdate_ = true; + eeprom_updated = 0; + } + else + { + if (needUpdate_) + { + stack.config_service()->trigger_update(); + needUpdate_ = false; + } + } + return RESTART; + } + + bool needUpdate_ {false}; +} update_timer; + /** Entry point to application. * @param argc number of command line arguments * @param argv array of command line arguments diff --git a/boards/ti-ek-tm4c123gxl-launchpad/HwInit.cxx b/boards/ti-ek-tm4c123gxl-launchpad/HwInit.cxx index 4eb4a0fe5..eb087679f 100644 --- a/boards/ti-ek-tm4c123gxl-launchpad/HwInit.cxx +++ b/boards/ti-ek-tm4c123gxl-launchpad/HwInit.cxx @@ -110,6 +110,15 @@ StoredBitSet* g_gpio_stored_bit_set = nullptr; constexpr unsigned EEPROM_BIT_COUNT = 84; constexpr unsigned EEPROM_BITS_PER_CELL = 28; +/// This variable will be set to 1 when a write arrives to the eeprom. +uint8_t eeprom_updated = 0; + +// Overridesthe default behavior to keep track of eeprom writes. +void EEPROMEmulation::updated_notification() +{ + eeprom_updated = 1; +} + extern "C" { void hw_set_to_safe(void); diff --git a/src/freertos_drivers/common/EEPROMEmulation.cxx b/src/freertos_drivers/common/EEPROMEmulation.cxx index 89630aff5..d220a4701 100644 --- a/src/freertos_drivers/common/EEPROMEmulation.cxx +++ b/src/freertos_drivers/common/EEPROMEmulation.cxx @@ -194,6 +194,8 @@ void EEPROMEmulation::write(unsigned int index, const void *buf, size_t len) { memcpy(shadow_ + shadow_index, shadow_data, shadow_len); } + + updated_notification(); } /** Write to the EEPROM on a native block boundary. diff --git a/src/freertos_drivers/common/EEPROMEmulation.hxx b/src/freertos_drivers/common/EEPROMEmulation.hxx index b8e5d4680..07e646d76 100644 --- a/src/freertos_drivers/common/EEPROMEmulation.hxx +++ b/src/freertos_drivers/common/EEPROMEmulation.hxx @@ -154,6 +154,12 @@ protected: static const size_t BLOCK_SIZE; private: + /** This function will be called after every write. The default + * implementation is a weak symbol with an empty function. It is intended + * to be overridden in the application to get callbacks for eeprom writes + * that can trigger a reload. */ + void updated_notification(); + /** Write to the EEPROM. NOTE!!! This is not necessarily atomic across * byte boundaries in the case of power loss. The user should take this * into account as it relates to data integrity of a whole block. diff --git a/src/freertos_drivers/common/EEPROMEmulation_weak.cxx b/src/freertos_drivers/common/EEPROMEmulation_weak.cxx index e77dcd606..b7b4aca61 100644 --- a/src/freertos_drivers/common/EEPROMEmulation_weak.cxx +++ b/src/freertos_drivers/common/EEPROMEmulation_weak.cxx @@ -37,3 +37,11 @@ // emulation implementation to prevent GCC from mistakenly optimizing away the // constant into a linker reference. const bool __attribute__((weak)) EEPROMEmulation::SHADOW_IN_RAM = false; + +/// This function will be called after every write. The default +/// implementation is a weak symbol with an empty function. It is intended +/// to be overridden in the application to get callbacks for eeprom writes +/// that can trigger a reload. +void __attribute__((weak)) EEPROMEmulation::updated_notification() +{ +}