Skip to main content
tarasov.alex.m
Associate II
May 15, 2019
Solved

Is there a way to maintain RTC ticking without any shifts while performing a power reset?

  • May 15, 2019
  • 15 replies
  • 3350 views

/*UPDATE*/

It turned out that im my case the problem was in the start up routine:

There was a "Start up" project (written not by me) that was downloaded at 0 flash address and it was jumping to another address where my project was located.

I did not know that in this "Start up" project there was an RTC initialization (which prevented my RTC from running continuously).

Everything below this sentence is what I wrote before I knew where the problem is.

Good day!

I'm using RTC in a STM32F407VG controller.

I configured RTC_ALARM_A to generate an interrupt every second (this indicates when a second changes in RTC). By this interrupt, an oscilloscope and a reference 1Hz clock from another device (that is not being reset) I watch whether my RTC is ticking consistently.

With this setting it can be seen if MCU's RTC is shifting during power reset. And that's exactly what I'm observing (don't know the absolute value of the time shift, but I see that the phase of MCU's 1Hz clock output is changing randomly after power reset is done).

Can anyone tell me if there is anything that can be done to make RTC run continгously, even when a power reset is performed?

Also this things need to be mentioned:

  • I do use a battery for RTC and clocks are ticking while MCU is not powered.
  • I am not reinitializing the RTC periphery each time.
  • Backup registers preserve their values, so no "Backup domain reset" occures.
  • RTC clock is consistent during "System reset", this behavior is only seen when "Power reset" is done
This topic has been closed for replies.
Best answer by waclawek.jan

And in the startup code, i.e. before main(), what code is there?

JW

15 replies

waclawek.jan
Super User
May 15, 2019

> Is there a way to maintain RTC ticking without any shifts while performing a power reset?

Yes, don't call the Cube/HAL init routine.

https://community.st.com/s/question/0D50X00009XkgBWSAZ/stm32-rtc-loses-one-second-after-each-reset and maybe a dozen of other threads here.

JW

tarasov.alex.m
Associate II
May 16, 2019

Thanks for your answer, but I'd seen this thread. It didn't help. As I mentioned, I'm not reinitializing RTC each time the MCU restarts.

Posting my code below. 

tarasov.alex.m
Associate II
May 16, 2019

Here's my code 

void MX_RTC_Init(void){
 
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
 RCC_OscInitTypeDef RCC_OscInitStruct;
 
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
 
 hrtc.Instance = RTC;
 hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
 hrtc.Init.AsynchPrediv = RTC_ASYNCH_DIV - 1;
 hrtc.Init.SynchPrediv = RTC_SYNCH_DIV - 1;
 hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
 
 if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != RTC_SECRET_DATA){/*if RTC 
 was not previously iinitialized*/
 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
 HAL_RCC_OscConfig(&RCC_OscInitStruct);
 HAL_RTC_Init(&hrtc) ;
 rtc_date_time_config_frst_time();
 }else{/*if RTC was initialized, we only need to call HAL_RTC_MspInit*/
 HAL_RTC_MspInit(&hrtc);
 }
 rtc_alarm_a_set_it();
}
 
void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
{
 __HAL_RCC_RTC_ENABLE();
 HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 1, RTC_ALARM_IRQ_PRIO);
 HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
}
 
void rtc_alarm_a_set_it(void){
 RTC_AlarmTypeDef sAlarm;
 /**Enable the Alarm A 
 */
 sAlarm.AlarmTime.Hours = 0;
 sAlarm.AlarmTime.Minutes = 0;
 sAlarm.AlarmTime.Seconds = 0;
 sAlarm.AlarmTime.SubSeconds = 0;
 sAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT_24;
 sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
 sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
 sAlarm.AlarmMask = RTC_ALARMMASK_ALL;
 sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_None;
 sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
 sAlarm.AlarmDateWeekDay = 1;
 sAlarm.Alarm = RTC_ALARM_A;
 HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, FORMAT_BIN);
}

turboscrew
Senior III
May 16, 2019

CubeMX puts the RTC initialization there for every reset.

You need to make the change every time you generate code with CubeMX.

But if you have the backup battery, and you edit the code CubeMX generates, the RTC is reset only when you program the backup domain reset.

tarasov.alex.m
Associate II
May 16, 2019

Hi. I'm not using CubeMX's code, I do use a battery (I've checked the voltage on VBAT pin, is constanty 3V) and I don't see a backup domain reset taking place.

waclawek.jan
Super User
May 16, 2019

> if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != RTC_SECRET_DATA){/*if RTC

So, did you verify that this expression evaluates always false?

JW

tarasov.alex.m
Associate II
May 16, 2019

Yes I did. I use a debug LED in "rtc_date_time_config_frst_time"(line 22), so I know whether it was called.

tarasov.alex.m
Associate II
May 16, 2019

Also I found out that after power reset "RTC_PRER" register (the one that contains prescaler values) resets to its default value. That event takes place before executing anything in "main()". I placed a loop at the begining to ckeck that. This loop can be skipped only in debug mode, so when I enter debug mode after performing a power reset I know that nothing was previously executed in "main()".

waclawek.jan
waclawek.janBest answer
Super User
May 16, 2019

And in the startup code, i.e. before main(), what code is there?

JW

turboscrew
Senior III
May 16, 2019

The startup code (start.S). You can also put a breakpoint there. You don't have to wait for main.

 Usually, though, there is just the reset vector entry that has the address of _start, and the code under that label only branches to main.

turboscrew
Senior III
May 16, 2019

The rtc_date_time_config_frst_time() puts the RTC_SECRET_DATA to the backup register 0?

That's the way I've been doing too.

tarasov.alex.m
Associate II
May 17, 2019

Yes, that's it.

tarasov.alex.m
Associate II
May 17, 2019

MCU starts in a Reset_Handler, which in my case is this:

THUMB
 PUBWEAK Reset_Handler
 SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
 
 LDR R0, =SystemInit
 BLX R0
 LDR R0, =__iar_program_start
 BX R0

"SystemItinit" contains this code:

void SystemInit(void)
{
 /* FPU settings ------------------------------------------------------------*/
 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
 SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
 #endif
 /* Reset the RCC clock configuration to the default reset state ------------*/
 /* Set HSION bit */
 RCC->CR |= (uint32_t)0x00000001;
 
 /* Reset CFGR register */
 RCC->CFGR = 0x00000000;
 
 /* Reset HSEON, CSSON and PLLON bits */
 RCC->CR &= (uint32_t)0xFEF6FFFF;
 
 /* Reset PLLCFGR register */
 RCC->PLLCFGR = 0x24003010;
 
 /* Reset HSEBYP bit */
 RCC->CR &= (uint32_t)0xFFFBFFFF;
 
 /* Disable all interrupts */
 RCC->CIR = 0x00000000;
 
 /* Configure the Vector Table location add offset address ------------------*/
 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
}

As you see, nothing here appeals to RTC or LSE.

tarasov.alex.m
Associate II
May 17, 2019

Oh, I found the problem.

I began working on this project when a bunch of coding had allready been done, so it was not me who made the start up routine.

There is a "Start up" project that is downloaded at 0 flash address and it jumps to another address where another project (the one I'm working in) is located.

It turned out that there is a useless RTC initialization (RTC is not being used there).

Nevertheless it was quite silly of me not to think about that possibility.

@turboscrew​ and @Community member​ really appreciate your help!