/**
* @brief Returns the rtc's counter (i.e. time/date) value.
*
* This value is likely to be inaccurate if the counter is running
* with a low prescaler.
*/
uint32 rtc_get_count() {
uint32 h, l;
rtc_clear_sync();
rtc_wait_sync();
rtc_wait_finished();
h = RTC->regs->CNTH & 0xffff;
l = RTC->regs->CNTL & 0xffff;
return (h << 16) | l;
}
RSF: Registers synchronized flag
This bit is set by hardware at each time the RTC_CNT and RTC_DIV registers are updated
and cleared by software. Before any read operation after an APB1 reset or an APB1 clock
stop, this bit must be cleared by software, and the user application must wait until it is set to
be sure that the RTC_CNT, RTC_ALR or RTC_PRL registers are synchronized.
0: Registers not yet synchronized.
1: Registers synchronized.
So you can clear a bit that the RTC will set whenever it updates its registers, and can use that to make sure you only read right after a write to those registers.
Haven’t read much further into it, but if it’s possible to get an interrupt from the rtc after an update to the registers, that might also be useful to address this (if you can handle the interrupt fast enough)
*edit*
I’m also wondering how well the proposed repetitive read solution would work. It works perfectly if you assume the write is atomic, but is that guaranteed?

However, for the sake of science, I came up with two solutions that I would feel confident of. Both are implementations of a double read and compare. I feel that I need some guidance with this, for one thing, this is helping me get familiar with the mechanics of the software so I can move on to step two, the calibration.
One is to modify the class, leaving the utility function rtc_get_count() unchanged:
time_t RTClock::getTime() {
time_t t1, t2;
do {
t1 = rtc_get_count();
t2 = rtc_get_count();
} while (t1 != t2);
return t2;
}
void RTClock::getTime(tm_t & tm_ptr) {
time_t res = getTime();
breakTime(res, tm_ptr);
}
you are correct. the code is wrong.
the typical strategy is a double read:
uint32_t msw, lsw; //most and least significant word
do {
msw = CNTH; //read the high word
lsw = CNTL; //read the low word
} while (msw ^ CNTH); //keep reading until msw:lsw are atomic
return (msw << 16) | lsw;