SAMD21 GCLK->CLKCTRL.CLKEN not getting set

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What am I doing wrong? After running the code below the value of GCLK->CLKCTRL.CLKEN is not 1 for for all peripherals


int main(void)
{
/* Store the value of CLKEN for each peripheral in clken_values */
  uint8_t clken_values[GCLK_CLKCTRL_ID_I2S_0_Val + 1];

  SystemInit();
/* SystemInit() does nothing, system has default configuration, GCLK0 has frequency
  OSC8M / 8, GCLK2 is OSCULP32K
  GCLK_CLKCTRL_Type gclk_clkctrl =
  { .bit.GEN = GCLK_CLKCTRL_GEN_GCLK0_Val,
    .bit.ID = GCLK_CLKCTRL_ID_WDT_Val,
    .bit.CLKEN = 1
  };
  for (uint16_t n = GCLK_CLKCTRL_ID_WDT_Val; n <=  GCLK_CLKCTRL_ID_I2S_0_Val; n++)
  {
    gclk_clkctrl.bit.ID = n;
    GCLK->CLKCTRL.reg = gclk_clkctrl.reg;
    while(GCLK->STATUS.reg)	/* SYNCBUSY is the only bit */
      ;
    clken_values[n] = GCLK->CLKCTRL.bit.CLKEN;
  }
}

The clken_values for the peripherals WDT to SERCOMx_SLOW are all zero except for RTC and USB, then all from SERCOM0 to I2S are 1, except for TCC0_TCC1 (known special feature) and AC_ANA

GCLK0 and GCLK2 are both enabled in GCLK->GENCTRL

At the moment I need EIC, but can't enable the clock for it

This problem has been discussed several times, but none of the suggestions lead to success

Dispairing, Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, we discussed that before. So it looks that reading back GENCTRL doesn't work for some peripherals. So, why do you think you cannot enable the EIC clock (besides not seeing the CLKEN bit)? Show us your EIC code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The EIC bit in PM->APBAMASK is already set at power on (checked)

  /* Give the EIC a clock */
GCLK->CLKCTRL.reg = (uint16_t)(GCLK_CLKCTRL_CLKEN |
    GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_EIC);
  GCLK->CLKCTRL.reg |= (uint16_t) GCLK_CLKCTRL_CLKEN;
/* CLKEN is not set after writing to CLKCTRL */
/* Enable event from the External Interrupt Controller, 
  EXTINT number is PPS_PIN % 16
  The symbols below are defined elsewhere
*/
  EIC->EVCTRL.reg = PPS_EIC_EVCTRL_EXTINTEO;
/* Set FILTER bit and SENSE to RISING */
  EIC->CONFIG[(PPS_PIN % 16) / 8].reg = PPS_EIC_CONFIG;	
  
  EIC->CTRL.reg = EIC_CTRL_ENABLE;
  while (EIC->STATUS.bit.SYNCBUSY)
    ;
/* Never gets here. ENABLE is set, but SYNCBUSY also */

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is GCLK_CLKCTRL_GEN_GCLK1? Is it enabled? How is it configured?
What is PPS_PIN, PPS_EIC_EVCTRL_EXTINTEO, PPS_EIC_CONFIG?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:

What is GCLK_CLKCTRL_GEN_GCLK1? Is it enabled? How is it configured?
What is PPS_PIN, PPS_EIC_EVCTRL_EXTINTEO, PPS_EIC_CONFIG?

 

 

GCLK1 is enabled - I tried the EIC code with GCLK2, which is enabled after power up, with the same result

The GCLK initialisation code is:

GCLK_SET gclk_set =
	{ .genctrl_src	= GCLK_CLKCTRL_GEN_GCLK0_Val,
		.gendiv_div = GCLK1_GENDIV_DIV,
		.gendiv_id  = GCLK_CLKCTRL_GEN_GCLK1_Val
	};
	gclk_gen_setup(&gclk_set);

Where gclk_gen_setup() is defined as:

void gclk_gen_setup(GCLK_SET *gclk_set)
{ GCLK_GENDIV_Type gclk_gendiv =
  { .bit.DIV = gclk_set->gendiv_div,
    .bit.ID  = gclk_set->gendiv_id
  };
  GCLK_GENCTRL_Type gclk_genctrl =
  { .bit.GENEN  = 1,        /* Always enable */
    .bit.ID     = gclk_set->gendiv_id,
    .bit.SRC    = gclk_set->genctrl_src,
    .bit.DIVSEL = 0         /* Divide by value in GENDIV.DIV */
  };

  GCLK->GENDIV.reg = gclk_gendiv.reg;
  GCLK->GENCTRL.reg = gclk_genctrl.reg;
  while(GCLK->STATUS.bit.SYNCBUSY)
    ;
} // gclk_gen_setup

The symbols are all derived from the #include files for SAMD21, corresponding to the particular HW configuration, here the number of the pin (PPS_PIN, PA17) to which the GPS PPS signal is attached

#define GCLK_CLKCTRL_GEN_GCLK1 (GCLK_CLKCTRL_GEN_GCLK1_Val << GCLK_CLKCTRL_GEN_Pos)
#define PPS_PIN PA17			/* GPS PPS signal connected here */
/* EVSYS->EXTINTSET bit corresponding to PPS_PIN */
#define PPS_EIC_EVCTRL_EXTINTEO	EIC_EVCTRL_EXTINTEO1
/* A tricky definition for EIC->CONFIG corresponding to PPS_PIN from eic.h */

#define PPS_FILTER EIC_CONFIG_FILTEN0	/* Enable filter for PPS pin */
#define PPS_SENSE EIC_CONFIG_SENSE0_RISE	/* Positive flank of PPS */
#define PPS_EIC_CONFIG ((PPS_FILTER | PPS_SENSE) << (4 * ((PPS_PIN % 16) % 8)))

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is the intended source of GCLK1? This looks wrong

	{ .genctrl_src	= GCLK_CLKCTRL_GEN_GCLK0_Val,

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:

What is the intended source of GCLK1? This looks wrong

	{ .genctrl_src	= GCLK_CLKCTRL_GEN_GCLK0_Val,

/Lars

Hello Lars,

    GCLK1 has indeed GCLK0 and looking at the datasheet again (RTFM) only GCLKGEN1 can be a source. O dear! 

Now changed, but still the same result, CLKEN is still not set

Now, however EIC can be enabled, then GCLK->CLKCTRL.CLKEN is set. Another undocumented case like TCC0/TCC1

Well observed Lars! You rescued me again

Best wshes,

 

Jerry

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jerry,

 

Did you determine the underlying cause of this issue?  I think I am having a similar issue.  I am trying to configure the clock for the EVSYS_CHANNEL_4 and I cannot set the CLKEN bit.  In fact, I cannot set the CLKEN for any EVSYS_CHANNEL_x.  

 

Here is the code from the RTCZero Arduino library.  I have added the last line:

 

void RTCZero::configureClock() {
  GCLK->GENDIV.reg = GCLK_GENDIV_ID(2)|GCLK_GENDIV_DIV(4);
  while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
    ;
  GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_DIVSEL );
  while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
    ;
  GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
  while (GCLK->STATUS.bit.SYNCBUSY)
    ;
  // Feed clock to RTC Event System Channel - Note, this register is not write synchronized so does not require SYNCBUSY wait
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | RTCZERO_GCLK_CLKCTRL_ID;
}

RTCZERO_GCLK_CLKCTRL_ID is defined as GCLK_CLKCTRL_ID_EVSYS_4

 

When I read the CLKEN bit after setting up the clock, it reads back as 0.  I configured the RTC periodic event 7 to be the event generator.  When I enable the event in the RTC->EVCTRL.reg the MCU stalls and then reboots when my watchdog fires.  So, I believe I have a clock problem and the problem is that the clock is not configured.  But, I do not understand why I cannot enable the clock.

 

Any ideas or suggestions?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I figured out the problem.  I was able to confirm that the clock was configured properly.  For anyone stumbling across this thread, the issue was I was enabling the RTC before the wrote the EVCTRL register.  The RTC has an "Enable Protection" feature that prevents writes to some of the registers after the RTC is enabled.  The EVCTRL register is one of the registers protected.