Strange problem with GCLK

Hmm. According to my debugging, the sketch is hanging in the sketch clock initialization:

  GCLK->CTRL.reg = GCLK_CTRL_SWRST ;
  while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) )
  {
    /* Wait for reset to complete */
  }

Never exits…
This is really weird, since:

  1. It shouldn’t happen.
  2. It looks like a double-tap reset to the bootloader does nearly identical clock initialization, and doesn’t fail. (although that will end up causing a reset while the clocks are in their nearly-default state.)

There is an item in the errata for SAMD20 (http://ww1.microchip.com/downloads/en/DeviceDoc/80000747B.pdf) that sounds like exactly what is happening, but it doesn’t appear in the SAMD21 errata, and is apparently supposed to be fixed in newer silicon (though maybe if they never noticed it in SAMD21, they never fixed it there, either.)

westfw:
2) It looks like a double-tap reset to the bootloader does nearly identical clock initialization, and doesn't fail. (although that will end up causing a reset while the clocks are in their nearly-default state.)

Just to clarify when you say double-tap reset doesnt fail, that is not in the state where it had already failed. The only thing that recovers that situation is a power-on-reset?

westfw:
There is an item in the errata for SAMD20...

I was wondering which item you were referring to. I understand this errata sheet is not for these devices but 3 items looked relevant in some way. 1.5.7, 1.5.11 & 1.10.1.

westfw:
Hmm. According to my debugging, the sketch is hanging in the sketch clock initialization:

  GCLK->CTRL.reg = GCLK_CTRL_SWRST ;

while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) )
 {
   /* Wait for reset to complete */
 }

Bearing in mind what you discovered here, I decided to go and read the register descriptions for the GCLK CTRL register and specifically the SWRST bit.

Writing a one to this bit resets all registers in the GCLK to their initial state after a power reset, except for generic clocks and associated generators that have their WRTLOCK bit in CLKCTRL read as one.

It would be logical to think that if GCLK_GEN4 was protected with a WRTLOCK then it would be skipped during the GCLK_SWRST. After modifying the setup code for Clock generator in the RTCZero library to enable the write protection for GCLK4, the problem disappears and the board now resets reliably with no hangs.

Obviously this is not the ideal situation, requiring a power-on reset before GCLK4 can be reconfigured for anything else but it does offer a usable workaround in the meantime

Working clock configuration

void RTCZero::configureClock() {
  GCLK->GENDIV.reg = GCLK_GENDIV_ID(4)|GCLK_GENDIV_DIV(4);
  while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);

  GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_GCLKIN | GCLK_GENCTRL_ID(4) | GCLK_GENCTRL_DIVSEL );
  while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);

  GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_WRTLOCK | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK4 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
  while (GCLK->STATUS.bit.SYNCBUSY);
}

Hi,
I am impressed with the in detailed discussion about why my original problem came up. I am as you see a “newbe” (but perhaps not, as I started with PDP 11/04 and CAMAC). It seems the issue with the RTC and GLCK4 is deep going and far beyond my competence.

I did some playing with the RTC and my observation was, as MartinL pointed out, the datasheet indicated that it would not work when connected to GLCK0. In fact I had to set the clock period to 1/96 MHz, and even then it produced incorrect times… It works fine on the 32.768 kHz GCLK1 which is the crystal oscillator.

MartinL also suggested using TC4+TC5 as a 32 bit counter. and provided a link to a working code. I am very grateful for this. I tried this and fed this from GCLK0 (48 MHz). I worked wonderfully and the circa 5% time error with the RTC dropped to less than 0.1% against a quartz clock which was the accuracy limit for a 10 h test. I want to use the timer for time stamping with an precision of better than 100 ns over days. (The absolute accuracy is not so important.). So I adapted the MartinL’s code to extend the range beyond 32 bit uint32_t overflow at 89.5 s with a 48 MHz clock. It is attached.

This opens more questions… (1) While the 48 MHz tick corresponds to about 20.5 ns, what is the time jitter that will be introduced by the bus synchronization? My first though was since the TC4, AHB and APB are running from the 48 MHz, the sync time should be max one clock cycle. Since my most critical measurement is the difference between two times 10-12 µs apart, this would give max 3 clock cycle or ~60 ns uncertainty. (2) It seems, reading the datasheet, that if you don’t do a sync the last value is read out. Since this would be within 1 LSB of the true value is there any meaning to using the sync? I have no experience with such bus-sync in this form before so I am unsure of how it works.

Best regards,

Harry J. Whitlow

TSC_3.ino (4.13 KB)

what is the time jitter that will be introduced by the bus synchronization?

Data sheet says 5 to 6 cycles of the slower clock. :frowning:
No one seems to understand why it would take that long, or how long a clock stays synchronized, or ...
It's not well understood at all...
If you access a register that needs synchronization, at least SOME of them will just stall the bus automatically until synchronization happens. But while the bus is stalled, nothing else happens, so if it takes 6 clocks of your RTC running at 1kHz, that can be a real problem.

Data sheet says 5 to 6 cycles of the slower clock. :frowning:
No one seems to understand why it would take that long, or how long a clock stays synchronized, or …
It’s not well understood at all…
If you access a register that needs synchronization, at least SOME of them will just stall the bus automatically until synchronization happens. But while the bus is stalled, nothing else happens, so if it takes 6 clocks of your RTC running at 1kHz, that can be a real problem.

That’s a good point and something I hadn’t considered, why does it take 5 to 6 cycles to synchronize? You’d expect it to be 1 or 2 cycles at most.

Synchronization seems a high price to pay for the flexibility of being able to clock peripherals at differing clock rates, considering the amount of trouble it causes both in terms of programming registers and timing issues. I mean, to my knowledge the good old SAM3X8E on the Arduino Due doesn’t have any of these problems.

Hi Everybody,

I believe, that the synchronization delay itself is not a serious problem, but the variation in the delay, the so called time-jitter, is more of an issue for many timing applications.

I did change my code to use TC4-5 and because I am trying to measure the time an event took place relative to the ADC sampling time, I did some study of the time jitter. I looked into the manual and found this at 13.3.16.

“The synchronization will delay the write or read access duration by a delay D, given by the equation:
5 ⋅ PGCLK + 2 ⋅ PAPB < D < 6 ⋅ PGCLK + 3 ⋅ PAPB
Where PGCLK is the period of the generic clock and PAPB is the period of the peripheral bus clock. A normal peripheral bus register access duration is 2⋅PAPB .”

As Westfw pointed out it will get bad the RTC at low clock frequencies. If you run at 32 kHz the time-jitter is a whole 61 µs.

I did notice that peripheral interrupt flag register and event registers do not require synchronization. This suggest a technique to get round the time-jitter is use interupts/events/DMA to handle time critical operations - and, of course, use a high a GCLK frequency as possible.

Best regards,
Harry