summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorScott Shawcroft <scott@adafruit.com>2020-10-13 10:10:50 -0700
committerGitHub <noreply@github.com>2020-10-13 10:10:50 -0700
commit33dee4ae0707cc12ef3a752960adea543e29b31a (patch)
tree477d990f9ede75494e587be48f418bebd6474a7a /ports
parent9de96786ad578b4e96e8219e48c778a1a556f0cf (diff)
parenta0e5e961c594e26713aa9e255bf6e43214bf42a4 (diff)
Merge pull request #3545 from tannewt/stm_rtc
Fix STM RTC read so it's atomic.
Diffstat (limited to 'ports')
-rw-r--r--ports/stm/supervisor/port.c18
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);