How to access the internal RTC in a Teensy 4.0?

starfire151

Active member
Sorry if this has been answered. I looked in previous postings but saw no direct answer to this question.

Is there a code example showing how to access the internal RTC (set date/time, read date/time, etc.) in the Teensy 4.0? I have connected a 3.0VDC coin cell between Vbat and Gnd.

Thanks.
 
Using the existing Time Library :: pjrc.com/teensy/td_libs_Time.html

In T_4.0 using TeensyLoader will put the time at upload into the T_4.0 - though right now I'm seeing it off by an hour from time change - I thought that got fixed ...

this sample is open in the editor here::
Code:
#include <TimeLib.h>

time_t RTCTime;


void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 4000 );
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
  setSyncProvider(getTeensy3Time);
}

void loop() {


  Serial.print("[c] ");
  Serial.print(hour());
  Serial.print(":");
  Serial.print(minute());
  Serial.print(":");
  Serial.print(second());
  Serial.print(" ");
  Serial.print(month());
  Serial.print("/");
  Serial.print(day());
  Serial.print("/");
  Serial.print(year());
  Serial.println();

  delay(1000);

}

time_t getTeensy3Time() {
  return Teensy3Clock.get();
}
 
There are, somewhat confusingly, two RTCs in the Teensy 4.0.

There's one called the RTC (which is what the your program is talking to when you make a Teensy3Clock.get() or .set() call) and another called the SRTC (Secure Real Time Clock, if memory serves). The SRTC is what the loader sets the time in and what preserves the time when you pull the power - assuming you have 3V on Vbat.

At startup, the time in the RTC is synced from the SRTC. This happens in cores/teensy4/startup.c, towards the end of ResetHandler(). If the SRTC isn't running (which will be the case when there's no battery on Vbat), the SRTC is initialised to Jan 1, 2019 before the RTC is synced.

Teensy3Clock.get() reads the RTC and returns a value suitable for use in TimeLib's setTime() call.

Teensy3Clock.set() sets the RTC, but, again confusingly, not the SRTC. Your program can set the RTC and all will be well and good until you lose power. When the Teensy is powered back up again, the RTC will be synced to the SRTC (which is still running using the time originally set by the loader).

So let's say that you load your program in. The loader sets the time, which, right now, is an hour behind. Let's say it shows as April 2, 2020 8:00AM. You want to fix that and do something like this (with some appropriate logic around it to ensure that it only gets called once after the Teensy is loaded - have fun with that!):
Code:
time_t newTime = Teensy3Clock.get() + 3600;
Teensy3Clock.set(newTime);

Now the time is set to April 2, 9:00AM.

An hour later, the RTC would show Apr 2, 10:00AM. You pull the power and a minute later plug it back in again. You might expect the RTC to show a value of Apr 2, 2020 10:01AM. But instead it shows Apr 2, 2020 9:01AM. The SRTC was an hour behind all this time, and when the RTC was synced again at powerup, time travel ensued.

The problem is that Teensy3Clock.set() only sets the RTC. You can see this for yourself by looking at the rtc_set() routine in cores/teensy/rtc.c. On my development box, I've replaced the rtc_set() routine with one that sets the SRTC instead, and then syncs the RTC. Doing this means that any time changes you make are preserved across power outages.

Code:
void rtc_set(unsigned long t)
{
   // stop the RTC
   SNVS_HPCR &= ~(SNVS_HPCR_RTC_EN | SNVS_HPCR_HP_TS);
  while (SNVS_HPCR & SNVS_HPCR_RTC_EN) ; // wait
   // stop the SRTC
  SNVS_LPCR &= ~SNVS_LPCR_SRTC_ENV;
  while (SNVS_LPCR & SNVS_LPCR_SRTC_ENV); // wait
   // set the SRTC
   SNVS_LPSRTCLR = t << 15;
   SNVS_LPSRTCMR = t >> 17;
   // start the SRTC
  SNVS_LPCR |= SNVS_LPCR_SRTC_ENV;
  while (!(SNVS_LPCR & SNVS_LPCR_SRTC_ENV)); // wait
   // start the RTC and sync it to the SRTC
  SNVS_HPCR |= SNVS_HPCR_RTC_EN | SNVS_HPCR_HP_TS;
}

I came up with based on the code in cores/teensy4/startup.c and from reading the i.MX RT1060 Processor Reference Manual. The SNVS_HPCR_HP_TS bit is used in the startup code but I couldn't find it in the reference manual; it appeared to be in a block of reserved bits in the register I was looking it (SNVS_HP Control Register on pages 1299-1300). I assume it's what syncs the RTC to the SRTC. Anyhow, it works for my purposes; you might find it useful too but YMMV.

One thing to keep in mind is that if you do this, you'll have to re-patch the rtc.c file each time you upgrade Teensyduino.
 
As noted - it has full support - and given a battery it should work. There is a battery backed RTC as noted. Once running the time is kept 'locally' in the CPU.

This isn't new and should have full support - assuming you are using current TeensyDuino 1.51 or 1.52b1 - that sample just happened to be open.

It almost seems as if the battery is not supplying voltage and an older TeensyDuino scheme of loading 'COMPILE TIME' is being used - rather than current process available on T4 using TeensyLoader to apply current PC time at time of upload when the clock is not set.

Searching the forum brings up : Can-t-get-RTC-to-save-time-and-remember-on-power-up

Looks like code above came from post #1 - more details in that thread and others - there are samples.
 
As noted - it has full support - and given a battery it should work. There is a battery backed RTC as noted. Once running the time is kept 'locally' in the CPU.

This isn't new and should have full support - assuming you are using current TeensyDuino 1.51 or 1.52b1 - that sample just happened to be open.

It almost seems as if the battery is not supplying voltage and an older TeensyDuino scheme of loading 'COMPILE TIME' is being used - rather than current process available on T4 using TeensyLoader to apply current PC time at time of upload when the clock is not set.

Searching the forum brings up : Can-t-get-RTC-to-save-time-and-remember-on-power-up

Looks like code above came from post #1 - more details in that thread and others - there are samples.

Thanks to all for responding so quickly!

Excellent information. I have another Teensy 4.0 on order and will test this out when it comes... hopefully early next week.
 
I can confirm that Silverlock's fix works for me on T4 as well.

Have you considered submitting a patch for this?
 
I think I understand most of what's been discussed in this thread, but I'd like to ask a couple of questions. I've got the code working to read the RTC, and I see that the time is one hour behind, as set by the Teensy loader (this is on MacOS). It sounds like this time offset will be fixed in a future release of Teensyduino. Assuming that this will be in the next month or so (?), that's fine for me; no huge rush.

If I were using the Arduino/TD IDE, I would understand how to install the new version of TD. But..I started using PlatformIO recently, and it's not obvious to me how or where the TD code is integrated in that environment. Advice?

It might be fine for me to rely on the loader to set the time in the SRTC, but if it were necessary for my application to set the time, how would I do that? It doesn't seem like it should be necessary to patch rtc.c as shown above. I'm probably misunderstanding something.

Thanks for any help!
 
There is a link to download just the loader from PJRC.com - but it seems last I did that I got version 1.48 or something old like that. I always keep current IDE and TD here - even thought I trigger it from SublimeText editor for build using Windows CmdLine interface.

@Aerokeith If the time needs setting it needs a time sourse. TeensyLoader is one if it has a battery and persists … except for being off an hour needing adjustment. Otherwise it needs to be set through one of the other source providers - or manually - as shown in the examples.

@Silverlock - so your changes to set T_4 SRTC work like that for all T_3.x's? Or does it need #ifdef to exclude the mods that make T_4.x's work?

That needs to be tested and a PR done or clean enough for Paul to put in before TD 1.52 ships ideally.
 
The change I made was in cores/teensy4/rtc.c, so it would already only apply to the T4s. The T3s have their own separate cores/teensy3 directory (and a completely different rtc_set() function in a completely different file) and so shouldn't be affected.

Keep in mind that when I came up with that code I'd only worked with the T4 for 3 weeks. While it's essentially a mashup of the SRTC setting code from cores/teensy4/startup.c and the original RTC setting code from cores/teensy4/rtc.c, the fact that I couldn't find one of the bits that the code was manipulating in the reference manual still bothers me.
 
The change I made was in cores/teensy4/rtc.c, so it would already only apply to the T4s. The T3s have their own separate cores/teensy3 directory (and a completely different rtc_set() function in a completely different file) and so shouldn't be affected.

Keep in mind that when I came up with that code I'd only worked with the T4 for 3 weeks. While it's essentially a mashup of the SRTC setting code from cores/teensy4/startup.c and the original RTC setting code from cores/teensy4/rtc.c, the fact that I couldn't find one of the bits that the code was manipulating in the reference manual still bothers me.

Doh - my editor makes it easy for me to not see directory location - it just showed the file and I didn't pay attention to that as I wasn't in a curious mood it seems.

If you can post follow up ( Teensyduino-1-52-Beta-3 ) - or ideally make a PR to the CORES { github.com/PaulStoffregen/cores/blob/master/teensy4/rtc.c } it might help it get into TD 1.52 before release.
 
It looks to me like the change to rtc_set() is already in there. I just forked the cores repository and opened up teensy4/rtc.c to add the change and saw some very familiar code in rtc_set().
 
OK, I'm feeling a bit dense. Let me try again.

As in the examples, I'm currently using:
Code:
setSyncProvider(getTeensy3Time);
and
Code:
time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}

(I guess there's no Teensy4 version of these calls?)

That works fine for accessing time using the Time library.

@Defragster, I'm not sure what you meant by
Otherwise it needs to be set through one of the other source providers - or manually - as shown in the examples.

I thought the issue was that Teensy3Clock.set() would not set the SRTC, and therefore the time set using that call would not persist across a power outage. Are you saying that a new release of TD will fix this issue?

Also, it sounds like the off-by-one-hour issue is in the loader, not in the TD code. Correct?

In any case, I still don't understand how to install an updated loader or TD code in PlatformIO.
 
Paul committed @sliverlock's change to the cores directory, so the T4 RTC should work correctly across power cycles (assuming there's a battery on VBAT) in the next beta release.
 
Is there any way to fix the annoying bug that causes the (S)RTC to lag one hour behind when I load a program into my Teensy?

[I am using about 40 Teensy 3.6 in different audio and ultrasound recorder setups. That is really annoying having to set the time manually in every recorder after I upload a new recorder firmware version . . .]

This one hour lag bug has been reported quite a few times in different threads, but to my knowledge has never been fixed.
Would be nice if you could point me to a solution for that.
 
Is there any way to fix the annoying bug that causes the (S)RTC to lag one hour behind when I load a program into my Teensy?

This problem is not currently on my list of issues to investigate.

Details matter. The RTC default setting works differently on Teensy 3 vs 4. On Teensy 3, it's done mostly by the Arduino IDE and compiler and startup code, so which version of the IDE you are using matters. On Teensy 4 it's done by Teensy Loader, so click Help > About and check which version you are really using.

These 1 hour off issues are probably a matter of how the PC side software gets the local time, so which operating system you are using and what time of year and where in the world you are located (whether on standard time or daylight saving time in your region) also matters.
 
Sketch: T:\arduino-1.8.12\hardware\teensy\avr\libraries\Time\examples\TimeTeensy3\TimeTeensy3.ino
Compiled and uploaded and output below with Win 10 and IDE 1.8.12 and TD 1.52 b3.

Teensy 3.6 - represents Windows Compile time:
Code:
RTC has set the system time
[B][COLOR="#FF0000"]2:49:43[/COLOR][/B] 2 5 2020

A few minutes later same sketch sent to T_4.0:
Code:
RTC has set the system time
[B][COLOR="#FF0000"]1:53:02[/COLOR][/B] 2 5 2020

Post #15 noted above : " I see that the time is one hour behind, as set by the Teensy loader (this is on MacOS)."

Have been seeing this on windows using TD 1.52 - seems it may have started with the 'Spring ahead time change' as that is about when it was noticed.
 
Good work @blackketter. Didn't see post #16 above but went to make a PR and see it in place after making time to look at it.

PaulStoffregen Fix rtc_set on Teensy 4.0 (thanks blackketter)
 
Thanks Paul, for that quick and important info about the difference between T4 and T3.6 RTC setting on upload.

I can report that the bug is still there with Windows 10 and Teensyloader 1.52 beta3 in time zone Berlin (daylight saving time UTC + 2).

Local time is 12:00h right now and on upload the Teensy 4.0 RTC shows 11:00h.

The sketch uses (in setup)
Code:
  setSyncProvider(getTeensy3Time);
  T4_rtc_set(Teensy3Clock.get());

T4_rtc_set is exactly the code provided by Silverlock in #3
 
code provided by Silverlock in #3

My T4.1 is battery backed up and I use Teensy3Clock.set() from GPS reported values, but on reboot, the RTC reports a 0 value.

Given that the T4.1 RTC is set to 0 (or maybe 2019) in cores/teensy4/startup.c, aren't we still missing the startup code in the case where the S-RTC is battery backed up? Shouldn't the volatile RTC be set from the S-RTC?

In any case, can someone provide a routine or the name of the routine to read the value that was saved in the S-RTC, so I can put it into the RTC at setup()?
 
My T4.1 is battery backed up and I use Teensy3Clock.set() from GPS reported values, but on reboot, the RTC reports a 0 value.

Given that the T4.1 RTC is set to 0 (or maybe 2019) in cores/teensy4/startup.c, aren't we still missing the startup code in the case where the S-RTC is battery backed up? Shouldn't the volatile RTC be set from the S-RTC?

In any case, can someone provide a routine or the name of the routine to read the value that was saved in the S-RTC, so I can put it into the RTC at setup()?

The samples with TeensyDuino 1.53 should work. Is that version installed? Is TeensyLoader being used for upload?
 
I had trouble compiling my code (in the Arduino environment) when I had placed the definition of getTeensy3Time() in a separate file. After some head scratching, I realized I had to explicitly #include "core_pins.h" for the compiler to recognize the Teensy3Clock object. This was not necessary when I instead put the definition in the .ino file.

So this is the relevant code in the separate cpp file:

Code:
#include <TimeLib.h>
#include "core_pins.h"

time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}

Maybe this can help someone else solve a similar issue.
 
Back
Top