Stalled Feather M0 Express while configuring RTC (Ardu)

Please tell us which board you are using.
For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
lutzray
 
Posts: 13
Joined: Fri Nov 06, 2020 12:02 pm

Stalled Feather M0 Express while configuring RTC (Ardu)

Post by lutzray »

Bonjour,

as a noob I don't really master all the setting this code does (I copied it from the tubes) but I stumbled onto something strange:

0- the code simply generates a 1 Hz software interrupt using the RTC
1- the same code behave differently on a trinket M0 and on a feather M0 Express
2a- it stalls on a feather M0 Express but not right away (after flashing, it is always OK)
2b- you have to unplug and replug it to reproduce the problem
3- the same code is OK on a trinket M0 and never stall when power cycling the board
4- once stalled, the feather will always stall at the first SYNCBUSY wait, even when reflashed
5- to un-stall the feather, I reflash it twice with the Arduino IDE Board set as a Trinket M0 and then as a Feather M0 Express

my running set up:
Adafruit Feather M0 Express (SN: 8B80728B50533830332E3120FF162525)
Arduino IDE 1.8.14 on Ubuntu 20.04.3, Adafruit SAMD Boards 1.6.7 installed

Thanks for any help!

PS: I need the 1 Hz RTC event to replace the GPS PPS when signal reception is bad.

Code: Select all

  // Set-up RTC interrupt to fire every second (1Hz) in clock/calendar mode (Mode 2)

  void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("\n\nentered setup()");
  // Configure clock source and clock generators (gclk.h)------------------------
  GCLK->GENDIV.reg =  GCLK_GENDIV_ID(4) | GCLK_GENDIV_DIV(4); 
  while (GCLK->STATUS.bit.SYNCBUSY);
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(4) |  GCLK_GENCTRL_SRC_OSC32K |  
                      GCLK_GENCTRL_IDC | GCLK_GENCTRL_RUNSTDBY |  
                      GCLK_GENCTRL_DIVSEL |  GCLK_GENCTRL_GENEN;  
  while (GCLK->STATUS.bit.SYNCBUSY);    
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN_GCLK4 |  GCLK_CLKCTRL_ID_RTC |  
                      GCLK_CLKCTRL_CLKEN;  
  while (GCLK->STATUS.bit.SYNCBUSY); 
  // configure RTC 
  RTC->MODE2.CTRL.reg |= RTC_MODE2_CTRL_PRESCALER_DIV1024 | 
                         RTC_MODE2_CTRL_MODE_CLOCK; 
  RTC->MODE2.Mode2Alarm[0].ALARM.bit.SECOND = RTC_MODE2_ALARM_SECOND(0); 
  Serial.println("just before while (RTC->MODE2.STATUS.bit.SYNCBUSY);");---------
  while (RTC->MODE2.STATUS.bit.SYNCBUSY);  // <---  it stalls here
    // if a Feather M0 Express is power cycled...
    // but not a Trinket M0 !
    // once the feather is stalled, reflashing it changes nothing.
    // to un-stall the feather, you have to flash it as a TrinketM0
  Serial.println("just after while (RTC->MODE2.STATUS.bit.SYNCBUSY);");-----------
  RTC->MODE2.Mode2Alarm[0].MASK.bit.SEL = RTC_MODE2_MASK_SEL_SS;
  while (RTC->MODE2.STATUS.bit.SYNCBUSY);   
  // Configure RTC interrupts 
  NVIC_SetPriority(RTC_IRQn, 0);  
  NVIC_EnableIRQ(RTC_IRQn); 
  RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_ALARM0; 
  // Enable RTC
  RTC->MODE2.CLOCK.reg = 0x0000000;   
  while (RTC->MODE2.STATUS.bit.SYNCBUSY); 
  RTC->MODE2.CTRL.reg |= RTC_MODE2_CTRL_ENABLE;
  while (RTC->MODE2.STATUS.bit.SYNCBUSY);
  Serial.println("Setup complete...");
}

void loop() {}

void RTC_Handler(void)
{
  if (RTC->MODE2.INTFLAG.bit.ALARM0 && RTC->MODE2.INTENSET.bit.ALARM0) 
  {
    Serial.print(F("RTC Handler, "));
    RTC->MODE2.READREQ.reg = RTC_READREQ_RREQ;
    while (RTC->MODE2.STATUS.bit.SYNCBUSY);
    uint8_t min = RTC->MODE2.CLOCK.bit.MINUTE;
    uint8_t sec = RTC->MODE2.CLOCK.bit.SECOND;
    Serial.print(min); Serial.print("m "); Serial.print(sec); Serial.println("s");
    RTC->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM0; 
    RTC->MODE2.Mode2Alarm[0].ALARM.bit.SECOND = (RTC->MODE2.Mode2Alarm[0].ALARM.bit.SECOND + 1) % 60;
  }
}

User avatar
mikeysklar
 
Posts: 13936
Joined: Mon Aug 01, 2016 8:10 pm

Re: Stalled Feather M0 Express while configuring RTC (Ardu)

Post by mikeysklar »

Does it help if you add a delay to the M0 express at the beginning of setup()? We often have to do that for displays and other accessories on the M0/M4 boards.

Also there are some simple RTC timer libraries like RTCZero which would make this code a lot less obscure with all the manual setting of register bits.

https://www.arduino.cc/en/Tutorial/SimpleRTC

Code: Select all

/*

  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 <[email protected]>

  15 Jun 2015

  modified

  18 Feb 2016

  modified by Andrea Richetta <[email protected]>

  24 Aug 2016

*/

#include <RTCZero.h>

/* Create an rtc object */

RTCZero rtc;

/* Change these values to set the current initial time */

const byte seconds = 0;

const byte minutes = 0;

const byte hours = 16;

/* Change these values to set the current initial date */

const byte day = 15;

const byte month = 6;

const byte year = 15;

void setup()
{

  Serial.begin(9600);

  rtc.begin(); // initialize RTC

  // Set the time

  rtc.setHours(hours);

  rtc.setMinutes(minutes);

  rtc.setSeconds(seconds);

  // Set the date

  rtc.setDay(day);

  rtc.setMonth(month);

  rtc.setYear(year);

  // you can use also

  //rtc.setTime(hours, minutes, seconds);

  //rtc.setDate(day, month, year);
}

void loop()
{

  // 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);
}

User avatar
lutzray
 
Posts: 13
Joined: Fri Nov 06, 2020 12:02 pm

Re: Stalled Feather M0 Express while configuring RTC (Ardu)

Post by lutzray »

Yes, it works! Thanks for the suggestion!

For a 1 Hz event, I used the 'next second alarm' modulo trick:

Code: Select all

#include <RTCZero.h>

/* Create an rtc object */
RTCZero rtc;

void setup()
{
  Serial.begin(9600);
  rtc.begin(); // initialize RTC 24H format
  rtc.setAlarmTime(0, 0, 0);
  setAlarmNextSecond();
  rtc.enableAlarm(rtc.MATCH_SS);
  rtc.attachInterrupt(alarmMatch);
}

void loop() {}

void setAlarmNextSecond()
{
  RTC->MODE2.Mode2Alarm[0].ALARM.bit.SECOND =
    (RTC->MODE2.Mode2Alarm[0].ALARM.bit.SECOND + 1) % 60;
}

void alarmMatch()
{
  Serial.println("ding: 1 second has passed");
  setAlarmNextSecond();
}
And just for fun I did some stats:

Image

Note: the jitter probably comes not from the OSC32K itself but from serving the ISR... And the drift is not that bad, it's on par with the clock drifts I measure on my recorders and cameras:

Image
Context

Oh zut... I just realised this is not jitter but some kind of rolling error and I can't use this to timestamp seconds to a 20 μs precision I guess I'll ditch the RTC solution and go with using TC4 to generates my 1 Hz event (I'm already using TC5 for driving the DAC)
roll.png
roll.png (21.62 KiB) Viewed 233 times
Tanks again.
PS: how can I edit my topic title to prepend a [SOLVED] tag?

User avatar
mikeysklar
 
Posts: 13936
Joined: Mon Aug 01, 2016 8:10 pm

Re: Stalled Feather M0 Express while configuring RTC (Ardu)

Post by mikeysklar »

I'm glad that library worked out for some degree. The charts are interesting even if they might have the 20uS error in charting them.

Were you using the micros() for some of the timing precision? I see it is supposed to support one microsecond resolution.

https://www.arduino.cc/reference/en/lan ... me/micros/

We don't need to update the thread title.

User avatar
lutzray
 
Posts: 13
Joined: Fri Nov 06, 2020 12:02 pm

Re: Stalled Feather M0 Express while configuring RTC (Ardu)

Post by lutzray »

Were you using the micros() for some of the timing precision?
I don't time anything on the samd21: I'm using it to 'punch' a 1 PPS mark into an audio track and I use the samples count to do precise timing of the record beginning (knowing the recording frequency).

As for the observed rolling 25 ms error of the RTC 1 PPS, I think it's due to the low baud rate: you can't time events to the milliseconds if they arrive through a 9600 baud link... I'll check.

RL

User avatar
lutzray
 
Posts: 13
Joined: Fri Nov 06, 2020 12:02 pm

Re: Stalled Feather M0 Express while configuring RTC (Ardu)

Post by lutzray »

PS: I posted a more thorough test of RTC clocks in Adafruit Trinket forum

Locked
Please be positive and constructive with your questions and comments.

Return to “Feather - Adafruit's lightweight platform”