Tag Archives: GCLK

ASF: SAMD20/SAMD21 External interrupts in standby and the side effect of debugging

The EIC driver in the ASF for the SAMD20 defaults to using GCLK_GENERATOR_0. Unforunately I overlooked this little configuration when I was trying to use EIC in standby. So when I debugged, I could get external interrupts in standby, if I didn’t debug, my interrupts would not fire at all (while my RTC was fine). Fixing this was simple.

Cause

The root cause of the problem is in standby, all clocks are turned off and only the GCLKs are that are configured to remain on still run. The debugger appears to not allow clocks to turn off while debugging and thus peripherals will work even with clock configuration issues. However without the debugger it will fail.

Also, the EIC needs a running clock in standby if you want edge detection based interrupts to occur or if set to logic level interrupt with filtering. Purely logic level interrupts do not require a clock.

Solution

So my solution was because I was running GCLK2 in standby for the RTC, I configured the EIC to use it. This brings two benefits

1. My signals are not time critical, the 32khz clock has no effect on my application’s performance

2. Less power consumption from slower clocking and less gclks

Power saving in my application was critical so every microamp I saved is great.

So the simplest place to “fix” the configuration is to go into conf/conf_extint.c and change the GCLK define to GCLK_GENERATOR_1 in case of using the RTC.

Otherwise you can either

  1. Enable the GCLK_GENERATOR_0 to run in standby
  2. Configure another GCLK that will run in standby by editing conf_clocks.h. You can consider running it from the 32khz clock if you don’t have response time requirements.

And tada, you get external interrupts in standby outside of debug.

Additional Note

In conf_clocks.h

Check to make sure your 8mhz clock or 32khz clock that you are using to run your gclk is also enabled to run in standby or else the gclk won’t run.

# define CONF_CLOCK_OSC8M_RUN_IN_STANDBY true
or
# define CONF_CLOCK_OSC32K_RUN_IN_STANDBY true
also make sure your OSC32K is enabled in the first place(that’s not default)
# define CONF_CLOCK_OSC32K_ENABLE true