@@ -47,6 +47,11 @@ volatile uint32_t cached_date = 0;
47
47
volatile uint32_t seconds_to_minute = 0 ;
48
48
volatile uint32_t cached_hours_minutes = 0 ;
49
49
50
+ // The RTC starts at 2000-01-01 when it comes up.
51
+ // If the RTC is set to a later time, the ticks the RTC returns will be offset by the new time.
52
+ // Remember that offset so it can be removed when returning a monotonic tick count.
53
+ static int64_t rtc_ticks_offset ;
54
+
50
55
volatile bool alarmed_already [2 ];
51
56
52
57
bool peripherals_wkup_on = false;
@@ -59,6 +64,8 @@ uint32_t stm32_peripherals_get_rtc_freq(void) {
59
64
}
60
65
61
66
void stm32_peripherals_rtc_init (void ) {
67
+ rtc_ticks_offset = 0 ;
68
+
62
69
// RTC oscillator selection is handled in peripherals/<family>/<line>/clocks.c
63
70
__HAL_RCC_RTC_ENABLE ();
64
71
hrtc .Instance = RTC ;
@@ -74,49 +81,9 @@ void stm32_peripherals_rtc_init(void) {
74
81
HAL_NVIC_EnableIRQ (RTC_Alarm_IRQn );
75
82
}
76
83
77
- #if CIRCUITPY_RTC
78
- void stm32_peripherals_rtc_get_time (timeutils_struct_time_t * tm ) {
79
- RTC_DateTypeDef date = {0 };
80
- RTC_TimeTypeDef time = {0 };
81
-
82
- int code ;
83
- if ((code = HAL_RTC_GetTime (& hrtc , & time , RTC_FORMAT_BIN )) == HAL_OK &&
84
- (code = HAL_RTC_GetDate (& hrtc , & date , RTC_FORMAT_BIN )) == HAL_OK ) {
85
- tm -> tm_hour = time .Hours ;
86
- tm -> tm_min = time .Minutes ;
87
- tm -> tm_sec = time .Seconds ;
88
- tm -> tm_wday = date .WeekDay - 1 ;
89
- tm -> tm_mday = date .Date ;
90
- tm -> tm_mon = date .Month ;
91
- tm -> tm_year = date .Year + 2000 ;
92
- tm -> tm_yday = -1 ;
93
- }
94
- }
95
-
96
- void stm32_peripherals_rtc_set_time (timeutils_struct_time_t * tm ) {
97
- RTC_DateTypeDef date = {0 };
98
- RTC_TimeTypeDef time = {0 };
99
-
100
- time .Hours = tm -> tm_hour ;
101
- time .Minutes = tm -> tm_min ;
102
- time .Seconds = tm -> tm_sec ;
103
- date .WeekDay = tm -> tm_wday + 1 ;
104
- date .Date = tm -> tm_mday ;
105
- date .Month = tm -> tm_mon ;
106
- date .Year = tm -> tm_year - 2000 ;
107
- time .DayLightSaving = RTC_DAYLIGHTSAVING_NONE ;
108
- time .StoreOperation = RTC_STOREOPERATION_RESET ;
109
-
110
- if (HAL_RTC_SetTime (& hrtc , & time , RTC_FORMAT_BIN ) != HAL_OK ||
111
- HAL_RTC_SetDate (& hrtc , & date , RTC_FORMAT_BIN ) != HAL_OK ) {
112
- // todo - throw an exception
113
- }
114
- }
115
- #endif
116
-
117
84
// This function is called often for timing so we cache the seconds elapsed computation based on the
118
85
// register value. The STM HAL always does shifts and conversion if we use it directly.
119
- uint64_t stm32_peripherals_rtc_raw_ticks (uint8_t * subticks ) {
86
+ STATIC uint64_t stm32_peripherals_rtc_raw_ticks (uint8_t * subticks ) {
120
87
// Disable IRQs to ensure we read all of the RTC registers as close in time as possible. Read
121
88
// SSR twice to make sure we didn't read across a tick.
122
89
__disable_irq ();
@@ -164,6 +131,57 @@ uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t *subticks) {
164
131
return raw_ticks ;
165
132
}
166
133
134
+ // This function returns monotonically increasing ticks by adjusting away the RTC tick offset
135
+ // from the last time the date was set.
136
+ uint64_t stm32_peripherals_rtc_monotonic_ticks (uint8_t * subticks ) {
137
+ return stm32_peripherals_rtc_raw_ticks (subticks ) - rtc_ticks_offset ;
138
+ }
139
+
140
+ #if CIRCUITPY_RTC
141
+ void stm32_peripherals_rtc_get_time (timeutils_struct_time_t * tm ) {
142
+ RTC_DateTypeDef date = {0 };
143
+ RTC_TimeTypeDef time = {0 };
144
+
145
+ int code ;
146
+ if ((code = HAL_RTC_GetTime (& hrtc , & time , RTC_FORMAT_BIN )) == HAL_OK &&
147
+ (code = HAL_RTC_GetDate (& hrtc , & date , RTC_FORMAT_BIN )) == HAL_OK ) {
148
+ tm -> tm_hour = time .Hours ;
149
+ tm -> tm_min = time .Minutes ;
150
+ tm -> tm_sec = time .Seconds ;
151
+ tm -> tm_wday = date .WeekDay - 1 ;
152
+ tm -> tm_mday = date .Date ;
153
+ tm -> tm_mon = date .Month ;
154
+ tm -> tm_year = date .Year + 2000 ;
155
+ tm -> tm_yday = -1 ;
156
+ }
157
+ }
158
+
159
+ void stm32_peripherals_rtc_set_time (timeutils_struct_time_t * tm ) {
160
+ RTC_DateTypeDef date = {0 };
161
+ RTC_TimeTypeDef time = {0 };
162
+
163
+ uint64_t current_monotonic_ticks = stm32_peripherals_rtc_monotonic_ticks (NULL );
164
+
165
+ time .Hours = tm -> tm_hour ;
166
+ time .Minutes = tm -> tm_min ;
167
+ time .Seconds = tm -> tm_sec ;
168
+ date .WeekDay = tm -> tm_wday + 1 ;
169
+ date .Date = tm -> tm_mday ;
170
+ date .Month = tm -> tm_mon ;
171
+ date .Year = tm -> tm_year - 2000 ;
172
+ time .DayLightSaving = RTC_DAYLIGHTSAVING_NONE ;
173
+ time .StoreOperation = RTC_STOREOPERATION_RESET ;
174
+
175
+ if (HAL_RTC_SetTime (& hrtc , & time , RTC_FORMAT_BIN ) != HAL_OK ||
176
+ HAL_RTC_SetDate (& hrtc , & date , RTC_FORMAT_BIN ) != HAL_OK ) {
177
+ // todo - throw an exception
178
+ }
179
+
180
+ rtc_ticks_offset = stm32_peripherals_rtc_raw_ticks (NULL ) - current_monotonic_ticks ;
181
+ ;
182
+ }
183
+ #endif
184
+
167
185
void stm32_peripherals_rtc_assign_wkup_callback (void (* callback )(void )) {
168
186
wkup_callback = callback ;
169
187
}
0 commit comments