cancel
Showing results for 
Search instead for 
Did you mean: 

How to generate periodic alarm interrupt from RTC

HBavi.1
Associate III

Hello,

I am quite new to STM32G0 based development. I want to generate periodic alarm interrupt from RTC (e.g. RTC should generate an interrupt at every 5 minute, 4 second and 400msec). Is it possible to generate interrupt like this? I tried various ways but none of them worked. Any clue or support in this regard would be appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions
Peter BENSCH
ST Employee

Subseconds (RTC_SSR) are often misunderstood because they don't count up but count down:

"The ck_apre clock is used to clock the binary RTC_SSR subseconds downcounter. When it reaches 0, RTC_SSR is reloaded with the content of PREDIV_S."

With a clock of 32768Hz, PREDIV_S (the 15bit synchronous predivider) is normally set to 256-1. Due to the downcounter you have to think the other way around in order to program a time difference for a future interrupt, i.e. subtracting it from the current value and correct the underflow, like e.g.:

// for 32kHz, PREDIVS=255 --> e.g. 80/256*1s=312.5ms
uint32_t subseconds_diff = 80; // example
// threatens underflow?
if (subsecond < subseconds_diff)
{
  // yes, add PREDIV_S+1 first:
  subsecond = subsecond+hrtc->Init.SynchPrediv+1-subseconds_diff;
  next_second++;
}
else
{
  subsecond -= subseconds_diff;
}

Please insert the following lines to get the next alarm:

// mask date and weekday as only hh:mm:ss:sss is of interest:
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
 
// use subseconds:
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
 
// alarm is not triggered if missing:
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.Alarm = RTC_ALARM_A;

BTW: please use the Code Snippet button </> to insert source code.

When your question is answered, please close this topic by choosing Select as Best.

/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

8 REPLIES 8
Peter BENSCH
ST Employee

Yes, this can be done using the RTC, which can be clocked by either HSE, LSE or LSI.

Just activate clock source for the RTC, enable the Internal WakeUp, set the WakeUp Counter and don't forget to enable the RTC global interrupt.

When your question is answered, please close this topic by choosing Select as Best.

/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
HBavi.1
Associate III

Isn't it possible to handle it using Alarm? I am unable to understand how SubSecond, SubSecondFraction and SubSecondMask works in case of STM32G0.

In the below example, I am trying to generate interrupt at every 1.5msec?

 hrtc.Instance = RTC;

 hrtc.Init.HourFormat = RTC_HOURFORMAT_24;

 hrtc.Init.AsynchPrediv = 32;

 hrtc.Init.SynchPrediv = 1024;

 hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;

 hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;

 hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;

 hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

 hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;

 sAlarm.AlarmTime.Hours = 0x0;

 sAlarm.AlarmTime.Minutes = 0x0;

 sAlarm.AlarmTime.Seconds = 0x1;

 sAlarm.AlarmTime.SecondFraction = 512;

 sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;

 sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;

 sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;

 sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;

 sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;

 sAlarm.AlarmDateWeekDay = 0x1;

 sAlarm.Alarm = RTC_ALARM_A;

I reload alarm value at every interrupt.

Can you give some hint?

Peter BENSCH
ST Employee

An alarm is best used when you want to receive interrupts at absolute time values, e.g. at 5pm for your tea time. :D

You must always set the RTC to a start time of 00:00:00.000 if you want to use the alarm for time differences. If you did this, your code mentioned above would trigger an interrupt at 00:00:01.512 i.e. after 1.512 seconds. Without resetting the RTC to 0:00:00.000, the next alarm would be triggered 24 hours later.

"Periodic Alarm" sounds like just one frequency, so I understood your request as an interrupt every 05:04.4 minutes, but you probably mean interrupts after 5 minutes, after 4 seconds, and after 0.4 seconds, so all in all three interrupts, right?

For these time differences, the internal wake-up is possibly the best solution, since the largest interval is 5min/0.4sec=150, which could be covered with the 16bit wake-up counter and one setting for the predividers.

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
HBavi.1
Associate III

Dear Peter,

Thank you for your response. I've scenario where I need to set an interrupt which is user configurable and time varies from hours to milli second. I am really not sure whether wakeup counter can serve this purpose. For an example, user can configure interrupt at every 9 hours, 9 minutes, 9 second and 9 millisecond.

I also understand Periodic Alarm logic and to handle the requirement I've, I incremented alarm periodically based on second, minutes and hour value. Using the below code, I achieved generating periodic interrupt using alarm but somehow millisecond part is not working as expected. If you could help me to resolve this issue, it would be of great help.

HBavi.1
Associate III

I've attached image for your reference. Somehow millisecond handling is not working as expected. It would be great if you could suggest better way to handle millisecond interrupt.

0693W000005Bl34QAC.png

Peter BENSCH
ST Employee

Subseconds (RTC_SSR) are often misunderstood because they don't count up but count down:

"The ck_apre clock is used to clock the binary RTC_SSR subseconds downcounter. When it reaches 0, RTC_SSR is reloaded with the content of PREDIV_S."

With a clock of 32768Hz, PREDIV_S (the 15bit synchronous predivider) is normally set to 256-1. Due to the downcounter you have to think the other way around in order to program a time difference for a future interrupt, i.e. subtracting it from the current value and correct the underflow, like e.g.:

// for 32kHz, PREDIVS=255 --> e.g. 80/256*1s=312.5ms
uint32_t subseconds_diff = 80; // example
// threatens underflow?
if (subsecond < subseconds_diff)
{
  // yes, add PREDIV_S+1 first:
  subsecond = subsecond+hrtc->Init.SynchPrediv+1-subseconds_diff;
  next_second++;
}
else
{
  subsecond -= subseconds_diff;
}

Please insert the following lines to get the next alarm:

// mask date and weekday as only hh:mm:ss:sss is of interest:
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
 
// use subseconds:
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
 
// alarm is not triggered if missing:
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.Alarm = RTC_ALARM_A;

BTW: please use the Code Snippet button </> to insert source code.

When your question is answered, please close this topic by choosing Select as Best.

/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

> I am really not sure whether wakeup counter can serve this purpose.

Why not?

Have you read the Periodic auto-wakeup subchapter of RTC chapter in RM?

JW

Hello JW,

Problem is Wakeup Counter doesn't support if resolution is in msec and range is bit higher. For an example if I want to generate an interrupt at every 24 hours 44 minute 16 second and 550 msec then I wakeup counter doesn't serve the purpose. If you have different opinion then do let me know.

BR,

HB