cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 RTC loses one second after each reset

coppercrimp
Associate III
Posted on May 23, 2017 at 07:46

I have a custom board based on the STM32F407 device. The board is running well except for one nagging detail: the RTC loses one second each time I power the board on/off

My device uses a low frequency external crystal and a backup coincell battery. The crystal is the CM7V-T1A 32.768kHz from Micro Crystal and it runs fine and keeps accurate time from either the coincell or main battery power. But again, the RTC looses approximately 1 second every time the board is powered on from the main external batteries. If the user powers the board on and off ten times (while keeping the backup coincell connected of course), then approximately 10 seconds of time is lost on the RTC.

I see many postings on this forum of people reporting loss of time when coming out of sleep modes. However my problem happens irregardless of whether the processor ever enters sleep mode. I do check the Wakeup Flag and the Standby Flag on power up though. Below is the first lines of code from my main() function:

int main(void)

{

HAL_Init();

/* Configure the system clock */

SystemClock_Config_HighSpeed();

/* Initialize all configured peripherals */

MX_GPIO_Init();

CheckFlashDefaults();

MX_DMA_Init();

MX_I2C1_Init();

MX_SDIO_SD_Init();

StatusLED_ConfigI2C(&hi2c1);

if(__HAL_PWR_GET_FLAG(PWR_FLAG_WU) != RESET)

{

      __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

}

/* Check the status of standby flag SB*/

if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) == RESET)

{

      RTC_Init();

}

else

{

      /*Resuming from standby routine */

      __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);

}

And here is the code that initializes the RTC:

void RTC_Init(void)

{

   RTC_TimeTypeDef sTime;

   RTC_DateTypeDef sDate;

   /**Initialize RTC and set the Time and Date

   */

   hrtc.Instance = RTC;

   hrtc.Init.HourFormat = RTC_HOURFORMAT_24;

   hrtc.Init.AsynchPrediv = 127;

   hrtc.Init.SynchPrediv = 255;

   hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;

   hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;

   hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

   HAL_RTC_Init(&hrtc);

   /* Read the Back Up Register 0 Data */

   if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2)

   {

      /* Configure RTC Calendar */

      sTime.Hours = 4;

      sTime.Minutes = 0;

      sTime.Seconds = 0;

      sTime.SubSeconds = 0;

      sTime.TimeFormat = RTC_HOURFORMAT12_AM;

      sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;

      sTime.StoreOperation = RTC_STOREOPERATION_RESET;

      HAL_RTC_SetTime(&hrtc, &sTime, FORMAT_BCD);

      sDate.WeekDay = RTC_WEEKDAY_MONDAY;

      sDate.Month = RTC_MONTH_JANUARY;

      sDate.Date = 1;

      sDate.Year = 0;

      HAL_RTC_SetDate(&hrtc, &sDate, FORMAT_BCD);

      /*♯♯-3- Writes a data in a RTC Backup data Register0 ♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯*/

      HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);

   }

}

#stm32f4 #rtc
35 REPLIES 35
Siddharth Singh
Associate
Posted on May 27, 2017 at 15:07

I have the exact same problem. I am using STM32F103, CubeMX and an external LSE 32.768 KHz crystal with VBat source as a CR2032 Lithium cell. The clock is keeping accurate time while either on power or on backup coin cell. However, I lose around 500 - 600 ms every time the micro is powered up or if I reset the micro using the reset button.

If I hit reset button 100 times, I lose close to a minute.

I do not suspect the crystal as I have taken measurements using an oscilloscope and also I have enabled output on RTC pin and the timing measures perfectly.

It has something to do with the initialization and I have not been able to figure that out so far!

Posted on May 28, 2017 at 16:26

If the RTC is already running, you need no initialization at all.

JW

coppercrimp
Associate III
Posted on May 30, 2017 at 20:32

Ok, so I'm back to trying to get my RTC problem corrected. I appreciate the help I've gotten so far. I'm pursuing Tut's suggestion of checking RTC_FLAG_INITS flag before configuring the RTC external clock. Tut uses the code:

if(RTC_GetFlagStatus(RTC_FLAG_INITS)==RESET) {

This appears to be from the Standard Peripheral Libraries. Since I'm fairly new to the STM32 I've gotten started with the HAL libraries. I'm having trouble finding an equivalent function in the HAL libraries to RTC_GetFlagStatus() function. Does anyone know the function to use? Again, I need to check the RTC_FLAG_INITS flag using the HAL libraries.

Also if anyone can point me to an example project or documentation showing properconfiguring the RTC clock that would be a huge help! All the documentation I've seen so far seems to skip this crucial bit of initialization code

Thanks again,

Rob

coppercrimp
Associate III
Posted on May 31, 2017 at 01:45

After some trial and error I came up with a solution that seems to work. The key piece Iseemed to be missing was this:

You SHOULD configure the peripheral clock for the RTC every time the themicrocontroller resets. I.e. the following code:

RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);�?�?�?�?

The aboveconfiguration doesn't seem to save after a power on reset in the backup domain

You SHOULD NOT need to reconfigure the 32kHz oscillator after each reset. I.e. the following code:

RCC_OscInitTypeDef RCC_OscInitStruct; 
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; 
 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
 HAL_RCC_OscConfig(&RCC_OscInitStruct);�?�?�?�?

In the end I settled on the following RTC_INIT() function, which seems to work in my testing so far:

void RTC_Init(void)
{ 
 RTC_HandleTypeDef hrtc;
 hrtc.Instance = RTC;
 
 /* Read the Back Up Register 0 Data */
 if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2) 
 {
 //Only execute this code if the RTC has not previously been configured
 //**INITIALIZE 32kHz CLOCK*********************************
 RCC_OscInitTypeDef RCC_OscInitStruct; 
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; 
 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
 HAL_RCC_OscConfig(&RCC_OscInitStruct);
 //**END INITIALIZE 32kHz CLOCK************************************************ 
 
 /* Initialize RTC and set the Time and Date */
 hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
 hrtc.Init.AsynchPrediv = 127;
 hrtc.Init.SynchPrediv = 255;
 hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
 hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
 hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
 HAL_RTC_Init(&hrtc); 
 
 RTC_TimeTypeDef sTime;
 RTC_DateTypeDef sDate; 
 
 /* Configure RTC Calendar */
 sTime.Hours = 0;
 sTime.Minutes = 0;
 sTime.Seconds = 0;
 sTime.SubSeconds = 0;
 sTime.TimeFormat = RTC_HOURFORMAT12_AM;
 sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
 sTime.StoreOperation = RTC_STOREOPERATION_RESET;
 HAL_RTC_SetTime(&hrtc, &sTime, FORMAT_BCD);
 sDate.WeekDay = RTC_WEEKDAY_MONDAY;
 sDate.Month = RTC_MONTH_JANUARY;
 sDate.Date = 1;
 sDate.Year = 1;
 HAL_RTC_SetDate(&hrtc, &sDate, FORMAT_BCD);
 /*##-3- Writes a data in a RTC Backup data Register0 #####################*/
 HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2); 
 } 
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on May 31, 2017 at 00:01

Rob,

I need to check the RTC_FLAG_INITS flag using the HAL libraries.

I don't understand you. You've used a Cube example code, to find out it's faulty, and still insist in using Cube?

The INITS flag is in RTC_ISR register. Read the RTC chapter of RM0090, especially RTC initialization and configuration  mainly its final note mentioning the INITS flag; and see the description of RTC_ISR.INITS in the registers description subchapter.

Now do you still insist on using a 'library' to check a single read-only bit?

Btw., I went through the 'library' files, and there's nothing specifically intended to check INITS. You could use something like

__HAL_RTC_ALARM_GET_FLAG(your_rtc_instance, RTC_FLAG_INITS)

(no guarantee, as you've might have found out I despice using libraries) but the comment (thus doxygen-autovomited 'documentation') says that the second parameter is to be one of

STM32F411xE HAL User Manual: RTC Exported Macros

  • RTC_FLAG_ALRAF
  • RTC_FLAG_ALRBF
  • RTC_FLAG_ALRAWF
  • RTC_FLAG_ALRBWF

so it's up to you.

JW

PS. Oh, and checking INITS is not the only way how to check whether RTC has been already started... although maybe the easiest one.

Posted on May 31, 2017 at 18:32

Thanks Rob, this did the trick 

🙂

 

🙂

coppercrimp
Associate III
Posted on December 05, 2017 at 20:57

Just wanted to point out that there still doesn't seem to be any workable code examples for configuring the RTC with the HAL libraries. Seems funny that such a basic feature is still missing

-Rob

Posted on December 06, 2017 at 01:40

What is unworkable about the existing examples?  And which chip family do you mean?  The newer chips have much better RTC capabilities.

Posted on December 06, 2017 at 02:43

There is a bug in the HAL code where the RTC loses a second every time the processor is reset or powered on. The chip I'm using is the STM32F407 but I believe the problem is in the code and not the microcontroller

Posted on December 06, 2017 at 13:36

When the BYPSHAD control bit is set in the RTC_CR register (bypass shadow registers)

Reading the calendar registers gives the values from the calendar counters directly, thus eliminating the need to wait for the RSF bit to be set. This is especially useful after exiting from low-power modes (STOP or Standby), since the shadow registers are not updated during these modes.

have you tried BYPSHAD = 1?  I'm reading the L4 manual not F4 though.