arduino-libraries / RTCZero

RTC Library for SAMD21 based boards
http://arduino.cc/en/Reference/RTC
GNU Lesser General Public License v2.1
76 stars 79 forks source link

In testing SAMD51 port... #61

Open trlafleur opened 4 years ago

trlafleur commented 4 years ago

update1: Problem solved, please see my last message in this string... I expect this is also an issue with SAMD21 CPU chip...

update: If I take a new processor chip, and run the program, it fails, but if I use a processor that has had the RTC register set by using the rtc.setHours(hours); etc function, it work as expected. very odd...

just a note:

I'm testing the SAMD51 port by: ericbaril72 at: https://github.com/ericbaril72/RTCZero/tree/SAMD51_E54

In my test program below, if I run it on a SAMD21 processor, I get the expected results, if I set the time via a: rtc.setEpoch(1451606400); // Jan 1, 2016, it returns the expected: 01/01/16 00:00:00

But if I run it on a SAMD51 processor, it returns: 16/06/16 08:39:05 looks to be an issue in the SAMD51 port if setting time via rtc.setEpoch or ??

IDE 1.8.12 Feather M0 and M4 processors

/*
  Simple RTC for Arduino Zero and MKR1000
  Demonstrates the use of the RTC library for the Arduino Zero and MKR1000
  This example code is in the public domain
  http://arduino.cc/en/Tutorial/SimpleRTC
  created by Arturo Guadalupi <a.guadalupi@arduino.cc>
  15 Jun 2015
  modified 
  18 Feb 2016
  modified by Andrea Richetta <a.richetta@arduino.cc>
  24 Aug 2016
*/

#include <RTCZero.h>
/* Create an rtc object */
RTCZero rtc;

void setup()
{
  Serial.begin(9600);

  rtc.begin(); // initialize RTC

 // Set the time
    rtc.setEpoch(1451606400); // Jan 1, 2016 00:00:00
}

void loop()
{
  Serial.println(rtc.getEpoch());
// Print date...
  print2digits(rtc.getDay());
  Serial.print("/");
  print2digits(rtc.getMonth());
  Serial.print("/");
  print2digits(rtc.getYear());
  Serial.print(" ");

  // ...and time
  print2digits(rtc.getHours());
  Serial.print(":");
  print2digits(rtc.getMinutes());
  Serial.print(":");
  print2digits(rtc.getSeconds());

  Serial.println();

  delay(1000);
}

void print2digits(int number) {
  if (number < 10) {
    Serial.print("0"); // print a 0 before if the number is < than 10
  }
  Serial.print(number);
}
drewfish commented 4 years ago

It looks like your test sketch prints the time every second. Does the RTC clock increment 1 second each time it prints, or does the RTC run faster or slower?

trlafleur commented 4 years ago

RTC is an asynchronous process, and it runs independently of CPU and Arduino

~~ /) ~~~~ /) ~~ _/) ~~ _/) ~~

Tom Lafleur

On Mon, Jun 1, 2020 at 8:09 PM Drew Folta notifications@github.com wrote:

It looks like your test sketch prints the time every second. Does the RTC clock increment 1 second each time it prints, or does the RTC run faster or slower?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/arduino-libraries/RTCZero/issues/61#issuecomment-637243426, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABC4EK3DIW5HORMDMEY5YD3RURUQFANCNFSM4NP4LYKA .

drewfish commented 4 years ago

Sure, but its speed depends on how it's hooked up to the clocks in the SAMD51 chip. Specifically this code in that RTCZero fork is assuming that the board has an external 32k oscillator attached to the SAMD51: https://github.com/ericbaril72/RTCZero/blob/2c92351e4581dcf32125ce771211e4cf79485f4e/src/RTCZero.cpp#L508 It assumes other things as well. If the RTC isn't configured to clock at 1Hz then that could very well cause a wrong datetime.

trlafleur commented 4 years ago

The clock is connected via the 32.768KHz external xtal, it appears to keeps proper time.... The issue I expect appears to be one of not properly initializing a register or synchronizing register access with the main processor as required. see section 21.12 of the SAM D5x/E5x Family Data Sheet "Some registers require synchronization when read and/or written. Synchronization is denoted by the "Read- Synchronized" and/or "Write-Synchronized" property in each individual register description."

If you set the time with the rtc.setYear, month, day...etc, and read back the time set with rtc.getEpoch(), it appears to work just fine, but if you set the time with rtc.setEpoch(1451606400);, and read it back, you often get the wrong value back.

here is output from my test program using rtc.setEpoch(1451606400); it should read 01/01/16 00:00:00 Starting... 1451606709 01/01/16 00:05:09 1451606710 01/01/16 00:05:10 1451606711 01/01/16 00:05:11 1451606712 01/01/16 00:05:12 1451606713

here is the output using rtc.setYear, month, day...etc Starting... 1451606400 01/01/16 00:00:00 1451606401 01/01/16 00:00:01 1451606402 01/01/16 00:00:02 1451606403 01/01/16 00:00:03

On Mon, Jun 1, 2020 at 8:42 PM Drew Folta notifications@github.com wrote:

Sure, but its speed depends on how it's hooked up to the clocks in the SAMD51 chip. Specifically this code in that RTCZero fork is assuming that the board has an external 32k oscillator attached to the SAMD51:

https://github.com/ericbaril72/RTCZero/blob/2c92351e4581dcf32125ce771211e4cf79485f4e/src/RTCZero.cpp#L508 It assumes other things as well. If the RTC isn't configured to clock at 1Hz then that could very well cause a wrong datetime.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/arduino-libraries/RTCZero/issues/61#issuecomment-637252562, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABC4EK3CIPPWJCYECPU6PI3RURYLVANCNFSM4NP4LYKA .

trlafleur commented 4 years ago

It looks to be as I stated in my last email, adding a synchronization request after EACH register change appears to have solved the issue...

In the original code, one was done at the end of the register change, "not for each register change as required"...

I expect this is also an issue with SAMD21 CPU chip...


void RTCZero::setEpoch(uint32_t ts)
{
  if (_configured) {
    if (ts < EPOCH_TIME_OFF) {
      ts = EPOCH_TIME_OFF;
    }

    time_t t = ts;
    struct tm* tmp = gmtime(&t);

    RTC->MODE2.CLOCK.bit.YEAR =     tmp->tm_year - EPOCH_TIME_YEAR_OFF;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.MONTH =    tmp->tm_mon + 1;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.DAY =      tmp->tm_mday;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.HOUR =     tmp->tm_hour;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.MINUTE =   tmp->tm_min;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.SECOND =   tmp->tm_sec;

    while (RTCisSyncing())
      ;
  }
}

~~ /) ~~~~ /) ~~ _/) ~~ _/) ~~

Tom Lafleur

On Tue, Jun 2, 2020 at 5:52 AM Tom Lafleur lafleur@lafleur.us wrote:

The clock is connected via the 32.768KHz external xtal, it appears to keeps proper time.... The issue I expect appears to be one of not properly initializing a register or synchronizing register access with the main processor as required. see section 21.12 of the SAM D5x/E5x Family Data Sheet "Some registers require synchronization when read and/or written. Synchronization is denoted by the "Read- Synchronized" and/or "Write-Synchronized" property in each individual register description."

If you set the time with the rtc.setYear, month, day...etc, and read back the time set with rtc.getEpoch(), it appears to work just fine, but if you set the time with rtc.setEpoch(1451606400);, and read it back, you often get the wrong value back.

here is output from my test program using rtc.setEpoch(1451606400); it should read 01/01/16 00:00:00 Starting... 1451606709 01/01/16 00:05:09 1451606710 01/01/16 00:05:10 1451606711 01/01/16 00:05:11 1451606712 01/01/16 00:05:12 1451606713

here is the output using rtc.setYear, month, day...etc Starting... 1451606400 01/01/16 00:00:00 1451606401 01/01/16 00:00:01 1451606402 01/01/16 00:00:02 1451606403 01/01/16 00:00:03

On Mon, Jun 1, 2020 at 8:42 PM Drew Folta notifications@github.com wrote:

Sure, but its speed depends on how it's hooked up to the clocks in the SAMD51 chip. Specifically this code in that RTCZero fork is assuming that the board has an external 32k oscillator attached to the SAMD51:

https://github.com/ericbaril72/RTCZero/blob/2c92351e4581dcf32125ce771211e4cf79485f4e/src/RTCZero.cpp#L508 It assumes other things as well. If the RTC isn't configured to clock at 1Hz then that could very well cause a wrong datetime.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/arduino-libraries/RTCZero/issues/61#issuecomment-637252562, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABC4EK3CIPPWJCYECPU6PI3RURYLVANCNFSM4NP4LYKA .

trlafleur commented 4 years ago

One should note an errata in the SAMD51 rev A silicon. In the errata sheet for the SAMD51, section 2.17.1

2.17.1 Write Corruption Reference:TMR102-46
A 8-bit or 16-bit write access for a 32-bit register, or 8-bit write access for a 16-bit register can fail for the following registers:
• COUNT register in COUNT32 mode
• COUNT register in COUNT16 mode
• CLOCK register in CLOCK mode
Workaround
Write the registers with:
• A 32-bit write access for COUNT register in COUNT32 mode, CLOCK register in CLOCK mode
• A 16-bit write access for the COUNT register in COUNT16 mode

A clean copy of the changes...


void RTCZero::setEpoch(uint32_t ts)
{
  if (_configured) {
    if (ts < EPOCH_TIME_OFF) {
      ts = EPOCH_TIME_OFF;
    }

    time_t t = ts;
    struct tm* tmp = gmtime(&t);

    RTC->MODE2.CLOCK.bit.YEAR =     tmp->tm_year - EPOCH_TIME_YEAR_OFF;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.MONTH =    tmp->tm_mon + 1;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.DAY =      tmp->tm_mday;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.HOUR =     tmp->tm_hour;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.MINUTE =   tmp->tm_min;
     while (RTCisSyncing());
    RTC->MODE2.CLOCK.bit.SECOND =   tmp->tm_sec;

    while (RTCisSyncing())
      ;
  }
}