/** * \brief Performs the low-level initialization of the chip. * This includes EFC and master clock configuration. * It also enable a low level on the pin NRST triggers a user reset. */ extern WEAK void LowLevelInit( void ) { uint32_t dwTimeout; /* Set 3 WS for Embedded Flash Access for 84 MHz */ EFC0->EEFC_FMR = EEFC_FMR_FWS( 3 ); EFC1->EEFC_FMR = EEFC_FMR_FWS( 3 ); /* Initialize main oscillator */ if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) /* Main Oscillator Selection */ { /* The Main Crystal Oscillator is enabled */ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(0x8) /* Main Crystal Oscillator Start-up Time: 1.4ms(datasheet) */ /* Specifies the number of Slow Clock cycles multiplied by 8 for the Main Crystal Oscillator start-up time */ | CKGR_MOR_MOSCRCEN /* Main On-Chip RC Oscillator Enable */ | CKGR_MOR_MOSCXTEN; /* Main Crystal Oscillator Enable */ /* MOSCSEL: The Main On-Chip RC Oscillator is selected */ /* MOSCRCF: The Fast RC Oscillator Frequency is at 4 MHz (default) */ /* CFDEN: The Clock Failure Detector is disabled. */ dwTimeout = 0; while ( !(PMC->PMC_SR & PMC_SR_MOSCXTS) && (dwTimeout++ < CLOCK_TIMEOUT) ); } /* Switch to 3-20MHz Xtal oscillator */ /* The Main Crystal Oscillator is enabled */ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(0x8) /* Main Crystal Oscillator Start-up Time: 1.4ms(datasheet) */ /* Specifies the number of Slow Clock cycles multiplied by 8 for the Main Crystal Oscillator start-up time */ | CKGR_MOR_MOSCRCEN /* Main On-Chip RC Oscillator Enable */ | CKGR_MOR_MOSCXTEN /* Main Crystal Oscillator Enable */ | CKGR_MOR_MOSCSEL; /* The Main Crystal Oscillator is selected */ /* MOSCRCF: The Fast RC Oscillator Frequency is at 4 MHz (default) */ /* CFDEN: The Clock Failure Detector is disabled. */ dwTimeout = 0; /* Wait Main XTAL Oscillator Status */ while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (dwTimeout++ < CLOCK_TIMEOUT)); /* configure PLLA to 168 MHz */ PMC->CKGR_PLLAR = CKGR_PLLAR_STUCKTO1 | CKGR_PLLAR_MULA(13) /* PLLA Multiplier 12 MHz x (13+1) = 168 MHz */ | CKGR_PLLAR_PLLACOUNT(2) /* PLLA Counter 200µs(datasheet) */ | CKGR_PLLAR_DIVA(1); /* Divider bypassed */ dwTimeout = 0; /* Wait PLL A Lock Status */ while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (dwTimeout++ < CLOCK_TIMEOUT)); PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_2 /* Selected clock divided by 2 => 168/2 = 84 MHz */ | PMC_MCKR_CSS_MAIN_CLK; /* Main Clock is selected */ dwTimeout = 0; /* Wait Master Clock Status */ while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (dwTimeout++ < CLOCK_TIMEOUT)); PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_2 /* Selected clock divided by 2 => 168/2 = 84 MHz */ | PMC_MCKR_CSS_PLLA_CLK; /* PLLA Clock is selected */ dwTimeout = 0; /* Wait Master Clock Status */ while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (dwTimeout++ < CLOCK_TIMEOUT)); }
/** * \brief Performs the low-level initialization of the chip. * This includes EFC and master clock configuration. * It also enable a low level on the pin NRST triggers a user reset. */ extern WEAK void LowLevelInit( void ) { uint32_t timeout = 0; /* Set 3 FWS for Embedded Flash Access */ EFC->EEFC_FMR = EEFC_FMR_FWS(3); /* Initialize main oscillator */ if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) { PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; timeout = 0; while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT)); } /* Switch to 3-20MHz Xtal oscillator */ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; timeout = 0; while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT)); PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); /* Initialize PLLB */ PMC->CKGR_PLLBR = BOARD_PLLBR; timeout = 0; while (!(PMC->PMC_SR & PMC_SR_LOCKB) && (timeout++ < CLOCK_TIMEOUT)); /* Switch to main clock */ PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); PMC->PMC_MCKR = BOARD_MCKR ; for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); }
void clock_init(void) { uint32_t timeout; /* Disable watchdog */ WDT_MR = BV(WDT_WDDIS); /* Set wait states for flash access, needed for higher CPU clock rates */ EEFC0_FMR = EEFC_FMR_FWS(3); #ifdef EEFC1_FMR EEFC1_FMR = EEFC_FMR_FWS(3); #endif // Initialize main oscillator if (!(CKGR_MOR & BV(CKGR_MOR_MOSCSEL))) { CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(0x8) | BV(CKGR_MOR_MOSCRCEN) | BV(CKGR_MOR_MOSCXTEN); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MOSCXTS)) && --timeout); } // Switch to external oscillator CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(0x8) | BV(CKGR_MOR_MOSCRCEN) | BV(CKGR_MOR_MOSCXTEN) | BV(CKGR_MOR_MOSCSEL); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MOSCXTS)) && --timeout); // Initialize and enable PLL clock CKGR_PLLR = evaluate_pll() | BV(CKGR_PLLR_STUCKTO1) | CKGR_PLLR_PLLCOUNT(0x2); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_LOCK)) && --timeout); PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK; timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MCKRDY)) && --timeout); PMC_MCKR = PMC_MCKR_CSS_PLL_CLK; timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MCKRDY)) && --timeout); /* Enable clock on PIO for inputs */ // TODO: move this in gpio_init() for better power management? pmc_periphEnable(PIOA_ID); pmc_periphEnable(PIOB_ID); pmc_periphEnable(PIOC_ID); #ifdef PIOF_ID pmc_periphEnable(PIOD_ID); pmc_periphEnable(PIOE_ID); pmc_periphEnable(PIOF_ID); #endif }
/** * @brief Initialize the CPU, set IRQ priorities */ void cpu_init(void) { /* disable the watchdog timer */ WDT->WDT_MR |= WDT_MR_WDDIS; /* initialize the Cortex-M core */ cortexm_init(); /* setup the flash wait states */ EFC0->EEFC_FMR = EEFC_FMR_FWS(CLOCK_FWS); EFC1->EEFC_FMR = EEFC_FMR_FWS(CLOCK_FWS); /* unlock write protect register for PMC module */ PMC->PMC_WPMR = PMC_WPMR_WPKEY(WPKEY); /* activate the external crystal */ PMC->CKGR_MOR = (CKGR_MOR_KEY(MORKEY) | CKGR_MOR_MOSCXTST(XTAL_STARTUP) | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCRCEN); /* wait for crystal to be stable */ while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)); /* select crystal to clock the main clock */ PMC->CKGR_MOR = (CKGR_MOR_KEY(MORKEY) | CKGR_MOR_MOSCXTST(XTAL_STARTUP) | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCSEL); /* wait for main oscillator selection to be complete */ while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)); /* setup PLLA */ PMC->CKGR_PLLAR = (CKGR_PLLAR_ONE | CKGR_PLLAR_PLLACOUNT(PLL_CNT) | CKGR_PLLAR_MULA(CLOCK_PLL_MUL) | CKGR_PLLAR_DIVA(CLOCK_PLL_DIV)); /* wait for PLL to lock */ while (!(PMC->PMC_SR & PMC_SR_LOCKA)); /* before switching to PLLA, we need to switch to main clock */ PMC->PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK; while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); /* use PLLA as main clock source */ PMC->PMC_MCKR = PMC_MCKR_CSS_PLLA_CLK; /* wait for master clock to be ready */ while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); /* trigger static peripheral initialization */ periph_init(); }
void clock_init(void) { uint32_t timeout; /* Disable watchdog */ WDT_MR = BV(WDT_WDDIS); /* Set 4 wait states for flash access, needed for higher CPU clock rates */ EEFC_FMR = EEFC_FMR_FWS(3); // Select external slow clock if (!(SUPC_SR & BV(SUPC_SR_OSCSEL))) { SUPC_CR = BV(SUPC_CR_XTALSEL) | SUPC_CR_KEY(0xA5); while (!(SUPC_SR & BV(SUPC_SR_OSCSEL))); } // Initialize main oscillator if (!(CKGR_MOR & BV(CKGR_MOR_MOSCSEL))) { CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSC_COUNT | BV(CKGR_MOR_MOSCRCEN) | BV(CKGR_MOR_MOSCXTEN); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MOSCXTS)) && --timeout); } // Switch to external oscillator CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSC_COUNT | BV(CKGR_MOR_MOSCRCEN) | BV(CKGR_MOR_MOSCXTEN) | BV(CKGR_MOR_MOSCSEL); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MOSCSELS)) && --timeout); PMC_MCKR = (PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_MASK) | PMC_MCKR_CSS_MAIN_CLK; timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MCKRDY)) && --timeout); // Initialize and enable PLL clock CKGR_PLLR = evaluate_pll() | BV(CKGR_PLLR_STUCKTO1) | CKGR_PLLR_PLLCOUNT(0x1); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_LOCK)) && --timeout); PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK; timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MCKRDY)) && --timeout); PMC_MCKR = PMC_MCKR_CSS_PLL_CLK; timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MCKRDY)) && --timeout); /* Enable clock on PIO for inputs */ PMC_PCER = BV(PIOA_ID) | BV(PIOB_ID) | BV(PIOC_ID); }
/** * \brief Enable internal 4/8/12MHz fast RC as main clock input. * * \param freqSelect fast RC frequency (FAST_RC_4MHZ, FAST_RC_8MHZ, FAST_RC_12MHZ). */ extern void PMC_EnableIntRC4_8_12MHz(uint32_t freqSelect) { uint32_t read_MOR; /* Before switching MAIN OSC on RC OSC : enable it and don't disable * at the same time external crystal in case of if MAIN OSC is still using external crystal */ read_MOR = PMC->CKGR_MOR; read_MOR &= ~CKGR_MOR_MOSCRCF_Msk; /* reset MOSCRCF field in MOR register before select RC 12MHz */ read_MOR |= (CKGR_MOR_KEY(0x37u) | freqSelect | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTST(PmcFastRcCnt)); /* enable external crystal - enable RC OSC */ PMC->CKGR_MOR = read_MOR; while( !(PMC->PMC_SR & PMC_SR_MOSCRCS ) ); /* wait end of RC oscillator stabilization */ while( !(PMC->PMC_SR & PMC_SR_MCKRDY) ); read_MOR &= ~CKGR_MOR_MOSCSEL; /* select internal fast RC */ PMC->CKGR_MOR = read_MOR; while( !(PMC->PMC_SR & PMC_SR_MOSCSELS ) ); /* Wait end of Main Oscillator Selection */ while( !(PMC->PMC_SR & PMC_SR_MCKRDY) ); }
static void mcu_xtal_mainck_start (void) { PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) | CKGR_MOR_KEY (0x37) | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCXTST (MCU_MAINCK_COUNT); /* Wait for the xtal oscillator to stabilize. */ while (! (PMC->PMC_SR & PMC_SR_MOSCXTS)) continue; PMC->CKGR_MOR |= CKGR_MOR_KEY (0x37) | CKGR_MOR_MOSCSEL; /* Could check if xtal oscillator fails to start; say if xtal not connected. */ }
/** * \brief Select internal 12M OSC. */ extern void PMC_SelectInt12M_Osc(void) { uint32_t count; /* switch from external OSC 12 MHz to internal RC 12 MHz*/ /* enable internal RC 12 MHz */ PMC->CKGR_MOR |= CKGR_MOR_MOSCRCEN | CKGR_MOR_KEY(0x37); /* Wait internal 12 MHz RC Startup Time for clock stabilization (software loop) */ for (count = 0; count < 0x100000; count++); /* switch MAIN clock to internal RC 12 MHz */ PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | CKGR_MOR_KEY(0x37); /* wait MAIN clock status change for internal RC 12 MHz selection*/ while(PMC->PMC_SR & PMC_SR_MOSCSELS); /* in case where MCK is running on MAIN CLK */ while(!(PMC->PMC_SR & PMC_SR_MCKRDY)); /* disable external OSC 12 MHz */ PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) | CKGR_MOR_KEY(0x37); }
/** * \brief Disable external oscilator. */ extern void PMC_DisableExtOsc(void) { uint32_t read_MOR; read_MOR = PMC->CKGR_MOR; read_MOR &= ~CKGR_MOR_MOSCXTEN; /* disable main xtal osc */ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37u) | read_MOR; while( !(PMC->PMC_SR & PMC_SR_MCKRDY) ); }
/** * \brief Select external OSC. */ extern void PMC_SelectExtBypassOsc(void) { PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTST(0xFF) | CKGR_MOR_MOSCXTBY; PMC->CKGR_MOR |= CKGR_MOR_MOSCSEL; /* wait MAIN clock status change for external OSC 12 MHz selection*/ while(!(PMC->PMC_SR & PMC_SR_MOSCSELS)); }
/** * \brief Enable Wait Mode. Enter condition: (WAITMODE bit = 1) + * (SLEEPDEEP bit = 0) + FLPM */ void pmc_enable_waitmode(void) { uint32_t i; /* Flash in Deep Power Down mode */ i = PMC->PMC_FSMR; i &= ~PMC_FSMR_FLPM_Msk; i |= ul_flash_in_wait_mode; PMC->PMC_FSMR = i; /* Clear SLEEPDEEP bit */ SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; /* Backup FWS setting and set Flash Wait State at 0 */ #if defined(ID_EFC) uint32_t fmr_backup; fmr_backup = EFC->EEFC_FMR; EFC->EEFC_FMR &= (uint32_t) ~ EEFC_FMR_FWS_Msk; #endif #if defined(ID_EFC0) uint32_t fmr0_backup; fmr0_backup = EFC0->EEFC_FMR; EFC0->EEFC_FMR &= (uint32_t) ~ EEFC_FMR_FWS_Msk; #endif #if defined(ID_EFC1) uint32_t fmr1_backup; fmr1_backup = EFC1->EEFC_FMR; EFC1->EEFC_FMR &= (uint32_t) ~ EEFC_FMR_FWS_Msk; #endif /* Set the WAITMODE bit = 1 */ PMC->CKGR_MOR |= CKGR_MOR_KEY(0x37u) | CKGR_MOR_WAITMODE; /* Waiting for Master Clock Ready MCKRDY = 1 */ while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); /* Waiting for MOSCRCEN bit cleared is strongly recommended * to ensure that the core will not execute undesired instructions */ for (i = 0; i < 500; i++) { __NOP(); } while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN)); /* Restore EFC FMR setting */ #if defined(ID_EFC) EFC->EEFC_FMR = fmr_backup; #endif #if defined(ID_EFC0) EFC0->EEFC_FMR = fmr0_backup; #endif #if defined(ID_EFC1) EFC1->EEFC_FMR = fmr1_backup; #endif }
/** * \brief Disable internal 4/8/12MHz fast RC. */ extern void PMC_DisableIntRC4_8_12MHz(void) { uint32_t read_MOR; read_MOR = PMC->CKGR_MOR; read_MOR &= ~CKGR_MOR_MOSCRCF_Msk; /* reset MOSCRCF field in MOR register */ read_MOR &= ~CKGR_MOR_MOSCRCEN; /* disable fast RC */ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37u) | read_MOR; while( !(PMC->PMC_SR & PMC_SR_MCKRDY) ); }
/** * \brief Select external OSC. */ extern void PMC_SelectExtOsc(void) { /* switch from internal RC 12 MHz to external OSC 12 MHz */ /* wait Main XTAL Oscillator stabilisation*/ while(!(PMC->PMC_SR & PMC_SR_MOSCXTS)); /* enable external OSC 12 MHz */ PMC->CKGR_MOR |= CKGR_MOR_MOSCXTEN | CKGR_MOR_KEY(0x37); /* wait Main CLK Ready */ while(!(PMC->CKGR_MCFR & CKGR_MCFR_MAINFRDY)); /* disable external OSC 12 MHz bypass */ PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) | CKGR_MOR_KEY(0x37); /* switch MAIN clock to external OSC 12 MHz*/ PMC->CKGR_MOR |= CKGR_MOR_MOSCSEL | CKGR_MOR_KEY(0x37); /* wait MAIN clock status change for external OSC 12 MHz selection*/ while(!(PMC->PMC_SR & PMC_SR_MOSCSELS)); /* in case where MCK is running on MAIN CLK */ while(!(PMC->PMC_SR & PMC_SR_MCKRDY)); /* disable internal RC 12 MHz*/ //PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN) | CKGR_MOR_KEY(0x37); }
//------CPU时钟初始化----------------------------------------------------- //功能: 初始化CPU时钟,上电默认使用的是内部的晶振时钟,该函数将晶振源切换到 // 外部调整时钟,后面将main clock时钟切换到PLLB分频后的时钟 //参数: 无 //返回: 无 //----------------------------------------------------------------------- void cpu_clk_init(void) { uint32_t timeout = 0; /* Initialize main oscillator */ if ( !(SAM_PMC_REG->CKGR_MOR & CKGR_MOR_MOSCSEL) ) { SAM_PMC_REG->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; timeout = 0; while (!(SAM_PMC_REG->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT)); } /* Switch to 3-20MHz Xtal oscillator */ SAM_PMC_REG->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; timeout = 0; while (!(SAM_PMC_REG->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT)); SAM_PMC_REG->PMC_MCKR = (SAM_PMC_REG->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; for ( timeout = 0; !(SAM_PMC_REG->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); /* Initialize PLLB */ SAM_PMC_REG->CKGR_PLLBR = BOARD_PLLBR; timeout = 0; while (!(SAM_PMC_REG->PMC_SR & PMC_SR_LOCKB) && (timeout++ < CLOCK_TIMEOUT)); /* Switch to main clock */ SAM_PMC_REG->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; for ( timeout = 0; !(SAM_PMC_REG->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); SAM_PMC_REG->PMC_MCKR = BOARD_MCKR ; for ( timeout = 0; !(SAM_PMC_REG->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); }
/** * \brief Disable all clocks. */ extern void PMC_DisableAllClocks(void) { uint32_t read_reg; PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2; /* disable PCK */ _PMC_SwitchMck2MainClock(); PMC->CKGR_PLLR = PMC->CKGR_PLLR & ~CKGR_PLLR_MUL_Msk; /* disable PLL A */ _PMC_SwitchMck2SlowClock(); read_reg = PMC->CKGR_MOR; read_reg = (read_reg & ~CKGR_MOR_MOSCRCEN) | CKGR_MOR_KEY(0x37u); /* disable RC OSC */ PMC->CKGR_MOR = read_reg; PMC_DisableAllPeripherals(); /* disable all peripheral clocks */ }
/** * \brief Performs the low-level initialization of the chip. * This includes EFC and master clock configuration. * It also enable a low level on the pin NRST triggers a user reset. */ extern WEAK void LowLevelInit( void ) { uint32_t dwTimeout ; /* Set 2 WS for Embedded Flash Access */ EFC0->EEFC_FMR = EEFC_FMR_FWS( 4 ) ; EFC1->EEFC_FMR = EEFC_FMR_FWS( 4 ) ; /* Initialize main oscillator */ if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) /* Main Oscillator Selection */ { // 48MHz PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(0x8) /* Main Crystal Oscillator Start-up Time: 1.4ms(datasheet) */ | CKGR_MOR_MOSCRCEN /* Main On-Chip RC Oscillator Enable */ | CKGR_MOR_MOSCXTEN; /* Main Crystal Oscillator Enable */ /* The Main On-Chip RC Oscillator is selected */ dwTimeout = 0 ; while ( !(PMC->PMC_SR & PMC_SR_MOSCXTS) && (dwTimeout++ < CLOCK_TIMEOUT) ) ; } /* Switch to 3-20MHz Xtal oscillator */ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(0x8) /* Main Crystal Oscillator Start-up Time: 1.4ms(datasheet) */ | CKGR_MOR_MOSCRCEN /* Main On-Chip RC Oscillator Enable */ | CKGR_MOR_MOSCXTEN /* Main Crystal Oscillator Enable */ | CKGR_MOR_MOSCSEL; /* The Main Crystal Oscillator is selected */ dwTimeout = 0; /* Wait Main Oscillator Selection Status */ while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (dwTimeout++ < CLOCK_TIMEOUT)); PMC->PMC_MCKR = (PMC->PMC_MCKR & ~ (0x7UL << 0)/*AT91C_PMC_CSS*/) | PMC_MCKR_CSS_MAIN_CLK; /* Main Clock is selected */ dwTimeout = 0; /* Wait Master Clock Status */ while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (dwTimeout++ < CLOCK_TIMEOUT)); /* Initialize PLLA */ PMC->CKGR_PLLAR = CKGR_PLLAR_STUCKTO1 | CKGR_PLLAR_MULA(13) /* PLLA Multiplier */ | CKGR_PLLAR_PLLACOUNT(2) /* PLLA Counter 200µs(datasheet) */ | CKGR_PLLAR_DIVA(1); /* Divider */ dwTimeout = 0; /* Wait PLL A Lock Status */ while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (dwTimeout++ < CLOCK_TIMEOUT)); /* Initialize UTMI for USB usage, can be disabled if not using USB for the sake of saving power*/ PMC->CKGR_UCKR |= CKGR_UCKR_UPLLCOUNT(3) /* UTMI PLL Start-up Time */ | CKGR_UCKR_UPLLEN; /* UTMI PLL Enable */ dwTimeout = 0; /* Wait UTMI PLL Lock Status */ while (!(PMC->PMC_SR & PMC_SR_LOCKU) && (dwTimeout++ < CLOCK_TIMEOUT)); /* Switch to PLLA*/ PMC->PMC_MCKR = ((PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK) & ~(0x7UL << 0)/*AT91C_PMC_CSS*/) | PMC_MCKR_CSS_MAIN_CLK; /* Main Clock is selected */ dwTimeout = 0; /* Wait Master Clock Status */ while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (dwTimeout++ < CLOCK_TIMEOUT)); PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_2 /* Selected clock divided by 2 */ | PMC_MCKR_CSS_PLLA_CLK; /* PLLA Clock is selected */ dwTimeout = 0; /* Wait Master Clock Status */ while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (dwTimeout++ < CLOCK_TIMEOUT)); }
/** * \brief Performs the low-level initialization of the chip. * This includes EFC and master clock configuration. * It also enable a low level on the pin NRST triggers a user reset. */ extern WEAK void LowLevelInit( void ) { uint8_t i; uint32_t _dwTimeout = 0; volatile uint32_t read = 0; if ((uint32_t)LowLevelInit < EBI_CS0_ADDR) /* Code not in external mem */ { /* Switch to PLL + prescaler */ read = PMC->PMC_MCKR; read &= ~(PMC_MCKR_CSS_Msk); read |= PMC_MCKR_CSS_MAIN_CLK; PMC->PMC_MCKR = read; while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(64) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; _dwTimeout = 0; while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (_dwTimeout++ < CLOCK_TIMEOUT)); PMC->CKGR_PLLAR = 0; /* Initialize PLLA */ PMC->CKGR_PLLAR = CKGR_PLLAR_STUCKTO1 | CKGR_PLLAR_MULA(199) | CKGR_PLLAR_OUTA(0) | CKGR_PLLAR_PLLACOUNT(63) | CKGR_PLLAR_DIVA(3); _dwTimeout = 0; while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (_dwTimeout++ < CLOCK_TIMEOUT)); /* Wait for the master clock if it was already initialized */ for ( _dwTimeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (_dwTimeout++ < CLOCK_TIMEOUT) ; ); /* Switch to fast clock **********************/ /* Switch to main oscillator + prescaler */ read = PMC->PMC_MCKR; read &= ~(PMC_MCKR_MDIV_Msk); read |= (PMC_MCKR_MDIV_PCK_DIV3 | PMC_MCKR_PLLADIV2_DIV2); PMC->PMC_MCKR = read; /* Wait for the master clock if it was already initialized */ for ( _dwTimeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (_dwTimeout++ < CLOCK_TIMEOUT) ; ); /* Switch to main oscillator + prescaler */ read = PMC->PMC_MCKR; read &= ~(PMC_MCKR_PRES_Msk); read |= PMC_MCKR_PRES_CLOCK; PMC->PMC_MCKR = read; /* Wait for the master clock if it was already initialized */ for ( _dwTimeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (_dwTimeout++ < CLOCK_TIMEOUT) ; ); /* Switch to PLL + prescaler */ read = PMC->PMC_MCKR; read &= ~(PMC_MCKR_CSS_Msk); read |= PMC_MCKR_CSS_PLLA_CLK; PMC->PMC_MCKR = read; /* Wait for the master clock if it was already initialized */ for ( _dwTimeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (_dwTimeout++ < CLOCK_TIMEOUT) ; ); } /* Initialize AIC */ AIC->AIC_IDCR = 0xFFFFFFFF; AIC->AIC_SVR[0] = (unsigned int) defaultFiqHandler; for (i = 1; i < 31; i++) { AIC->AIC_SVR[i] = (unsigned int) defaultIrqHandler; } AIC->AIC_SPU = (unsigned int) defaultSpuriousHandler; /* Unstack nested interrupts */ for (i = 0; i < 8 ; i++) { AIC->AIC_EOICR = 0; } /* Remap */ BOARD_RemapRam(); BOARD_ConfigureDdram(); }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #define MHz(x) (x * 1000000) extern "C" const PMC_DRIVER_INFO pmc_driver = { { DRIVER_INFO_STUB, (DRV_ISR)PMC_ISR, (DRV_DCR)PMC_DCR, (DRV_DSR)PMC_DSR, PMC_IRQn, DRV_PRIORITY_KERNEL, ID_PMC }, PMC, CKGR_MOR_CFDEN | CKGR_MOR_MOSCSEL | CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(255) | CKGR_MOR_MOSCXTEN, //CFG_CKGR_MOR // CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCRCF_4MHZ | CKGR_MOR_KEY(0x37) | // CKGR_MOR_CFDEN, //CFG_CKGR_MOR //PCK = 12000000 * (7+1) / 2 = 48 MHz //PCK = 12000000 * (7+1) / 1 = 96 MHz CKGR_PLLAR_STUCKTO1 | CKGR_PLLAR_MULA(7) | CKGR_PLLAR_PLLACOUNT(0x3f) | CKGR_PLLAR_DIVA(2), //PCK = 12000000 * (15+1) / 3 = 64 MHz // CKGR_PLLAR_STUCKTO1 | CKGR_PLLAR_MULA(15) | CKGR_PLLAR_PLLACOUNT(0x3f)
static void SetupCpuClock ( void ) { // WARNING: This routine is called very early after a reset, so things // like the .data and .bss segments have probably not been initialised yet. // NOTE about JTAG debugging: // You may have trouble connecting with a JTAG debugger before the clock // has been setup. After a hardware reset, the core runs at 4 MHz by default. // This routine switches to a 12 MHz clock (or 6 MHz after a soft reset), and // then to the final 84 MHz. Even if your debugger can slow the JTAG clock down, // I am not sure that the JTAG connection will always survive the clock changes. // Set the FWS (Flash Wait State in the Flash Mode Register) for both flash banks: // - FAM: Flash Access Mode: 0: 128-bit access in read Mode only, enhances access speed at the cost of power consumption. // - FRDY: Ready Interrupt Enable: 0: Flash Ready does not generate an interrupt. // - FWS: Flash Wait State: 4 + 1 = 5 wait states. See also constant CHIP_FREQ_FWS_3. // The core will run at 84 MHz, and the CPU's VDDCORE pins are tied on the Arduino Due // to signal VDDOUT -> VDDPLL. VDDIN has 3.3V, but I could not find any information on // how to program the embedded Power Regulator. // According to the data sheet, section "Embedded Flash Characteristics", if we run // the CPU core at 84 MHz with VDDCORE set to 1.80 V, then we need 5 wait states, // which matches our setting. However, should VDDCORE be 1.62 V, we are out of spec. EFC0->EEFC_FMR = EEFC_FMR_FWS(4); EFC1->EEFC_FMR = EEFC_FMR_FWS(4); const uint32_t SYS_BOARD_OSCOUNT = CKGR_MOR_MOSCXTST( 0x8 ); // Start-up time in Slow Clock cycles (multiplied by 8). const uint32_t SYS_CKGR_MOR_KEY_VALUE = CKGR_MOR_KEY( 0x37 ); // Key to unlock MOR register. // If the crystal oscillator has not already been selected into the Main Clock, // assume that it has not been enabled and stabilised yet, so do it here. if ( !( PMC->CKGR_MOR & CKGR_MOR_MOSCSEL ) ) { PMC->CKGR_MOR = SYS_CKGR_MOR_KEY_VALUE | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | // Main On-Chip RC Oscillator Enable. This is probably the on-chip fast RC oscillator. // After a hardware reset we are running on it, so it probably must be kept enabled // until we are finished configuring the clocks. CKGR_MOR_MOSCXTEN; // Main Crystal Oscillator Enable. // Wail until the PMC Status Register reports that the main XTAL oscillator is stabilised. while ( !(PMC->PMC_SR & PMC_SR_MOSCXTS) ) { } } // Switch the Main Clock to the crystal oscillator. By default after a hardware reset, the on-chip fast RC oscillator runs at 4 MHz, // and the crystal oscillator on the Arduino Due runs at 12 MHz. So we are running the CPU faster here, // assuming we came here after a hardware reset. PMC->CKGR_MOR = SYS_CKGR_MOR_KEY_VALUE | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; // Wail until the PMC Status Register reports that the switch is complete. while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) { } // Switch the Master Clock to the Main Clock, leaving other clock settings unchanged. // If we were on the PLL clock, remember that we cannot change the clock source and // the prescaler factor at the same time, so the resulting speed may be 12 MHz / 2 = 6 MHz for a short time. const uint32_t prevPmcMckr = PMC->PMC_MCKR; // - After a hard reset, prevPmcMckr is 1, which means that the Main Clock is selected, as expected. // - After a GDB 'load' command (which does a kind of soft reset), the value is 18 (0b10010), // meaning that the PLLA clock divided by 2 was selected (which is what this routine does at the end). PMC->PMC_MCKR = (prevPmcMckr & ~uint32_t(PMC_MCKR_CSS_Msk) ) | PMC_MCKR_CSS_MAIN_CLK; // Wail until the PMC Status Register reports that the Master Clock is ready. while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) ) { } // Generate a fast clock with the PLL by setting the PLLA Register in the PMC Clock Generator. PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | // Always 1. CKGR_PLLAR_MULA(0xdUL) | // Multiplier is 0xd + 1 = 0xe (14). The crystal oscillator freq. is 12 MHz, // so the resulting frequency is 12 MHz x 14 = 168 MHz (84 MHz x 2). CKGR_PLLAR_PLLACOUNT(0x3fUL) | // Some delay used during the switching. CKGR_PLLAR_DIVA(0x1UL); // 1 = The divider is bypassed. // Wail until the PMC Status Register reports that the PLL is locked. while ( !(PMC->PMC_SR & PMC_SR_LOCKA) ) { } // We cannot switch directly to the PLL / 2 clock, we must set the prescaler factor first. const uint32_t PLL_FACTOR = PMC_MCKR_PRES_CLK_2; // 168 MHz / prescaler of 2 = our target core frequency of 84 MHz. PMC->PMC_MCKR = PLL_FACTOR | PMC_MCKR_CSS_MAIN_CLK; // Wail until the PMC Status Register reports that the Master Clock is ready. while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) ) { } // Switch the Master Clock to the PLLA / 2 clock. PMC->PMC_MCKR = PLL_FACTOR | PMC_MCKR_CSS_PLLA_CLK; // Wail until the PMC Status Register reports that the Master Clock is ready. while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) { } // You can check the Main Clock frequency by reading the CKGR_MCFR register like this: // const uint16_t measuredMainClockFreqIn16SlowClockCycles = PMC->CKGR_MCFR & CKGR_MCFR_MAINF_Msk; // On the Arduino Due, the crystal oscillator freq. is 12 MHz, and the Slow Clock runs at 32 KHz, // that would be 375 Main Clock ticks for every Slow Clock tick. // In 16 Slow Clock ticks, we have 6000 Main Clock ticks then. On my board, the value read // is 6601, which is around 10 % off. }