cancel
Showing results for 
Search instead for 
Did you mean: 

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

EngyCZ
Associate II

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;
}

12 REPLIES 12

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.

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
Associate II

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