Skip to main content
EngyCZ
Associate II
February 3, 2022
Question

STM32F4 / STM32H7 RTC HW BUG - Shadow registers for seconds and subseconds are inconsistent

  • February 3, 2022
  • 9 replies
  • 3482 views

Hi.

I found a bug in RTC shadow registers inconsistency of seconds and subseconds.

Subseconds are counted from PREDIV_S down to 0. Then the seconds are incremented and subseconds start again from PREDIV_S.

Sometimes subseconds contain PREDIV_S value and seconds contain the old value (not incremented).

Example of correct sequence:

sec:22 subsec: 2

sec:22 subsec: 1

sec:22 subsec: 0

sec:23 subsec: 255

sec:23 subsec: 254

sec:23 subsec: 253

Example of incorrect sequence:

sec:22 subsec: 2

sec:22 subsec: 1

sec:22 subsec: 0

sec:22 subsec: 255 <-- Error

sec:23 subsec: 255

sec:23 subsec: 254

sec:23 subsec: 253

I have tested it with our own design and also with STM32H743I-EVAL board.

Call this in the loop:

RTC_TimeTypeDef Laststimestructureget;
int ErrCnt;
static void RTC_CalendarShow(void)
{
 RTC_DateTypeDef sdatestructureget;
 RTC_TimeTypeDef stimestructureget;
 
 HAL_RTC_WaitForSynchro(&RtcHandle);
 /* Get the RTC current Time */
 HAL_RTC_GetTime(&RtcHandle, &stimestructureget, RTC_FORMAT_BIN);
 /* Get the RTC current Date */
 HAL_RTC_GetDate(&RtcHandle, &sdatestructureget, RTC_FORMAT_BIN);
 
 if (Laststimestructureget.Hours != 0 &&
 Laststimestructureget.Seconds == stimestructureget.Seconds &&
 Laststimestructureget.SubSeconds < stimestructureget.SubSeconds)
 {
 ErrCnt++; // <--- Error detected
 }
 Laststimestructureget = stimestructureget;
}

//=======================

I found a note in STM32H7 Errata but the workaround doesn't work.

Chapter 2.11.1 https://www.st.com/resource/en/errata_sheet/es0392-stm32h742xig-and-stm32h743xig-device-limitations-stmicroelectronics.pdf

"If BYPSHAD = 0, read SSR again after reading SSR/TR/DR to confirm that SSR is still

the same, otherwise read the values again."

RTC_TimeTypeDef Laststimestructureget;
int ErrCnt;
static void RTC_CalendarShow(void)
{
 RTC_DateTypeDef sdatestructureget, sdatestructureget2;
 RTC_TimeTypeDef stimestructureget, stimestructureget2;
 
 do
 {
 HAL_RTC_WaitForSynchro(&RtcHandle);
 /* Get the RTC current Time */
 HAL_RTC_GetTime(&RtcHandle, &stimestructureget, RTC_FORMAT_BIN);
 /* Get the RTC current Date */
 HAL_RTC_GetDate(&RtcHandle, &sdatestructureget, RTC_FORMAT_BIN);
 
 HAL_RTC_WaitForSynchro(&RtcHandle);
 /* Get the RTC current Time */
 HAL_RTC_GetTime(&RtcHandle, &stimestructureget2, RTC_FORMAT_BIN);
 /* Get the RTC current Date */
 HAL_RTC_GetDate(&RtcHandle, &sdatestructureget2, RTC_FORMAT_BIN);
 } while (stimestructureget.SubSeconds != stimestructureget2.SubSeconds);
 
 if (Laststimestructureget.Hours != 0 &&
 Laststimestructureget.Seconds == stimestructureget.Seconds &&
 Laststimestructureget.SubSeconds < stimestructureget.SubSeconds)
 {
 ErrCnt++; // <--- Error detected
 }
 Laststimestructureget = stimestructureget;
}

This topic has been closed for replies.

9 replies

TDK
Super User
February 3, 2022

nevermind, you're counting down. sorry for the noise.

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
February 4, 2022

Do you use RTOS? Isn't this routine called from multiple threads?

Don't you read RTC registers somewhere else in the program?

Try writing a minimal but complete compilable example exhibiting the problem and post.

JW

EngyCZ
EngyCZAuthor
Associate II
February 4, 2022

Hi @Community member​ 

No RTOS, reading time only on one place.

Step to reproduce:

Download STM32CubeH7 and replace

STM32CubeH7\Projects\STM32H743I-EVAL\Examples\RTC\RTC_TimeStamp

with this https://filetransfer.io/data-package/eaM3elQ1#link

Can anyone confirm this HW bug on his/her HW?

waclawek.jan
Super User
February 4, 2022

In RTC_CalendarShow(), ErrCnt is a local variable and is not initialized anywhere. This may give you the impression that the reads fail. [see below]

JW

[EDIT] Experimenting with a 'F429 and it appears that you may be up to something. Need more time.

EngyCZ
EngyCZAuthor
Associate II
February 5, 2022

>In RTC_CalendarShow(), ErrCnt is a local variable and is not initialized anywhere. This may give you the impression that the reads fail.

ErrCnt is a global variable that is initialized to 0. If you make a breakpoint on ErrCnt++ you will see the bug.

"Laststimestructureget.Hours != 0" is only for first-pass initialization. Yes, not nice but it is only for testing this bug.

Thank you for trying to confirm the bug.

...

int ErrCnt; // <---

static void RTC_CalendarShow(void)

{

...

waclawek.jan
Super User
February 5, 2022

> ErrCnt is a global variable

Indeed, I stand corrected.

JW

waclawek.jan
Super User
February 6, 2022

Can you please try replacing HAL_RTC_WaitForSynchro() by

     RTC->ISR &= (uint32_t)~(RTC_ISR_RSF | RTC_ISR_INIT);

     while ((RTC->ISR AND RTC_ISR_RSF) == 0);

Thanks,

JW

EngyCZ
EngyCZAuthor
Associate II
February 7, 2022

>Can you please try replacing HAL_RTC_WaitForSynchro() by

>     RTC->ISR &= (uint32_t)~(RTC_ISR_RSF | RTC_ISR_INIT);

>     while ((RTC->ISR AND RTC_ISR_RSF) == 0);

Hello. Thanks for the suggestion, but it doesn't help. I still see the RTC error.

waclawek.jan
Super User
February 7, 2022

I was not able to reproduce your problem.

I don't use 'H7 and don't use Cube, so I wrote my own version of the readout and run it on an 'F429 Disco, and as long as RSF is cleared/tested before each readout, the problem does not occur.

Also, the problem described in Errata would result in:

sec:22 subsec: 2

sec:22 subsec: 1

sec:22 subsec: 0

sec:23 subsec: 0 <-- Error

sec:23 subsec: 255

sec:23 subsec: 254

sec:23 subsec: 253

so what you observe has a different source.

Also, what puzzles me, the source you've provided appears to select LSI as clock source in main.h:

#define RTC_CLOCK_SOURCE_LSI

/*#define RTC_CLOCK_SOURCE_LSE*/

and the synchrononous prescaler for LSI appears to be 0xF9 rather than 0xFF

#ifdef RTC_CLOCK_SOURCE_LSI

#define RTC_ASYNCH_PREDIV   0x7F

#define RTC_SYNCH_PREDIV    0xF9

#endif

so I don't understand how could subseconds be 255. But maybe I'm overlooking something, as I've said, I don't use Cube/HAL.

Can you please read out and post RCC_BDCR and RTC registers content.

Also, please try to remove/block/disable the tamper interrupt. I believe you don't activate it (don't press the PC13-connected button), and I also don't see anything in the ISR code which would be suspicious, but just to be sure.

Thanks,

JW

EngyCZ
EngyCZAuthor
Associate II
February 7, 2022

ad LSI / LSE)

  • My board runs with LSE which has SYNCH_PREDIV = 0xFF
  • STM32Cube example for EVAL board is configured for LSI which has SYNCH_PREDIV = 0xF9

I have no tamper input activated.

Can @Community member​ send me​ your test SW for your F429 Disco? I will check it.

waclawek.jan
Super User
February 13, 2022

We've discussed this further with @Jiří Engelthaler​ off-forum and he made several observations:

  • HAL_RTC_WaitForSynchro() as called above fails to wait for synchonization, as HAL_RTC_Init() (correctly) enables RTC write protection, and the RSF flag indicating shadow registers reload is write protected. Thus, writing zero to RSF is ignored and HAL_RTC_WaitForSynchro() sees RSF being (remaining) set and exits immediately. I've written this up in more detail here.
  • HAL_RTC_WaitForSynchro(), if called immediately after a previous such call, waits 2 RTCCLK periods, which is 60us - and that's an unjustifiable time period just to read out RTC registers. Because of that, EngyCZ looked into ways of using BYPSHAD=1 . I've told about the method suggested by @Piranha​ in this thread (below "More Answers", reload if you don't see that). However, by experimenting, EngyCZ found out that while BYPSHAD=1, RTC SSR/TR/DR readouts can be not only mutually inconsistent, but they can be entirely incorrect (some bits flipped). Strict reading of RM revealed that this indeed is documented, although IMO entirely unexpected and unpleasantly surprising: "Additionally, the value of one of the registers may be incorrect if an RTCCLK edge occurs during the read operation.". RM provides solution, though, in repeated reading of all three registers until two successful readouts are identical in all three of them, or at least in SSR.

JW

EngyCZ
EngyCZAuthor
Associate II
February 14, 2022

In the end, I used the solution with BYPSHAD=1 because it doesn't have a problem with locking registers described in errata and doesn't have to wait an unreasonable amount of time (60 µs).

I tested this code 500,000x / 1sec for several tens of hours without any problem.

void ReadDateTime(void)
{
 volatile u32 subsec, timereg, datereg;
 volatile u32 subsec2, timereg2, datereg2;
 
 do
 {
 datereg = RTC->DR;
 timereg = RTC->TR;
 subsec = RTC->SSR;
 
 datereg2 = RTC->DR;
 timereg2 = RTC->TR;
 subsec2 = RTC->SSR;
 } while (datereg != datereg2 ||
 timereg != timereg2 ||
 subsec != subsec2
 );
 
 ... process subsec,timereg & datereg ...