@@ -47,6 +47,11 @@ volatile uint32_t cached_date = 0;
4747volatile uint32_t seconds_to_minute = 0 ;
4848volatile uint32_t cached_hours_minutes = 0 ;
4949
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+
5055volatile bool alarmed_already [2 ];
5156
5257bool peripherals_wkup_on = false;
@@ -59,6 +64,8 @@ uint32_t stm32_peripherals_get_rtc_freq(void) {
5964}
6065
6166void stm32_peripherals_rtc_init (void ) {
67+ rtc_ticks_offset = 0 ;
68+
6269 // RTC oscillator selection is handled in peripherals/<family>/<line>/clocks.c
6370 __HAL_RCC_RTC_ENABLE ();
6471 hrtc .Instance = RTC ;
@@ -74,49 +81,9 @@ void stm32_peripherals_rtc_init(void) {
7481 HAL_NVIC_EnableIRQ (RTC_Alarm_IRQn );
7582}
7683
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-
11784// This function is called often for timing so we cache the seconds elapsed computation based on the
11885// 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 ) {
12087 // Disable IRQs to ensure we read all of the RTC registers as close in time as possible. Read
12188 // SSR twice to make sure we didn't read across a tick.
12289 __disable_irq ();
@@ -164,6 +131,57 @@ uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t *subticks) {
164131 return raw_ticks ;
165132}
166133
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+
167185void stm32_peripherals_rtc_assign_wkup_callback (void (* callback )(void )) {
168186 wkup_callback = callback ;
169187}
0 commit comments