DFLL gives 46.9 MHz instead of 47.9 MHz

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

My samd21g18a board is outputting 46.9 MHz instead of 47.9 MHz when I use DFLL with XOSC32K as the source.  I tried to match my settings to those found in Table 37-51 of the datasheet (3/2017).  Anyone had issues with the DFLL frequency being low.  I tried this on an xplained board and saw a similarly low frequency (47.1 MHz).  Here is the clock code if it helps.  One thing I am observing is it appears that the out of boundaries flag is being set (SYSCTRL_PCLKSR_DFLLOOB), indicating that the reference is unstable but my XOSC32K appears stable.  Any feedback is appreciated.

 

static void clockBootup(void) {
	/* enable clocks for the power, sysctrl, and gclk modules */
	PM->APBAMASK.reg = (PM_APBAMASK_PM | PM_APBAMASK_SYSCTRL | PM_APBAMASK_GCLK);

	/* adjust NVM wait states */
	PM->APBBMASK.reg |= PM_APBBMASK_NVMCTRL;
	NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(WAITSTATES);
	PM->APBBMASK.reg &= ~PM_APBBMASK_NVMCTRL;

	/* reset the GCLK module so it is in a known state */
	GCLK->CTRL.reg = GCLK_CTRL_SWRST;
	while (GCLK->STATUS.bit.SYNCBUSY) { }

	/* redirect all peripherals to a disabled clock generator (7) by default */
	for (int i = 0x0; i <= 0x3F; i++) {
		GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_Type){{.ID=i, .GEN=GCLK_CLKCTRL_GEN_GCLK7_Val}}.reg;
		while (GCLK->STATUS.bit.SYNCBUSY) { }
	}

	/* Use External 32.768KHz Oscillator */
	SYSCTRL->XOSC32K.reg = (SYSCTRL_XOSC32K_Type){{.RUNSTDBY=true, .STARTUP=7, .EN32K=true, .XTALEN=true }}.reg;
	/* ENABLE solo */
	SYSCTRL->XOSC32K.bit.ENABLE = true;
	while (SYSCTRL->PCLKSR.bit.XOSC32KRDY == 0) { }

	/* Setup GCLK1 with XOSC32 */
	GCLK->GENDIV.reg = (GCLK_GENDIV_Type){{.ID=1, .DIV=1}}.reg;
	while (GCLK->STATUS.bit.SYNCBUSY) { }
	GCLK->GENCTRL.reg = (GCLK_GENCTRL_Type){{.ID=1, .SRC=GCLK_GENCTRL_SRC_XOSC32K_Val, .RUNSTDBY=true, .GENEN=true}}.reg;
	while (GCLK->STATUS.bit.SYNCBUSY) { }

	/* Set GEN1_XOSC32 as source for DFLL */
	GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_Type){{.ID=GCLK_CLKCTRL_ID_DFLL48_Val, .GEN=GCLK_CLKCTRL_GEN_GCLK1_Val, .CLKEN=true}}.reg;
	while (GCLK->STATUS.bit.SYNCBUSY) { }

	/* Disable ONDEMAND mode while writing configurations */
	SYSCTRL->DFLLCTRL.bit.ONDEMAND = false;
	while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { }

	/* get the coarse and fine values stored in NVM (Section 9.3) */
	//uint32_t coarse = (*(uint32_t *)(0x806024) >> 26);  /* Bits 63:58 */
	uint32_t coarse = (*(uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR  >> FUSES_DFLL48M_COARSE_CAL_Pos);
	//uint32_t fine = (*(uint32_t *)(0x806028) & 0x3FF);  /* Bits 73:64 */
	uint32_t fine = 512;

	SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_FSTEP(10) | SYSCTRL_DFLLMUL_MUL(1464);
	SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(fine);
	SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_CCDIS;
	while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { } /* Wait for DFLL sync */
	SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE;
	while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { } /* Wait for DFLL sync */

	SYSCTRL->INTENCLR.reg = SYSCTRL_PCLKSR_DFLLRDY | SYSCTRL_PCLKSR_DFLLLCKF | SYSCTRL_PCLKSR_DFLLLCKC | SYSCTRL_PCLKSR_DFLLOOB;
	while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { } /* Wait for DFLL sync */
	SYSCTRL->DFLLCTRL.bit.ENABLE = 1;
	while ((SYSCTRL->PCLKSR.reg & (SYSCTRL_PCLKSR_DFLLRDY | SYSCTRL_PCLKSR_DFLLLCKF | SYSCTRL_PCLKSR_DFLLLCKC | SYSCTRL_PCLKSR_DFLLOOB)) == 0) { } /* Wait for DFLLLXXX sync */

	/* select the DFLL as source for clock generator 0 (CPU core clock) */
	GCLK->GENDIV.reg = (GCLK_GENDIV_Type){{.ID=0, .DIV=1}}.reg;
	while (GCLK->STATUS.bit.SYNCBUSY) { }
	GCLK->GENCTRL.reg = (GCLK_GENCTRL_Type){{.ID=0, .SRC=GCLK_GENCTRL_SRC_DFLL48M_Val, .OE=true, .GENEN=true}}.reg;
	while (GCLK->STATUS.bit.SYNCBUSY) { }

	SYSCTRL->DFLLCTRL.bit.ONDEMAND = true;
	while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) { } /* Wait for DFLL sync */

	/* Make sure GCLK0 is on */
	GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_Type){{.ID=GCLK_CLKCTRL_GEN_GCLK0_Val, .CLKEN=true}}.reg;
	while (GCLK->STATUS.bit.SYNCBUSY) { }
	
	GPIO gpio = {.group=PA, .pin=27, .out=true, .mux=MuxH};
	gpioConfigure(gpio);
}

 

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

photonthunder wrote:
XOSC32K as the source

So did you actually measure the XOSC32K  frequency?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, measured it out one of the pins in a similar fashion to GCLK0.  I was thinking there might be some strange issue with our crystal, thus why I tried it on the xplained board.  Makes me think there might be something in my setup of XOSC32K...

Last Edited: Tue. Jan 23, 2018 - 04:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The lock wait looks wrong, I would expect something like

	uint32_t mask = SYSCTRL_PCLKSR_DFLLRDY | SYSCTRL_PCLKSR_DFLLLCKF | SYSCTRL_PCLKSR_DFLLLCKC;
	while ((SYSCTRL->PCLKSR.reg & mask) != mask) { } /* Wait for DFLL lock */

Also there is no SYSCTRL_DFLLMUL_CSTEP setting. However the code still locks (both coarse and fine) at a mean about 48.09 MHz on my D21 XPlained Pro. 

/Lars

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

I just threw a water bottle at the wall!!! That is so obvious now, I wasn't waiting for it to lock like I thought.  Thanks for the insight.