RTC on Teensy 4.x

Status
Not open for further replies.

cyrille

Well-known member
Hello,

I was wondering if they was a RTC library for the Teensy4.x available?

I would like to be able, at least, to set the time/date, and get them... and hope that it stays "counting" when not in use...

Thanks,
Cyrille
 
Hello again.

I got this code from an older project on a different i.MX chip...
I made some small changes, but it does not yet work (does not compile, as I am missing the CCM module defintions)...
I am posting it here in case it helps...

Code:
  static unsigned int const halNbDaysSince[] =   {  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, };
  static bool halDateLeap(uint32_t y) //return true if y is leap year
  {
    if (y%400==0) return true;
    if (y%100==0) return false;
    return ((y&3)==0);
  }
  static int32_t halDateDayIndexFromDateinternal(uint32_t d, uint32_t m, uint32_t y, bool leap)
  { 
    y=y-1582;
    uint32_t r= y*365;
    r+=(y+2)/4; // every 4th year is leap
    r-=(y+82)/100; // but every 100 is not
    r+=(y+382)/400; // but every 400 is!
    r+= halNbDaysSince[m-1]; // add months
    if (leap && (m<=2)) r--; // adjust for leaps
    r+= d-1; // add current day, 0 based, not 1...
    if (r<273+14) return -1; // if before 15 october 1582, not a good date
    return r;
  }
  static bool halDateFromDayIndex2(uint32_t a, uint32_t *Y, uint32_t *M, uint32_t *D)
  { 
    uint32_t y, m;
    if (a<273+14) return false; // begining of time
    if (a>3074610) return false; // end of time 31 dec 9999
    y= 1582;
    if (a>=365) { y++; a-= 365; }
    if (a>=365) { y++; a-= 365; } // up to 84, leap
    if (a>=1461) { y+= 4; a-=1461; }
    if (a>=1461) { y+= 4; a-=1461; }
    if (a>=1461) { y+= 4; a-=1461; }
    if (a>=1461) { y+= 4; a-=1461; } // up to 1600, leap...
    while (a>=146097) { y+= 400; a-=146097; } // number of days in 400 years, leap years included
    if (a>=36525) { y+= 100; a-=36525; } // number of days in 100 years with first year leap...
    if (a>=36524) { y+= 100; a-=36524; } // number of days in 100 years
    if (a>=36524) { y+= 100; a-=36524; } // number of days in 100 years
    while (a>=(1461-(halDateLeap(y)?0:1))) { a-=(1461-(halDateLeap(y)?0:1)); y+= 4; } // number of days in 4 years.. handle case where first year is not leap!
    while (a>=(365+(halDateLeap(y)?1:0))) { a-= (365+(halDateLeap(y)?1:0)); y++; }
    m=11;
    while ((uint32_t)a<(halNbDaysSince[m]+((m>=2)&&(halDateLeap(y)?1:0)))) m--;
    a= a - halNbDaysSince[m] - ((m>=2)&&(halDateLeap(y)?1:0));
    a++; // days are 1 based, not 0...
    m++; // same for months
    if (Y!=NULL) *Y= y; if (M!=NULL) *M= m; if (D!=NULL) *D= a;
    return true;
  }
static uint32_t volatile * const SNVS= (uint32_t volatile *)0x400D4000;
static uint32_t volatile * const HPCOMR= SNVS+(0x4/4);
static uint32_t volatile * const HPCR= SNVS+(0x8/4);
static uint32_t volatile * const HPSRTCMR= SNVS+(0x24/4);
static uint32_t volatile * const HPSRTCLR= SNVS+(0x28/4);

  static uint64_t RTC_GetNow()
  {
    // get timer. since it is spread on 2 registers. one 32 bit one and one 15 bit ones, need to do 2 reads and make sure that they match
    uint64_t t1= (((uint64_t)*HPSRTCMR)<<32) + *HPSRTCLR; // Get "now"
    while (true) { uint64_t t2= (((uint64_t)*HPSRTCMR)<<32) + *HPSRTCLR; if (t1==t2) return t1; t1= t2; }
  }
void getDateTime(uint32_t *year, uint32_t *month, uint32_t *day, uint32_t *hour, uint32_t *min, uint32_t *sec, uint32_t *ms)
{
  uint64_t t1= RTC_GetNow();
  // 15 bit per seconds... use lower 15 bits for ms if needed
  if (ms!=NULL) *ms= (((uint32_t)t1 & 0x7fff) * 1000) >> 15; // get the number of ms if needed
  uint32_t tquot= (uint32_t)(t1>>15)/60; if (sec!=NULL) *sec= (uint32_t)(t1>>15)-tquot*60; // div mod nb seconds by 60 to separate seconds from the rest
  uint32_t tquot2= tquot/60; if (min!=NULL) *min= tquot-tquot2*60;               // div mod rest by 60 to get minutes and the rest
  tquot= tquot2/24; if (hour!=NULL) *hour= tquot2-tquot*24;                 // div mod rest by 24 to get hours and days since jan 1 2000
  // 152671 days from jan 1 1582 to jan 1 2000 (uncorrected for calendar change), which is what is used by DateFromDayIndex2 in napier
  halDateFromDayIndex2(152671+tquot, year, month, day);
}
void setDateTime(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec)
{
  uint32_t y2, m2, d2, h2, M2, s2;
  getDateTime(&y2, &m2, &d2, &h2, &M2, &s2, NULL);
  if (year==-1) year= y2; if (month==-1) month= m2; if (day==-1) day= d2; if (hour==-1) hour= h2; if (min==-1) min= M2; if (sec==-1) sec= s2;
  uint64_t res= (halDateDayIndexFromDateinternal(day, month, year, halDateLeap(year))-152671)*24*60*60;
  res+= 60*60*hour + 60*min + sec;
  res<<=15;
  *HPCR&= ~1; while ((*HPCR&1)!=0);               // stop RTC
  *HPSRTCLR= (uint32_t)res; *HPSRTCMR= (uint32_t)(res>>32); // program registers
  *HPCR|= 1; while ((*HPCR&1)==0);                // re-enable RTC
}
void RTC_boot()
{
    CCM->CCGR5 |= CCM_CCGR5_CG14(3);   //SNVS_HP_CLK_ENABLE
    CCM->CCGR5 |= CCM_CCGR5_CG15(3);  //SNVS_LP_CLK_ENABLE
    *HPCOMR = (1U<<31); // enable all can read registers
//    SNVS->HPCR= SNVS_HPCR_BTN_CONFIG(3) | SNVS_HPCR_BTN_MASK_MASK; // ON button active on falling edge and ON button irq enabled
//    while ((SNVS->HPCR&SNVS_HPCR_BTN_MASK_MASK)==0); // wait until validated
    //SNVS->LPCR= (2<<20) | (3<<16) | (1<<5) | 1;   // Set ON_TIME delay, BTN debounce, dumb_pmic, clock enabled
    *HPCR|= 1;
    while ((*HPCR&1)==0); // make sure clock is on!
}
 
Sorry, I have not played around very much with RTC...

But if I were going to, I would look at the stuff built into the core:

Both Teensy 3.x and 4.x have a class built in:
Code:
class teensy3_clock_class
{
public:
        static unsigned long get(void) __attribute__((always_inline)) { return rtc_get(); }
        static void set(unsigned long t) __attribute__((always_inline)) { rtc_set(t); }
        static void compensate(int adj) __attribute__((always_inline)) { rtc_compensate(adj); }
};
extern teensy3_clock_class Teensy3Clock;

And also the time library and at the example: examples->Time->TeensyTime3
 
Hello,

Thanks for the info.
Where do you actually find that information? Is there a list of all the classes? or a "class explorer" of some type?

Cyrille
 
Part of it by playing with a lot of this stuff over several years.

And then an open SublimeText 3 (editor) window open on the (<arduino install>/hardware/teensy/avr) directory and doing a global Search command for something like RTC and see where I get hits...
 
Status
Not open for further replies.
Back
Top