Page 1 of 1

Errata STM32: RTC calendar registers are not locked properly

Posted: Tue Oct 26, 2021 1:15 pm
by guineafowl
Hi,

i was stumbling over the errata sheet of STM32F7:

https://www.st.com/resource/en/errata_s ... ronics.pdf from here

The chapter 3.11.1:
RTC calendar registers are not locked properly
Description
When reading the calendar registers with BYPSHAD = 0, the RTC_TR and RTC_DR registers may not be locked after reading the RTC_SSR register. This happens if the read operation is initiated one APB clock period before the shadow registers are updated. This can result in a non-consistency of the three registers. Similarly, the RTC_DR register can be updated after reading the RTC_TR register instead of being locked.
Workaround
Apply one of the following measures:
1.Use BYPSHAD = 1 mode (bypass shadow registers), or
2. If BYPSHAD = 0, read the RTC_SSR register again after reading the RTC_SSR, RTC_TR, RTC_DR registers to confirm that RTC_SSR is still the same, otherwise read the values again.


I did not see any measures in the driver to tackle this.

After the readout of CR in file os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c in line 657:

Code: Select all

cr  = rtcp->rtc->CR;


...I would have expected something like this :

Code: Select all

#if defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx)
  /* Handling of errata: Lock of shadow registers is not working properly
     on some controllers*/
#if STM32_RTC_HAS_SUBSECONDS
  if (rtcp->rtc->CR & RTC_CR_BYPSHAD == 0 && ssr != rtcp->rtc->SSR)
  {
    ssr = rtcp->rtc->SSR;
    tr  = rtcp->rtc->TR;
    dr  = rtcp->rtc->DR;
    cr  = rtcp->rtc->CR;
  }
#endif /* STM32_RTC_HAS_SUBSECONDS */
#endif /* affected STM controllers */


Note: Also other STM32 controllers do have this errata. E.g.: STM32F427/437 and STM32F429/439 errata

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Sat Apr 09, 2022 8:55 am
by Giovanni
Hi,

Fixed as bug #1231.

I implemented the following fix:

Code: Select all

  /* Synchronization with the RTC and reading the registers, note
     DR must be read last.*/
  while ((rtcp->rtc->ISR & RTC_ISR_RSF) == 0)
    ;
#if STM32_RTC_HAS_SUBSECONDS
  oldssr = rtcp->rtc->SSR;
  do
#endif /* STM32_RTC_HAS_SUBSECONDS */
  {
    tr  = rtcp->rtc->TR;
    dr  = rtcp->rtc->DR;
    cr  = rtcp->rtc->CR;
  }
#if STM32_RTC_HAS_SUBSECONDS
  while (oldssr != (ssr = rtcp->rtc->SSR));
#endif /* STM32_RTC_HAS_SUBSECONDS */
  rtcp->rtc->ISR &= ~RTC_ISR_RSF;


I am not sure I got it right, I would appreciate some feedback.

Giovanni

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Fri Apr 22, 2022 8:32 pm
by wild-boar
I tried the fix with a STM32F417 (silicon "Z") and the calendar freezes. The sub-seconds keep on incrementing normally.

I think the errata is misleading. I found this statement in the reference manual to be important:

To ensure consistency between the 3 values, reading either RTC_SSR or RTC_TR locks the values in the higher-order calendar shadow registers until RTC_DR is read.


Incorporating that quote and removing CR reading from the loop (since it is a constant), this is my patch:

Code: Select all

diff --git a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c
index ebd10ddbe..68dd78ecf 100644
--- a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c
+++ b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c
@@ -655,11 +655,12 @@ void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) {
   {
     tr  = rtcp->rtc->TR;
     dr  = rtcp->rtc->DR;
-    cr  = rtcp->rtc->CR;
   }
 #if STM32_RTC_HAS_SUBSECONDS
   while (oldssr != (ssr = rtcp->rtc->SSR));
+  (void)rtcp->rtc->DR;
 #endif /* STM32_RTC_HAS_SUBSECONDS */
+  cr  = rtcp->rtc->CR;
   rtcp->rtc->ISR &= ~RTC_ISR_RSF;
 
   /* Leaving a reentrant critical zone.*/


Thanks!

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Fri Apr 22, 2022 8:40 pm
by Giovanni
Thanks for the patch, I will make the change tomorrow.

Giovanni

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Sat Apr 23, 2022 11:26 am
by Giovanni
Change committed, thanks.

Giovanni

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Wed Sep 14, 2022 1:31 pm
by russian
We suspect that this change causes our firmware to randomly hang for a complete second, roughly once every 30 minutes

See https://sourceforge.net/p/chibios/bugs/1234/
See https://github.com/rusefi/rusefi/issues/4557

this seems important

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Wed Sep 14, 2022 1:42 pm
by Giovanni
Hi,

Reopening.

Giovanni

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Fri Sep 16, 2022 8:42 am
by Giovanni
Hi,

Maybe I found the problem, I think you mean this loop:

Code: Select all

#if STM32_RTC_HAS_SUBSECONDS
  oldssr = rtcp->rtc->SSR;
  do
#endif /* STM32_RTC_HAS_SUBSECONDS */
  {
    tr = rtcp->rtc->TR;
    dr = rtcp->rtc->DR;
  }
#if STM32_RTC_HAS_SUBSECONDS
  while (oldssr != (ssr = rtcp->rtc->SSR));
  (void) rtcp->rtc->DR;
#endif /* STM32_RTC_HAS_SUBSECONDS */


Could you try to change it as follows?

Code: Select all

#if STM32_RTC_HAS_SUBSECONDS
  do
#endif /* STM32_RTC_HAS_SUBSECONDS */
  {
    oldssr = rtcp->rtc->SSR;
    tr = rtcp->rtc->TR;
    dr = rtcp->rtc->DR;
  }
#if STM32_RTC_HAS_SUBSECONDS
  while (oldssr != (ssr = rtcp->rtc->SSR));
  (void) rtcp->rtc->DR;
#endif /* STM32_RTC_HAS_SUBSECONDS */


Giovanni

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Sat Sep 17, 2022 9:25 pm
by mck1117
That does look better. I think the exact bug before was that if you managed to exactly catch a subsecond rollover (ie, oldssr != ssr on the first iteration), then you had to wait a full second for it to "come back around".

Is it guaranteed that we need a loop, instead of the if originally proposed? Any time there's a loop under lock like this there's an opportunity for a hang like this.

Re: Errata STM32: RTC calendar registers are not locked properly

Posted: Sun Sep 18, 2022 9:05 am
by Giovanni
Thanks, assuming fixed then (bug #1234).

Giovanni