cancel
Showing results for 
Search instead for 
Did you mean: 

how to restore date/time in RTC with the backup battery connected.

MNapi
Senior III

I do have time working but it will reset each time when I power it off. I do have the backup battery connected.

I thought that it is supposed to keep working on battery and I guess it does.

But I guess I might be missing a few lines to read registers and update the time once power in back on.

14 REPLIES 14

Which STM32?

Measure VBAT voltage directly on the pin. Measure it using oscilloscope during powerup and powerdown.

In software, prevent RTC initialization if it is already initialized.

JW

MNapi
Senior III

it is custom board STM32L4S9ZIT6

The clock is supposed to be working with battery the question is how I get the time when I connect power. I have to start the clock somehow, not reset and setup the time again..

JPeac.1
Senior

The LSE oscillator should continue to run, powered from VBAT. Your code should never stop the LSE or reset it, providing it is already running. The LSERDY flag should be checked at startup to see if the RTC is already running. If the flag is reset only then do you configure and start the LSE.

If youa re using the LSI oscilaltor to run the RTC then the RTC will stop when power is removed. VBAT does not power the LSI.

It is possible your startup code is the reason you are losing the RTC time. I checked my RTC startup code. Here is a relevant comment that may help:

/* On a reset, check the LSERDY flag in RCC_BDCR to determine if

 * the LSE is already running from backup power. If LSE running,

 * check the INITS flag in RTC_ISR to see if time has been set. If

 * time is set the BKP flag in RTC_CR indicates if DST has been set. If

* RTC operates on GMT (UTC) time then no DST is used.

*/

I don;t use the HAL or Cube so my code won't help you, but this is the strategy I use. Not sure what HAL does.

Jack Peacock

SKacp.1
Senior II

Hi,

Please see my code for initialization RTC. You can add write magic number to the backup register which is battery backup. After starting code You should check only this backup register, if is different than Your magic number then You should init RTC with default values.

void MX_RTC_Init(void)
{
 
  /* USER CODE BEGIN RTC_Init 0 */
 
  /* USER CODE END RTC_Init 0 */
 
  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};
 
  /* USER CODE BEGIN RTC_Init 1 */
 
  /* USER CODE END RTC_Init 1 */
  /** Initialize RTC Only
  */
  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;
  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
 
  /* USER CODE BEGIN Check_RTC_BKUP */
   if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2)
  {
 
  /* USER CODE END Check_RTC_BKUP */
 
  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0;
  sTime.Minutes = 0;
  sTime.Seconds = 0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 1;
  sDate.Year = 0;
 
  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */
	  HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);
  }
 
  /* USER CODE END RTC_Init 2 */
 
}

MNapi
Senior III

I do have external crystal so all should be fine.

I have seen the code around and wonder what the number means 0x32F2

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

I just wonder about the code, where it stores the time with power off and how it gets it back with power on. I have check all the backup registers from 0-31 and all see to be empty, except the one with 0x32F2.

Hi,

Number 0x32F2 it my magic number. You can write in register RTC_BKP_DR0 Your number, ex. 0x55AA. You must remember that You cannot use this register in code. After power is off the RTC still working (if have power from input Vbat) so after power is back You have in register actual time.

Best Regards,

Slawek

JPeac.1
Senior

As long as VBAT has power the date and time are stored in the RTC date, time and subsec registers. While you can use the magic number to check validity of the 32 RTC backup registers it isn't needed for date and time, since the RTC has the INITS flag to signal if date and time are still valid after restart.

The RTC peripheral does not stop when VCC power is removed. Instead, the LSE oscillator and RTC logic continues to operate using VBAT as the power source. Internal circuitry in the STM32 disconnects the RTC to reduce parasitic current leakage, to minimize drain on the VBAT power source. In the reference manual you'll see references to the "backup power domain", which is the LSE, the RTC and in some STM2s a 4KB block of RAM.

The 32 data registers in the RTC peripheral are independent of date and time, other than both are powered by VBAT when power is shut down. Those 32 registers are useful in quickly preserving context information across a reset, without resorting to some type of flash or EEPROM storage.

Jack Peacock

Tinnagit
Senior II

I think that you want RTC run in VBat while It power was off.

It require 3 things.

  1. you have to connect Battery with 1uF capacitor to VBat pin without nothing connect to VDD.
  2. you have to let MCU check RTC Backup register by HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2 , The 0x32F2 is dummy value but it must be same value that it write in HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2)
  3. you have to let RTC actual register synchronize to RTC shadow register by HAL_RTC_WaitForSynchro(&hrtc) != HAL_OK

the reason is

  1. VBat Level has sensitive and it's not same voltage level to VDD so when the power off was occurred VBat may change if it was connected.
  2. this for checking that it is first time running and it have to initial RTC with initial value, if it's not a first time that it require synchronize with shadow register to restore Date and Time
  3. shadow register is still running by VBat but you shouldn't read it directly so you need to synchronize it to actual register and read it normally.

this is my RTC initial code

/**
  * @brief RTC Initialization Function
  * @param None
  * @retval None
  */
static void MX_RTC_Init(void)
{
 
  /* USER CODE BEGIN RTC_Init 0 */
 
  /* USER CODE END RTC_Init 0 */
 
  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};
 
  /* USER CODE BEGIN RTC_Init 1 */
 
  /* USER CODE END RTC_Init 1 */
 
  /** Initialize RTC Only
  */
  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.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
 
  /* USER CODE BEGIN Check_RTC_BKUP */
  rtc_state |= 0x02;
  if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) != 0x32F2){
  	  rtc_state |= 0x04;
  	  //  HAL_RTCEx_EnableBypassShadow(&hrtc);
  	  if(HAL_RTC_WaitForSynchro(&hrtc) != HAL_OK)
  	  {
  		  Error_Handler();
  	  }
  /* USER CODE END Check_RTC_BKUP */
 
  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0x0;
  sTime.Minutes = 0x0;
  sTime.Seconds = 0x0;
  sTime.SubSeconds = 0x0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_SET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 0x1;
  sDate.Year = 0x0;
 
  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */
  }
     rtc_state |= 0x08;
     HAL_PWR_EnableBkUpAccess();
     HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR1,0x32F2);
     HAL_PWR_DisableBkUpAccess();
     rtc_state |= 0x10;
 
  /* USER CODE END RTC_Init 2 */
 
}

I use STM32G0

but after that I have a problem with LSE initial

LSERDY is not ready when boot after power off in VBAT mode. (st.com)

I'm not sure it related to use RTC while power off.

thank you

waclawek.jan to answer my question in

my RTC don't run after power off and RTC_BKP_DR0 was cleared (st.com)

Lucky be with you

MNapi
Senior III

I see your code if you run it each time

sTime.Hours = 0x0;

sTime.Minutes = 0x0;

sTime.Seconds = 0x0;

sTime.SubSeconds = 0x0;

sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;

sTime.StoreOperation = RTC_STOREOPERATION_SET;

if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)

{

Error_Handler();

}

sDate.WeekDay = RTC_WEEKDAY_MONDAY;

sDate.Month = RTC_MONTH_JANUARY;

sDate.Date = 0x1;

sDate.Year = 0x0;

you reset your clock to default value each time

am I right or wrong ?

so you would need to remove this code from executing after power loss