Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: RTC on Teensy 4.x

  1. #1

    RTC on Teensy 4.x

    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

  2. #2
    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!
    }

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,671
    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

  4. #4
    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

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,671
    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...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •