Skip to main content
MMarx.1
Associate
February 3, 2023
Solved

STM32L0 GetTime after Stop returns hours > 24 or pm in 24h Mode unpredictable

  • February 3, 2023
  • 4 replies
  • 3695 views

Using RTC with LSI Clock, BinaryMode and 24h Format.

HAL_RTC_GetTime/Date returns unpredictable values after stop mode crossing midday or midnight:

  1. hours value above 24h. see a)
  2. "pm" (Timeformat "64") in 24h Mode, which is sometimes wrong additionally, which prevents correction. see b & c
a)
INFO: Entering Sleep for 28763463 ms (approx. 8h)
INFO: StartSleep DateTime: 23/01/29, 20:50:33 TimeFormat:0
INFO: EndSleep DateTime: 23/01/29, 28:49:56 TimeFormat:0 -> Should be 23/01/30, 04:49:56
 
b)
INFO: Entering Sleep for 28765979 ms (approx. 8h)
INFO: StartSleep DateTime: 23/01/31, 05:33:32 TimeFormat:0
INFO: EndSleep DateTime: 23/01/31, 01:32:58 TimeFormat:64 -> Should be 13:32:58 and TimeFormat:0
 
c) early IRQ wakeup (approx. 6.5h)
INFO: StartSleep DateTime: 23/02/01, 05:32:20 TimeFormat:0
INFO: EndSleep DateTime: 23/02/01, 12:00:58 TimeFormat:64 -> Should be TimeFormat:0

unsigned int sleep(unsigned int sleepDuration){	
	RTC_TimeTypeDef startTime;
	RTC_DateTypeDef startDate;
	RTC_TimeTypeDef endTime;
	RTC_DateTypeDef endDate;
	
	HAL_RTC_GetTime(&hrtc, &startTime, RTC_FORMAT_BIN); // Read GetDate after GetTime to keep RTC working!!!
	HAL_RTC_GetDate(&hrtc, &startDate, RTC_FORMAT_BIN); // Necessary to keep rtc working
	debugf("INFO: StartSleep %s\n", getDateTimeString(&startTime, &startDate));
	
 GPIO_Sleep();		// Disable GPIO (->Analog)
 /* RTC interrupt Init */
 // max 0xFFFF seconds = 18,2 hours; 0: 1 Second
 HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, MIN((sleepDuration / 1000u) -1u, 0xFFFFu), RTC_WAKEUPCLOCK_CK_SPRE_16BITS); // Don't use 17Bit (36h), because of 24H overflow
 HAL_SuspendTick(); // Disable INT and keep current value
 // ####### Enter STOP mode ##########
 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
 
 SystemClock_Config();
 HAL_ResumeTick(); // Enable INT and continue counting
 GPIO_Wakeup();		// Enable GPIO		
 HAL_RTC_WaitForSynchro(&hrtc);
 
 HAL_RTC_GetTime(&hrtc, &endTime, RTC_FORMAT_BIN); // Read GetDate after GetTime to keep RTC working!!!
 HAL_RTC_GetDate(&hrtc, &endDate, RTC_FORMAT_BIN); // Necessary to keep rtc working		
 debugf("INFO: EndSleep %s\n", getDateTimeString(&endTime, &endDate));		
 sleepDuration = sleepDuration - (elapsedSeconds(&startTime, &startDate, &endTime, &endDate) * 1000u);	
	uwTick += sleepDuration; // Atomic access to Base Tick Count
	return sleepDuration;
}

Does anyone know the reason for it, or has a workaround?

This topic has been closed for replies.
Best answer by waclawek.jan

At this point I have no more ideas, sorry.

You may want to take this to ST directly, maybe through the web support form.

JW

4 replies

waclawek.jan
Super User
February 3, 2023

Does the real wakeup time match the expected time?

What is in the wakeup ISR?

Is the power supply rock stable all the time while the mcu is in sleep? What is the VDD voltage?

Is there any code which writes to the RTC? If so, isn't there an uninitialized struct used in it?

JW

MMarx.1
MMarx.1Author
Associate
February 3, 2023

Yes, the real wakeup time matches the expected time, thus HAL_RTCEx_SetWakeUpTimer_IT is working correctly. But I need the sleepduration in case of EXTI wakes up the uC early.

WakeUp ISR (When not in sleep, I'm using the WakeupTimer as a software watchdog, which never has elapsed):

void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
	if (sleeping)
		wakeUpReason = WakeUpTimer;
	else {
		debugf("ERROR: Software Watchdog elapsed. Restarting Device!\n");
		resetSystem();
	}
 
 /* Clear Wake Up Flag */
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // May be used with uC Standby instead of Stop
}

Power supply is from 2 AA batteries above 2,5V. Should be absolut stable, due to no other consumers during sleep.

RTC is written in awake state when receiving ntp time from network. GetTime/Date afterwards works correctly.

RTC_DateTypeDef date = {0};
RTC_TimeTypeDef time = {0};
if (!parseDate(&resp[6], &date) && !parseTime(&resp[15], &time))
 setDateTimeWithCompensation(&time, &date);
 
HAL_StatusTypeDef setDateTimeWithCompensation(RTC_TimeTypeDef * pTime, RTC_DateTypeDef * pDate) {
	#define RTC_ASYNC_PREDIVIDER 8u // 0..127 Bigger is better for power consumption. Smaller is better for accuracy
 
hrtc.Init.AsynchPrediv = RTC_ASYNC_PREDIVIDER;	// 0 and 127
hrtc.Init.SynchPrediv = (uint32_t) (currentDivider / RTC_ASYNC_PREDIVIDER); // 0 and 32 767
ret = HAL_RTC_Init(&hrtc);
if (!ret)
 ret = setDateTime(pTime, pDate);
return ret;
}

hrtc is global HAL init struct (initialised).

date and time are initialised to {0}, relevant fields are written in parseDate/Time, only.

waclawek.jan
waclawek.janBest answer
Super User
February 3, 2023

At this point I have no more ideas, sorry.

You may want to take this to ST directly, maybe through the web support form.

JW

MMarx.1
MMarx.1Author
Associate
February 13, 2023

Hi Jan, Thank you for your advice. I've send an support request to st, but they were not ablet to reproduce the failure. I've a new hardware revision now, and it seems that the failure doesn't occure anymore. Maybe it was a Voltage drop during run mode.

waclawek.jan
Super User
February 3, 2023

Perhaps there is one: read out RTC_CR content and print it out together with the time and date.

JW

MMarx.1
MMarx.1Author
Associate
February 13, 2023

Unfortunately I did my last tests with the revised hardware, which didn't produce the failure. I always got dezimal 17412 from CR register. What was your idea with that? Would like to find a solution for old hardware , too.