RTC Alarm Modes

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hello All,

   

I am working with the RTC component. I would like to schedule an alarm to trigger on time intervals relative to a set time. For example:

   

Start time = 10:20:32

   

Next alarm interval = Start time + 10 seconds = 10:20:42

   

"Next Next" alarm interval = Start time + 20 seconds = 10:21:02

   

I thought that this might be possible using the RTC's Alarm functionality. I wrote the following code to test it (with the other supporting code for the RTC of course):

   

RTC_WriteAlarmMask(RTC_ALARM_SEC_MASK);

   

RTC_WriteAlarmSecond(10u);

   

Unfortunatley, this seems to not work. I may need to provide a full date and time to compare to. Does anyone have experience dealing with this sort of thing?

   

Thank you.

0 Likes
1 Solution
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Think of the RTC alarm as a cron job specification: it takes the alarm register values specified by the alarm register mask, and compares them to the current time registers. If they all match, it triggers the alarm. (See data sheet page 21) So you need to take the time difference for the next alarm, add it to the current time, and set this as the alarm register values.

View solution in original post

0 Likes
10 Replies
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Think of the RTC alarm as a cron job specification: it takes the alarm register values specified by the alarm register mask, and compares them to the current time registers. If they all match, it triggers the alarm. (See data sheet page 21) So you need to take the time difference for the next alarm, add it to the current time, and set this as the alarm register values.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You are right, different from your alarm-clock you have to specify not only a time but a date as well. Of course you can read-out the RTC and provide the alarm with the current date the clock provides.

   

When you want to keep track of several different alarm-times you will have to build a list of events (ordered by time) and create new events when the first occurs. This smells a bit as if you could use a linked-list.

   

 

   

Bob

Anonymous
Not applicable

 Thank you for all your replies. Further research into the source code has determined that it is a direct comparison. For example:

   

alarm.sec == currentTime.sec

   

I have come up with an idea for a function:

   

RTC_TIME_DATE addInterval(RTC_TIME_DATE currentTime, RTC_TIME_DATE increment)

   

This function would return a structure with fields that reflect currentTime + increment. The question that I have now is would this lead to a memory leak?

   

If I used the code:

   

RTC_TIME_DATE nextTime;

   

for(;;)

   

{

   

//Assume that arguments are valid

   

nextTime = addInterval(RTC_GetCurrentTime(), 4_MIN_INCREMENT);

   

}

   

Wouldn't this cause nextTime to continue to be reassigned to a new struct created in local memory in the function addInterval? Is there a way to use free() on the nextTime pointer before reassigning it?

   

Thank you

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Typically such function take a pointer to the data structure, so the caller can control it. Your function would look like

   
void addInterval(RTC_TIME_DATE *currentTime, RTC_TIME_DATE *increment, RTC_TIME_DATE *target)
   

and the main code then has three fixed instances, and calls it like

   
addInterval(&currentTime, &increment, &alarmTime);
   

That way there is not memory leak.

0 Likes
Anonymous
Not applicable

 hli,

   

Thanks for your input. I agree that that method is probably best. I ended up using the following code:

   

 

   

RTC_TIME_DATE* currentTime;

   

RTC_TIME_DATE interval; //Holds the time that an interval will run

   

RTC_TIME_DATE nextConnectTime; //Holds the next time that the system is expected to connect

   

 

   

 

   

currentTime = RTC_ReadTime();

   

addInterval(currentTime, &interval, &nextConnectTime);

   

 

   

Since currentTime is a pointer, everytime you reassign it, it should simply change the memory location it is pointing to. This should prevent any potential memory leaks. So far, this method seems to work, but I haven't run it for an extended period of time to ensure that it does not crash.

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Yes, this is the proper way to do it. RTC_ReadTime propably return the same pointer each time, but even if not (the documentation says nothing about it) you can trust it not to leak memory.

   

Just checked the component source code - the method is implemented as:

   
    return (&`$INSTANCE_NAME`_currentTimeDate); 
   

So you get a constant value. Therefore note the documentation on this method:

   
* Side Effects: *  You should disable the interrupt for the RTC component before calling any *  read API to avoid an RTC Counter increment in the middle of a time or date *  read operation. Re-enable the interrupts after the data is read. 
   

The value you get a pointer to will change otherwise...

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

This is exactly what CyEnterCriticalSection() and CyExitCriticalSection() are made for: just to temporarily disable interrupts and restore them back again to the prior state, regardless what that state (en- or disabled) was. Find the description in "System Reference Guide" under Creator -> Help -> Documentation ->system Reference.

   

 

   

Happy coding

   

Bob

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Unfortunately the data sheet for the RTC is silent about this issue - for RTC_ReadTime it says "side effect - none". The comment is only in the component source code.

0 Likes
Anonymous
Not applicable

 The only thing that makes sense it that they would return the current time struct. This is exactly the kind of thing that an interrupt going off in the middle of the read could cause trouble. My thought is that I should probably use some kind of "copy" method.

   

RTC_TIME_DATE* currentTime;

   

RTC_TIME_DATE timeStamp;

   

currentTime = RTC_ReadTime();

   

//Copy time would copy the pertinent values from the RTC timer to a struct being used for manipulation

   

CyEnterCriticalSection();

   

copyTime(currentTime, &timeStamp);

   

CyExitCriticalSection();

   

//At the end of this, the timeStamp variable has the current time without needing to wory about the timer changing on us.

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Yes, when you don't want to do all your calculation / update stuff in the critical section, copying the time structure (a simple memcpy should be OK) is advisable. But you should include the ReadTime() call in the critical section too (just to be sure).

0 Likes