status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config)
{
/*
This function is designed to change MCG to PBE mode from PEE/BLPE/FBE,
but with this workflow, the source mode could be all modes except PEI/PBI.
*/
MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */
/* Change to use external clock first. */
MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));
/* Wait for CLKST clock status bits to show clock source is ext ref clk */
while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
(MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
{
}
/* Disable PLL first, then configure PLL. */
MCG->C6 &= ~MCG_C6_PLLS_MASK;
while (MCG->S & MCG_S_PLLST_MASK)
{
}
/* Configure the PLL. */
{
CLOCK_EnablePll0(config);
}
/* Change to PLL mode. */
MCG->C6 |= MCG_C6_PLLS_MASK;
while (!(MCG->S & MCG_S_PLLST_MASK))
{
}
return kStatus_Success;
}
开发者ID:butok,项目名称:FNET,代码行数:36,代码来源:fsl_clock.c
示例2: Cpu_SetMCGModePEE
/*
** ===================================================================
** Method : Cpu_SetMCGModePEE (component MK21FN1M0MC12)
**
** Description :
** This method sets the MCG to PEE mode.
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void Cpu_SetMCGModePEE(uint8_t CLKMode)
{
switch (CLKMode) {
case 0U:
/* Switch to PEE Mode */
/* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=1,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
OSC_CR = (OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK);
/* MCG_C7: OSCSEL=0 */
MCG_C7 &= (uint8_t)~(uint8_t)(MCG_C7_OSCSEL_MASK);
/* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
MCG_C1 = (MCG_C1_CLKS(0x00) | MCG_C1_FRDIV(0x03));
/* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=0 */
MCG_C2 = (MCG_C2_RANGE0(0x02) | MCG_C2_EREFS0_MASK);
/* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=1 */
MCG_C5 = MCG_C5_PRDIV0(0x01);
/* MCG_C6: LOLIE0=0,PLLS=1,CME0=0,VDIV0=6 */
MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0x06));
while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */
}
break;
default:
break;
}
}
/**
* @brief K20x clock initialization.
* @note All the involved constants come from the file @p board.h.
* @note This function is meant to be invoked early during the system
* initialization, it is usually invoked from the file
* @p board.c.
* @todo This function needs to be more generic.
*
* @special
*/
void k20x_clock_init(void) {
#if !KINETIS_NO_INIT
/* Disable the watchdog */
WDOG->UNLOCK = 0xC520;
WDOG->UNLOCK = 0xD928;
WDOG->STCTRLH &= ~WDOG_STCTRLH_WDOGEN;
SIM->SCGC5 |= SIM_SCGC5_PORTA |
SIM_SCGC5_PORTB |
SIM_SCGC5_PORTC |
SIM_SCGC5_PORTD |
SIM_SCGC5_PORTE;
#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEI
/* This is the default mode at reset. */
/* Configure FEI mode */
MCG->C4 = MCG_C4_DRST_DRS(KINETIS_MCG_FLL_DRS) |
(KINETIS_MCG_FLL_DMX32 ? MCG_C4_DMX32 : 0);
/* Set clock dividers */
SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) |
SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) |
SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1);
SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0); /* not strictly necessary since usb_lld will set this */
#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE
uint32_t ratio, frdiv;
uint32_t ratios[] = { 32, 64, 128, 256, 512, 1024, 1280, 1536 };
uint8_t ratio_quantity = sizeof(ratios) / sizeof(ratios[0]);
uint8_t i;
/* EXTAL0 and XTAL0 */
PORTA->PCR[18] = 0;
PORTA->PCR[19] = 0;
/*
* Start in FEI mode
*/
/* Internal capacitors for crystal */
#if defined(KINETIS_BOARD_OSCILLATOR_SETTING)
OSC0->CR = KINETIS_BOARD_OSCILLATOR_SETTING;
#else /* KINETIS_BOARD_OSCILLATOR_SETTING */
/* Disable the internal capacitors */
OSC0->CR = 0;
#endif /* KINETIS_BOARD_OSCILLATOR_SETTING */
/* TODO: need to add more flexible calculation, specially regarding
* divisors which may not be available depending on the XTAL
* frequency, which would required other registers to be modified.
*/
/* Enable OSC, low power mode */
MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0;
if (KINETIS_XTAL_FREQUENCY > 8000000UL)
MCG->C2 |= MCG_C2_RANGE0(2);
else
MCG->C2 |= MCG_C2_RANGE0(1);
frdiv = 7;
ratio = KINETIS_XTAL_FREQUENCY / 31250UL;
for (i = 0; i < ratio_quantity; ++i) {
if (ratio == ratios[i]) {
frdiv = i;
break;
}
}
/* Switch to crystal as clock source, FLL input of 31.25 KHz */
MCG->C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(frdiv);
/* Wait for crystal oscillator to begin */
while (!(MCG->S & MCG_S_OSCINIT0));
/* Wait for the FLL to use the oscillator */
while (MCG->S & MCG_S_IREFST);
/* Wait for the MCGOUTCLK to use the oscillator */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2));
/*
* Now in FBE mode
*/
#define KINETIS_PLLIN_FREQUENCY 2000000UL
/*
* Config PLL input for 2 MHz
* TODO: Make sure KINETIS_XTAL_FREQUENCY >= 2Mhz && <= 50Mhz
*/
//.........这里部分代码省略.........
/**
* @brief MK20D5 clock initialization.
* @note All the involved constants come from the file @p board.h.
* @note This function is meant to be invoked early during the system
* initialization, it is usually invoked from the file
* @p board.c.
* @todo This function needs to be more generic.
*
* @special
*/
void mk20d50_clock_init(void) {
uint32_t ratio, frdiv;
uint32_t ratios[] = { 32, 64, 128, 256, 512, 1024, 1280, 1536 };
int ratio_quantity = sizeof(ratios) / sizeof(ratios[0]);
int i;
/* Disable the watchdog */
WDOG->UNLOCK = 0xC520;
WDOG->UNLOCK = 0xD928;
WDOG->STCTRLH &= ~WDOG_STCTRLH_WDOGEN;
SIM->SCGC5 |= SIM_SCGC5_PORTA |
SIM_SCGC5_PORTB |
SIM_SCGC5_PORTC |
SIM_SCGC5_PORTD |
SIM_SCGC5_PORTE;
/* EXTAL0 and XTAL0 */
PORTA->PCR[18] = 0;
PORTA->PCR[19] = 0;
/*
* Start in FEI mode
*/
/* Disable capacitors for crystal */
OSC->CR = 0;
/* TODO: need to add more flexible calculation, specially regarding
* divisors which may not be available depending on the XTAL
* frequency, which would required other registers to be modified.
*/
/* Enable OSC, low power mode */
MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0;
if (KINETIS_XTAL_FREQUENCY > 8000000)
MCG->C2 |= MCG_C2_RANGE0(2);
else
MCG->C2 |= MCG_C2_RANGE0(1);
frdiv = 7;
ratio = KINETIS_XTAL_FREQUENCY / 31250;
for (i = 0; i < ratio_quantity; ++i) {
if (ratio == ratios[i]) {
frdiv = i;
break;
}
}
/* Switch to crystal as clock source, FLL input of 31.25 KHz */
MCG->C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(frdiv);
/* Wait for crystal oscillator to begin */
while (!(MCG->S & MCG_S_OSCINIT0));
/* Wait for the FLL to use the oscillator */
while (MCG->S & MCG_S_IREFST);
/* Wait for the MCGOUTCLK to use the oscillator */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2));
/*
* Now in FBE mode
*/
/* Config PLL input for 2 MHz */
MCG->C5 = MCG_C5_PRDIV0((KINETIS_XTAL_FREQUENCY / 2000000) - 1);
/* Config PLL for 96 MHz output */
MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);
/* Wait for PLL to start using crystal as its input */
while (!(MCG->S & MCG_S_PLLST));
/* Wait for PLL to lock */
while (!(MCG->S & MCG_S_LOCK0));
/*
* Now in PBE mode
*/
/* Switch to PLL as clock source */
MCG->C1 = MCG_C1_CLKS(0);
/* Wait for PLL clock to be used */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL);
/*
* Now in PEE mode
//.........这里部分代码省略.........
开发者ID:gflerm,项目名称:ChibiOS,代码行数:101,代码来源:hal_lld.c
示例8: SystemInit
/**
* Initialize the system
*
* @param none
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System.
*/
void SystemInit (void) {
// system dividers
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV3(2) | SIM_CLKDIV1_OUTDIV4(5);
// after reset, we are in FEI mode
// enable external clock source - OSC0
#if __SYS_OSC_CLK <= 8000000
MCG_C2 = MCG_C2_LOCRE0_MASK | MCG_C2_RANGE(RANGE0_VAL) | (/*hgo_val*/0 << MCG_C2_HGO_SHIFT) | (/*erefs_val*/0 << MCG_C2_EREFS_SHIFT);
#else
// On rev. 1.0 of silicon there is an issue where the the input bufferd are enabled when JTAG is connected.
// This has the affect of sometimes preventing the oscillator from running. To keep the oscillator amplitude
// low, RANGE = 2 should not be used. This should be removed when fixed silicon is available.
MCG_C2 = MCG_C2_LOCRE_MASK | MCG_C2_RANGE(2) | (/*hgo_val*/0 << MCG_C2_HGO_SHIFT) | (/*erefs_val*/0 << MCG_C2_EREFS_SHIFT);
// MCG_C2 = MCG_C2_LOCRE_MASK | MCG_C2_RANGE(1) | (/*hgo_val*/0 << MCG_C2_HGO_SHIFT) | (/*erefs_val*/0 << MCG_C2_EREFS_SHIFT);
#endif
// select clock mode, we want FBE mode
// CLKS = 2, FRDIV = frdiv_val, IREFS = 0, IRCLKEN = 0, IREFSTEN = 0
MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(FRDIV_VAL);
/* wait until the MCG has moved into the proper mode */
// if the external oscillator is used need to wait for OSCINIT to set
// for (i = 0 ; i < 10000 ; i++)
// {
// if (MCG_S & MCG_S_OSCINIT_MASK) break; // jump out early if OSCINIT sets before loop finishes
// }
// if (!(MCG_S & MCG_S_OSCINIT_MASK)) return 0x23; // check bit is really set and return with error if not set
// wait for reference clock status bit is cleared and clock source is ext ref clk
while ((MCG_S & MCG_S_IREFST_MASK) || MCG_S_CLKST(2) != (MCG_S & MCG_S_CLKST_MASK));
// ... FBE mode
// enable clock monitor for osc0
MCG_C6 = MCG_C6_CME_MASK;
// PLL0
MCG_C5 = MCG_C5_PRDIV(PRDIV_VAL - 1); // set PLL0 ref divider, osc0 is reference
MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(VDIV_VAL - 16); // set VDIV and enable PLL
// wait to lock...
while (!(MCG_S & MCG_S_PLLST_MASK));
while (!(MCG_S & MCG_S_LOCK_MASK));
// // Use actual PLL settings to calculate PLL frequency
// prdiv = ((MCG_C5 & MCG_C5_PRDIV_MASK) + 1);
// vdiv = ((MCG_C6 & MCG_C6_VDIV_MASK) + 16);
// ... PBE mode
MCG_C1 &= ~MCG_C1_CLKS_MASK; // CLKS = 0, select PLL as MCG_OUT
while (MCG_S_CLKST(3) != (MCG_S & MCG_S_CLKST_MASK));
// ... PEE mode
/* ToDo: add code to initialize the system
do not use global variables because this function is called before
reaching pre-main. RW section maybe overwritten afterwards. */
SystemCoreClock = __SYSTEM_CLOCK;
}
void __startup(void) {
// The CPU has a watchdog feature which is on by default,
// so we have to configure it to not have nasty reset-surprises
// later on.
startup_watchdog_hook();
// If the system was in VLLS mode, some peripherials and
// the I/O pins are in latched mode. We need to restore
// config and can then acknowledge the isolation to get back
// to normal. For now, we'll just ack TODO: properly do this
if (PMC_REGSC & PMC_REGSC_ACKISO_MASK) PMC_REGSC |= PMC_REGSC_ACKISO_MASK;
// There is a write-once-after-reset register that allows to
// set which power states are available. Let's set it here.
SMC_PMPROT = ENABLED_POWER_MODES;
// For the sake of simplicity, enable all GPIO port clocks
SIM_SCGC5 |= ( SIM_SCGC5_PORTA_MASK
| SIM_SCGC5_PORTB_MASK
| SIM_SCGC5_PORTC_MASK
| SIM_SCGC5_PORTD_MASK
| SIM_SCGC5_PORTE_MASK);
// ----------------------------------------------------------------------------------
// Setup clocks
// ----------------------------------------------------------------------------------
// See section 5 in the Freescale K20 manual for how clock distribution works
// The limits are outlined in section 5.5:
// Core and System clocks: max 72 MHz
// Bus/peripherial clock: max 50 MHz (integer divide of core)
// Flash clock: max 25 MHz
//
// The teensy 3.x has a 16 MHz external oscillator
// So we'll enable the external clock for the OSC module. Since
// we're in high-frequency mode, also enable capacitors
OSC_CR = OSC_CR_SC8P_MASK | OSC_CR_SC2P_MASK; // TODO This does not actually seem enable the ext crystal
// Set MCG to very high frequency crystal and request oscillator. We have
// to do this first so that the divisor will be correct (512 and not 16)
MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK;
// Select the external reference clock for MCGOUTCLK
// The divider for the FLL has to be chosen that we get something in 31.25 to 39.0625 kHz
// 16MHz / 512 = 31.25 kHz -> set FRDIV to 4
MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(4);
// Wait for OSC to become ready
while ((MCG_S & MCG_S_OSCINIT0_MASK) == 0) ;
// Wait for the FLL to synchronize to external reference
while ((MCG_S & MCG_S_IREFST_MASK) != 0) ;
// Wait for the clock mode to synchronize to external
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) ;
// The clock is now in FBE mode
#if F_CPU <= 16000000
// For 16 MHz and below, the crystal is fast enough
// -> enable BLPE mode which will disable both FLL and PLL
MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS_MASK | MCG_C2_LP_MASK;
#else
// We need PLL to go above 16 MHz
#if F_CPU == 96000000
MCG_C5 = MCG_C5_PRDIV0(3); // 16MHz / 4 = 4MHz (this needs to be 2-4MHz)
MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0); // Enable PLL*24 = 96 MHz
#elif F_CPU == 72000000
MCG_C5 = MCG_C5_PRDIV0(5); // 16 MHz / 6 = 2.66 MHz (this needs to be 2-4MHz)
MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0(3); // Enable PLL*27 = 71.82 MHz
#elif F_CPU == 48000000
MCG_C5 = MCG_C5_PRDIV0(7); // 16 MHz / 8 = 2 MHz (this needs to be 2-4MHz)
MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0); // Enable PLL*24 = 48 MHz
#elif F_CPU == 24000000
// For 24 MHz, we'll use a 48 MHz PLL and divide in the SIM
MCG_C5 = MCG_C5_PRDIV0(7); // 16 MHz / 8 = 2 MHz (this needs to be 2-4MHz)
MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0); // Enable PLL*24 = 48 MHz
#else
#error "Unknown F_CPU value"
#endif
// Now that we setup and enabled the PLL, wait for it to become active
while (!(MCG_S & MCG_S_PLLST_MASK)) ;
// and locked
while (!(MCG_S & MCG_S_LOCK0_MASK)) ;
#endif
// Next up: Setup clock dividers for MCU, peripherials, flash and USB
// This is done by the SIM (System Integration Module)
// There are two registers:
// SIM_CLKDIV1:
// OUTDIV1: Core/system clock divider
// OUTDIV2: Peripherial/Bus clock
// OUTDIV4: Flash clock
// SIM_CLKDIV2:
// USBDIV: Divisor
// USBFRAC: Fraction
// Output is input_clock*(USBFRAC+1)/(USBDIV+1)
//
// USB needs a 48MHz clock, so the divider should be setup accordingly. Also,
// for the USB FS OTG controller to work, the system clock needs to be >= 20 MHz
//.........这里部分代码省略.........
请发表评论