2013-03-20 09:36 AM
I'm having an issue wherein TR and SSR values don't logically match up, on an approximately 1 Hz read cycle where reads occur very close to the RTC update time. I'm perplexed, and almost ready to throw my board onto the interstate and get a job as a bagger at my grocery store.
Summary: - µC is STM32F405RG. SYSCLK is 168 MHz and PCLK1 is 42 MHz. - RTC is configured and started once (board has a backup battery) on startup when not already configured. - RTC is clocked by 768 KHz LSE. - PREDIV_S is set to 1024 to provide millisecond time resolution. - An external device delivers messages to the µC every 1 sec (±20 ms or so) via a USART, and as a first test I added a call to fetch RTC time on (after) receipt of these messages. Sometimes, if the timing is just right (such that the time fetch occurs close to the 1 Hz RTC update), I’ll see times like this:RTC: 2013/03/20 08:48:024
RTC: 2013/03/20 08:48:026
RTC: 2013/03/20 08:48:027
RTC: 2013/03/20 08:48:025
RTC: 2013/03/20 08:49:993
<-- hey, it did NOT take that long!RTC: 2013/03/20 08:49:015
<-- whoa, we moved backward in time?RTC: 2013/03/20 08:49:995
RTC: 2013/03/20 08:49:995
RTC: 2013/03/20 08:49:015
RTC: 2013/03/20 08:49:994
RTC: 2013/03/20 08:49:982
RTC: 2013/03/20 08:49:015
RTC: 2013/03/20 08:49:994
RTC: 2013/03/20 08:49:994
RTC: 2013/03/20 08:49:014
RTC: 2013/03/20 08:49:993
Here is the time fetch procedure: 1) Clear RTC_ISR.RSF and wait for it to assert (tried manually and via RTC_WaitForSynchro()).2) Read RTC_TR, RTC_SSR, and RTC_DR registers, in that order (also tried swapping TR/SSR read).
For absolute clarity, here's the code:void TESTRTC()
{
uint8_t year, month, day, dow, hour, minute, second;
uint32_t treg, dreg;
uint16_t fracsec;
if (RTC_WaitForSynchro() != SUCCESS)
SIGNAL_FATAL_FAULT(FAULT_RTCRead);
treg = RTC->TR;
fracsec = RTC->SSR;
dreg = RTC->DR;
fracsec = fracsec - fracsec / 42;
year = BCD2ToByte((dreg >> 16) & 0xff);
month = BCD2ToByte((dreg >> 8) & 0x1f);
day = BCD2ToByte(dreg & 0x3f);
hour = BCD2ToByte((treg >> 16) & 0x3f);
minute = BCD2ToByte((treg >> 8) & 0x7f);
second = BCD2ToByte(treg & 0x7f);
printf(''RTC: 20%02d/%02d/%02d %02d:%02d:%02d.%03d\n'',
year, month, day, hour, minute, second, fracsec);
}
Anyone have any suggestions or observations to offer? I'd even be somewhat less surprised if the fetch attempts were acting odd with the SSR returning 1023, but they're significantly farther away from the RTC ''tick'' than that. (The millisecond value of 993 in the sample output above corresponds to an SSR value of 1)
Many thanks in advance!! #stm32f4-f4-rtc-subsecond2013-03-20 01:36 PM
Actually... Not that this is any longer relevant to the original topic, but...
As it turns out, neither my math:fracsec = 999 - (fracsec - fracsec / 42)...nor yours:fracsec = 1000 * (1023 - fracsec) / 1024...works the way I want it to.The issue is that I want the maximum error between reported integer ms value and actual decimal ms value to be no larger in magnitude than 0.5. Both of those equations get up to about 0.984.As fugly as it might be, the best integer equation is (commas added for clarity only):fracsec = (10,000 * (1,023 - fracsec) + 5,100) / 10,240That exhibits a maximum actual-to-reported ms error magnitude of 0.5. It's not just a cerebral exercise - it's actually important to my application.