Skip to content

Commit 93e73d6

Browse files
committed
Preserve time across warm resets on nRF52 (watchdog, soft reset, pin reset)
nRF52 boards without I2C RTC will drop back to seed time on every reset. Mirrors fix in #1896 for ESP32.
1 parent df01fd3 commit 93e73d6

29 files changed

Lines changed: 72 additions & 27 deletions

File tree

src/helpers/NRF52Board.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#if defined(NRF52_PLATFORM)
22
#include "NRF52Board.h"
33

4+
// Single definitions for noinit backup variables (declared extern in NRF52Board.h)
5+
uint32_t _noinit_backup_time __attribute__((section(".noinit")));
6+
uint32_t _noinit_backup_magic __attribute__((section(".noinit")));
7+
48
#include <bluefruit.h>
59
#include <nrf_soc.h>
610

src/helpers/NRF52Board.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,47 @@
55

66
#if defined(NRF52_PLATFORM)
77

8+
// noinit variables survive watchdog, soft, pin, and lockup resets (RAM retained).
9+
// Lost on power-on and System OFF (magic check handles this).
10+
extern uint32_t _noinit_backup_time __attribute__((section(".noinit")));
11+
extern uint32_t _noinit_backup_magic __attribute__((section(".noinit")));
12+
#define NRF52_BACKUP_MAGIC 0xAA55CC33
13+
#define NRF52_TIME_MIN 1772323200 // 1 Mar 2026
14+
15+
class NRF52RTCClock : public mesh::RTCClock {
16+
uint32_t base_time;
17+
uint64_t accumulator;
18+
unsigned long prev_millis;
19+
public:
20+
NRF52RTCClock() {
21+
if (_noinit_backup_magic == NRF52_BACKUP_MAGIC && _noinit_backup_time > NRF52_TIME_MIN) {
22+
base_time = _noinit_backup_time;
23+
} else {
24+
base_time = NRF52_TIME_MIN;
25+
}
26+
accumulator = 0;
27+
prev_millis = millis();
28+
}
29+
uint32_t getCurrentTime() override { return base_time + accumulator / 1000; }
30+
void setCurrentTime(uint32_t time) override {
31+
base_time = time;
32+
accumulator = 0;
33+
prev_millis = millis();
34+
_noinit_backup_time = time;
35+
_noinit_backup_magic = NRF52_BACKUP_MAGIC;
36+
}
37+
void tick() override {
38+
unsigned long now = millis();
39+
accumulator += (now - prev_millis);
40+
prev_millis = now;
41+
uint32_t current = base_time + accumulator / 1000;
42+
if (current > NRF52_TIME_MIN && current != _noinit_backup_time) {
43+
_noinit_backup_time = current;
44+
_noinit_backup_magic = NRF52_BACKUP_MAGIC;
45+
}
46+
}
47+
};
48+
849
#ifdef NRF52_POWER_MANAGEMENT
950
// Shutdown Reason Codes (stored in GPREGRET before SYSTEMOFF)
1051
#define SHUTDOWN_REASON_NONE 0x00

variants/heltec_mesh_solar/target.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU
99

1010
WRAPPER_CLASS radio_driver(radio, board);
1111

12-
VolatileRTCClock fallback_clock;
12+
NRF52RTCClock fallback_clock;
1313
AutoDiscoverRTCClock rtc_clock(fallback_clock);
1414
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
1515
SolarSensorManager sensors = SolarSensorManager(nmea);

variants/heltec_t114/target.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU
1717

1818
WRAPPER_CLASS radio_driver(radio, board);
1919

20-
VolatileRTCClock fallback_clock;
20+
NRF52RTCClock fallback_clock;
2121
AutoDiscoverRTCClock rtc_clock(fallback_clock);
2222

2323
#if ENV_INCLUDE_GPS

variants/ikoka_handheld_nrf/target.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU
88

99
WRAPPER_CLASS radio_driver(radio, board);
1010

11-
VolatileRTCClock fallback_clock;
11+
NRF52RTCClock fallback_clock;
1212
AutoDiscoverRTCClock rtc_clock(fallback_clock);
1313

1414
EnvironmentSensorManager sensors;

variants/ikoka_nano_nrf/target.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU
1313

1414
WRAPPER_CLASS radio_driver(radio, board);
1515

16-
VolatileRTCClock fallback_clock;
16+
NRF52RTCClock fallback_clock;
1717
AutoDiscoverRTCClock rtc_clock(fallback_clock);
1818
EnvironmentSensorManager sensors;
1919

variants/ikoka_stick_nrf/target.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU
1313

1414
WRAPPER_CLASS radio_driver(radio, board);
1515

16-
VolatileRTCClock fallback_clock;
16+
NRF52RTCClock fallback_clock;
1717
AutoDiscoverRTCClock rtc_clock(fallback_clock);
1818
EnvironmentSensorManager sensors;
1919

variants/keepteen_lt1/target.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU
88

99
WRAPPER_CLASS radio_driver(radio, board);
1010

11-
VolatileRTCClock fallback_clock;
11+
NRF52RTCClock fallback_clock;
1212
AutoDiscoverRTCClock rtc_clock(fallback_clock);
1313
#if ENV_INCLUDE_GPS
1414
#include <helpers/sensors/MicroNMEALocationProvider.h>

variants/lilygo_techo/target.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU
99

1010
WRAPPER_CLASS radio_driver(radio, board);
1111

12-
VolatileRTCClock fallback_clock;
12+
NRF52RTCClock fallback_clock;
1313
AutoDiscoverRTCClock rtc_clock(fallback_clock);
1414

1515
#ifdef ENV_INCLUDE_GPS

variants/lilygo_techo_lite/target.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU
99

1010
WRAPPER_CLASS radio_driver(radio, board);
1111

12-
VolatileRTCClock fallback_clock;
12+
NRF52RTCClock fallback_clock;
1313
AutoDiscoverRTCClock rtc_clock(fallback_clock);
1414

1515
#ifdef ENV_INCLUDE_GPS

0 commit comments

Comments
 (0)