Hello,
I'm absolutely loving the Teensy line of products -- they are solving so many immediate needs for our projects that used to require a number of special-purpose boards.
We're wanting to use the Real Time Clock (RTC) in several of our applications, all on Teensy 3.5 or 3.6 boards with a CR2032 backing up the RTC. However, the Teensy loader / startup coade automatically setting the time can get in our way. I know that for most applications, having the system "automatically" initialize the RTC when code is loaded is incredibly user-friendly, but for our purposes it gets in the way. For one, the timestamp coming from the loader appears to be technically incorrect -- storing a "time_t" value that is offset by the compiler's local timezone, instead of using direct UTC values that time_t is supposed to have (per the C standard, and what we want to log/record).
For our needs, it would be far better for an unset/automatically set RTC to give us clearly erroneous values (e.g., pre-2000 dates) that flag that it is not the true time than to give us values that are offset from the true time but not detectably/obviously so.
In short, if the RTC value hasn't been explicitly set by our software but has a value coming from the loader, we'd like to have a way to know that.
Here's what I've surmised from Paul's *excellent* post in https://forum.pjrc.com/threads/4798...tes-wrong-time?p=160639&viewfull=1#post160639 and other forum posts, and where our specific challenge with the current system is...
I understand that once a battery is hooked up to vBat and the time is set (either by sketch or by the loader), then the loader/startup code won't subsequently modify the RTC value as long as power exists to vBat. Excellent. Our problem arises that technicians in the field may end up disconnecting vBat, either accidentally or purposefully. Then when things are restarted, the RTC gets a value from a sketch and it's not obviously wrong.
On the first reboot after losing vBat, my understanding is that the startup code sets the RTC to the timestamp of the currently loaded sketch, and puts a special value into vBat memory so we know that it's "wrong". Okay, we can use that. Our sketches could look at the vBat memory location and know that the clock is "off" and flag things accordingly.
However, if while in this "stale" state the technician also loads a new sketch onto the Teensy (e.g. for a software update), then the loader causes the RTC to be initialized with a value coming from the compiler and clears the vBat memory flag. Now we're in trouble, because it appears to the sketch as though the RTC clock is set (the flag has been cleared), but it unfortunately has a value that isn't a true time_t value (it's offset by the timezone of the loader). So our logs/programs start using/logging timestamps that aren't actually UTC.
For a variety of reasons we don't want timezone-offset values in the RTC clock; we want to use UTC time_t values only. For one, keeping the offset in the 32-bit "time_t" value is very non-standard -- it won't work with most Unix tools and C-libraries; for another, it doesn't play well with DST changes, which are also important to us.
If there's a way to prevent the loader from ever setting the RTC clock, that'd likely work for us. Or if there's a non-volatile flag or something that can be queried in a sketch to determine if the RTC contains an "automatic" value, that'd work great also.
If there's not a way in the existing configuration to determine the RTC state, then I'm thinking we may have to use some of the unused vBat memory to store our own flag value to say "yes, we've explicitly set the clock", similar to the way the startup code is currently using 0x4003E01C. But I'd prefer to take that approach as a last resort, since it's poking around in storage not specifically allocated to us for that purpose.
Another approach might be to have our sketches look at the 0x4003E01C location and if it's the special startup code flag value, then explicitly set the RTC clock to a "clearly impossible" (pre-2000) date so subsequent loads don't change it. But that assumes that our sketches are the only ones that get loaded onto the Teensy; if another sketch (e.g. Blink) is loaded for testing purposes, then there's a chance the loader will end up setting the clock and our values are incorrect again.
Are there other ways of detecting the "automatic initialization" of the RTC that I haven't found yet?
Thanks again for such a wonderful product.
Pm
I'm absolutely loving the Teensy line of products -- they are solving so many immediate needs for our projects that used to require a number of special-purpose boards.
We're wanting to use the Real Time Clock (RTC) in several of our applications, all on Teensy 3.5 or 3.6 boards with a CR2032 backing up the RTC. However, the Teensy loader / startup coade automatically setting the time can get in our way. I know that for most applications, having the system "automatically" initialize the RTC when code is loaded is incredibly user-friendly, but for our purposes it gets in the way. For one, the timestamp coming from the loader appears to be technically incorrect -- storing a "time_t" value that is offset by the compiler's local timezone, instead of using direct UTC values that time_t is supposed to have (per the C standard, and what we want to log/record).
For our needs, it would be far better for an unset/automatically set RTC to give us clearly erroneous values (e.g., pre-2000 dates) that flag that it is not the true time than to give us values that are offset from the true time but not detectably/obviously so.
In short, if the RTC value hasn't been explicitly set by our software but has a value coming from the loader, we'd like to have a way to know that.
Here's what I've surmised from Paul's *excellent* post in https://forum.pjrc.com/threads/4798...tes-wrong-time?p=160639&viewfull=1#post160639 and other forum posts, and where our specific challenge with the current system is...
I understand that once a battery is hooked up to vBat and the time is set (either by sketch or by the loader), then the loader/startup code won't subsequently modify the RTC value as long as power exists to vBat. Excellent. Our problem arises that technicians in the field may end up disconnecting vBat, either accidentally or purposefully. Then when things are restarted, the RTC gets a value from a sketch and it's not obviously wrong.
On the first reboot after losing vBat, my understanding is that the startup code sets the RTC to the timestamp of the currently loaded sketch, and puts a special value into vBat memory so we know that it's "wrong". Okay, we can use that. Our sketches could look at the vBat memory location and know that the clock is "off" and flag things accordingly.
However, if while in this "stale" state the technician also loads a new sketch onto the Teensy (e.g. for a software update), then the loader causes the RTC to be initialized with a value coming from the compiler and clears the vBat memory flag. Now we're in trouble, because it appears to the sketch as though the RTC clock is set (the flag has been cleared), but it unfortunately has a value that isn't a true time_t value (it's offset by the timezone of the loader). So our logs/programs start using/logging timestamps that aren't actually UTC.
For a variety of reasons we don't want timezone-offset values in the RTC clock; we want to use UTC time_t values only. For one, keeping the offset in the 32-bit "time_t" value is very non-standard -- it won't work with most Unix tools and C-libraries; for another, it doesn't play well with DST changes, which are also important to us.
If there's a way to prevent the loader from ever setting the RTC clock, that'd likely work for us. Or if there's a non-volatile flag or something that can be queried in a sketch to determine if the RTC contains an "automatic" value, that'd work great also.
If there's not a way in the existing configuration to determine the RTC state, then I'm thinking we may have to use some of the unused vBat memory to store our own flag value to say "yes, we've explicitly set the clock", similar to the way the startup code is currently using 0x4003E01C. But I'd prefer to take that approach as a last resort, since it's poking around in storage not specifically allocated to us for that purpose.
Another approach might be to have our sketches look at the 0x4003E01C location and if it's the special startup code flag value, then explicitly set the RTC clock to a "clearly impossible" (pre-2000) date so subsequent loads don't change it. But that assumes that our sketches are the only ones that get loaded onto the Teensy; if another sketch (e.g. Blink) is loaded for testing purposes, then there's a chance the loader will end up setting the clock and our values are incorrect again.
Are there other ways of detecting the "automatic initialization" of the RTC that I haven't found yet?
Thanks again for such a wonderful product.
Pm