Strange problem with GCLK

Hi,
I am currently developing a pulse analyser using a MKR Zero. Starting with “Blink” and “ASCIITable” I can upload the and execute sketches repeatedly without any need to reset. The Pulse analyser needs to use the RTC, Analogue comparator, ADC and DMA. I am using GCLK4 from the 48 MHz clock generator divided by 6 to get 8 MHz for clocking the RTC and ADC prescalers to give the 8 MHz and 2 MHz clocks, respectively. The 48 MHz GCLK0 is used to clock AC-DIG and the GCLK1 (32 kHz) is used to clock AC_ANA.

I get a strange behavior in that after I have executed the sketch that sets-up the clocks the IDE environment does not recognize the board. I need to do a power reset followed by a quick double reset to be abel to upload any sketch from the IDE. Obviously, by redefining the GCLKs I have messed up something. I am wondering what? I know that the Arduino system uses some timers.

So my question is what GCLK can I redefine and which are going to mess up the system?

Digging a little deeper I did find buried in the Arduino environment startup.c file the following useful information.

/**

  • \brief SystemInit() configures the needed clocks and according Flash Read Wait States.
  • At reset:
    • OSC8M clock source is enabled with a divider by 8 (1MHz).
    • Generic Clock Generator 0 (GCLKMAIN) is using OSC8M as source.
  • We need to:
    1. Enable XOSC32K clock (External on-board 32.768Hz oscillator), will be used as DFLL48M reference.
    1. Put XOSC32K as source of Generic Clock Generator 1
    1. Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
    1. Enable DFLL48M clock
    1. Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
    1. Modify PRESCaler value of OSCM to have 8MHz
    1. Put OSC8M as source for Generic Clock Generator 3

I don’t modify the source of Generic Clock Generator 0, 1, 2 or 3. I do redefine GCLK4. Is this used somewhere?

The source code is attached below:

Many thanks if somebody can tell me what stupid thing I am doing wrong.

H.J. Whitlow

DPP_v04.ino (17.7 KB)

Hi h_whitlow,

I think the issue is that the SAMD21 Arduino core code has already attached the ADC to GLCK0 at 48MHz.

To disconnect GCLK0 and reconnect GCLK4:

GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_ADC |           // Disconnect GCLK0 from the ADC
                    GCLK_CLKCTRL_GEN_GCLK0;         // Select GCLK0                                          
  while (GCLK->STATUS.bit.SYNCBUSY);                // Wait for synchronization

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |          // Enable GCLK
                      GCLK_CLKCTRL_ID_ADC |         // Connect GCLK4 to the ADC
                      GCLK_CLKCTRL_GEN_GCLK4;       // Select GCLK4                                          
  while (GCLK->STATUS.bit.SYNCBUSY);                // Wait for synchronization

The Analog Comparator and RTC peripherals are not used by the Arduino core and therefore start unconfigured and unattached to any generic clock.

Thanks MartinL,

I agree it is not a good idea to have a peripheral driven by two generic clocks at the same time. it turned out not to be the solution to the problem. (The need to do a power-reset with double reset click) to be able to upload sketches.

So by a process of elimination by commenting out code sections I made a skeleton piece of code for the RTC (attached) that reproduced the problem/issue.

Then by further tests I was able to ascertain the following:

  1. The first 8 lines of code that set up the divisor for GCLK4 are not the problem because commenting them out does not reproduce the problem.

  2. Changing GCLK4 for GCLK5 (should also be free) does reproduce the problem.

  3. Using GCLK0 (48 MHz) directly to clock the RTC does not reproduce the problem.

  4. Using GCLK1 (32 kHz) directly to clock the RTC does not reproduce the problem.

It seems the RTC has special reset features. According to Table 14-5 and 14-6 on p. 108-109 of the Atmel | SMART SAM D21 [DATASHEET] Atmel-42181F–SAM-D21_Datasheet–07/2015 it resets differently for a Power Reset compared to a user reset. With the GCLK setting retained after a user reset. Since these are used in the SAMD21 initialization and Arduino code initialization. This should get overwritten on us user reset.

So it seems the problem is that reassigning the GCLK4 frequency messes with subsequent a user reset - but not a power-reset.

Any help/ideas on how to solve this issue would be appreciated! My best idea so far is to use GCLK0 for feeding the RTC and just defining GCLK4 and ADC prescaler factors to get a 2 MHz phase-locked to GCLK0.

Harry J. Whitlow

CGLK_test.ino (1.68 KB)

Hi Harry,

I ran your "GCLK_test.ino", but I'm unable to reproduce the problem. Whether I do a power-on or user (single press of the reset button) reset, the microcontroller resumes sending "Do Something to the console every 2 seconds.

One option is to do a complete software reset of the RTC, after connecting it to GCLK4:

RTC->MODE2.CTRL.bit.SWRST = 1;                       // Software reset the RTC
while (RTC->MODE2.STATUS.bit.SYNCBUSY);              // Wait for synchronization ...
while(RTC->MODE2.CTRL.bit.ENABLE);                   // Wait for the RTC to become disabled

Another option is to use the SAMD21's TCC or TC timers, instead of the RTC. In particular TC4 and TC5 can be chained together to create a 32-bit timer/counter, simply by setting TC4 to 32-bit count mode.

Also, I noticed that for some reason the SAMD21 datasheet says: "The RTC should not work with the Generic Clock Generator 0.". This statement can be found in the RTC section - Product Dependencies - Clocks.

Hi MartinL,

Thanks for taking the time to help me with this issue. My specific problem is that Although the sketch uploads once and functions OK, when you try subsequently to upload the same or another sketch the IDE is unable to make contact with the board. This is a bit of problem for me as I use the MKR Zero connected to a circuit board that provides a dedicated +5 V power to Vin from a voltage regulator as the USB power from my Mac produces a lot of high frequency noise. This means its a bit tedious to have to do a hard reset every time I want to try a new sketch. Viz. taking the MKR off the board, disconnecting and reconnecting the USB and pressing reset twice.

Thanks for pointing out about manual making the comment about not using GCLK0. I tried it and it it allowed me to upload multiple times without hard resetting. I checked this with the RTC code I plan to use t(hat I will use to produce time stamps.) I tried with GLCK1 and that also allowed uploading multiple times without hard resetting. Any other GCLK did not. Maybe it is just an error in the manual.

I attach the test code.

Best regards,
Harry J. Whitlow

CGLK_test_V2.ino (2.14 KB)

Hi Harry,

Thanks for the new GCLK test code. I see what you mean, I can reproduce the problem. Only a power-on reset recovers the board, single tap reset fails and double tap reset fails to invoke the bootloader.

I'll have a look.

Kind regards,
Martin

Hi Harry,

After some investigation, it appears to have something to do with the clock source. If I connect GCLK4 to one of the 32k oscillators such as the internal (OSC32K) or the external crystal (XOSC32K), it recovers from a user reset. However if it’s connected to the 48MHz (DFLL48M) it doesn’t:

GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |           // Force to 50:50 mark space
                    GCLK_GENCTRL_GENEN |         // Enable GCLK4
                    //GCLK_GENCTRL_SRC_DFLL48M |   // RTC connected to 48MHz doesn't work
                    //GCLK_GENCTRL_SRC_XOSC32K |   // RTC connected to XOSC32K does
                    GCLK_GENCTRL_SRC_OSC32K |    // RTC connected to OSC32K does
                    GCLK_GENCTRL_ID(4);          // Select GCLK4

It's also possible to test the type of reset, by testing the bits set in the SAMD21's power manager's RCAUSE register:

if (PM->RCAUSE.bit.POR) {}  // Test for power on reset
if (PM->RCAUSE.bit.EXT) {}  // Test for external reset
if (PM->RCAUSE.bit.SYST) {} // Test for system reset request

I had a samd10 RTC running off a 16MHz GCLK: SAMD10-experiments/ticker_rtc.c at master · WestfW/SAMD10-experiments · GitHub
There are some notes on the rtc in the project read me file.

The code MartinL posted sets up the clock of the rtc significantly differently than I did. Iirc, I decided that the SRC field values were for setting up the GCLKS themselves, but you wanted to use the GEN values for attaching a GCLK to a peripheral. But OTHO, I’d tend to trust Martin’s code more than my own...

Hi westfw,

Thanks for the link to your code and notes on the RTC.

I think I can now see the reason why your notes state that the SAMD2x can only be used with a 32K clock source.

Is this what's happening?:

The SAMD21 datasheet states that during a user (button) reset the 32K clocks and RTC keep running. However, the 48MHz DFLL48M clock source dies during a user reset, even though the RTC is still active, effectively stalling microcontroller upon restart.

I guess this is why, if I disconnect GLK4 from the RTC before a user reset, the microcontroller restarts as normal:

GCLK->CLKCTRL.reg = //GCLK_CLKCTRL_CLKEN |       // Disable GCLK
                      GCLK_CLKCTRL_GEN_GCLK4 |    // Select GCLK4 source 
                      GCLK_CLKCTRL_ID_RTC;        // Select RTC destination
while(GCLK->CLKCTRL.bit.CLKEN);                   // Wait for CLKEN to clear

I can now see the reason why your notes state that the SAMD2x

I'm no longer very sure about that statement. The SAMD5x can't connect the RTC to a GCLK, just to assorted low-speed clocks, and I THOUGHT I had found something similar about SAMD21, back when I was "the RTC would be great for Arduino millis()/micros()." But now all the datasheets I can find say that the SAMD RTC can use a 48MHz GCLK...
Ah! Maybe it was the SAMC - I was fiddling with SAMC and SAMD10 at about the same time, and the SAMC RTC is low-speed oscillators only. (In any case, I was annoyed by the inconsistency of the RTC, and I think with the SAMC in general...)

Sigh. It looks like the bootloader tries to use the RTC.
I'm not sure how that affects things; it seems to do an RTC reset prior to its configuration. But I dunno.
The symptom is consistent with the bootloader hanging, right? It does DISABLE before SWRST, and the docs are a bit ambiguous on the correct ordering...

ASF - SO much redirection and nesting :frowning:

Ive been running into a similar problem. I put up a post here last night. Hopefully that might add something to this thread.

For context, Im using a DS3231 RTC with a 32kHz output as my clock source through GCLK_IO4 but the problem is essentially the same.

The symptom is consistent with the bootloader hanging, right?

Yeah, I think Id agree with this

Hmm. I think I was looking at the wrong bootloader source. AFAICT, the MKRZero is built from the code in the bootloaders/zero directory, which is much different than the bootloaders/mzero directory (and doesn't use ASF, and doesn't use the RTC.)

I've got a Sparkfun SAMD21 board connected up to an ICE and reprogrammed with the MKRZero Bootloader, and it does seem to be getting out of the bootloader and into the sketch code...
But it's not clear it's making it to the RTC code, so that's pretty weird...

westfw:
Hmm. I think I was looking at the wrong bootloader source. AFAICT, the MKRZero is built from the code in the bootloaders/zero directory, which is much different than the bootloaders/mzero directory (and doesn’t use ASF, and doesn’t use the RTC.)

Oh this makes more sense now, Ive been looking through it myself now you’ve pointed that out.
I though Id just go for a scroll as well.

Turns out that the USB peripheral uses GCLK Multiplexer 6! I had always been under the impression that the bootloader/firmware only ever used 0-3 and that left the other multiplexers open for general use but this is obviously not the case.

Time to keep searching, but this makes me think that GCLK 4 is used somewhere (probably well hidden) and reusing it for the RTC breaks everything due to the special reset properties of the RTC peripheral.

Either than or try using different GCLK muxes until I find one which does work (if this is actually the problem, still just guessing)

Edit: I was wrong. No references to GCLK 4 anywhere. Still interesting to know about the USB though. I’ve gone and ordered myself a j-link to give myself some hope of doing any testing with the bootloader. Will check back when it arrives and do some more testing in between times.

Note that "clock multiplexer" is not the same as "clock generator." the multiplexor is fixed for each peripheral (table 15-3 in the datasheet.)

westfw:
Note that "clock multiplexer" is not the same as "clock generator." the multiplexor is fixed for each peripheral (table 15-3 in the datasheet.)

Thanks for the correction. Im starting to realise how unhelpful assumptions can be.

Hi,
Regarding MartinL's comment about the RTC not working with GCLK0. I just did a couple of tests with running it from GLCK0 and just counting. It seems seems to be running about 6% fast compared to a quartz watch.

Its seems to me GLCK0 is a digital phase locked looped against the 32 kHz crystal. Then the 6% error is much larger than I would expect. I also get what seem to be random deviations compared to micros(). So maybe there is something special with the RTC.

I want to read the RTC to time-stamp analogue pulses when an AC triggers and generates an interrupt. As the ADC and AC are driven from the same clock this should not be a problem. However, the precision of the time-stamping is important for may application.

I will look into using one of the other timers in a 32 bit configuration. I can't use TC4 as this, I believe used to be used by the delay function on the M0 Pro. (https://forum.arduino.cc/index.php?topic=332275.0 see post #13).

I concur with the remark that the problem with uploading code is most likely associated with by the Bootloader assuming the clock for the RTC had not been modified.

Many thanks to those that have helped me on this matter.

Harry

Hi Harry,

Just recently another forum member asked about creating absolute timestamps, accurate to milliseconds using an RTC. I implemented some code that used the RTC in conjuction with timers TC4 and TC5, chained to act as a 32-bit counter.

I’m not sure if this is helpful for your application, but the code sets up RTC with a 32k external crystal clock source and as a calendar clock in mode 2. The RTC triggers an interrupt and an event every second. The interupt simply moves the RTC’s ALARM0 on by one second, to trigger the another interrupt a second later. The event however retriggers (resets) the TC4 timer to count the number of elapsed microseconds for each second. This allows a timerstamp consisting of year, month, day, hour, seconds, millisconds and microseconds to be generated.

The forum thread containing the code is here:https://forum.arduino.cc/index.php?topic=684501.0.

I’ve also attached the complete sketch:

RTCTest14.ino (9.34 KB)

The MKRZero uses the system tick timer for delay() and TC4 and TC5 should be free to use, (unless you’re using the tone library or analogWrite() on certain pins).