Skip to content

Commit 83680c4

Browse files
committed
nrf: rtc: persist rtc offset across reboots
Store the RTC value in the .uninitialized section, but make sure to flank it with some known values. That way we can determine if the RTC value has been initialized, or if it's random uninitialized garbage. As part of this, add a `common_hal_rtc_init()` routine to determine if the value is correct, or reset it to 0 if it is not valid. Signed-off-by: Sean Cross <[email protected]>
1 parent 3b5f5dd commit 83680c4

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

ports/nrf/common-hal/rtc/RTC.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,42 @@
3434
#include "supervisor/shared/translate.h"
3535

3636
// This is the time in seconds since 2000 that the RTC was started.
37-
static uint32_t rtc_offset = 0;
37+
__attribute__((section(".uninitialized"))) static uint32_t rtc_offset[3];
38+
39+
// These values are placed before and after the current RTC count. They are
40+
// used to determine if the RTC count is valid. These randomly-generated values
41+
// will be set when the RTC value is set in order to mark the RTC as valid. If
42+
// the system crashes or reboots, these values will remain undisturbed and the
43+
// RTC offset will remain valid.
44+
//
45+
// If Circuit Python is updated or these symbols shift around, the prefix and
46+
// suffix will no longer match, and the time will no longer be valid.
47+
#define RTC_OFFSET_CHECK_PREFIX 0x25ea7e2a
48+
#define RTC_OFFSET_CHECK_SUFFIX 0x2b80b69e
49+
50+
void common_hal_rtc_init(void) {
51+
// If the prefix and suffix are not valid, zero-initialize the RTC offset.
52+
if ((rtc_offset[0] != RTC_OFFSET_CHECK_PREFIX) || (rtc_offset[2] != RTC_OFFSET_CHECK_SUFFIX))
53+
rtc_offset[1] = 0;
54+
}
3855

3956
void common_hal_rtc_get_time(timeutils_struct_time_t *tm) {
4057
uint64_t ticks_s = port_get_raw_ticks(NULL) / 1024;
41-
timeutils_seconds_since_2000_to_struct_time(rtc_offset + ticks_s, tm);
58+
timeutils_seconds_since_2000_to_struct_time(rtc_offset[1] + ticks_s, tm);
4259
}
4360

4461
void common_hal_rtc_set_time(timeutils_struct_time_t *tm) {
4562
uint64_t ticks_s = port_get_raw_ticks(NULL) / 1024;
4663
uint32_t epoch_s = timeutils_seconds_since_2000(
4764
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec
4865
);
49-
rtc_offset = epoch_s - ticks_s;
66+
rtc_offset[1] = epoch_s - ticks_s;
67+
68+
// Set the prefix and suffix in order to indicate the time is valid. This
69+
// must be done after the offset is updated, in case there is a crash or
70+
// power failure.
71+
rtc_offset[0] = RTC_OFFSET_CHECK_PREFIX;
72+
rtc_offset[2] = RTC_OFFSET_CHECK_SUFFIX;
5073
}
5174

5275
int common_hal_rtc_get_calibration(void) {

ports/nrf/common-hal/rtc/RTC.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@
2929

3030
extern void rtc_init(void);
3131
extern void rtc_reset(void);
32+
extern void common_hal_rtc_init(void);
3233

3334
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_RTC_RTC_H

0 commit comments

Comments
 (0)