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.
This commit is contained in:
Jeff Epler 2021-03-21 13:23:24 -05:00 committed by Graham Sanderson
parent f76567eb7f
commit e9a521a9b1

View File

@ -92,13 +92,16 @@ bool rtc_get_datetime(datetime_t *t) {
} }
// Note: RTC_0 should be read before RTC_1 // 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; uint32_t rtc_0 = rtc_hw->rtc_0;
t->hour = (rtc_hw->rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB; uint32_t rtc_1 = rtc_hw->rtc_1;
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->dotw = (rtc_0 & RTC_RTC_0_DOTW_BITS ) >> RTC_RTC_0_DOTW_LSB;
t->year = (rtc_hw->rtc_1 & RTC_RTC_1_YEAR_BITS ) >> RTC_RTC_1_YEAR_LSB; t->hour = (rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB;
t->month = (rtc_hw->rtc_1 & RTC_RTC_1_MONTH_BITS) >> RTC_RTC_1_MONTH_LSB; t->min = (rtc_0 & RTC_RTC_0_MIN_BITS ) >> RTC_RTC_0_MIN_LSB;
t->day = (rtc_hw->rtc_1 & RTC_RTC_1_DAY_BITS ) >> RTC_RTC_1_DAY_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; return true;
} }