cancel
Showing results for 
Search instead for 
Did you mean: 

RTC losing fractions of second on uP reset - how to solve?

Peter Mather
Associate III

My code initialises the RTC using the standard CubeMX code but before setting the clock it tests for a valid year > 2018. This works perfectly and the time and date are preserved through resets of the uP.

However, it appear that either the reset or the call to HAL_RTC_Init zeroes the fractions of a second stored in the RTC registers. This can be proven by repeated resetting the processor each time withing a second which causes time to stand still.

Is there a solution to this so that the fractions of a second are preserved through resets and power cycles?

Thanks

static void MX_RTC_Init(void)
{
 
  /* USER CODE BEGIN RTC_Init 0 */
	int up=RTC_SMOOTHCALIB_PLUSPULSES_RESET;
	int calibrate= -Option.RTC_Calibrate;
  /* USER CODE END RTC_Init 0 */
 
  RTC_TimeTypeDef sTime;
  RTC_DateTypeDef sDate;
 
  /* 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 = 7;
  hrtc.Init.SynchPrediv = 4095;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
 
  /* USER CODE BEGIN Check_RTC_BKUP */
  if (HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
  {
	  Error_Handler();
  }
 
  if (HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
  {
	  Error_Handler();
  }
  RtcGetTime();
  if(sDate.Year<18){
    
  /* USER CODE END Check_RTC_BKUP */
 
  /** Initialize RTC and set the Time and Date 
  */
  sTime.Hours = 0x0;
  sTime.Minutes = 0x0;
  sTime.Seconds = 0x0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  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 */
  }
  if(Option.RTC_Calibrate>0){
	  up=RTC_SMOOTHCALIB_PLUSPULSES_SET;
	  calibrate=512-Option.RTC_Calibrate;
  }
  HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC, up, calibrate);
 
  /* USER CODE END RTC_Init 2 */
 
}

1 ACCEPTED SOLUTION

Accepted Solutions
Peter Mather
Associate III

Thanks that and one of the cube example programs gave the clue. Key is the statement that restores the RTC structure.

  RTC_TimeTypeDef sTime;
  RTC_DateTypeDef sDate;
 
  /* 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 = 7;
  hrtc.Init.SynchPrediv = 4095;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  __HAL_RTC_RESET_HANDLE_STATE(&hrtc);
  if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST)){
	  MMPrintString("Full Init\r\n");
	  if (HAL_RTC_Init(&hrtc) != HAL_OK)
	  {
		  Error_Handler();
	  }
}

View solution in original post

13 REPLIES 13

I don't Cube but IMO you are not supposed to do

  HAL_RTC_Init(&hrtc);

every time you reset the mcu

https://community.st.com/s/question/0D50X00009XkgBWSAZ/stm32-rtc-loses-one-second-after-each-reset

JW

Peter Mather
Associate III

Thanks that and one of the cube example programs gave the clue. Key is the statement that restores the RTC structure.

  RTC_TimeTypeDef sTime;
  RTC_DateTypeDef sDate;
 
  /* 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 = 7;
  hrtc.Init.SynchPrediv = 4095;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  __HAL_RTC_RESET_HANDLE_STATE(&hrtc);
  if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST)){
	  MMPrintString("Full Init\r\n");
	  if (HAL_RTC_Init(&hrtc) != HAL_OK)
	  {
		  Error_Handler();
	  }
}

Ingmar
Associate II

@Community member​ : Thanks a lot! These two lines

__HAL_RTC_RESET_HANDLE_STATE(&hrtc);
 
  if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST)){

were not included in the code I was using, obviously taken from some older reference example.

Thus, HAL_RTC_Init() was called on every startup.

Edit: Works only after reset, but not after power down... :(

Ingmar
Associate II

Yep, I just found this (kind of official ST) answer which implements that solution:

HAL_RTC_Init() looses time · Issue #24 · STMicroelectronics/STM32CubeH7 (github.com)

Seems to work in my code. Thanks a lot, confirms it somehow.

Piranha
Chief II

Better test the RCC_BDCR configuration, especially the RTCEN bit.

Ingmar
Associate II
Piranha
Chief II

Jan and I gave you a better solution than the incompetent HAL/Cube developers.

not everyone is very smart to understand "Better test the RCC_BDCR configuration, especially the RTCEN bit." or "It may be a better idea to use RCC_BDCR.RTCEN as basis for this test" without working example. At least I do not know how implement it. :(