cancel
Showing results for 
Search instead for 
Did you mean: 

RTC has wrong value after _WFI()

ricardomiguel
Associate II
Posted on August 24, 2016 at 16:23

I noticed some problems with the RTC value after waking up from an interrupt (_WFI() instruction) so I made this code to test it out. It prints RTC value in seconds since the epoch and sleeps after 5s:


sysclock_reset();


while
(1)

{

int
passed = 0;


printf
(
''\r\n''
);

while
(passed < 5)

{

uint32_t secs = sysclock_get_secs();


if
(secs != last_secs)

{

++passed;

last_secs = secs;

printf
(
''[%d]\r\n''
, (
int
)secs);

}

}


printf
(
''\r\n''
);


HAL_SuspendTick();

__WFI();

HAL_ResumeTick();


sysclock_reset();

sysclock_reset();

}

In this case the interrupt is me pausing the debug session and resuming it. This is the output:


sysclock reset at 1472047415 seconds 2500 ms


[1472047415]

[1472047416]

[1472047417]

[1472047418]

[1472047419]


sysclock reset at 1472047415 seconds 6501 ms

sysclock reset at 1472047423 seconds 6506 ms

So basically, I reset my sysclock at 2.5s since the MCU woke up, print the seconds for 5s and go to sleep. Right after that I wake up and reset the clock again, but the function HAL_RTC_GetTime returns the same value as before (function returns HAL_OK). I realised that this only happens once and right after the first time the MCU wakes up from _WFI(), the next iterations are ok. Debugging in the HAL_RTC_GetTime function I realised that the TR register is not being updated, if I have a breakpoint in

1.
/* Get the TR register */
2.
tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK);

and put the cursor on top of TR it gives me the wrong value for the first time, and the right one at the next. According to the definition the register is volatile, so what can be doing this? Thanks for the help, here is my RTC initialization code:


void
cfg_rtc(RTC_HandleTypeDef* rtc)

{

__HAL_RCC_RTC_ENABLE();

__HAL_RTC_RESET_HANDLE_STATE(rtc);


rtc->Instance = RTC;

rtc->Init.HourFormat = RTC_HOURFORMAT_24;

rtc->Init.AsynchPrediv = RTC_ASYNCH_PREDIV;

rtc->Init.SynchPrediv = RTC_SYNCH_PREDIV;

rtc->Init.OutPut = RTC_OUTPUT_DISABLE;

rtc->Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;

rtc->Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;


HAL_StatusTypeDef status = HAL_RTC_Init(rtc);


assert
(status == HAL_OK);

}

2 REPLIES 2
Posted on August 24, 2016 at 17:03

While I'm sure this makes a whole lot of sense to you, those of us without much context to work from would need to see more info.

What STM32 part are we talking about?

What does sysclock_get_secs(); do? exactly?

Doesn't the RTC have a feature where reading the date/time freeze one of the measurements so you can get an atomic value? Can't remember the order, and don't have a specific part to look at the right manual.

Try to avoid viewing in the debugger, it reads things and alters reality sufficiently that you can't clearly understand what the hardware is doing. If you want to see registers, printf() them. And take a more hands-off approach to debugging rather than sticking your hands in the gears.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Walid FTITI_O
Senior II
Posted on August 24, 2016 at 17:42

Hi nunes.ricardo;

What sysclock_reset() do ? where you are calling the cfg_RTC() in main?

Anyway, there is no need to use sysclock reset function to reconfigure or reinitialize clock controller  and RTC peripherals after exiting the sleep mode, because the clock controller configuration remains in the previous programmed state. That maybe your source of conflict.

Be careful to another point: to debug a device in low power mode, you should set DBG_SLEEP bit in DBGMU_CR register. Since the RTC is used accross the application set the DBG_RTC_STOP in DBGMCU_APB1_FZ register.

-Hannibal-