From e9a521a9b1ecc66f4e90c3b40cd9625dea57583d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 21 Mar 2021 13:23:24 -0500 Subject: [PATCH] rtc_get_datetime: read the rtc registers just once each In order for the returned value to accurately reflect a single moment in time, ensure the registers are read just once and in the datasheet order. Before this change, the RTC registers would each be read multiple times, leading (infrequently) to the returned fields not all reflecting the same moment in time. The rp2040 datasheet has what I believe is an incorrect example (embedding the source of this function); will the datasheet be updated if this function is fixed? This problem is only a speculative one; I did not actually observe it in the wild. --- src/rp2_common/hardware_rtc/rtc.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/rp2_common/hardware_rtc/rtc.c b/src/rp2_common/hardware_rtc/rtc.c index 813b5f1..5429acd 100644 --- a/src/rp2_common/hardware_rtc/rtc.c +++ b/src/rp2_common/hardware_rtc/rtc.c @@ -92,13 +92,16 @@ bool rtc_get_datetime(datetime_t *t) { } // Note: RTC_0 should be read before RTC_1 - t->dotw = (rtc_hw->rtc_0 & RTC_RTC_0_DOTW_BITS ) >> RTC_RTC_0_DOTW_LSB; - t->hour = (rtc_hw->rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB; - t->min = (rtc_hw->rtc_0 & RTC_RTC_0_MIN_BITS ) >> RTC_RTC_0_MIN_LSB; - t->sec = (rtc_hw->rtc_0 & RTC_RTC_0_SEC_BITS ) >> RTC_RTC_0_SEC_LSB; - t->year = (rtc_hw->rtc_1 & RTC_RTC_1_YEAR_BITS ) >> RTC_RTC_1_YEAR_LSB; - t->month = (rtc_hw->rtc_1 & RTC_RTC_1_MONTH_BITS) >> RTC_RTC_1_MONTH_LSB; - t->day = (rtc_hw->rtc_1 & RTC_RTC_1_DAY_BITS ) >> RTC_RTC_1_DAY_LSB; + uint32_t rtc_0 = rtc_hw->rtc_0; + uint32_t rtc_1 = rtc_hw->rtc_1; + + t->dotw = (rtc_0 & RTC_RTC_0_DOTW_BITS ) >> RTC_RTC_0_DOTW_LSB; + t->hour = (rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB; + t->min = (rtc_0 & RTC_RTC_0_MIN_BITS ) >> RTC_RTC_0_MIN_LSB; + t->sec = (rtc_0 & RTC_RTC_0_SEC_BITS ) >> RTC_RTC_0_SEC_LSB; + t->year = (rtc_1 & RTC_RTC_1_YEAR_BITS ) >> RTC_RTC_1_YEAR_LSB; + t->month = (rtc_1 & RTC_RTC_1_MONTH_BITS) >> RTC_RTC_1_MONTH_LSB; + t->day = (rtc_1 & RTC_RTC_1_DAY_BITS ) >> RTC_RTC_1_DAY_LSB; return true; } @@ -185,4 +188,4 @@ void rtc_disable_alarm(void) { while(rtc_hw->irq_setup_0 & RTC_IRQ_SETUP_0_MATCH_ACTIVE_BITS) { tight_loop_contents(); } -} \ No newline at end of file +}