Skip to content

Commit af68dde

Browse files
authored
Merge pull request #2924 from simmel-project/nrf-rtc-persist
NRF: Persist RTC offset across reboots
2 parents 9811c1f + 9f7c26c commit af68dde

File tree

4 files changed

+56
-10
lines changed

4 files changed

+56
-10
lines changed

ports/nrf/boards/common.template.ld

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ SECTIONS
103103
_edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
104104
} >RAM
105105

106-
/* Uninitialized data section */
106+
/* Zero-initialized data section */
107107
.bss :
108108
{
109109
. = ALIGN(4);
@@ -116,6 +116,19 @@ SECTIONS
116116
_ebss = .; /* define a global symbol at bss end; used by startup code and GC */
117117
} >RAM
118118

119+
/* Uninitialized data section
120+
Data placed into this section will remain unchanged across reboots. */
121+
.uninitialized (NOLOAD) :
122+
{
123+
. = ALIGN(4);
124+
_suninitialized = .; /* define a global symbol at uninitialized start; currently unused */
125+
*(.uninitialized)
126+
*(.uninitialized*)
127+
128+
. = ALIGN(4);
129+
_euninitialized = .; /* define a global symbol at uninitialized end; currently unused */
130+
} >RAM
131+
119132
/* this is to define the start of the heap, and make sure we have a minimum size */
120133
.heap :
121134
{

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

ports/nrf/supervisor/port.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ safe_mode_t port_init(void) {
120120
// Configure millisecond timer initialization.
121121
tick_init();
122122

123+
#if CIRCUITPY_RTC
124+
common_hal_rtc_init();
125+
#endif
126+
123127
#if CIRCUITPY_ANALOGIO
124128
analogin_init();
125129
#endif
@@ -177,30 +181,35 @@ void reset_cpu(void) {
177181
NVIC_SystemReset();
178182
}
179183

184+
// The uninitialized data section is placed directly after BSS, under the theory
185+
// that Circuit Python has a lot more .data and .bss than the bootloader. As a
186+
// result, this section is less likely to be tampered with by the bootloader.
187+
extern uint32_t _euninitialized;
188+
180189
uint32_t *port_heap_get_bottom(void) {
181-
return port_stack_get_limit();
190+
return &_euninitialized;
182191
}
183192

184193
uint32_t *port_heap_get_top(void) {
185194
return port_stack_get_top();
186195
}
187196

188197
uint32_t *port_stack_get_limit(void) {
189-
return &_ebss;
198+
return &_euninitialized;
190199
}
191200

192201
uint32_t *port_stack_get_top(void) {
193202
return &_estack;
194203
}
195204

196-
extern uint32_t _ebss;
197-
// Place the word to save just after our BSS section that gets blanked.
205+
// Place the word in the uninitialized section so it won't get overwritten.
206+
__attribute__((section(".uninitialized"))) uint32_t _saved_word;
198207
void port_set_saved_word(uint32_t value) {
199-
_ebss = value;
208+
_saved_word = value;
200209
}
201210

202211
uint32_t port_get_saved_word(void) {
203-
return _ebss;
212+
return _saved_word;
204213
}
205214

206215
uint64_t port_get_raw_ticks(uint8_t* subticks) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy