diff options
| author | Scott Shawcroft <scott@tannewt.org> | 2020-10-12 17:43:13 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott@tannewt.org> | 2020-10-12 17:43:25 -0700 |
| commit | a0e5e961c594e26713aa9e255bf6e43214bf42a4 (patch) | |
| tree | 375732c5625d9905c6ec3f316fb537d44749999a /ports | |
| parent | 699f19f44a7b8ed5b5b678001fb94f5491459c76 (diff) | |
Fix STM RTC read so it's atomic.
Fixes #3376
Diffstat (limited to 'ports')
| -rw-r--r-- | ports/stm/supervisor/port.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index bb304a317..79e4584b0 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -190,6 +190,7 @@ safe_mode_t port_init(void) { _hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; HAL_RTC_Init(&_hrtc); + HAL_RTCEx_EnableBypassShadow(&_hrtc); HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); // Turn off SysTick @@ -328,9 +329,23 @@ volatile uint32_t cached_date = 0; volatile uint32_t seconds_to_minute = 0; volatile uint32_t cached_hours_minutes = 0; uint64_t port_get_raw_ticks(uint8_t* subticks) { - uint32_t subseconds = rtc_clock_frequency - (uint32_t)(RTC->SSR); + // Disable IRQs to ensure we read all of the RTC registers as close in time as possible. Read + // SSR twice to make sure we didn't read across a tick. + __disable_irq(); + uint32_t first_ssr = (uint32_t)(RTC->SSR); uint32_t time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); uint32_t date = (uint32_t)(RTC->DR & RTC_DR_RESERVED_MASK); + uint32_t ssr = (uint32_t)(RTC->SSR); + while (ssr != first_ssr) { + first_ssr = ssr; + time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); + date = (uint32_t)(RTC->DR & RTC_DR_RESERVED_MASK); + ssr = (uint32_t)(RTC->SSR); + } + __enable_irq(); + + uint32_t subseconds = rtc_clock_frequency - 1 - ssr; + if (date != cached_date) { uint32_t year = (uint8_t)((date & (RTC_DR_YT | RTC_DR_YU)) >> 16U); uint8_t month = (uint8_t)((date & (RTC_DR_MT | RTC_DR_MU)) >> 8U); @@ -349,6 +364,7 @@ uint64_t port_get_raw_ticks(uint8_t* subticks) { hours = (uint8_t)RTC_Bcd2ToByte(hours); minutes = (uint8_t)RTC_Bcd2ToByte(minutes); seconds_to_minute = 60 * (60 * hours + minutes); + cached_hours_minutes = hours_minutes; } uint8_t seconds = (uint8_t)(time & (RTC_TR_ST | RTC_TR_SU)); seconds = (uint8_t)RTC_Bcd2ToByte(seconds); |
