diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 82c8c21d9..6be597dcd 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -228,4 +228,5 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); + board.tick(); } diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 8c745613e..3dc030d12 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -124,6 +124,7 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); + board.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 diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 1a3b4d6e0..002eb3914 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -111,4 +111,5 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); + board.tick(); } diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index da1bac5b3..9b0439d4c 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -588,4 +588,5 @@ void setup() { void loop() { the_mesh.loop(); rtc_clock.tick(); + board.tick(); } diff --git a/examples/simple_sensor/main.cpp b/examples/simple_sensor/main.cpp index a5fcc1484..e48dbcc65 100644 --- a/examples/simple_sensor/main.cpp +++ b/examples/simple_sensor/main.cpp @@ -145,4 +145,5 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); + board.tick(); } diff --git a/platformio.ini b/platformio.ini index 75d37e869..f9e11eee0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -86,6 +86,8 @@ build_flags = ${arduino_base.build_flags} -D NRF52_PLATFORM -D LFS_NO_ASSERT=1 -D EXTRAFS=1 +build_src_filter = ${arduino_base.build_src_filter} + + lib_deps = ${arduino_base.lib_deps} https://github.com/oltaco/CustomLFS @ 0.2.1 diff --git a/src/MeshCore.h b/src/MeshCore.h index 718660d3b..9b82c5e38 100644 --- a/src/MeshCore.h +++ b/src/MeshCore.h @@ -56,6 +56,7 @@ class MainBoard { virtual void setGpio(uint32_t values) {} virtual uint8_t getStartupReason() const = 0; virtual bool startOTAUpdate(const char* id, char reply[]) { return false; } // not supported + virtual void tick() { } // called each loop iteration for board-specific periodic tasks }; /** diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 2fc93006b..e9d741056 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -4,6 +4,10 @@ #include "AdvertDataHelpers.h" #include +#if defined(NRF52_PLATFORM) && defined(ENABLE_WATCHDOG) +#include "nrf52/Watchdog.h" +#endif + // Believe it or not, this std C function is busted on some platforms! static uint32_t _atoi(const char* sp) { uint32_t n = 0; @@ -364,6 +368,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch } else { sprintf(reply, "> %.3f", adc_mult); } +#if defined(NRF52_PLATFORM) && defined(ENABLE_WATCHDOG) + } else if (memcmp(config, "wdt.status", 10) == 0) { + sprintf(reply, "> %s", nrf52::Watchdog::isEnabled() ? "enabled" : "disabled"); +#endif } else { sprintf(reply, "??: %s", config); } diff --git a/src/helpers/NRF52Board.cpp b/src/helpers/NRF52Board.cpp index c0d58314e..126fa1f91 100644 --- a/src/helpers/NRF52Board.cpp +++ b/src/helpers/NRF52Board.cpp @@ -3,6 +3,10 @@ #include +#ifdef ENABLE_WATCHDOG +#include "nrf52/Watchdog.h" +#endif + static BLEDfu bledfu; static void connect_callback(uint16_t conn_handle) { @@ -19,6 +23,15 @@ static void disconnect_callback(uint16_t conn_handle, uint8_t reason) { void NRF52Board::begin() { startup_reason = BD_STARTUP_NORMAL; +#ifdef ENABLE_WATCHDOG + nrf52::Watchdog::begin(); +#endif +} + +void NRF52Board::tick() { +#ifdef ENABLE_WATCHDOG + nrf52::Watchdog::feed(); +#endif } void NRF52BoardDCDC::begin() { diff --git a/src/helpers/NRF52Board.h b/src/helpers/NRF52Board.h index 0d6c0a431..27862e4f2 100644 --- a/src/helpers/NRF52Board.h +++ b/src/helpers/NRF52Board.h @@ -14,6 +14,7 @@ class NRF52Board : public mesh::MainBoard { virtual uint8_t getStartupReason() const override { return startup_reason; } virtual float getMCUTemperature() override; virtual void reboot() override { NVIC_SystemReset(); } + virtual void tick() override; }; /* diff --git a/src/helpers/nrf52/Watchdog.cpp b/src/helpers/nrf52/Watchdog.cpp new file mode 100644 index 000000000..a1c9064d3 --- /dev/null +++ b/src/helpers/nrf52/Watchdog.cpp @@ -0,0 +1,50 @@ +#ifdef NRF52_PLATFORM + +#include "Watchdog.h" +#include + +// WDT reload request magic value +#define WDT_RR_VALUE 0x6E524635UL + +// 30 second timeout at 32.768kHz clock +// CRV = timeout_seconds * 32768 +#define WDT_TIMEOUT_SECONDS 30 +#define WDT_CRV_VALUE (WDT_TIMEOUT_SECONDS * 32768UL) + +namespace nrf52 { + +// Init watchdog timer - return true if success, false if already running +bool Watchdog::begin() { + // Check if already running - WDT cannot be reconfigured once started + if (NRF_WDT->RUNSTATUS) { + return false; + } + // Configure WDT to pause during sleep and halt modes + NRF_WDT->CONFIG = (WDT_CONFIG_SLEEP_Pause << WDT_CONFIG_SLEEP_Pos) | + (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos); + + // Set timeout value (30 seconds) + NRF_WDT->CRV = WDT_CRV_VALUE; + + // Enable reload request register 0 + NRF_WDT->RREN = WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos; + + // Start the watchdog + NRF_WDT->TASKS_START = 1; + + return true; +} + +// Feed watchdog timer within timout interval to prevent board reset +void Watchdog::feed() { + // Write magic value to reload request register 0 + NRF_WDT->RR[0] = WDT_RR_VALUE; +} + +bool Watchdog::isEnabled() { + return NRF_WDT->RUNSTATUS != 0; +} + +} // namespace nrf52 + +#endif // NRF52_PLATFORM diff --git a/src/helpers/nrf52/Watchdog.h b/src/helpers/nrf52/Watchdog.h new file mode 100644 index 000000000..4fb554103 --- /dev/null +++ b/src/helpers/nrf52/Watchdog.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef NRF52_PLATFORM + +#include + +namespace nrf52 { + +class Watchdog { +public: + static bool begin(); + static void feed(); + static bool isEnabled(); +}; + +} // namespace nrf52 + +#endif // NRF52_PLATFORM diff --git a/variants/heltec_t114/platformio.ini b/variants/heltec_t114/platformio.ini index 7b6f5ceef..0b6283b10 100644 --- a/variants/heltec_t114/platformio.ini +++ b/variants/heltec_t114/platformio.ini @@ -34,6 +34,7 @@ build_flags = ${nrf52_base.build_flags} -D PIN_GPS_EN=21 -D PIN_GPS_RESET=38 -D PIN_GPS_RESET_ACTIVE=LOW + -D ENABLE_WATCHDOG build_src_filter = ${nrf52_base.build_src_filter} + +<../variants/heltec_t114>