/** * \brief Disable PLLA clock. */ void pmc_disable_pllack(void) { #if (SAM4C || SAM4CM || SAM4CP || SAMG) PMC->CKGR_PLLAR = CKGR_PLLAR_MULA(0); #else PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0); #endif }
/** * \brief Enable PLLA clock. * * \param mula PLLA multiplier. * \param pllacount PLLA counter. * \param diva Divider. */ void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva) { /* first disable the PLL to unlock the lock */ pmc_disable_pllack(); #if (SAM4C || SAM4CM || SAM4CP || SAMG) PMC->CKGR_PLLAR = CKGR_PLLAR_PLLAEN(diva) | CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula); #else PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_DIVA(diva) | CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula); #endif while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0); }
/** * \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 Setup the microcontroller system. * * Initialize the System and update the SystemFrequency variable. */ void SystemInit( void ) { /* Set 6 FWS for Embedded Flash Access */ EFC->EEFC_FMR = EEFC_FMR_FWS(5) | EEFC_FMR_CLOE ; /* Initialize main oscillator */ if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) { PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTST(0x8U) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN ; while ( !(PMC->PMC_SR & PMC_SR_MOSCXTS) ) ; } /* Switch to 3-20MHz Xtal oscillator */ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTST(0x8U) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; while ( !(PMC->PMC_SR & PMC_SR_MOSCSELS) ) ; PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK ; while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) ) ; /* Initialize PLLA */ PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x13U) | CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U) ; while ( !(PMC->PMC_SR & PMC_SR_LOCKA) ) ; /* Switch to main clock */ PMC->PMC_MCKR = ((PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK) & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK ; while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) ) ; /* Switch to PLLA */ PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK ; while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) ) ; SystemCoreClock=__SYSTEM_CLOCK_120MHZ ; }
/** * \brief Enable PLLA clock. * * \param mula PLLA multiplier. * \param pllacount PLLA counter. * \param diva Divider. */ void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva) { pmc_disable_pllack(); // Hardware BUG FIX : first disable the PLL to unlock the lock! // It occurs when re-enabling the PLL with the same parameters. PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_DIVA(diva) | CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula); while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0); }
/** * \brief Enable PLLA clock. * * \param mula PLLA multiplier. * \param pllacount PLLA counter. * \param diva Divider. */ void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva) { /* first disable the PLL to unlock the lock!*/ pmc_disable_pllack(); PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_DIVA(diva) | CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula); while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0); }
/** * \brief Setup the microcontroller system. * * Initialize the System and update the System Frequency variable. */ void SystemInit( void ) { /* Set 6 FWS for Embedded Flash Access according to 120MHz configuration */ EFC0->EEFC_FMR = EEFC_FMR_FWS(5)|EEFC_FMR_CLOE; /* * We are coming from a Hard Reset or Backup mode. * The core is clocked by Internal Fast RC @ 8MHz. * We intend to use the device @120MHz from external 32kHz oscillator. * Steps are: * 1- Activation of external 32kHz oscillator * 2- Set PLLA configuration * 3- Select the master clock and processor clock * 4- Select the programmable clocks (optional) */ /* Step 1 - Activation of external 32kHz oscillator * Then, we wait the startup time to be finished by checking PMC_SR_MOSCXTS in PMC_SR. */ SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL; while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL) && (PMC->PMC_SR & PMC_SR_OSCSELS)) ; /* Step 2 - Set PLLA configuration * The external oscillator is 32kHz. As we intend to clock the system @120MHz, * we need to multiply the oscillator frequency by 3662 (120000000/32768). * This can be done by setting CKGR_PLLAR_MULA to value 0xe4d (3662 - 1). * We set the maximum PLL Lock time to maximum in CKGR_PLLAR_PLLACOUNT. * Reference is product datasheet at 18.19.9 PMC Clock Generator PLLA Register. * * In case of, we could check first if PLLA is already active and put CKGR_PLLAR_MULA * prior to set new configuration (not done here). */ PMC->CKGR_PLLAR = CKGR_PLLAR_PLLAEN(1ul) | CKGR_PLLAR_MULA(0xe4dul) | CKGR_PLLAR_PLLACOUNT(0x3ful); for ( ; (PMC->PMC_SR & PMC_SR_LOCKA) != PMC_SR_LOCKA ; ); /* Step 3 - Select the master clock and processor clock * Source clock will be PLLA, instead of MAINCK from startup (8MHz Fast-RC). * We first update the prescaler value to one and then switch source to PLLA. */ PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | PMC_MCKR_PRES_CLK_1; for ( ; !(PMC->PMC_SR & PMC_SR_MCKRDY);); PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_PLLA_CLK; for ( ; !(PMC->PMC_SR & PMC_SR_MCKRDY); ); /* * Step 4 - Select the programmable clocks * * Output MCK on PCK1/pins PA17/PA21/PA30 * Used to validate Master Clock settings */ // PMC->PMC_SCER = PMC_SCER_PCK1 ; SystemCoreClock=__SYSTEM_CLOCK_120MHZ; }
/** * @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(); }
/** * \brief Configure PLLA clock by giving MUL and DIV. * Disable PLLA when 'mul' set to 0. * * \param mul PLL multiplier factor. * \param div PLL divider factor. */ void PMC_SetPllaClock(uint32_t mul, uint32_t div) { if (mul != 0) { /* Init PLL speed */ PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_PLLACOUNT(DEFAUTL_PLLA_COUNT) | CKGR_PLLAR_MULA(mul - 1) | CKGR_PLLAR_DIVA(div); /* Wait for PLL stabilization */ while( !(PMC->PMC_SR & PMC_SR_LOCKA) ); } else { PMC->CKGR_PLLAR = CKGR_PLLAR_ONE; /* disable PLL A */ } }
/** * \brief Enable PLLB clock. * * \param mulb PLLB multiplier. * \param pllbcount PLLB counter. * \param divb Divider. */ void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb) { /* first disable the PLL to unlock the lock */ pmc_disable_pllbck(); #if SAMG55 PMC->CKGR_PLLAR = CKGR_PLLAR_PLLAEN(divb) | CKGR_PLLAR_PLLACOUNT(pllbcount) | CKGR_PLLAR_MULA(mulb); #else PMC->CKGR_PLLBR = CKGR_PLLBR_DIVB(divb) | CKGR_PLLBR_PLLBCOUNT(pllbcount) | CKGR_PLLBR_MULB(mulb); #endif while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0); }
void SAMA5D3X_ClockInit() { PMC_SelectExt12M_Osc(); PMC_SwitchMck2Main(); PMC_SetPllA(CKGR_PLLAR_STUCKTO1 | CKGR_PLLAR_PLLACOUNT(0x3F) | CKGR_PLLAR_OUTA(0x0) | CKGR_PLLAR_MULA(65) | CKGR_PLLAR_DIVA(1), 0x3u << 8); PMC_SetMckPllaDiv(PMC_MCKR_PLLADIV2_DIV2); PMC_SetMckPrescaler(PMC_MCKR_PRES_CLOCK); PMC_SetMckDivider(PMC_MCKR_MDIV_PCK_DIV3); PMC_SwitchMck2Pll(); }
//----------------------------------------------------------------------------- static void sys_init(void) { // Disable watchdog WDT->WDT_MR = WDT_MR_WDDIS; // Set flash wait states to maximum for 150 MHz operation EFC->EEFC_FMR = EEFC_FMR_FWS(5) | EEFC_FMR_CLOE; // Enable 32 kHz Xtal SUPC->SUPC_CR |= SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL; // Enable 12 MHz Xtal PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTST(8) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)); PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTST(8) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)); // Setup PLL (12 MHz * 25 = 300 MHz) PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(25-1) | CKGR_PLLAR_PLLACOUNT(0x3f) | CKGR_PLLAR_DIVA(1); while (!(PMC->PMC_SR & PMC_SR_LOCKA)); // Switch main clock to PLL (two step process) PMC->PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK | PMC_MCKR_MDIV_PCK_DIV2; while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); PMC->PMC_MCKR = PMC_MCKR_CSS_PLLA_CLK | PMC_MCKR_MDIV_PCK_DIV2; while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); // Enable PIOA, PIOB, PIOC, PIOD and PIOE PMC->PMC_PCER0 = PMC_PCER0_PID10 | PMC_PCER0_PID11 | PMC_PCER0_PID12 | PMC_PCER0_PID16 | PMC_PCER0_PID17; // Disable altenate functions on some pins MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO4; // Enable interrupts asm volatile ("cpsie i"); }
/** * \brief Disable PLLA Register. */ extern void PMC_DisablePllA(void) { PMC->CKGR_PLLAR = (PMC->CKGR_PLLAR & ~CKGR_PLLAR_MULA_Msk) | CKGR_PLLAR_MULA(0); }
/** * \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)); }
/** Set up the main clock (MAINCK), PLL clock, and master clock (MCK). */ static int mcu_clock_init (void) { /* To minimize the power required to start up the system, the main oscillator is disabled after reset and slow clock is selected. There are four clock sources: SLCK (the 32 kHz internal RC oscillator or 32 kHz external crystal slow clock), MAINCK (the external 3-20 MHz crystal or internal 4/8/12 MHz internal fast RC oscillator main clock), PLLACK, and PLLBCK. The two PLL clocks are the outputs of the the phase locked loop driven by MAINCK). One of these four clock sources can be fed to a prescaler (with divisors 2^0 ... 2^6) to drive MCK (master clock). The main oscillator (external crystal) can range from 3--20 MHz. The PLL frequency can range from 80--240 MHz. Here we assume that an external crystal is used for the MAINCK and this is multiplied by PLLA to drive MCK. PLLB is not touched here. Currently, the USB clock is derived from PLLA; this restricts MCK to be a multiple of 48 MHz required for the USB clock. This restriction could be relaxed using PLLB for the USB. Initially MCK is driven from the 4 MHz internal fast RC oscillator. */ /* Hack to handle JTAG reset when the PLLA is still operating. Without this call to mcu_reset, the PLLA is not enabled after every second reset. */ if ((PMC->PMC_MCKR & PMC_MCKR_CSS_Msk) == PMC_MCKR_CSS_PLLA_CLK) mcu_reset (); /* Start xtal oscillator and select as MAINCK. */ mcu_xtal_mainck_start (); /* Select MAINCK for MCK (this should already be selected). */ PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_MAIN_CLK; if (!mcu_mck_ready_wait ()) return 0; /* Set prescaler to 2. */ PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | PMC_MCKR_PRES_CLK_2; if (!mcu_mck_ready_wait ()) return 0; /* Could disable internal fast RC oscillator here. */ /* Disable PLLA if it is running and reset fields. */ PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA (0); /* Configure and start PLLA. The PLL start delay is MCU_PLL_COUNT SLCK cycles. Note, PLLA (but not PLBB) needs the mysterious bit CKGR_PLLAR_ONE set. */ PMC->CKGR_PLLAR = CKGR_PLLAR_MULA (MCU_PLL_MUL - 1) | CKGR_PLLAR_DIVA (MCU_PLL_DIV) | CKGR_PLLAR_PLLACOUNT (MCU_PLL_COUNT) | CKGR_PLLAR_ONE; /* Wait for PLLA to start up. */ while (! (PMC->PMC_SR & PMC_SR_LOCKA)) continue; /* Switch to PLLA_CLCK for MCK. */ PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_PLLA_CLK; if (!mcu_mck_ready_wait ()) return 0; return 1; }
/** * \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 i; if ((uint32_t)LowLevelInit < DDR_CS_ADDR) /* Code not in external mem */ { PMC_SelectExt12M_Osc(); PMC_SwitchMck2Main(); PMC_SetPllA( CKGR_PLLAR_STUCKTO1 | CKGR_PLLAR_PLLACOUNT(0x3F) | CKGR_PLLAR_OUTA(0x0) | CKGR_PLLAR_MULA(65) | CKGR_PLLAR_DIVA(1), 0x3u << 8); PMC_SetMckPllaDiv(PMC_MCKR_PLLADIV2_DIV2); PMC_SetMckPrescaler(PMC_MCKR_PRES_CLOCK); PMC_SetMckDivider(PMC_MCKR_MDIV_PCK_DIV3); PMC_SwitchMck2Pll(); } #if 0 uint32_t abcdsr; /* Configure PCK1 to measure MCK */ PIOD->PIO_IDR = (1<<31); abcdsr = PIOD->PIO_ABCDSR[0]; PIOD->PIO_ABCDSR[0] = ((1<<31) | abcdsr); abcdsr = PIOD->PIO_ABCDSR[1]; PIOD->PIO_ABCDSR[1] &= (~(1<<31) & abcdsr); PIOD->PIO_PDR = (1<<31); /* Disable programmable clock 1 output */ REG_PMC_SCDR = PMC_SCER_PCK1; /* Enable the DAC master clock */ PMC->PMC_PCK[1] = PMC_PCK_CSS_MCK_CLK | PMC_PCK_PRES_CLOCK; /* Enable programmable clock 1 output */ REG_PMC_SCER = PMC_SCER_PCK1; /* Wait for the PCKRDY1 bit to be set in the PMC_SR register*/ while ((REG_PMC_SR & PMC_SR_PCKRDY1) == 0); #endif /* select FIQ */ AIC->AIC_SSR = 0; AIC->AIC_SVR = (unsigned int) defaultFiqHandler; for (i = 1; i < 31; i++) { AIC->AIC_SSR = i; AIC->AIC_SVR = (unsigned int) defaultIrqHandler; } AIC->AIC_SPU = (unsigned int) defaultSpuriousHandler; /* Disable all interrupts */ for (i = 1; i < 31; i++) { AIC->AIC_SSR = i; AIC->AIC_IDCR = 1 ; } /* Clear All pending interrupts flags */ for (i = 1; i < 31; i++) { AIC->AIC_SSR = i; AIC->AIC_ICCR = 1 ; } /* Perform 8 IT acknoledge (write any value in EOICR) */ for (i = 0; i < 8 ; i++) { AIC->AIC_EOICR = 0; } /* Remap */ BOARD_RemapRam(); }
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) // | CKGR_PLLAR_DIVA(3), { 32768, //freq for slow clk MHz(12), // freq for main clk MHz(48), //freq for PLLA MHz(96) //freq for PLLB },
/** * \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(); }
/** * \brief Disable PLLA clock. */ void pmc_disable_pllack(void) { PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0); }
// ペリフェラルの初期化 // RTX RTOSの開始前に呼ばれる extern "C" void init(void){ // WDTを無効にする WDT->WDT_MR = WDT_MR_WDIDLEHLT | WDT_MR_WDDBGHLT | (0xFFF << WDT_MR_WDD_Pos) | WDT_MR_WDDIS | (0xFFF << WDT_MR_WDV_Pos); // RSWDTは標準で無効になっている // BODリセットは標準で有効になっている // 1度、強制的にリセットする(OpenOCDによるデバッグのため) if (RESET_GPBR == 0){ RESET_GPBR = 1; RSTC->RSTC_CR = RSTC_CR_KEY_PASSWD | RSTC_CR_PERRST | RSTC_CR_PROCRST; }else{ RESET_GPBR = 0; } // FPUを有効にする SCB->CPACR = 0x00F00000; // キャッシュを有効にする(キャッシュはROMとFlash領域のみ有効) //CMCC->CMCC_CTRL = CMCC_CTRL_CEN; // フラッシュのウェイト数を設定 EFC->EEFC_FMR = EEFC_FMR_CLOE | EEFC_FMR_FWS(5); // 最大129MHz // システムクロックを設定 // SLCK=32kHz, MAINCK=12MHz, PLLACK=240MHz, USB_48M=48MHz, MCK=120MHz PMC->CKGR_MOR = CKGR_MOR_MOSCSEL | CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCF_4_MHz | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY; while(~PMC->PMC_SR & PMC_SR_MOSCSELS); PMC->CKGR_MOR = CKGR_MOR_MOSCSEL | CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY; PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(20) | CKGR_PLLAR_PLLACOUNT(16) | CKGR_PLLAR_DIVA(1); while(~PMC->PMC_SR & PMC_SR_LOCKA); PMC->PMC_USB = PMC_USB_USBDIV(5 - 1); PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_MAIN_CLK; while(~PMC->PMC_SR & PMC_SR_MCKRDY); PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK; while(~PMC->PMC_SR & PMC_SR_MCKRDY); // クロック供給を有効にする // 31:AFEC1, 30:AFEC0, 23:TC2, 22:TC1, 21:TC0, 20:DMAC, 12:PIOD, 10:PIOB, 9:PIOA, 7:UART0 // 36:PWM, 35:UDP PMC->PMC_PCER0 = PMC_PCER0_PID31 | PMC_PCER0_PID30 | PMC_PCER0_PID23 | PMC_PCER0_PID22 | PMC_PCER0_PID21 | PMC_PCER0_PID20 | PMC_PCER0_PID12 | PMC_PCER0_PID10 | PMC_PCER0_PID9 | PMC_PCER0_PID7; PMC->PMC_PCER1 = PMC_PCER1_PID36 | PMC_PCER1_PID35; PMC->PMC_SCER = PMC_SCER_UDP; // NVICのベクターをRAMに移動 NVIC_Migration(); // I/Oピンの初期化 clDigitalIOInitializer IOInitializer; IOInitializer.Set(PIN_HOST_TX, DIR_IN, OUT_LOW, PINMODE_PU); IOInitializer.Set(PIN_HOST_RX, DIR_OUT, OUT_HIGH); IOInitializer.Set(PIN_CAM1_CLK, DIR_OUT, OUT_LOW); IOInitializer.Set(PIN_CAM2_CLK, DIR_OUT, OUT_LOW); IOInitializer.Set(PIN_CAM1_SI, DIR_OUT, OUT_LOW); IOInitializer.Set(PIN_CAM2_SI, DIR_OUT, OUT_LOW); IOInitializer.Set(PIN_CAM1_A0P, DIR_IN, OUT_LOW, PINMODE_PU); IOInitializer.Set(PIN_CAM2_A0P, DIR_IN, OUT_LOW, PINMODE_PU); IOInitializer.Set(PIN_USB_VBUS, DIR_IN, OUT_LOW); IOInitializer.Set(PIN_nSW1, DIR_IN, OUT_LOW, PINMODE_PU); IOInitializer.Set(PIN_LED1, DIR_OUT, OUT_LOW); IOInitializer.Set(PIN_LED_ENABLE, DIR_OUT, OUT_LOW); IOInitializer.Mux(PIN_HOST_TX, PINMUX_A, PIO_DISABLE); IOInitializer.Mux(PIN_HOST_RX, PINMUX_A, PIO_DISABLE); IOInitializer.Mux(PIN_CAM1_CLK, PINMUX_A, PIO_DISABLE); IOInitializer.Mux(PIN_CAM2_CLK, PINMUX_B, PIO_DISABLE); IOInitializer.Apply(); /* OSリソースの作成を伴わないデバイスインスタンスの初期化を行う */ }
/** * \brief Setup the microcontroller system. * * Initialize the System and update the SystemFrequency variable. */ void SystemInit( void ) { { /* Set 6 FWS for Embedded Flash Access according to 120MHz configuration */ EFC0->EEFC_FMR = EEFC_FMR_FWS(5)|EEFC_FMR_CLOE; #if defined(EFC1) // Only valid for products with two flash banks EFC1->EEFC_FMR = EEFC_FMR_FWS(5)|EEFC_FMR_CLOE; #endif // EFC1 /* * We are coming from a Hard Reset or Backup mode. * The core is clocked by Internal Fast RC @ 4MHz. * We intend to use the device @120MHz from external Oscillator. * Steps are (cf datasheet chapter '29.14 Programming Sequence'): * 1- Activation of external oscillator * 2- Switch the MAINCK to the main crystal oscillator * 3- Wait for the MOSCSELS to be set * 4- Check the main clock frequency * 5- Set PLLx and Divider * 6- Select the master clock and processor clock * 7- Select the programmable clocks (optional) */ /* Step 1 - Activation of external oscillator * As we are clocking the core from internal Fast RC, we keep the bit CKGR_MOR_MOSCRCEN. * Main Crystal Oscillator Start-up Time (CKGR_MOR_MOSCXTST) is set to maximum value. * Then, we wait the startup time to be finished by checking PMC_SR_MOSCXTS in PMC_SR. */ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTST(0xfful) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; for ( ; (PMC->PMC_SR & PMC_SR_MOSCXTS) != PMC_SR_MOSCXTS ; ); /* Step 2 - Switch the MAINCK to the main crystal oscillator * We add the CKGR_MOR_MOSCSEL bit. * Then we wait for the selection to be done by checking PMC_SR_MOSCSELS in PMC_SR. */ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTST(0xfful) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; /* Step 3 - Wait for the MOSCSELS to be set */ for ( ; (PMC->PMC_SR & PMC_SR_MOSCSELS) != PMC_SR_MOSCSELS ; ); /* Step 4 - Check the main clock frequency */ /* As written in the DS, we could check the MAINF value here (0x18a2) */ /* Step 5 - Set PLLx and Divider * The external oscillator is 12MHz. As we intend to clock the system @120MHz, * we need to multiply the oscillator frequency by 10. * This can be done by setting MULx to value 9 and DIV to 1. * We set the maximum PLL Lock time to maximum in CKGR_PLLAR_PLLACOUNT. */ //PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | (CKGR_PLLAR_MULA(0x1dul) | CKGR_PLLAR_DIVA(3ul) | CKGR_PLLAR_PLLACOUNT(0x1ul)); PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | (CKGR_PLLAR_MULA(0x9ul) | CKGR_PLLAR_DIVA(1ul) | CKGR_PLLAR_PLLACOUNT(0x3ful)); for ( ; (PMC->PMC_SR & PMC_SR_LOCKA) != PMC_SR_LOCKA ; ); /* Step 6 - Select the master clock and processor clock * Source for MasterClock will be PLLA output (PMC_MCKR_CSS_PLLA_CLK), without frequency division. */ PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_1 | PMC_MCKR_CSS_PLLA_CLK; for ( ; (PMC->PMC_SR & PMC_SR_MCKRDY) != PMC_SR_MCKRDY ; ); /* * Step 7 - Select the programmable clocks * * * Output MCK on PCK1/pin PA17 * Used to validate Master Clock settings */ // PMC->PMC_SCER = PMC_SCER_PCK1 ; SystemCoreClock=__SYSTEM_CLOCK_120MHZ; } }
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. }
void reset_vector(void) { g_stack[0] = 0; // need to put a reference in here to the stack array // to make sure the linker brings it in. I'm sure there // is a more elegant way to do this, but this seems to work EFC->EEFC_FMR = EEFC_FMR_FWS(5); // slow down flash for our blazing speed WDT->WDT_MR = WDT_MR_WDDIS; // disable watchdog for now // TODO: a block of code which can be ifdef'd in and out to source the // slow clock from a 32 kHz crystal rather than the (relatively) inaccurate // internal RC oscillator PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTST(0x10) | // startup time: slowclock*8*this CKGR_MOR_MOSCRCEN | // keep main on-chip RC oscillator on ! CKGR_MOR_MOSCXTEN; // crystal oscillator enable (not select) while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) { } // spin until stable while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) { } // spin until selected PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | // "password" hard-wired in logic CKGR_MOR_MOSCXTST(0x10) | // startup time: slowclock*8*this CKGR_MOR_MOSCRCEN | // keep main on-chip RC oscillator on ! CKGR_MOR_MOSCXTEN; // main crystal oscillator enable while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) { } // busy wait // switch to main crystal oscillator PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTST(0x10) | CKGR_MOR_MOSCRCEN | // keep on-chip RC oscillator on ! CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) || !(PMC->PMC_SR & PMC_SR_MCKRDY) ) { } // spin until stable PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) { } // spin until selected // now, let's measure the frequency of the main crystal oscillator PMC->CKGR_MCFR = CKGR_MCFR_CCSS | // measure the crystal oscillator CKGR_MCFR_RCMEAS ; // start a new measurement // PLLA must output between 150 MHz and 500 MHz // board has 12 MHz crystal; let's multiply by 24 for 288 MHz PLL freq #define MUL 23 PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | // per datasheet, must set 1<<29 CKGR_PLLAR_MULA(MUL) | // pll = crystal * (mul+1)/div CKGR_PLLAR_DIVA(1) | CKGR_PLLAR_PLLACOUNT(0x3f); while (!(PMC->PMC_SR & PMC_SR_LOCKA)) { } // spin until lock // don't use a divider... use the PLL output as CPU clock and divide CPU // clock by 2 to get 144 MHz for the master clock PMC->PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK | // | PMC_MCKR_MDIV_PCK_DIV2; while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) { } // spin until ready // finally, dividers are all set up, so let's switch CPU to the PLLA output PMC->PMC_MCKR = PMC_MCKR_CSS_PLLA_CLK | PMC_MCKR_MDIV_PCK_DIV2; while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) { } // spin until selected // now we're running the CPU at 288 MHz and the system at 144 MHz uint32_t *pSrc, *pDest; // set up data segment pSrc = &_etext; pDest = &_srelocate; if (pSrc != pDest) for (; pDest < &_erelocate; ) *pDest++ = *pSrc++; // set up bss segment for (pDest = &_szero; pDest < &_ezero; ) *pDest++ = 0; // set vector table base address (if needed) pSrc = (uint32_t *)&_sfixed; SCB->VTOR = ( (uint32_t)pSrc & SCB_VTOR_TBLOFF_Msk ); // 7 LSB's are 0 if (((uint32_t)pSrc >= IRAM_ADDR) && ((uint32_t)pSrc < IRAM_ADDR+IRAM_SIZE)) SCB->VTOR |= 1 << 29; // TBLBASE bit enable_fpu(); __libc_init_array(); static char metal_stdout_buf[1024]; setvbuf(stdout, metal_stdout_buf, _IOLBF, sizeof(metal_stdout_buf)); systime_init(); led_init(); console_init(); main(); while (1) { } // hopefully we never get here... }