cancel
Showing results for 
Search instead for 
Did you mean: 

RTC Alarm Random Failures

Richard Lowe
Senior III

I have Alarm A and Alarm B both enabled. Alarm A is triggered every second, Alarm B is triggered every minute.

They are rock solid for hours to days, but at seemingly random times, the RTC freezes.

Here is AlarmA handler:

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
	RTC_AlarmTypeDef sAlarm;

	HAL_RTC_GetAlarm(hrtc, &sAlarm, RTC_ALARM_A, FORMAT_BIN);

	sAlarm.AlarmTime.Seconds = (sAlarm.AlarmTime.Seconds > 58) ? 0 : sAlarm.AlarmTime.Seconds + 1;

	while(HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK){}

	osEventFlagsSet(SystemEventHandle, EVENT_CLOCK);
}

 

And this is Alarm B handler:

void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef * hrtc)
{
	RTC_AlarmTypeDef sAlarm;
	uint32_t hobb_time;

	hobb_time = HAL_RTCEx_BKUPRead(hrtc, RTC_BKP_DR1);

	// Write the new hobbs incremented value to backup register
	HAL_RTCEx_BKUPWrite(hrtc, RTC_BKP_DR1, ++hobb_time);
	HAL_RTC_GetAlarm(hrtc, &sAlarm, RTC_ALARM_B, FORMAT_BIN);

	sAlarm.AlarmTime.Seconds = (sAlarm.AlarmTime.Seconds == 0) ? 59 : sAlarm.AlarmTime.Seconds - 1;

	while(HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK){}

	osEventFlagsSet(SystemEventHandle, EVENT_HOBBS);
}

 

Nothing out of the extra ordinary except for one piece of code, I am incrementing the value stored in the backup register every minute.

Anyone have any experience with RTC alarms and inconsistency?

 

6 REPLIES 6

Is there any low-power mode involved? How is VBAT connected?

> RTC freezes

What does it exactly mean? Have you read out and checked the RTC registers' content to find out RTC_TR does not advance, or any other symptoms?

JW

Piranha
Chief II

When the RTC increments the seconds while your code is incrementing the alarm values, you end up setting the alarm to a time, which is already the current time. I'm not absolutely sure, but probably the alarm will not be triggered in such case.

Periodic minute or second alarms can be achieved by just setting an alarm on 0 seconds or PREDIV_S subseconds respectively. That way one doesn't have to reconfigure the alarm continuously and it also avoids the race conditions.

Not using any low-power modes. VBAT is connected. Using the STM32H747I-Eval board.

I'd love to check out the registers, but it fails randomly somewhere between 6 and 11 hours into operation.
No other symptoms.

Piranha, I'd love to understand what you are saying about setting the slams to 0 seconds and having that work continuously. I'd tried several iterations of something like that only to find the alarm triggers a single time. 

I did take your advice and change the code a bit in hopes of avoiding some type of race condition. Here is the alarm handler now:

 

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
	RTC_AlarmTypeDef sAlarm;
	RTC_TimeTypeDef  sTime;
	RTC_DateTypeDef  sDate;

	HAL_RTC_GetTime(hrtc, &sTime, RTC_FORMAT_BIN);
	HAL_RTC_GetDate(hrtc, &sDate, RTC_FORMAT_BIN);
	HAL_RTC_GetAlarm(hrtc, &sAlarm, RTC_ALARM_A, FORMAT_BIN);

	sAlarm.AlarmTime.Seconds = (sTime.Seconds > 58) ? 0 : sTime.Seconds + 1;

	while(HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK){}

	osEventFlagsSet(SystemEventHandle, EVENT_CLOCK);
}

 

So far it is stable, but it's only been in operation for a few hours. The main change is getting the current time and setting the alarm based on that, instead of setting the alarm based on the previous alarm setting.

Please elaborate on your solution for setting the alarm so I don't have to reconfigure the alarm at each handler callback.

Piranha
Chief II

The problem is in the fact that you are not reading the reference manual and therefore do not understand what the hardware does.

// Minute alarm
sAlarm.AlarmTime.Seconds = 0;
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY | RTC_ALARMMASK_HOURS | RTC_ALARMMASK_MINUTES;

// Second alarm
sAlarm.AlarmTime.SubSeconds = RTC->PRER & RTC_PRER_PREDIV_S;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;

 

P.S. As almost everything in the HAL/Cube broken bloatware, the RTC read code is also broken:

https://community.st.com/t5/stm32-mcus-embedded-software/32f417-rtc-errata-sheet-if-reading-subseconds-is-this-code-ok/m-p/207827

I have, in fact, read the reference manual. Certainly, I missed something. Use of HAL libraries are out of convenience and agree they can be seriously bloated but I don't see any harm in using them in this case.

My query was directed to you in clarification of what you had previously presented. It sounded like you could set the alarm once and have perpetual interrupts without having to reset the alarm.  That intrigued me because the reference manual eludes to an interrupt that is singular. But it is, unclear at best.

I appreciate your code in the response, and really like the use of the SubSeconds register in use of the alarm rather than the seconds. Thank you for that.

It does appear that the interrupt is perpetual! 

RTC_AlarmTypeDef sAlarm = {0};
	
/** Enable the Alarm A */
sAlarm.AlarmTime.SubSeconds = RTC->PRER & RTC_PRER_PREDIV_S;
sAlarm.AlarmMask = RTC_ALARMMASK_ALL;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
sAlarm.Alarm = RTC_ALARM_A;

if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
{
    Error_Handler();
}

Thanks Piranha.