2017-05-22 10:46 PM
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 #rtcSolved! Go to Solution.
2019-02-21 02:45 AM
2017-05-25 08:19 AM
Anyone out there have a suggestion on how to fix this?
Thanks,
Rob
2017-05-25 08:55 AM
I don't HAL or Cube either, but I think you may want to look at the flag check prior to calling HAL_RTC_Init()
You have:
if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) == RESET)
I use SPL and I believe the correct check using SPL is:
if(RTC_GetFlagStatus(RTC_FLAG_INITS)==RESET)
I'm thinking the HAL equivalent is probably very similar.
I believe initialization freezes the clock, so it shouldn't be performed every reset.
2017-05-25 09:13 AM
Hi Tut,
Yes I considered that the initialization might freeze the clock, so I tried calling
RTC_Init() multiple times consecutively on startup to see if this increased the number of missing seconds. It did not. The problem might have more to do with the section of code that configures the pins and the 32kHz external crystal. Here's my code for that:
void SystemClock_Config_HighSpeed(void)
{RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.LSEState = RCC_LSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); }RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); }PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S|RCC_PERIPHCLK_RTC;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 192; PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); }HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_4);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);}This code is called each time the board is powered up. Would changing this fix the problem?
2017-05-25 10:28 AM
Exactly 1 second missing? Even if you power it down for say 10 seconds?
[EDIT}
I don't Cube but IMO you are not supposed to do
HAL_RTC_Init(&hrtc);
every time you reset the mcu
JW
2017-05-25 10:32 AM
It's not exactly one second but it's close. Probably more like 800ms
It doesnt matter how long the board is powered down (as long as the backup battery is connected). The problem only seems to be effected by the number of times the power is cycled or the processor is reset
2017-05-25 10:53 AM
I don't Cube but IMO you are not supposed to do
HAL_RTC_Init(&hrtc);
every time you reset the mcu
2017-05-25 11:27 AM
I really don't have time to go through your code. There are a number of things I do after checking the RTC_FLAG_INITS flag (there are a few function calls to my own code mixed in here, but you should get the idea). Note the clock configuration which I believe you were asking about:
EDIT ... Added top line to enable the power controller interface clock prior to test for RTC initialization (sorry I missed seeing that line in my code).
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); // Enable the Power Controller interface clock
if(RTC_GetFlagStatus(RTC_FLAG_INITS)==RESET) // Initialization freezes clock so only perform this if new vbat/vdd power-up
{
PWR_BackupAccessCmd(ENABLE); // Enable access to RTC domain
RCC_LSEConfig(RCC_LSE_ON); // Turns on the external 768khz oscillator (if not already on)
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {}; // Wait until LSE is ready
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // Selects the external 768khz oscillator (LSE) for the RTC
RCC_RTCCLKCmd(ENABLE); // Enable the RTC Clock
RTC_StructInit(&RTC_InitStruct); // Set RTC_InitStruct to default values
RTC_InitStruct.RTC_HourFormat = RTC_HOUR_FORMAT;
RTC_Init(&RTC_InitStruct);
#if defined(USE_EEPROM)
// Get rtc_calib_val from EEPROM
eeprom_bytes = 2;
if(sEE_ReadBuffer((uint8_t*)&rtc_calib_val,EEPROM_RTC_CAL_OFFSET,(uint32_t*)&eeprom_bytes)==sEE_FAIL)
{
rtc_calib_val = RTC_CALIB_VAL; // Set to default value defined in mydefs.h if EEPROM read fails
}
else while(eeprom_bytes) {}; // Wait for DMA to complete reading into buffer
#else
rtc_calib_val = RTC_CALIB_VAL; // Set to default value defined in mydefs.h if EEPROM read fails
#endif
Board_set_rtc_calib_val(rtc_calib_val);
PWR_BackupAccessCmd(DISABLE); // Disable access to RTC domain (must re-enable to set time and date or access internal backup RAM)
} // end if(RTC_GetFlagStatus(RTC_FLAG_INITS)==RESET)
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2017-05-25 12:24 PM
if(RTC_GetFlagStatus(RTC_FLAG_INITS)==RESET) { // Initialization freezes clock so only perform this if new vbat/vdd power-up
PWR_BackupAccessCmd(ENABLE); // Enable access to RTC domain
RCC_LSEConfig(RCC_LSE_ON); // Turns on the external 768khz oscillator (if not already on)
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {}; // Wait until LSE is ready
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // Selects the external 768khz oscillator (LSE) for the RTC
RCC_RTCCLKCmd(ENABLE); // Enable the RTC Clock
RTC_StructInit(&RTC_InitStruct); // Set RTC_InitStruct to default values
RTC_InitStruct.RTC_HourFormat = RTC_HOUR_FORMAT;
RTC_Init(&RTC_InitStruct);
#if defined(USE_EEPROM)
// Get rtc_calib_val from EEPROM
eeprom_bytes = 2;
if(sEE_ReadBuffer((uint8_t*)&rtc_calib_val,EEPROM_RTC_CAL_OFFSET,(uint32_t*)&eeprom_bytes)==sEE_FAIL) {
rtc_calib_val = RTC_CALIB_VAL; // Set to default value defined in mydefs.h if EEPROM read fails
} else while(eeprom_bytes) {}; // Wait for DMA to complete reading into buffer
#else
rtc_calib_val = RTC_CALIB_VAL; // Set to default value defined in mydefs.h if EEPROM read fails
#endif
Board_set_rtc_calib_val(rtc_calib_val);
PWR_BackupAccessCmd(DISABLE); // Disable access to RTC domain (must re-enable to set time and date or access internal backup RAM)
} // end if(RTC_GetFlagStatus(RTC_FLAG_INITS)==RESET)�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
... -> More -> Syntax Highlighter
May
Will impose moderation.JW
2017-05-25 01:47 PM
Thanks Tut! I'll give your code a try and see what happens