cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L433CCT6 RTC calendar incorrect after coming out of shutdown whilst using an external VBAT and LSE

eddie McS
Associate III

My current code configures the RTC and updates date/time on initial turn on only.

void set_date(void)
{
  /* Select LSE as RTC Input */
  __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
 
  /* Enable RTC */
  __HAL_RCC_RTC_ENABLE();
 
    RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
    RCC_OscInitStruct.LSEState = RCC_LSE_ON;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
   /* 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);
 
  RTC_TimeTypeDef currentTime;
  RTC_DateTypeDef currentDate;
 
  /*##-1- Configure the Date #################################################*/
  currentDate.Year = 0x18;
  currentDate.Month = RTC_MONTH_NOVEMBER;
  currentDate.Date = 0x20;
  currentDate.WeekDay = RTC_WEEKDAY_TUESDAY;
 
  if (HAL_RTC_SetDate(&hrtc, &currentDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
 
  /*##-2- Configure the Time #################################################*/
  currentTime.Hours = 0x10;
  currentTime.Minutes = 0x19;
  currentTime.Seconds = 0x00;
  currentTime.TimeFormat = RTC_HOURFORMAT12_PM;
  currentTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  currentTime.StoreOperation = RTC_STOREOPERATION_RESET;
 
  if (HAL_RTC_SetTime(&hrtc, &currentTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
}

Every wake-up from shutdown i configure the PeriphClk to indicate LSE usage.

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    /* Initialization Error */
    while (1);
  }

I read the RTC with this function

time_t get_timestamp(void)
{
 
  HAL_RTC_GetTime(&hrtc, &currentTime, RTC_FORMAT_BIN);
  HAL_RTC_GetDate(&hrtc, &currentDate, RTC_FORMAT_BIN);
 
  currTime.tm_year = currentDate.Year + 100;  // In fact: 2000 + 18 - 1900
  currTime.tm_mday = currentDate.Date;
  currTime.tm_mon = currentDate.Month - 1;
 
  currTime.tm_hour = currentTime.Hours - 1;
  currTime.tm_min = currentTime.Minutes;
  currTime.tm_sec = currentTime.Seconds;
  timestamp = mktime(&currTime);
 
  return timestamp;
}

My issue is that once i wake-up from shutdown my RTC is back to default unless i call

hrtc.Instance = RTC;

but unfortunately this command delays the RTC and after a few wake-ups the RTC is reading a few second behind actual time. Is there an alternative to sync the RTC once it has awoken from shutdown?

Thanks

Ed

5 REPLIES 5
eddie McS
Associate III

After wake-up i have tried

  /* Disable the write protection for RTC registers */
  __HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
 
  /*Wait until the RTC Time and Date registers are synchronized with RTC APB clock*/
   HAL_RTC_WaitForSynchro(&hrtc);
 
  /* Enable the write protection for RTC registers */
  __HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);

But still not working.

eddie McS
Associate III
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <time.h>
 
RTC_HandleTypeDef hrtc;
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
 
time_t get_timestamp(void);
time_t timestamp;
struct tm currTime;
 
RTC_TimeTypeDef currentTime;
RTC_DateTypeDef currentDate;
 
int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
 
  /* Check if the system was resumed from Shutdown mode */
    if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB))
    {
        /* Clear Standby flag */
        __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
    }
    else
    {
    	MX_RTC_Init();
    	RCC_OscInitTypeDef RCC_OscInitStruct;
    	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
    	RCC_OscInitStruct.LSEState = RCC_LSE_ON;
    	HAL_RCC_OscConfig(&RCC_OscInitStruct);
    }
 
  while (1)
  {
	  uint32_t checktime = get_timestamp();
 
	    if (checktime >= 1020000) //has the RTC calendar been set?
	    {
	    	Shutdown_Mode();
	    }
  }
}
 
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
  /**Configure LSE Drive Capability 
  */
  HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
  /**Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /**Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
  /**Configure the main internal regulator output voltage 
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    Error_Handler();
  }
  /**Enable MSI Auto calibration 
  */
  HAL_RCCEx_EnableMSIPLLMode();
}
 
/**
  * @brief RTC Initialization Function
  * @param None
  * @retval None
  */
static void MX_RTC_Init(void)
{
  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};
 
  /**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;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
 
  /**Initialize RTC and set the Time and Date 
  */
  sTime.Hours = 0x12;
  sTime.Minutes = 0x13;
  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 = 0x19;
 
  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
 
}
 
time_t get_timestamp(void)
{
 
  HAL_RTC_GetTime(&hrtc, &currentTime, RTC_FORMAT_BIN);
  HAL_RTC_GetDate(&hrtc, &currentDate, RTC_FORMAT_BIN);
 
  currTime.tm_year = currentDate.Year + 100;  // In fact: 2000 + 18 - 1900
  currTime.tm_mday = currentDate.Date;
  currTime.tm_mon = currentDate.Month - 1;
 
  currTime.tm_hour = currentTime.Hours - 1;
  currTime.tm_min = currentTime.Minutes;
  currTime.tm_sec = currentTime.Seconds;
  timestamp = mktime(&currTime);
 
  return timestamp;
}
 
void Shutdown_Mode(void)
{
 
  HAL_PWREx_EnableGPIOPullDown(PWR_GPIO_A, PWR_GPIO_BIT_2);
  HAL_PWREx_EnablePullUpPullDownConfig();
 
  /* Disable used wakeup source: PWR_WAKEUP_PIN2 */
  HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN2);
 
 
  /* Clear all related wakeup flags */
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
 
  /* Enable wakeup pin WKUP1 */
  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN4_HIGH);
 
  /* Set RTC back-up register RTC_BKP31R to indicate
   later on that system has entered shutdown mode  */
  WRITE_REG(RTC->BKP31R, 0x1);
 
  /* Enter the Shutdown mode */
  HAL_PWREx_EnterSHUTDOWNMode();
}
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
 
  /* USER CODE END Error_Handler_Debug */
}

Hi, Still haven't found a solution to this problem i have. I used the cube to build the code above.. however when i return from sleep my RTC value has not been updated. If i initialise RTC again i lose a second on my actual RTC time....

Does anyone know how to read RTC once returning from low-power sleep without re-initialising the RTC?

thanks

Ed

What does the reference manual say on the matter?

JW

Hi JW,

Thanks for the reply.

The only reference i can see is:

calendar update or after wakeup from low power modes

       the software must first clear the RSF flag. The software must then

       wait until it is set again before reading the calendar, which means

       that the calendar registers have been correctly copied into the

       RTC_TR and RTC_DR shadow registers.The HAL_RTC_WaitForSynchro() function

       implements the above software sequence (RSF clear and RSF check).

  	  /* Disable Write Protection */
  	  __HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
 
    if (HAL_RTC_WaitForSynchro(&hrtc) != HAL_OK)
    	{
    		Error_Handler();
    	}
 
	  /* Enable Write Protection */
	  __HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);

However when i use the function HAL_RTC_WaitForSynchro() and look at the register value for RSF it is not being reset to zero during this function, always stays at 1. I assume this is an issue with HAL?

I don't know, but I don't think so. I also don't use Cube. RSF not being cleared sounds like the RTC input clock (LSE) is not running. In your initial post, you said that

> Every wake-up from shutdown i configure the PeriphClk to indicate LSE usage.

Are you sure this is harmless?

JW