/*** *** These examples have no copyright and can be used by anyone. *** The following examples are based on Device File Package *** required to compile the macro definitions used. *** The Device File Package is available by downloading Atmel Studio 7. ***/ /*** *** EXAMPLE 1: *** As the device boots using the OSC16M *** oscillator running @4MHz, *** Here is an example function configuring the device *** to use the OSC16M running @8MHz. *** The function performs the following steps: *** 1- Configure and Enable Clock Generator 0 (GCLK0), *** XOSC32K as source to switch back on OSC16M *** 2- Disabling the OSC16M to reconfigure it *** 3- Reconfigure the OSC16M oscillator frequency to 8MHz *** 4- Re-enable the OSC16M *** 5- Enable and Connect Generic clock 0 to OSC16M ***/ void switch_OSC16M_freq_8MHz() { /*** *** Configure and Enable Clock Generator 0 *** (GCLK0), XOSC32K as source to switch back on OSC16M ***/ GCLK->GENCTRL[0].reg = GCLK_GENCTRL_DIV(0) | GCLK_GENCTRL_SRC_XOSC32K |GCLK_GENCTRL_GENEN; /*** (write synchronized) ***/ while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0)); /*** Disabling the OSC16M to reconfigure it ***/ OSCCTRL->OSC16MCTRL.bit.ENABLE = 0; /*** Wait for OSC16M is ready ***/ while((OSCCTRL->STATUS.reg & OSCCTRL_STATUS_OSC16MRDY)); /*** Reconfigure the OSC16M oscillator frequency to 8MHz ***/ OSCCTRL->OSC16MCTRL.reg= OSCCTRL_OSC16MCTRL_FSEL(OSCCTRL_OSC16MCTRL_FSEL_8_Val); /*** Re Enable the OSC16M ***/ OSCCTRL->OSC16MCTRL.bit.ENABLE = 1; /*** Wait for OSC16M is ready ***/ while(!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_OSC16MRDY)); /*** Enable and Connect Generic clock 0 to OSC16M ***/ GCLK->GENCTRL[0].reg = (GCLK_GENCTRL_SRC_OSC16M| GCLK_GENCTRL_DIV(1)|GCLK_GENCTRL_GENEN); /*** (write synchronized) ***/ while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0)); } /******************************************************************************************/ /*** *** EXAMPLE 2: *** As the device boots using the OSC16M *** oscillator running @4MHz, *** Here is an example function configuring the device *** to use the DFLLULP running @fequency passed in argument. *** The function performs the following steps: *** 1- Configure and Enable Clock Generator 1 (GCLK1), XOSC32K as source not divided *** 2- Enable DFLLULP Peripheral Channel with GCLK1 as source *** 3- configure the DFLLULP output frequency *** 4- Get DFLLULP Division Factor in PL0 from NVM Software Calibration Area *** To be written to DFLLULPCTRL register *** 5- Configure DFLLULP with PL0 Division Factor *** 6- Switch DFLLULP clock on Main Clock (OSC16M = 4MHz by default after reset) +ERRATA *** 7- Disable OSC16M and GCLK0 (if not used). ***/ void configure_dfllulp(uint32_t freq) { uint8_t divider; /*** Configure and Enable Clock Generator 1 (GCLK1), XOSC32K as source not divided ***/ GCLK->GENCTRL[1].reg = GCLK_GENCTRL_DIV(1) | CURRENT_32KOSC | GCLK_GENCTRL_GENEN; /*** (write synchronized) ***/ while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL1)); /*** Enable DFLLULP Peripheral Channel with GCLK1 as source ***/ GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLLULP].reg = (GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN); /*** configure the DFLLULP output frequency ***/ OSCCTRL->DFLLULPRATIO.reg = OSCCTRL_DFLLULPRATIO_RATIO(freq/CURRENT_32KOSC_FREQ); /*** Get DFLLULP Division Factor in PL0 from NVM Software Calibration Area *** To be written to DFLLULPCTRL register ***/ divider = ((*((uint32_t *)FUSES_DFLLULP_DIV_PL0_ADDR) & FUSES_DFLLULP_DIV_PL0_Msk) >> FUSES_DFLLULP_DIV_PL0_Pos); /*** Configure DFLLULP with PL0 Division Factor ***/ OSCCTRL->DFLLULPCTRL.reg = OSCCTRL_DFLLULPCTRL_DIV(divider)| OSCCTRL_DFLLULPCTRL_BINSE| OSCCTRL_DFLLULPCTRL_SAFE| OSCCTRL_DFLLULPCTRL_ENABLE| OSCCTRL_DFLLULPCTRL_RUNSTDBY| OSCCTRL_DFLLULPCTRL_ONDEMAND; while(OSCCTRL->DFLLULPSYNCBUSY.bit.ENABLE==1); /* (write synchronized) */ /*** Switch DFLLULP clock on Main Clock (OSC16M = 4MHz by default after reset) ***/ MCLK->CTRLA.bit.CKSEL= 1; /*** Applying Workaround ERRATA DFLLULP Clock *** Add 6 NOP instructions after writing the CTRAL.CKSEL bit. ***/ __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); while(MCLK->INTFLAG.bit.CKRDY == 0); /*** Wait for DFLLULP lock flag ***/ while((OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLULPLOCK) == 0); /*** Disable OSC16M and GCLK0 ***/ GCLK->GENCTRL[0].bit.GENEN = 0; while (GCLK->SYNCBUSY.bit.GENCTRL0==1); /* (write synchronized) */ OSCCTRL->OSC16MCTRL.bit.ENABLE = 0; while(OSCCTRL->STATUS.bit.OSC16MRDY==1); } /******************************************************************************************/ /*** *** EXAMPLE 3: *** Here is an example function configuring the device *** to use the DPLL running to run at Full speed (32 MHz) *** The function performs the following steps: *** 1- Initialize the XOSC32K Oscillator (32 kHz On-board Crystal) *** 2- Switch Performance level from PL0 (Default after reset) to PL2 *** 3- Configure Flash Wait States based on next Main Clock frequency (32 MHz <-> 2 WS) *** 4- Initialize the DPLL to generate 64 MHz Set Main clock to DPLL/2 ***/ void Device_Fullspeed(void) { /*** *** Set XOSC32K Startup time *** (see "Start-Up Time for 32KHz External Crystal Oscillator" *** table from datasheet) *** Enable 32.768kHz output *** Enable Crystal Oscillator mode *** Enable XOSC32K ***/ OSC32KCTRL->XOSC32K.reg =(OSC32KCTRL_XOSC32K_STARTUP(0x3)| OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_XTALEN | OSC32KCTRL_XOSC32K_ENABLE); /*** Write Synchronized ***/ while(!(OSC32KCTRL->STATUS.bit.XOSC32KRDY)); /*** *** Switch Performance level *** from PL0 (Default after reset) to PL2 ***/ PM->PLCFG.bit.PLSEL = 2; while(PM->INTFLAG.bit.PLRDY == 0); /*** *** Configure Flash Wait States based *** on next Main Clock frequency (32 MHz <-> 2 WS) ***/ NVMCTRL->CTRLB.bit.RWS = 2; /*** *** Set DPLL Ratio to generate 64MHz clock *** (64MHz/32.768kHz=1953.125 *** => LDR=1952/LDRFRAC=2 <=> *** 64MHz=32.768*(LDR+1+LDRFRAC/16) ***/ OSCCTRL->DPLLRATIO.reg = (OSCCTRL_DPLLRATIO_LDR(1952)| OSCCTRL_DPLLRATIO_LDRFRAC(2)); /*** Write Synchronized ***/ while((OSCCTRL->DPLLSYNCBUSY.bit.DPLLRATIO)); /*** Disable On-demand ***/ OSCCTRL->DPLLCTRLA.bit.ONDEMAND = 0; /*** *** Set Lock time as automatic ***and reference clock to XOSC32KHz ***/ OSCCTRL->DPLLCTRLB.reg = (OSCCTRL_DPLLCTRLB_LTIME(0)| OSCCTRL_DPLLCTRLB_REFCLK_XOSC32K); /*** Enable DPLL ***/ OSCCTRL->DPLLCTRLA.bit.ENABLE = 1; while(OSCCTRL->DPLLSYNCBUSY.bit.ENABLE); /*** Wait for DPLL lock flag ***/ while(!OSCCTRL->DPLLSTATUS.bit.LOCK); /*** *** Set Generic clock 0 ***(MAIN clock for CPU and synchronous clock) ***/ GCLK->GENCTRL[0].reg = (GCLK_GENCTRL_SRC(0x07)| GCLK_GENCTRL_DIV(2)| GCLK_GENCTRL_GENEN); /*** Write Synchronized ***/ while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0)); /*** *** Set Generic clock 1 (GCLK1), *** XOSC32K as source not divided ***/ GCLK->GENCTRL[1].reg = (GCLK_GENCTRL_SRC_XOSC32K| GCLK_GENCTRL_DIV(1)| GCLK_GENCTRL_GENEN); /*** Write Synchronized ***/ while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0)); }