SAML21 DPLL doesn't lock when using OSCM16M at 4MHz, locks when OSCM16M at 12MHz

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

Hello,

 

I am working on ATSAML21J18B - SAML21Xplained board. 

 

I am trying to configure DPLL at 48MHz using two unidentical but similar configurations. One of them works and the other keeps waiting on CLKRDY and LOCK bits of DPLL.

 

This configuration works: OSC16M (12MHz) --> GCLK_GEN[1] (2MHZ) --> DPLL (48MHz) --> GCLK_GEN[0] (48MHz) --> CPU_CLK (48MHz).  

OSCM16M freq = OSCCTRL_OSC16MCTRL_FSEL_12

GCLK_GEN[1] divider = GCLK_GENCTRL_DIV(6)

This configuration breaks:  OSC16M (4MHz) --> GCLK_GEN[1] (2MHZ) --> DPLL (48MHz) --> GCLK_GEN[0] (48MHz) --> CPU_CLK (48MHz).

OSCM16M freq = OSCCTRL_OSC16MCTRL_FSEL_4

GCLK_GEN[1] divider = GCLK_GENCTRL_DIV(2)

 

In both configurations DPLL source is 2MHz. OSC16M should be independent of DPLL as long as DPLL frequency is within its range of 32KHz to 2MHz.

 

Does anyone have any idea what might be wrong?

 

static void CLOCKS_OSC16M_12MHz_Init(const uint8_t divider)
{
	OSCCTRL->OSC16MCTRL.reg =	OSCCTRL_OSC16MCTRL_ONDEMAND | OSCCTRL_OSC16MCTRL_RUNSTDBY
								| OSCCTRL_OSC16MCTRL_FSEL_4| OSCCTRL_OSC16MCTRL_ENABLE;
	
	while(OSCCTRL->STATUS.bit.OSC16MRDY == 0);
	
}

static void CLOCKS_DPLL_Init()
{
	NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(2) ;
	
	set_power_domain(2);
	

	GCLK->GENCTRL[1].reg = GCLK_GENCTRL_DIV(2) | GCLK_GENCTRL_IDC | GCLK_GENCTRL_SRC_OSC16M | GCLK_GENCTRL_OE | GCLK_GENCTRL_GENEN;

	while(GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL1);
	
	GCLK->PCHCTRL[1].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_WRTLOCK;
	
	while(GCLK->PCHCTRL[1].bit.CHEN != 1);
	
	
	while(OSCCTRL->DPLLSYNCBUSY.bit.DPLLRATIO == 1);
	
	OSCCTRL->DPLLRATIO.reg |= OSCCTRL_DPLLRATIO_LDR(23) | OSCCTRL_DPLLRATIO_LDRFRAC(0);
	
	while(OSCCTRL->DPLLSYNCBUSY.bit.DPLLRATIO == 1);
	
	OSCCTRL->DPLLCTRLB.reg |= OSCCTRL_DPLLCTRLB_DIV(0) |  OSCCTRL_DPLLCTRLB_LTIME(0) | OSCCTRL_DPLLCTRLB_REFCLK(2) | OSCCTRL_DPLLCTRLB_FILTER(0);
	
	while(OSCCTRL->DPLLSYNCBUSY.bit.ENABLE == 1);
	
	OSCCTRL->DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
	
	while(OSCCTRL->DPLLSTATUS.bit.CLKRDY == 0 || OSCCTRL->DPLLSTATUS.bit.LOCK == 0);
	
	
	GCLK->GENCTRL[0].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_IDC | GCLK_GENCTRL_SRC_DPLL96M | GCLK_GENCTRL_OE | GCLK_GENCTRL_GENEN;
	
	while(GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0);
	
}

Thanks in advance.

 

Regards,

Rishit

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

Hi Rishitborad,

 

I just used the DFLL on SAMD20 to scale my 32kHz to 48MHz and i only read a few things about the SamL21 so i cant help much.

 

However i found routing the generic clock to a GPIO very helpfull.  Refer to the PORT Function Multiplexing to see which gpio can be used for this.
This helps you see if the reference clock for the PLL is correct/stable.  In my case the reference clock was drifting so much that the drift control did overflow causing the DFLL to stop.

 

Good luck.