cancel
Showing results for 
Search instead for 
Did you mean: 

RTC Alarm interrupt skipped sometimes

Florian Moser
Senior

Hi all!

uC: STM32L433VCT

CubeMX, CubeIDE, CubeProgrammer

I've configured my RTC to set an alarm every minute. When an alarm occurs, the next alarm gets set and so on.

About once to twice a day, the rtc alarm is skipped, so there's a continous error, because no future alarms are set.

My function to calculate the next alarm is correct (rtc_get_next_time()) and the alarm was set to the correct time, regarding to the rtc handle (RTC_HandleTypeDef hrtc;) Just the alarm interrupt doesn't get triggered.

It is not happening at the same time of the day, it's pretty random. It never happend from 23:xx to 0:xx.

Here's how I set the alarm:

void main_set_rtc_alarm(uint8_t hour, uint8_t minute, uint8_t second)
{
	RTC_AlarmTypeDef sAlarm = {0};
	sAlarm.AlarmTime.Hours = hour;
	sAlarm.AlarmTime.Minutes = minute;
	sAlarm.AlarmTime.Seconds = second;
	sAlarm.AlarmTime.SubSeconds = 0x0;
	sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
	sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
	sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
	sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
	sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
	sAlarm.AlarmDateWeekDay = 0x1;
	sAlarm.Alarm = RTC_ALARM_A;
 
	HAL_StatusTypeDef state = HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
 
	if (state != HAL_OK)
	{
		Error_Handler();
	}
}

When the alarm occurs:

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
	timestamp_t next = rtc_get_next_time(rtc_get_current_time(),delay); // delay is 60s
        main_set_rtc_alarm(next.hour, next.minute, next.second);
}

I know this only works correct for delays up to 24h. That's just for testing purposes.

There are lots of different interrupts in this program. Maybe this causes the problem?

Thank you!

20 REPLIES 20

You read the RTC time. It happens to be 1 minute, 59 seconds and 999.99 msec. You set the alarm for 2 seconds. Between the time you read TOD and set alarm the TOD rolls over to 2 seconds. You just missed the interrupt.

The fix is to verify minutes have not rolled over after setting alarm.

Jack Peacock

Ahhhh, now I see what you mean.

That's a very good tips, thanks!

Ok, I'll do that the next time it happens.

Yeah, I'll try that.

Another function is called in the RTC interrupt and this function is not called if no interrupt happens.

That's what it looks like exactly:

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
        application_save(); //save data to sd card
	timestamp_t next = rtc_get_next_time(rtc_get_current_time(),delay); // delay is 60s
        main_set_rtc_alarm(next.hour, next.minute, next.second);
}

Florian Moser
Senior

Everytime the rtc interrupt is missing, I saved Error 43 to the sd card.

It happend more often then I thought.

[19.08.2020 14:45:18] Errors: 43
[19.08.2020 15:05:17] Errors: 43
[19.08.2020 16:30:16] Errors: 43
[19.08.2020 16:35:15] Errors: 43
[19.08.2020 16:45:14] Errors: 43
[19.08.2020 17:55:13] Errors: 43
[19.08.2020 18:10:12] Errors: 43
[19.08.2020 18:15:11] Errors: 43
[19.08.2020 18:40:10] Errors: 43
[19.08.2020 18:45:10] Errors: 43
[19.08.2020 18:55:09] Errors: 43
[19.08.2020 19:35:08] Errors: 43
[19.08.2020 20:50:07] Errors: 43
[19.08.2020 21:20:06] Errors: 43
[19.08.2020 21:45:05] Errors: 43
[19.08.2020 21:55:04] Errors: 43
[19.08.2020 22:25:04] Errors: 43
[19.08.2020 22:55:04] Errors: 43
[19.08.2020 23:10:01] Errors: 43
[20.08.2020 00:20:00] Errors: 43
[20.08.2020 01:05:59] Errors: 43
[20.08.2020 02:15:58] Errors: 43
[20.08.2020 02:45:57] Errors: 43
[20.08.2020 03:50:56] Errors: 43
[20.08.2020 04:00:55] Errors: 43
[20.08.2020 04:25:54] Errors: 43
[20.08.2020 04:40:53] Errors: 43

It's noticable that is has something to do with 5 minutes.

Every 5 minutes a lpwa module gets enabled in my program. There's a lot of uart communication going on.

Is it possible that the rtc alarm gets delayed because of the uart interrupts?

They have the same priority.

The probability that what Jack said would happen would be very high.

Fail:

0693W000003PvprQAC.jpg0693W000003PvpwQAC.jpg

success:

0693W000003Pvq1QAC.jpg

0693W000003Pvq6QAC.jpg

That was not the case. I check the RTC after setting the alarm and the TOD didn't roll over, but the alarm a interrupt still does not occur every minute.

The registers are essentially identical (next time you should present them in hexadecimal, decimal is mostly useless in microcontrolers settings). Namely. RTC_ISR.ALRAWF is set in both cases (while interrupt is enabled by RTC_CR.ALRAIE). So the problem is probably not there.

RTC alarms are EXTI18, so you should look at the EXTI registers and finally at the NVIC registers to find out why you don't have an interrupt.

Also, make sure you are indeed looking at the interrupt (e.g. by toggling a pin directly at the IRQ routine entry), and not just being tangled into some Cube/HAL nonsense tacked onto it.

JW

Ok, that's good to know. I forgot to set it to hex because I mostly use this view in dec, next time I'll set it to hex!

I don't really know how to check the EXTI registers. I've implemented it like that now and waiting for the error to occur:

uint32_t volatile nvic_test = NVIC_GetEnableIRQ(RTC_Alarm_IRQn);
EXTI_HandleTypeDef hexti;
HAL_EXTI_GetHandle(&hexti,EXTI_LINE_18);

I'm also toggling a pin at the IRQ routine entry now.

Thanks for your help!

The interrupt was enabled in the nvic, so nvic_test was 1.

hexti.Line = 0x12000012;

hexti.PendingCallback = 0x20006270 <htim15>

The pin was set, but void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) hasn't been called.

That's how I toggle the pin:

void RTC_Alarm_IRQHandler(void)
{
  /* USER CODE BEGIN RTC_Alarm_IRQn 0 */
	//RTC_DEBUG
  rtc_debug_pinstate = HAL_GPIO_ReadPin(RTC_DEBUG_GPIO_Port, RTC_DEBUG_Pin);
  rtc_debug_pinstate = !rtc_debug_pinstate;
  HAL_GPIO_WritePin(RTC_DEBUG_GPIO_Port, RTC_DEBUG_Pin, rtc_debug_pinstate);
  /* USER CODE END RTC_Alarm_IRQn 0 */
  HAL_RTC_AlarmIRQHandler(&hrtc);
  /* USER CODE BEGIN RTC_Alarm_IRQn 1 */
 
  /* USER CODE END RTC_Alarm_IRQn 1 */
}

rtc_debug_pinstate was GPIO_PIN_SET when HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) was skipped. The GPIO Pin is high, so the interrupt occured correctly, but it seems HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) hasn't been called this time.

Florian Moser
Senior

I'm really confused right now.

My IRQ handler looks like this:

void RTC_Alarm_IRQHandler(void)
{
  rtc_debug_pinstate = HAL_GPIO_ReadPin(RTC_DEBUG_GPIO_Port, RTC_DEBUG_Pin);
  rtc_debug_pinstate = !rtc_debug_pinstate;
  HAL_GPIO_WritePin(RTC_DEBUG_GPIO_Port, RTC_DEBUG_Pin, rtc_debug_pinstate);
 
  application_rtc_alarm();
 
  HAL_RTC_AlarmIRQHandler(&hrtc);
}

The pin get's toggled correctly everytime...

Here's was happens in application_rtc_alarm:

void application_rtc_alarm(void)
{
	rtc_reset_security_timer();
	application_save_interval();
	application_set_next_alarm();
}
 
 
void rtc_reset_security_timer(void)
{
	rtc_security_counter = 0;
	rtc_security_counter_max = 0;
}
 
void application_save_interval(void)
{
	if(!application_should_save && !application_saving)
	{
		application_should_save = 1;
	}
	else error_handle(APP_ALREADY_SAVING,SOFT);
}
 
void application_set_next_alarm(void)
{
	if(!application_set_next_alarm_var) application_set_next_alarm_var = 1;
	else error_handle(RTC_ALARM_ALREADY_PENDING,SOFT);
}

rtc_reset_security_timer() should reset the security timer, but that seems not to happen, because it counts till rtc_security_counter = 62 and rtc_security_counter_max = 63.

There's also no sign that application_save_interval() and application_set_next_alarm() have been called.

But as I said, the pin is toggled correctly everytime...