cancel
Showing results for 
Search instead for 
Did you mean: 

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

MMarx.1
Associate II

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?

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

6 REPLIES 6

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
Associate II

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.

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

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

JW

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.

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.