From e856965f2fc1d5d86a7682e347b334b67dd9e0ee Mon Sep 17 00:00:00 2001 From: Thibaut VIARD <thibaut.viard@atmel.com> Date: Mon, 28 Apr 2014 11:24:16 +0200 Subject: [PATCH] fixing clock setup according to review --- cores/arduino/startup.c | 77 ++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/cores/arduino/startup.c b/cores/arduino/startup.c index 238146a3..a02c8482 100644 --- a/cores/arduino/startup.c +++ b/cores/arduino/startup.c @@ -139,6 +139,14 @@ const DeviceVectors exception_table= * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. * 6) Put OSC8M as source for Generic Clock Generator 3 */ +// Constants for Clock generators +#define GENERIC_CLOCK_GENERATOR_MAIN (0u) +#define GENERIC_CLOCK_GENERATOR_XOSC32K (1u) +#define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */ +#define GENERIC_CLOCK_GENERATOR_OSC8M (3u) +// Constants for Clock multiplexers +#define GENERIC_CLOCK_MULTIPLEXER_DFLL48M (0u) + void SystemInit( void ) { /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */ @@ -150,16 +158,22 @@ void SystemInit( void ) /* * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator) */ - SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet */ - SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K | SYSCTRL_XOSC32K_ENABLE ; + SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */ + SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ; + SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_ENABLE ; /* separate call, as described in chapter 15.6.3 */ + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 ) { /* Wait for oscillator stabilization */ } /* Software reset the module to ensure it is re-initialized correctly */ + /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete. + * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1 + */ GCLK->CTRL.reg = GCLK_CTRL_SWRST ; - while ( GCLK->CTRL.reg & GCLK_CTRL_SWRST ) + + while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) ) { /* Wait for reset to complete */ } @@ -167,9 +181,7 @@ void SystemInit( void ) /* * 2) Put XOSC32K as source of Generic Clock Generator 1 */ - GCLK->GENDIV.reg = GCLK_GENDIV_ID( 1 ) | // Generic Clock Generator 1 - GCLK_GENDIV_DIV( 1 ) | // Divider set to 1 - GCLK_GENCTRL_DIVSEL ; + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1 while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { @@ -177,7 +189,7 @@ void SystemInit( void ) } /* Write Generic Clock Generator 1 configuration */ - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( 1 ) | // Generic Clock Generator 1 + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1 GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator GCLK_GENCTRL_GENEN ; @@ -189,7 +201,7 @@ void SystemInit( void ) /* * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference) */ - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( 0 ) | // Generic Clock 0 (GCLKMAIN) + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock 0 (GCLKMAIN) GCLK_CLKCTRL_GEN_GCLK1_Val | // Generic Clock Generator 1 is source GCLK_CLKCTRL_CLKEN ; @@ -204,13 +216,26 @@ void SystemInit( void ) /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */ - /* Enable the generic clock */ - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( SYSCTRL_GCLK_ID_DFLL48 ) | GCLK_CLKCTRL_CLKEN ; + /* Enable the generic clock */ + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( SYSCTRL_GCLK_ID_DFLL48 ) | + GCLK_CLKCTRL_CLKEN ; + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } /* DFLL Enable (Closed Loop) */ + SYSCTRL->DFLLCTRL.bit.ONDEMAND = 0 ; /* Remove the OnDemand mode, */ + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) + { + /* Wait for synchronization */ + } + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value - SYSCTRL_DFLLMUL_MUL( (48000000ul/32768ul) ) ; // External 32KHz is the reference + SYSCTRL_DFLLMUL_MUL( (VARIANT_MCK/VARIANT_MAINOSC) ) ; // External 32KHz is the reference /* Write full configuration to DFLL control register */ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */ @@ -225,9 +250,7 @@ void SystemInit( void ) /* * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. */ - GCLK->GENDIV.reg = GCLK_GENDIV_ID( 0 ) | // Generic Clock Generator 0 - GCLK_GENDIV_DIV( 1 ) | // Divider set to 1 - GCLK_GENCTRL_DIVSEL ; + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ) ; // Generic Clock Generator 0 while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { @@ -235,7 +258,7 @@ void SystemInit( void ) } /* Write Generic Clock Generator 0 configuration */ - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( 0 ) | // Generic Clock Generator 0 + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0 GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz GCLK_GENCTRL_GENEN ; @@ -247,18 +270,16 @@ void SystemInit( void ) /* * 6) Put OSC8M as source for Generic Clock Generator 3 */ - GCLK->GENDIV.reg = GCLK_GENDIV_ID( 3 ) | // Generic Clock Generator 3 - GCLK_GENDIV_DIV( 1 ) | // Divider set to 1 (8 MHz) - GCLK_GENCTRL_DIVSEL ; + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) ; // Generic Clock Generator 3 while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } - /* Write Generic Clock Generator 0 configuration */ - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( 3 ) | // Generic Clock Generator 3 - GCLK_GENCTRL_SRC_OSC8M | // Selected source is DFLL 48MHz + /* Write Generic Clock Generator 3 configuration */ + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3 + GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset) GCLK_GENCTRL_GENEN ; while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) @@ -267,15 +288,15 @@ void SystemInit( void ) } /* - * Now that all system clocks are configured, we can set CPU and APBx BUS clocks. - * There values are normally the one present after Reset. + * Now that all system clocks are configured, we can set CPU and APBx BUS clocks. + * There values are normally the one present after Reset. */ - PM->CPUSEL.reg = PM_CPUSEL_CPUDIV_DIV1 ; - PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val ; - PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val ; - PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val ; + PM->CPUSEL.reg = PM_CPUSEL_CPUDIV_DIV1 ; + PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val ; + PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val ; + PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val ; - SystemCoreClock=48000000ul ; + SystemCoreClock=VARIANT_MCK ; } /** -- GitLab