/*! Sets up the clock out of RESET *! */ void clock_initialise(void) { #ifdef ENABLE_CLKOUT showClocks(); #endif #if (CLOCK_MODE == CLOCK_MODE_RESET) // No clock setup #else // XTAL/EXTAL Pins SIM_SCGC6 |= SIM_SCGC6_PORTB_MASK; MXC_PTBPF1 = (MXC_PTBPF1&~MXC_PTBPF1_B6_MASK)|MXC_PTBPF1_B6(0); MXC_PTBPF2 = (MXC_PTBPF2&~MXC_PTBPF2_B5_MASK)|MXC_PTBPF2_B5(0); // Configure OSC2 (XTAL1/EXTAL1 OSC1_CR = OSC1_CR_ERCLKEN_M|OSC1_CR_EREFSTEN_M|OSC1_CR_SCP_M; // Configure OSC2 (XTAL2/EXTAL2 OSC2_CR = OSC2_CR_ERCLKEN_M|OSC2_CR_EREFSTEN_M|OSC2_CR_SCP_M; // Configure OSC1 (XTAL1/EXTAL1 SIM_OSC1 = SIM_OSC1_OSC1EN_M|SIM_OSC1_OSC1RANGE_M|SIM_OSC1_OSC1HGO_M|SIM_OSC1_OSC1EREFS_M; // Out of reset MCG is in FEI mode // ============================================================= // Switch from FEI -> FEI/FBI/FEE/FBE // ============================================================= // Set up crystal or external clock source MCG_C2 = MCG_C2_RANGE_M | // RANGE = 0,1,2 -> Oscillator low/high/very high clock range MCG_C2_HGO_M | // HGO = 0,1 -> Oscillator low power/high gain MCG_C2_EREFS_M | // EREFS = 0,1 -> Select external clock/crystal oscillator MCG_C2_IRCS_M; // IRCS = 0,1 -> Select slow/fast internal clock for internal reference SIM_CLKDIV0 = SIM_CLKDIV0_OUTDIV(3); #if ((CLOCK_MODE == CLOCK_MODE_FEI) || (CLOCK_MODE == CLOCK_MODE_FBI) || (CLOCK_MODE == CLOCK_MODE_BLPI) ) // Transition via FBI //===================================== #define BYPASS (1) // CLKS value used while FLL locks MCG_C1 = MCG_C1_CLKS(BYPASS) | // CLKS = 1 -> Internal reference source while PLL locks MCG_C1_FRDIV_M | // FRDIV = N -> XTAL/2^n ~ 31.25 kHz MCG_C1_IREFS_M | // IREFS = 0,1 -> External/Slow IRC for FLL source MCG_C1_IRCLKEN_M | // IRCLKEN = 0,1 -> IRCLK disable/enable MCG_C1_IREFSTEN_M; // IREFSTEN = 0,1 -> Internal reference enabled in STOP mode // Wait for S_IREFST to indicate FLL Reference has switched do { __asm__("nop"); } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT)); // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL do { __asm__("nop"); } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS)); // Set FLL Parameters MCG_C4 = (MCG_C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M; #endif #if ((CLOCK_MODE == CLOCK_MODE_FBE) || (CLOCK_MODE == CLOCK_MODE_FEE) || (CLOCK_MODE == CLOCK_MODE_PLBE) || (CLOCK_MODE == CLOCK_MODE_PBE) || (CLOCK_MODE == CLOCK_MODE_PEE)) // Transition via FBE //===================================== #define BYPASS (2) // CLKS value used while PLL locks MCG_C1 = MCG_C1_CLKS(BYPASS) | // CLKS = 2 -> External reference source while PLL locks MCG_C1_FRDIV_M | // FRDIV = N -> XTAL/2^n ~ 31.25 kHz MCG_C1_IREFS_M | // IREFS = 0,1 -> External/Slow IRC for FLL source MCG_C1_IRCLKEN_M | // IRCLKEN = 0,1 -> IRCLK disable/enable MCG_C1_IREFSTEN_M; // IREFSTEN = 0,1 -> Internal reference enabled in STOP mode #if (MCG_C2_EREFS_V != 0) // Wait for oscillator stable (if used) do { __asm__("nop"); } while ((MCG_S & MCG_S_OSCINIT_MASK) == 0); #endif // Wait for S_IREFST to indicate FLL Reference has switched do { __asm__("nop"); } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT)); // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL do { __asm__("nop"); } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS)); // Set FLL Parameters MCG_C4 = (MCG_C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M; #endif #if ((CLOCK_MODE == CLOCK_MODE_PBE) || (CLOCK_MODE == CLOCK_MODE_PEE)) // Configure PLL Reference Frequency // ============================================================= MCG_C5 = MCG_C5_PLLCLKEN_M | // PLLCLKEN = 0,1 -> PLL -/enabled (irrespective of PLLS) MCG_C5_PLLSTEN_M | // PLLSTEN0 = 0,1 -> disabled/enabled in normal stop mode MCG_C5_PRDIV_M; // PRDIV0 = N -> PLL divider so PLL Ref. Freq. = 2-4 MHz // Transition via PBE // ============================================================= MCG_C6 = MCG_C6_LOLIE_M | MCG_C6_PLLS_M | // PLLS = 0,1 -> Enable PLL MCG_C6_CME_M | // CME0 = 0,1 -> Disable/enable clock monitor MCG_C6_VDIV_M; // VDIV0 = N -> PLL Multiplication factor // Wait for PLL to lock do { __asm__("nop"); } while((MCG_S & MCG_S_LOCK_MASK) == 0); // Wait until PLLS clock source changes to the PLL clock out do { __asm__("nop"); } while((MCG_S & MCG_S_PLLST_MASK) == 0); #endif #if ((CLOCK_MODE == CLOCK_MODE_FEI) || (CLOCK_MODE == CLOCK_MODE_FEE)) // Wait for FLL to lock do { __asm__("nop"); } while ((MCG_C4&MCG_C4_DRST_DRS_MASK) != MCG_C4_DRST_DRS_M); #endif // Select FEI/FBI/FEE/FBE/PBE/PEE clock mode MCG_C1 = MCG_C1_CLKS_M | // CLKS = 0,1,2 -> Select FLL/IRCSCLK/ERCLK MCG_C1_FRDIV_M | // FRDIV = N -> XTAL/2^n ~ 31.25 kHz MCG_C1_IREFS_M | // IREFS = 0,1 -> External/Slow IRC for FLL source MCG_C1_IRCLKEN_M | // IRCLKEN = 0,1 -> IRCLK disable/enable MCG_C1_IREFSTEN_M; // IREFSTEN = 0,1 -> Internal reference enabled in STOP mode // Wait for mode change do { __asm__("nop"); } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT)); #if defined (MCG_C6_PLLS_V) && (MCG_C1_CLKS_V == 0) // FLL or PLL #define MCG_S_CLKST_M MCG_S_CLKST(MCG_C6_PLLS_V?3:0) #else #define MCG_S_CLKST_M MCG_S_CLKST(MCG_C1_CLKS_V) #endif // Wait for S_CLKST to indicating that OUTCLK has switched do { __asm__("nop"); } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST_M); #if (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI) // Select BLPE/BLPI clock mode MCG_C2 = MCG_C2_LOCRE_M | // LOCRE0 = 0,1 -> Loss of clock reset MCG_C2_RANGE_M | // RANGE0 = 0,1,2 -> Oscillator low/high/very high clock range MCG_C2_HGO_M | // HGO0 = 0,1 -> Oscillator low power/high gain MCG_C2_EREFS_M | // EREFS0 = 0,1 -> Select external clock/crystal oscillator MCG_C2_LP_M | // LP = 0,1 -> Select FLL enabled/disabled in bypass mode MCG_C2_IRCS_M; // IRCS = 0,1 -> Select slow/fast internal clock for internal reference #endif // (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI) #endif // (CLOCK_MODE == CLOCK_MODE_RESET) // Basic clock multiplexing #if defined(MCU_mcf51jf128) // SIM_SOPT2 = SIM_SOPT2_UART0SRC_M | // UART0 clock - 0,1,2,3 -> Disabled, (MCGFLLCLK, MCGPLLCLK/2), OSCERCLK, MCGIRCLK // SIM_SOPT2_TPMSRC_M ; // TPM2 source #else #error "CPU not set" #endif #ifdef SIM_CLKDIV1_USBFRAC_MASK SIM_CLKDIV1 = SIM_CLKDIV1_USBDIV_M | SIM_CLKDIV1_USBFRAC_M | SIM_CLKDIV1_USBSRC_M; #endif SIM_CLKDIV0 = SIM_CLKDIV0_M; SystemCoreClockUpdate(); }
/***************************************************************************** * @name MCG_Init * * @brief: Initialization of the Multiple Clock Generator. * * @param : None * * @return : None ***************************************************************************** * Provides clocking options for the device, including a phase-locked * loop(PLL) and frequency-locked loop (FLL) for multiplying slower reference * clock sources ****************************************************************************/ static void MCG_Init() { SIM_SCGC5 |= SIM_SCGC5_MCG_MASK; #ifndef EXTERNAL_OSC SIM_SCGC5 |= SIM_SCGC5_OSC2_MASK; #endif /* First move to FBE mode */ /* Enable external oscillator, RANGE=1, HGO=1, EREFS=1, LP=0, IRCS=0 */ #ifdef EXTERNAL_OSC MCG_C2 = 0; #else MCG_C2 = MCG_C2_RANGE(1) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK; #endif /* Select external oscillator and Reference Divider and clear IREFS to start ext. osc. */ // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); /* Wait for oscillator to initialize */ #ifndef EXTERNAL_OSC while (!(MCG_S & MCG_S_OSCINIT_MASK)) {;} #endif /* Wait for Reference clock Status bit to clear */ while (MCG_S & MCG_S_IREFST_MASK) {;} /* Wait for clock status bits to show clock source is ext. ref. clk. */ while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2) {;} /* Configure PLL Ref Divider, PLLCLKEN=0, PLLSTEN=0, PRDIV=5 The crystal frequency is used to select the PRDIV value. Only even frequency crystals are supported that will produce a 2MHz reference clock to the PLL. */ MCG_C5 = MCG_C5_PRDIV(BSP_REF_CLOCK_DIV); // Set PLL ref. divider to match the crystal used /* Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disabled, clk. monitor disabled, PLL VCO divider is clear */ MCG_C6 = 0x0; /* Set system options dividers MCG=PLL, core = MCG */ SIM_CLKDIV0 = SIM_CLKDIV0_OUTDIV(0); /* Set the VCO divider and enable the PLL for 48MHz, LOLIE=0, PLLS=1, CME=0, VDIV=0 */ MCG_C6 = MCG_C6_PLLS_MASK; //VDIV = 0 (x24) /* Wait for PLL status bit to set */ while (!(MCG_S & MCG_S_PLLST_MASK)) {;} /* Wait for LOCK bit to set */ while (!(MCG_S & MCG_S_LOCK_MASK)) {;} /* Now running PBE Mode */ /* Transition into PEE by setting CLKS to 0 CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 */ MCG_C1 &= ~MCG_C1_CLKS_MASK; /* Wait for clock status bits to update */ while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3) {;} /* Now running PEE Mode */ SIM_SOPT3 |= SIM_SOPT3_RWE_MASK; SIM_SOPT1 |= SIM_SOPT1_REGE_MASK; SIM_SOPT7 |= 0x80; /* Ensure PLL is selected as USB CLK source */ SIM_CLKDIV1 = 0x00; }