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.
1 of 1 people found this helpful
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.
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:
//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?
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(¤tTime, &increment, &alarmTime);
That way there is not memory leak.
Thanks for your input. I agree that that method is probably best. I ended up using the following code:
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.
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:
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...
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.
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.
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.
currentTime = RTC_ReadTime();
//Copy time would copy the pertinent values from the RTC timer to a struct being used for manipulation
//At the end of this, the timeStamp variable has the current time without needing to wory about the timer changing on us.
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).