cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4xx RTC issue: inconsistent TR, SSR values near update time - befuddled!!

cygnus
Associate II
Posted on March 20, 2013 at 17:36

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-subsecond
10 REPLIES 10
cygnus
Associate II
Posted on March 20, 2013 at 21:36

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,240

That 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.