Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
fsl_clock.c
00001 /* 00002 * Copyright (c) 2015, Freescale Semiconductor, Inc. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without modification, 00006 * are permitted provided that the following conditions are met: 00007 * 00008 * o Redistributions of source code must retain the above copyright notice, this list 00009 * of conditions and the following disclaimer. 00010 * 00011 * o Redistributions in binary form must reproduce the above copyright notice, this 00012 * list of conditions and the following disclaimer in the documentation and/or 00013 * other materials provided with the distribution. 00014 * 00015 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its 00016 * contributors may be used to endorse or promote products derived from this 00017 * software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 */ 00030 00031 #include "fsl_common.h" 00032 #include "fsl_clock.h " 00033 00034 /******************************************************************************* 00035 * Definitions 00036 ******************************************************************************/ 00037 00038 /* Macro definition remap workaround. */ 00039 #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) 00040 #define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK 00041 #endif 00042 #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK))) 00043 #define MCG_C2_HGO0_MASK MCG_C2_HGO_MASK 00044 #endif 00045 #if (defined(MCG_C2_RANGE_MASK) && !(defined(MCG_C2_RANGE0_MASK))) 00046 #define MCG_C2_RANGE0_MASK MCG_C2_RANGE_MASK 00047 #endif 00048 #if (defined(MCG_C6_CME_MASK) && !(defined(MCG_C6_CME0_MASK))) 00049 #define MCG_C6_CME0_MASK MCG_C6_CME_MASK 00050 #endif 00051 00052 /* PLL fixed multiplier when there is not PRDIV and VDIV. */ 00053 #define PLL_FIXED_MULT (375U) 00054 /* Max frequency of the reference clock used for internal clock trim. */ 00055 #define TRIM_REF_CLK_MIN (8000000U) 00056 /* Min frequency of the reference clock used for internal clock trim. */ 00057 #define TRIM_REF_CLK_MAX (16000000U) 00058 /* Max trim value of fast internal reference clock. */ 00059 #define TRIM_FIRC_MAX (5000000U) 00060 /* Min trim value of fast internal reference clock. */ 00061 #define TRIM_FIRC_MIN (3000000U) 00062 /* Max trim value of fast internal reference clock. */ 00063 #define TRIM_SIRC_MAX (39063U) 00064 /* Min trim value of fast internal reference clock. */ 00065 #define TRIM_SIRC_MIN (31250U) 00066 00067 #define MCG_S_IRCST_VAL ((MCG->S & MCG_S_IRCST_MASK) >> MCG_S_IRCST_SHIFT) 00068 #define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) 00069 #define MCG_S_IREFST_VAL ((MCG->S & MCG_S_IREFST_MASK) >> MCG_S_IREFST_SHIFT) 00070 #define MCG_S_PLLST_VAL ((MCG->S & MCG_S_PLLST_MASK) >> MCG_S_PLLST_SHIFT) 00071 #define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT) 00072 #define MCG_C2_LP_VAL ((MCG->C2 & MCG_C2_LP_MASK) >> MCG_C2_LP_SHIFT) 00073 #define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT) 00074 #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) 00075 #define MCG_S2_PLLCST_VAL ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT) 00076 #define MCG_C7_OSCSEL_VAL ((MCG->C7 & MCG_C7_OSCSEL_MASK) >> MCG_C7_OSCSEL_SHIFT) 00077 #define MCG_C4_DMX32_VAL ((MCG->C4 & MCG_C4_DMX32_MASK) >> MCG_C4_DMX32_SHIFT) 00078 #define MCG_C4_DRST_DRS_VAL ((MCG->C4 & MCG_C4_DRST_DRS_MASK) >> MCG_C4_DRST_DRS_SHIFT) 00079 #define MCG_C7_PLL32KREFSEL_VAL ((MCG->C7 & MCG_C7_PLL32KREFSEL_MASK) >> MCG_C7_PLL32KREFSEL_SHIFT) 00080 #define MCG_C5_PLLREFSEL0_VAL ((MCG->C5 & MCG_C5_PLLREFSEL0_MASK) >> MCG_C5_PLLREFSEL0_SHIFT) 00081 #define MCG_C11_PLLREFSEL1_VAL ((MCG->C11 & MCG_C11_PLLREFSEL1_MASK) >> MCG_C11_PLLREFSEL1_SHIFT) 00082 #define MCG_C11_PRDIV1_VAL ((MCG->C11 & MCG_C11_PRDIV1_MASK) >> MCG_C11_PRDIV1_SHIFT) 00083 #define MCG_C12_VDIV1_VAL ((MCG->C12 & MCG_C12_VDIV1_MASK) >> MCG_C12_VDIV1_SHIFT) 00084 #define MCG_C5_PRDIV0_VAL ((MCG->C5 & MCG_C5_PRDIV0_MASK) >> MCG_C5_PRDIV0_SHIFT) 00085 #define MCG_C6_VDIV0_VAL ((MCG->C6 & MCG_C6_VDIV0_MASK) >> MCG_C6_VDIV0_SHIFT) 00086 00087 #define OSC_MODE_MASK (MCG_C2_EREFS0_MASK | MCG_C2_HGO0_MASK | MCG_C2_RANGE0_MASK) 00088 00089 #define SIM_CLKDIV1_OUTDIV1_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT) 00090 #define SIM_CLKDIV1_OUTDIV2_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> SIM_CLKDIV1_OUTDIV2_SHIFT) 00091 #define SIM_CLKDIV1_OUTDIV3_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV3_MASK) >> SIM_CLKDIV1_OUTDIV3_SHIFT) 00092 #define SIM_CLKDIV1_OUTDIV4_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) 00093 #define SIM_SOPT1_OSC32KSEL_VAL ((SIM->SOPT1 & SIM_SOPT1_OSC32KSEL_MASK) >> SIM_SOPT1_OSC32KSEL_SHIFT) 00094 #define SIM_SOPT2_PLLFLLSEL_VAL ((SIM->SOPT2 & SIM_SOPT2_PLLFLLSEL_MASK) >> SIM_SOPT2_PLLFLLSEL_SHIFT) 00095 #define SIM_CLKDIV3_PLLFLLDIV_VAL ((SIM->CLKDIV3 & SIM_CLKDIV3_PLLFLLDIV_MASK) >> SIM_CLKDIV3_PLLFLLDIV_SHIFT) 00096 #define SIM_CLKDIV3_PLLFLLFRAC_VAL ((SIM->CLKDIV3 & SIM_CLKDIV3_PLLFLLFRAC_MASK) >> SIM_CLKDIV3_PLLFLLFRAC_SHIFT) 00097 00098 /* MCG_S_CLKST definition. */ 00099 enum _mcg_clkout_stat 00100 { 00101 kMCG_ClkOutStatFll, /* FLL. */ 00102 kMCG_ClkOutStatInt, /* Internal clock. */ 00103 kMCG_ClkOutStatExt, /* External clock. */ 00104 kMCG_ClkOutStatPll /* PLL. */ 00105 }; 00106 00107 /* MCG_S_PLLST definition. */ 00108 enum _mcg_pllst 00109 { 00110 kMCG_PllstFll, /* FLL is used. */ 00111 kMCG_PllstPll /* PLL is used. */ 00112 }; 00113 00114 /******************************************************************************* 00115 * Variables 00116 ******************************************************************************/ 00117 00118 /* Slow internal reference clock frequency. */ 00119 static uint32_t s_slowIrcFreq = 32768U; 00120 /* Fast internal reference clock frequency. */ 00121 static uint32_t s_fastIrcFreq = 4000000U; 00122 /* The MCG external PLL clock frequency. */ 00123 static uint32_t s_extPllFreq = 0U; 00124 00125 /* External XTAL0 (OSC0) clock frequency. */ 00126 uint32_t g_xtal0Freq; 00127 /* External XTAL32K clock frequency. */ 00128 uint32_t g_xtal32Freq; 00129 00130 /******************************************************************************* 00131 * Prototypes 00132 ******************************************************************************/ 00133 00134 /*! 00135 * @brief Get the MCG external reference clock frequency. 00136 * 00137 * Get the current MCG external reference clock frequency in Hz. It is 00138 * the frequency select by MCG_C7[OSCSEL]. This is an internal function. 00139 * 00140 * @return MCG external reference clock frequency in Hz. 00141 */ 00142 static uint32_t CLOCK_GetMcgExtClkFreq(void); 00143 00144 /*! 00145 * @brief Get the MCG FLL external reference clock frequency. 00146 * 00147 * Get the current MCG FLL external reference clock frequency in Hz. It is 00148 * the frequency after by MCG_C1[FRDIV]. This is an internal function. 00149 * 00150 * @return MCG FLL external reference clock frequency in Hz. 00151 */ 00152 static uint32_t CLOCK_GetFllExtRefClkFreq(void); 00153 00154 /*! 00155 * @brief Get the MCG FLL reference clock frequency. 00156 * 00157 * Get the current MCG FLL reference clock frequency in Hz. It is 00158 * the frequency select by MCG_C1[IREFS]. This is an internal function. 00159 * 00160 * @return MCG FLL reference clock frequency in Hz. 00161 */ 00162 static uint32_t CLOCK_GetFllRefClkFreq(void); 00163 00164 /*! 00165 * @brief Get the frequency of clock selected by MCG_C2[IRCS]. 00166 * 00167 * This clock's two output: 00168 * 1. MCGOUTCLK when MCG_S[CLKST]=0. 00169 * 2. MCGIRCLK when MCG_C1[IRCLKEN]=1. 00170 * 00171 * @return The frequency in Hz. 00172 */ 00173 static uint32_t CLOCK_GetInternalRefClkSelectFreq(void); 00174 00175 /*! 00176 * @brief Get the MCG PLL/PLL0 reference clock frequency. 00177 * 00178 * Get the current MCG PLL/PLL0 reference clock frequency in Hz. 00179 * This is an internal function. 00180 * 00181 * @return MCG PLL/PLL0 reference clock frequency in Hz. 00182 */ 00183 static uint32_t CLOCK_GetPll0RefFreq(void); 00184 00185 /*! 00186 * @brief Calculate the RANGE value base on crystal frequency. 00187 * 00188 * To setup external crystal oscillator, must set the register bits RANGE 00189 * base on the crystal frequency. This function returns the RANGE base on the 00190 * input frequency. This is an internal function. 00191 * 00192 * @param freq Crystal frequency in Hz. 00193 * @return The RANGE value. 00194 */ 00195 static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); 00196 00197 /*! 00198 * @brief Delay function to wait FLL stable. 00199 * 00200 * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least 00201 * 1ms. Every time changes FLL setting, should wait this time for FLL stable. 00202 */ 00203 static void CLOCK_FllStableDelay(void); 00204 00205 /******************************************************************************* 00206 * Code 00207 ******************************************************************************/ 00208 00209 static uint32_t CLOCK_GetMcgExtClkFreq(void) 00210 { 00211 uint32_t freq; 00212 00213 switch (MCG_C7_OSCSEL_VAL) 00214 { 00215 case 0U: 00216 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ 00217 assert(g_xtal0Freq); 00218 freq = g_xtal0Freq; 00219 break; 00220 case 1U: 00221 /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ 00222 assert(g_xtal32Freq); 00223 freq = g_xtal32Freq; 00224 break; 00225 case 2U: 00226 freq = MCG_INTERNAL_IRC_48M; 00227 break; 00228 default: 00229 freq = 0U; 00230 break; 00231 } 00232 00233 return freq; 00234 } 00235 00236 static uint32_t CLOCK_GetFllExtRefClkFreq(void) 00237 { 00238 /* FllExtRef = McgExtRef / FllExtRefDiv */ 00239 uint8_t frdiv; 00240 uint8_t range; 00241 uint8_t oscsel; 00242 00243 uint32_t freq = CLOCK_GetMcgExtClkFreq(); 00244 00245 if (!freq) 00246 { 00247 return freq; 00248 } 00249 00250 frdiv = MCG_C1_FRDIV_VAL; 00251 freq >>= frdiv; 00252 00253 range = MCG_C2_RANGE_VAL; 00254 oscsel = MCG_C7_OSCSEL_VAL; 00255 00256 /* 00257 When should use divider 32, 64, 128, 256, 512, 1024, 1280, 1536. 00258 1. MCG_C7[OSCSEL] selects IRC48M. 00259 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0. 00260 */ 00261 if (((0U != range) && (kMCG_OscselOsc == oscsel)) || (kMCG_OscselIrc == oscsel)) 00262 { 00263 switch (frdiv) 00264 { 00265 case 0: 00266 case 1: 00267 case 2: 00268 case 3: 00269 case 4: 00270 case 5: 00271 freq >>= 5u; 00272 break; 00273 case 6: 00274 /* 64*20=1280 */ 00275 freq /= 20u; 00276 break; 00277 case 7: 00278 /* 128*12=1536 */ 00279 freq /= 12u; 00280 break; 00281 default: 00282 freq = 0u; 00283 break; 00284 } 00285 } 00286 00287 return freq; 00288 } 00289 00290 static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) 00291 { 00292 if (kMCG_IrcSlow == MCG_S_IRCST_VAL) 00293 { 00294 /* Slow internal reference clock selected*/ 00295 return s_slowIrcFreq; 00296 } 00297 else 00298 { 00299 /* Fast internal reference clock selected*/ 00300 return s_fastIrcFreq >> MCG_SC_FCRDIV_VAL; 00301 } 00302 } 00303 00304 static uint32_t CLOCK_GetFllRefClkFreq(void) 00305 { 00306 /* If use external reference clock. */ 00307 if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) 00308 { 00309 return CLOCK_GetFllExtRefClkFreq(); 00310 } 00311 /* If use internal reference clock. */ 00312 else 00313 { 00314 return s_slowIrcFreq; 00315 } 00316 } 00317 00318 static uint32_t CLOCK_GetPll0RefFreq(void) 00319 { 00320 /* MCG external reference clock. */ 00321 return CLOCK_GetMcgExtClkFreq(); 00322 } 00323 00324 static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) 00325 { 00326 uint8_t range; 00327 00328 if (freq <= 39063U) 00329 { 00330 range = 0U; 00331 } 00332 else if (freq <= 8000000U) 00333 { 00334 range = 1U; 00335 } 00336 else 00337 { 00338 range = 2U; 00339 } 00340 00341 return range; 00342 } 00343 00344 static void CLOCK_FllStableDelay(void) 00345 { 00346 /* 00347 Should wait at least 1ms. Because in these modes, the core clock is 100MHz 00348 at most, so this function could obtain the 1ms delay. 00349 */ 00350 volatile uint32_t i = 30000U; 00351 while (i--) 00352 { 00353 __NOP(); 00354 } 00355 } 00356 00357 uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) 00358 { 00359 if (OSC0->CR & OSC_CR_ERCLKEN_MASK) 00360 { 00361 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ 00362 assert(g_xtal0Freq); 00363 return g_xtal0Freq; 00364 } 00365 else 00366 { 00367 return 0U; 00368 } 00369 } 00370 00371 uint32_t CLOCK_GetOsc0ErClkDivFreq(void) 00372 { 00373 if (OSC0->CR & OSC_CR_ERCLKEN_MASK) 00374 { 00375 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ 00376 assert(g_xtal0Freq); 00377 return g_xtal0Freq >> ((OSC0->DIV & OSC_DIV_ERPS_MASK) >> OSC_DIV_ERPS_SHIFT); 00378 } 00379 else 00380 { 00381 return 0U; 00382 } 00383 } 00384 00385 uint32_t CLOCK_GetEr32kClkFreq(void) 00386 { 00387 uint32_t freq; 00388 00389 switch (SIM_SOPT1_OSC32KSEL_VAL) 00390 { 00391 case 0U: /* OSC 32k clock */ 00392 freq = (CLOCK_GetOsc0ErClkDivFreq() == 32768U) ? 32768U : 0U; 00393 break; 00394 case 2U: /* RTC 32k clock */ 00395 /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ 00396 assert(g_xtal32Freq); 00397 freq = g_xtal32Freq; 00398 break; 00399 case 3U: /* LPO clock */ 00400 freq = LPO_CLK_FREQ; 00401 break; 00402 default: 00403 freq = 0U; 00404 break; 00405 } 00406 return freq; 00407 } 00408 00409 uint32_t CLOCK_GetPllFllSelClkFreq(void) 00410 { 00411 uint32_t freq; 00412 00413 switch (SIM_SOPT2_PLLFLLSEL_VAL) 00414 { 00415 case 0U: /* FLL. */ 00416 freq = CLOCK_GetFllFreq(); 00417 break; 00418 case 1U: /* PLL. */ 00419 freq = CLOCK_GetPll0Freq(); 00420 break; 00421 case 2U: 00422 freq = CLOCK_GetExtPllFreq(); 00423 break; 00424 case 3U: /* MCG IRC48M. */ 00425 freq = MCG_INTERNAL_IRC_48M; 00426 break; 00427 default: 00428 freq = 0U; 00429 break; 00430 } 00431 00432 freq *= (SIM_CLKDIV3_PLLFLLFRAC_VAL + 1U); 00433 freq /= (SIM_CLKDIV3_PLLFLLDIV_VAL + 1U); 00434 return freq; 00435 } 00436 00437 uint32_t CLOCK_GetOsc0ErClkFreq(void) 00438 { 00439 return CLOCK_GetOsc0ErClkDivFreq(); 00440 } 00441 00442 uint32_t CLOCK_GetPlatClkFreq(void) 00443 { 00444 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); 00445 } 00446 00447 uint32_t CLOCK_GetFlashClkFreq(void) 00448 { 00449 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); 00450 } 00451 00452 uint32_t CLOCK_GetFlexBusClkFreq(void) 00453 { 00454 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1); 00455 } 00456 00457 uint32_t CLOCK_GetBusClkFreq(void) 00458 { 00459 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); 00460 } 00461 00462 uint32_t CLOCK_GetCoreSysClkFreq(void) 00463 { 00464 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); 00465 } 00466 00467 uint32_t CLOCK_GetFreq(clock_name_t clockName) 00468 { 00469 uint32_t freq; 00470 00471 switch (clockName) 00472 { 00473 case kCLOCK_CoreSysClk : 00474 case kCLOCK_PlatClk : 00475 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); 00476 break; 00477 case kCLOCK_BusClk : 00478 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); 00479 break; 00480 case kCLOCK_FlexBusClk : 00481 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1); 00482 break; 00483 case kCLOCK_FlashClk : 00484 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); 00485 break; 00486 case kCLOCK_PllFllSelClk : 00487 freq = CLOCK_GetPllFllSelClkFreq(); 00488 break; 00489 case kCLOCK_Er32kClk : 00490 freq = CLOCK_GetEr32kClkFreq(); 00491 break; 00492 case kCLOCK_Osc0ErClk : 00493 freq = CLOCK_GetOsc0ErClkDivFreq(); 00494 break; 00495 case kCLOCK_Osc0ErClkUndiv : 00496 freq = CLOCK_GetOsc0ErClkUndivFreq(); 00497 break; 00498 case kCLOCK_McgFixedFreqClk : 00499 freq = CLOCK_GetFixedFreqClkFreq(); 00500 break; 00501 case kCLOCK_McgInternalRefClk : 00502 freq = CLOCK_GetInternalRefClkFreq(); 00503 break; 00504 case kCLOCK_McgFllClk : 00505 freq = CLOCK_GetFllFreq(); 00506 break; 00507 case kCLOCK_McgPll0Clk : 00508 freq = CLOCK_GetPll0Freq(); 00509 break; 00510 case kCLOCK_McgIrc48MClk : 00511 freq = MCG_INTERNAL_IRC_48M; 00512 break; 00513 case kCLOCK_LpoClk : 00514 freq = LPO_CLK_FREQ; 00515 break; 00516 default: 00517 freq = 0U; 00518 break; 00519 } 00520 00521 return freq; 00522 } 00523 00524 void CLOCK_SetSimConfig(sim_clock_config_t const *config) 00525 { 00526 SIM->CLKDIV1 = config->clkdiv1 ; 00527 CLOCK_SetPllFllSelClock(config->pllFllSel , config->pllFllDiv , config->pllFllFrac ); 00528 CLOCK_SetEr32kClock(config->er32kSrc ); 00529 } 00530 00531 bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) 00532 { 00533 /* In current implementation, USBPFDCLK is not used for USB FS. */ 00534 assert(kCLOCK_UsbSrcUsbPfd != src); 00535 00536 bool ret = true; 00537 00538 CLOCK_DisableClock(kCLOCK_Usbfs0); 00539 00540 if (kCLOCK_UsbSrcExt == src) 00541 { 00542 SIM->SOPT2 &= ~SIM_SOPT2_USBSRC_MASK; 00543 } 00544 else 00545 { 00546 switch (freq) 00547 { 00548 case 120000000U: 00549 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(4) | SIM_CLKDIV2_USBFRAC(1); 00550 break; 00551 case 96000000U: 00552 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(1) | SIM_CLKDIV2_USBFRAC(0); 00553 break; 00554 case 72000000U: 00555 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC(1); 00556 break; 00557 case 48000000U: 00558 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0) | SIM_CLKDIV2_USBFRAC(0); 00559 break; 00560 default: 00561 ret = false; 00562 break; 00563 } 00564 00565 SIM->SOPT2 = ((SIM->SOPT2 & ~(SIM_SOPT2_PLLFLLSEL_MASK | SIM_SOPT2_USBSRC_MASK)) | (uint32_t)src); 00566 } 00567 00568 CLOCK_EnableClock(kCLOCK_Usbfs0); 00569 00570 if (kCLOCK_UsbSrcIrc48M == src) 00571 { 00572 USB0->CLK_RECOVER_IRC_EN = 0x03U; 00573 USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK; 00574 } 00575 return ret; 00576 } 00577 00578 bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) 00579 { 00580 volatile uint32_t i; 00581 00582 /* 00583 * In order to bring up the internal 480MHz USB PLL clock, should make sure: 00584 * 1. 32kHz IRC clock enable by setting IRCLKEN bit in MCG_C1 register. 00585 * 2. External reference clock enable on XTAL by setting ERCLKEN bit in OSC_CR register. 00586 */ 00587 assert(MCG->C1 & MCG_C1_IRCLKEN_MASK); 00588 assert(!(MCG->C2 & MCG_C2_IRCS_MASK)); 00589 assert(OSC0->CR & OSC_CR_ERCLKEN_MASK); 00590 00591 /* Source and freq are not used for USB HS. */ 00592 src = src; 00593 freq = freq; 00594 00595 SIM->SOPT2 |= SIM_SOPT2_USBREGEN_MASK; 00596 SIM->SCGC3 |= (SIM_SCGC3_USBHS_MASK | SIM_SCGC3_USBHSPHY_MASK); 00597 00598 i = 500000U; 00599 while (i--) 00600 { 00601 __NOP(); 00602 } 00603 00604 SIM->USBPHYCTL = ((SIM->USBPHYCTL & ~(SIM_USBPHYCTL_USB3VOUTTRG_MASK)) | SIM_USBPHYCTL_USB3VOUTTRG(6U) /* 3.310V */ 00605 | SIM_USBPHYCTL_USBVREGSEL_MASK); /* VREG_IN1 */ 00606 00607 return true; 00608 } 00609 00610 uint32_t CLOCK_GetOutClkFreq(void) 00611 { 00612 uint32_t mcgoutclk; 00613 uint32_t clkst = MCG_S_CLKST_VAL; 00614 uint32_t pllcst = MCG_S2_PLLCST_VAL; 00615 00616 switch (clkst) 00617 { 00618 case kMCG_ClkOutStatPll: 00619 switch (pllcst) 00620 { 00621 case kMCG_PllClkSelExtPll: 00622 mcgoutclk = CLOCK_GetExtPllFreq(); 00623 break; 00624 case kMCG_PllClkSelPll0 : 00625 mcgoutclk = CLOCK_GetPll0Freq(); 00626 break; 00627 default: 00628 mcgoutclk = 0U; 00629 break; 00630 } 00631 break; 00632 case kMCG_ClkOutStatFll: 00633 mcgoutclk = CLOCK_GetFllFreq(); 00634 break; 00635 case kMCG_ClkOutStatInt: 00636 mcgoutclk = CLOCK_GetInternalRefClkSelectFreq(); 00637 break; 00638 case kMCG_ClkOutStatExt: 00639 mcgoutclk = CLOCK_GetMcgExtClkFreq(); 00640 break; 00641 default: 00642 mcgoutclk = 0U; 00643 break; 00644 } 00645 return mcgoutclk; 00646 } 00647 00648 uint32_t CLOCK_GetFllFreq(void) 00649 { 00650 static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; 00651 00652 uint8_t drs, dmx32; 00653 uint32_t freq; 00654 00655 /* If FLL is not enabled currently, then return 0U. */ 00656 if ((MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) 00657 { 00658 return 0U; 00659 } 00660 00661 /* Get FLL reference clock frequency. */ 00662 freq = CLOCK_GetFllRefClkFreq(); 00663 if (!freq) 00664 { 00665 return freq; 00666 } 00667 00668 drs = MCG_C4_DRST_DRS_VAL; 00669 dmx32 = MCG_C4_DMX32_VAL; 00670 00671 return freq * fllFactorTable[drs][dmx32]; 00672 } 00673 00674 uint32_t CLOCK_GetInternalRefClkFreq(void) 00675 { 00676 /* If MCGIRCLK is gated. */ 00677 if (!(MCG->C1 & MCG_C1_IRCLKEN_MASK)) 00678 { 00679 return 0U; 00680 } 00681 00682 return CLOCK_GetInternalRefClkSelectFreq(); 00683 } 00684 00685 uint32_t CLOCK_GetFixedFreqClkFreq(void) 00686 { 00687 uint32_t freq = CLOCK_GetFllRefClkFreq(); 00688 00689 /* MCGFFCLK must be no more than MCGOUTCLK/8. */ 00690 if ((freq) && (freq <= (CLOCK_GetOutClkFreq() / 8U))) 00691 { 00692 return freq; 00693 } 00694 else 00695 { 00696 return 0U; 00697 } 00698 } 00699 00700 uint32_t CLOCK_GetPll0Freq(void) 00701 { 00702 uint32_t mcgpll0clk; 00703 00704 /* If PLL0 is not enabled, return 0. */ 00705 if (!(MCG->S & MCG_S_LOCK0_MASK)) 00706 { 00707 return 0U; 00708 } 00709 00710 mcgpll0clk = CLOCK_GetPll0RefFreq(); 00711 00712 /* 00713 * Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. 00714 * Please call CLOCK_SetXtal1Freq base on board setting before using OSC1 clock. 00715 */ 00716 assert(mcgpll0clk); 00717 00718 mcgpll0clk /= (FSL_FEATURE_MCG_PLL_PRDIV_BASE + MCG_C5_PRDIV0_VAL); 00719 mcgpll0clk *= (FSL_FEATURE_MCG_PLL_VDIV_BASE + MCG_C6_VDIV0_VAL); 00720 00721 mcgpll0clk >>= 1U; 00722 return mcgpll0clk; 00723 } 00724 00725 uint32_t CLOCK_GetExtPllFreq(void) 00726 { 00727 return s_extPllFreq; 00728 } 00729 00730 void CLOCK_SetExtPllFreq(uint32_t freq) 00731 { 00732 s_extPllFreq = freq; 00733 } 00734 00735 status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) 00736 { 00737 bool needDelay; 00738 uint32_t i; 00739 00740 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 00741 /* If change MCG_C7[OSCSEL] and external reference clock is system clock source, return error. */ 00742 if ((MCG_C7_OSCSEL_VAL != oscsel) && (!(MCG->S & MCG_S_IREFST_MASK))) 00743 { 00744 return kStatus_MCG_SourceUsed ; 00745 } 00746 #endif /* MCG_CONFIG_CHECK_PARAM */ 00747 00748 if (MCG_C7_OSCSEL_VAL != oscsel) 00749 { 00750 /* If change OSCSEL, need to delay, ERR009878. */ 00751 needDelay = true; 00752 } 00753 else 00754 { 00755 needDelay = false; 00756 } 00757 00758 MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); 00759 if (kMCG_OscselOsc == oscsel) 00760 { 00761 if (MCG->C2 & MCG_C2_EREFS_MASK) 00762 { 00763 while (!(MCG->S & MCG_S_OSCINIT0_MASK)) 00764 { 00765 } 00766 } 00767 } 00768 00769 if (needDelay) 00770 { 00771 /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ 00772 i = 1500U; 00773 while (i--) 00774 { 00775 __NOP(); 00776 } 00777 } 00778 00779 return kStatus_Success; 00780 } 00781 00782 status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) 00783 { 00784 uint32_t mcgOutClkState = MCG_S_CLKST_VAL; 00785 mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; 00786 uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; 00787 00788 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 00789 /* If MCGIRCLK is used as system clock source. */ 00790 if (kMCG_ClkOutStatInt == mcgOutClkState) 00791 { 00792 /* If need to change MCGIRCLK source or driver, return error. */ 00793 if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs)) 00794 { 00795 return kStatus_MCG_SourceUsed ; 00796 } 00797 } 00798 #endif 00799 00800 /* If need to update the FCRDIV. */ 00801 if (fcrdiv != curFcrdiv) 00802 { 00803 /* If fast IRC is in use currently, change to slow IRC. */ 00804 if ((kMCG_IrcFast == curIrcs) && ((mcgOutClkState == kMCG_ClkOutStatInt) || (MCG->C1 & MCG_C1_IRCLKEN_MASK))) 00805 { 00806 MCG->C2 = ((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow ))); 00807 while (MCG_S_IRCST_VAL != kMCG_IrcSlow ) 00808 { 00809 } 00810 } 00811 /* Update FCRDIV. */ 00812 MCG->SC = (MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); 00813 } 00814 00815 /* Set internal reference clock selection. */ 00816 MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)); 00817 MCG->C1 = (MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode; 00818 00819 /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */ 00820 if ((mcgOutClkState == kMCG_ClkOutStatInt) || (enableMode & kMCG_IrclkEnable )) 00821 { 00822 while (MCG_S_IRCST_VAL != ircs) 00823 { 00824 } 00825 } 00826 00827 return kStatus_Success; 00828 } 00829 00830 uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv) 00831 { 00832 uint8_t ret_prdiv = FSL_FEATURE_MCG_PLL_PRDIV_BASE; /* PRDIV to return. */ 00833 uint8_t ret_vdiv = FSL_FEATURE_MCG_PLL_VDIV_BASE; /* VDIV to return. */ 00834 uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ 00835 uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ 00836 uint8_t prdiv_cur; /* PRDIV value for iteration. */ 00837 uint8_t vdiv_cur; /* VDIV value for iteration. */ 00838 uint32_t ret_freq = 0U; /* PLL output fequency to return. */ 00839 uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ 00840 uint32_t ref_div; /* Reference frequency after PRDIV. */ 00841 00842 /* 00843 Steps: 00844 1. Get allowed prdiv with such rules: 00845 1). refFreq / prdiv >= FSL_FEATURE_MCG_PLL_REF_MIN. 00846 2). refFreq / prdiv <= FSL_FEATURE_MCG_PLL_REF_MAX. 00847 2. For each allowed prdiv, there are two candidate vdiv values: 00848 1). (desireFreq / (refFreq / prdiv)). 00849 2). (desireFreq / (refFreq / prdiv)) + 1. 00850 If could get the precise desired frequency, return current prdiv and 00851 vdiv directly. Otherwise choose the one which is closer to desired 00852 frequency. 00853 */ 00854 00855 /* Reference frequency is out of range. */ 00856 if ((refFreq < FSL_FEATURE_MCG_PLL_REF_MIN) || 00857 (refFreq > (FSL_FEATURE_MCG_PLL_REF_MAX * (FSL_FEATURE_MCG_PLL_PRDIV_MAX + FSL_FEATURE_MCG_PLL_PRDIV_BASE)))) 00858 { 00859 return 0U; 00860 } 00861 00862 /* refFreq/PRDIV must in a range. First get the allowed PRDIV range. */ 00863 prdiv_max = refFreq / FSL_FEATURE_MCG_PLL_REF_MIN; 00864 prdiv_min = (refFreq + FSL_FEATURE_MCG_PLL_REF_MAX - 1U) / FSL_FEATURE_MCG_PLL_REF_MAX; 00865 00866 desireFreq *= 2U; 00867 00868 /* PRDIV traversal. */ 00869 for (prdiv_cur = prdiv_max; prdiv_cur >= prdiv_min; prdiv_cur--) 00870 { 00871 /* Reference frequency after PRDIV. */ 00872 ref_div = refFreq / prdiv_cur; 00873 00874 vdiv_cur = desireFreq / ref_div; 00875 00876 if ((vdiv_cur < FSL_FEATURE_MCG_PLL_VDIV_BASE - 1U) || (vdiv_cur > FSL_FEATURE_MCG_PLL_VDIV_BASE + 31U)) 00877 { 00878 /* No VDIV is available with this PRDIV. */ 00879 continue; 00880 } 00881 00882 ret_freq = vdiv_cur * ref_div; 00883 00884 if (vdiv_cur >= FSL_FEATURE_MCG_PLL_VDIV_BASE) 00885 { 00886 if (ret_freq == desireFreq) /* If desire frequency is got. */ 00887 { 00888 *prdiv = prdiv_cur - FSL_FEATURE_MCG_PLL_PRDIV_BASE; 00889 *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; 00890 return ret_freq / 2U; 00891 } 00892 /* New PRDIV/VDIV is closer. */ 00893 if (diff > desireFreq - ret_freq) 00894 { 00895 diff = desireFreq - ret_freq; 00896 ret_prdiv = prdiv_cur; 00897 ret_vdiv = vdiv_cur; 00898 } 00899 } 00900 vdiv_cur++; 00901 if (vdiv_cur <= (FSL_FEATURE_MCG_PLL_VDIV_BASE + 31U)) 00902 { 00903 ret_freq += ref_div; 00904 /* New PRDIV/VDIV is closer. */ 00905 if (diff > ret_freq - desireFreq) 00906 { 00907 diff = ret_freq - desireFreq; 00908 ret_prdiv = prdiv_cur; 00909 ret_vdiv = vdiv_cur; 00910 } 00911 } 00912 } 00913 00914 if (0xFFFFFFFFU != diff) 00915 { 00916 /* PRDIV/VDIV found. */ 00917 *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; 00918 *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; 00919 ret_freq = (refFreq / ret_prdiv) * ret_vdiv; 00920 return ret_freq / 2U; 00921 } 00922 else 00923 { 00924 /* No proper PRDIV/VDIV found. */ 00925 return 0U; 00926 } 00927 } 00928 00929 void CLOCK_EnablePll0(mcg_pll_config_t const *config) 00930 { 00931 assert(config); 00932 00933 uint8_t mcg_c5 = 0U; 00934 00935 mcg_c5 |= MCG_C5_PRDIV0(config->prdiv ); 00936 MCG->C5 = mcg_c5; /* Disable the PLL first. */ 00937 00938 MCG->C6 = (MCG->C6 & ~MCG_C6_VDIV0_MASK) | MCG_C6_VDIV0(config->vdiv ); 00939 00940 /* Set enable mode. */ 00941 MCG->C5 |= ((uint32_t)kMCG_PllEnableIndependent | (uint32_t)config->enableMode ); 00942 00943 /* Wait for PLL lock. */ 00944 while (!(MCG->S & MCG_S_LOCK0_MASK)) 00945 { 00946 } 00947 } 00948 00949 void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) 00950 { 00951 /* Clear the previous flag, MCG_SC[LOCS0]. */ 00952 MCG->SC &= ~MCG_SC_ATMF_MASK; 00953 00954 if (kMCG_MonitorNone == mode) 00955 { 00956 MCG->C6 &= ~MCG_C6_CME0_MASK; 00957 } 00958 else 00959 { 00960 if (kMCG_MonitorInt == mode) 00961 { 00962 MCG->C2 &= ~MCG_C2_LOCRE0_MASK; 00963 } 00964 else 00965 { 00966 MCG->C2 |= MCG_C2_LOCRE0_MASK; 00967 } 00968 MCG->C6 |= MCG_C6_CME0_MASK; 00969 } 00970 } 00971 00972 void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) 00973 { 00974 uint8_t mcg_c8 = MCG->C8; 00975 00976 mcg_c8 &= ~(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); 00977 00978 if (kMCG_MonitorNone != mode) 00979 { 00980 if (kMCG_MonitorReset == mode) 00981 { 00982 mcg_c8 |= MCG_C8_LOCRE1_MASK; 00983 } 00984 mcg_c8 |= MCG_C8_CME1_MASK; 00985 } 00986 MCG->C8 = mcg_c8; 00987 } 00988 00989 void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) 00990 { 00991 uint8_t mcg_c8; 00992 00993 /* Clear previous flag. */ 00994 MCG->S = MCG_S_LOLS0_MASK; 00995 00996 if (kMCG_MonitorNone == mode) 00997 { 00998 MCG->C6 &= ~MCG_C6_LOLIE0_MASK; 00999 } 01000 else 01001 { 01002 mcg_c8 = MCG->C8; 01003 01004 mcg_c8 &= ~MCG_C8_LOCS1_MASK; 01005 01006 if (kMCG_MonitorInt == mode) 01007 { 01008 mcg_c8 &= ~MCG_C8_LOLRE_MASK; 01009 } 01010 else 01011 { 01012 mcg_c8 |= MCG_C8_LOLRE_MASK; 01013 } 01014 MCG->C8 = mcg_c8; 01015 MCG->C6 |= MCG_C6_LOLIE0_MASK; 01016 } 01017 } 01018 01019 void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode) 01020 { 01021 uint8_t mcg_c9 = MCG->C9; 01022 01023 mcg_c9 &= ~(MCG_C9_PLL_LOCRE_MASK | MCG_C9_PLL_CME_MASK); 01024 01025 if (kMCG_MonitorNone != mode) 01026 { 01027 if (kMCG_MonitorReset == mode) 01028 { 01029 mcg_c9 |= MCG_C9_PLL_LOCRE_MASK; 01030 } 01031 mcg_c9 |= MCG_C9_PLL_CME_MASK; 01032 } 01033 MCG->C9 = mcg_c9; 01034 } 01035 01036 uint32_t CLOCK_GetStatusFlags(void) 01037 { 01038 uint32_t ret = 0U; 01039 uint8_t mcg_s = MCG->S; 01040 01041 if (MCG->SC & MCG_SC_LOCS0_MASK) 01042 { 01043 ret |= kMCG_Osc0LostFlag ; 01044 } 01045 if (mcg_s & MCG_S_OSCINIT0_MASK) 01046 { 01047 ret |= kMCG_Osc0InitFlag ; 01048 } 01049 if (MCG->C8 & MCG_C8_LOCS1_MASK) 01050 { 01051 ret |= kMCG_RtcOscLostFlag ; 01052 } 01053 if (mcg_s & MCG_S_LOLS0_MASK) 01054 { 01055 ret |= kMCG_Pll0LostFlag ; 01056 } 01057 if (mcg_s & MCG_S_LOCK0_MASK) 01058 { 01059 ret |= kMCG_Pll0LockFlag ; 01060 } 01061 if (MCG->C9 & MCG_C9_EXT_PLL_LOCS_MASK) 01062 { 01063 ret |= kMCG_ExtPllLostFlag ; 01064 } 01065 return ret; 01066 } 01067 01068 void CLOCK_ClearStatusFlags(uint32_t mask) 01069 { 01070 uint8_t reg; 01071 01072 if (mask & kMCG_Osc0LostFlag ) 01073 { 01074 MCG->SC &= ~MCG_SC_ATMF_MASK; 01075 } 01076 if (mask & kMCG_RtcOscLostFlag ) 01077 { 01078 reg = MCG->C8; 01079 MCG->C8 = reg; 01080 } 01081 if (mask & kMCG_Pll0LostFlag ) 01082 { 01083 MCG->S = MCG_S_LOLS0_MASK; 01084 } 01085 if (mask & kMCG_ExtPllLostFlag ) 01086 { 01087 reg = MCG->C9; 01088 MCG->C9 = reg; 01089 } 01090 } 01091 01092 void CLOCK_InitOsc0(osc_config_t const *config) 01093 { 01094 uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq ); 01095 01096 OSC_SetCapLoad(OSC0, config->capLoad ); 01097 OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig ); 01098 01099 MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode ); 01100 01101 if ((kOSC_ModeExt != config->workMode ) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) 01102 { 01103 /* Wait for stable. */ 01104 while (!(MCG->S & MCG_S_OSCINIT0_MASK)) 01105 { 01106 } 01107 } 01108 } 01109 01110 void CLOCK_DeinitOsc0(void) 01111 { 01112 OSC0->CR = 0U; 01113 MCG->C2 &= ~OSC_MODE_MASK; 01114 } 01115 01116 status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) 01117 { 01118 uint32_t multi; /* extFreq / desireFreq */ 01119 uint32_t actv; /* Auto trim value. */ 01120 uint8_t mcg_sc; 01121 01122 static const uint32_t trimRange[2][2] = { 01123 /* Min Max */ 01124 {TRIM_SIRC_MIN, TRIM_SIRC_MAX}, /* Slow IRC. */ 01125 {TRIM_FIRC_MIN, TRIM_FIRC_MAX} /* Fast IRC. */ 01126 }; 01127 01128 if ((extFreq > TRIM_REF_CLK_MAX) || (extFreq < TRIM_REF_CLK_MIN)) 01129 { 01130 return kStatus_MCG_AtmBusClockInvalid ; 01131 } 01132 01133 /* Check desired frequency range. */ 01134 if ((desireFreq < trimRange[atms][0]) || (desireFreq > trimRange[atms][1])) 01135 { 01136 return kStatus_MCG_AtmDesiredFreqInvalid ; 01137 } 01138 01139 /* 01140 Make sure internal reference clock is not used to generate bus clock. 01141 Here only need to check (MCG_S_IREFST == 1). 01142 */ 01143 if (MCG_S_IREFST(kMCG_FllSrcInternal ) == (MCG->S & MCG_S_IREFST_MASK)) 01144 { 01145 return kStatus_MCG_AtmIrcUsed ; 01146 } 01147 01148 multi = extFreq / desireFreq; 01149 actv = multi * 21U; 01150 01151 if (kMCG_AtmSel4m == atms) 01152 { 01153 actv *= 128U; 01154 } 01155 01156 /* Now begin to start trim. */ 01157 MCG->ATCVL = (uint8_t)actv; 01158 MCG->ATCVH = (uint8_t)(actv >> 8U); 01159 01160 mcg_sc = MCG->SC; 01161 mcg_sc &= ~(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); 01162 mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms)); 01163 MCG->SC = (mcg_sc | MCG_SC_ATME_MASK); 01164 01165 /* Wait for finished. */ 01166 while (MCG->SC & MCG_SC_ATME_MASK) 01167 { 01168 } 01169 01170 /* Error occurs? */ 01171 if (MCG->SC & MCG_SC_ATMF_MASK) 01172 { 01173 /* Clear the failed flag. */ 01174 MCG->SC = mcg_sc; 01175 return kStatus_MCG_AtmHardwareFail ; 01176 } 01177 01178 *actualFreq = extFreq / multi; 01179 01180 if (kMCG_AtmSel4m == atms) 01181 { 01182 s_fastIrcFreq = *actualFreq; 01183 } 01184 else 01185 { 01186 s_slowIrcFreq = *actualFreq; 01187 } 01188 01189 return kStatus_Success; 01190 } 01191 01192 mcg_mode_t CLOCK_GetMode(void) 01193 { 01194 mcg_mode_t mode = kMCG_ModeError ; 01195 uint32_t clkst = MCG_S_CLKST_VAL; 01196 uint32_t irefst = MCG_S_IREFST_VAL; 01197 uint32_t lp = MCG_C2_LP_VAL; 01198 uint32_t pllst = MCG_S_PLLST_VAL; 01199 01200 /*------------------------------------------------------------------ 01201 Mode and Registers 01202 ____________________________________________________________________ 01203 01204 Mode | CLKST | IREFST | PLLST | LP 01205 ____________________________________________________________________ 01206 01207 FEI | 00(FLL) | 1(INT) | 0(FLL) | X 01208 ____________________________________________________________________ 01209 01210 FEE | 00(FLL) | 0(EXT) | 0(FLL) | X 01211 ____________________________________________________________________ 01212 01213 FBE | 10(EXT) | 0(EXT) | 0(FLL) | 0(NORMAL) 01214 ____________________________________________________________________ 01215 01216 FBI | 01(INT) | 1(INT) | 0(FLL) | 0(NORMAL) 01217 ____________________________________________________________________ 01218 01219 BLPI | 01(INT) | 1(INT) | 0(FLL) | 1(LOW POWER) 01220 ____________________________________________________________________ 01221 01222 BLPE | 10(EXT) | 0(EXT) | X | 1(LOW POWER) 01223 ____________________________________________________________________ 01224 01225 PEE | 11(PLL) | 0(EXT) | 1(PLL) | X 01226 ____________________________________________________________________ 01227 01228 PBE | 10(EXT) | 0(EXT) | 1(PLL) | O(NORMAL) 01229 ____________________________________________________________________ 01230 01231 PBI | 01(INT) | 1(INT) | 1(PLL) | 0(NORMAL) 01232 ____________________________________________________________________ 01233 01234 PEI | 11(PLL) | 1(INT) | 1(PLL) | X 01235 ____________________________________________________________________ 01236 01237 ----------------------------------------------------------------------*/ 01238 01239 switch (clkst) 01240 { 01241 case kMCG_ClkOutStatFll: 01242 if (kMCG_FllSrcExternal == irefst) 01243 { 01244 mode = kMCG_ModeFEE ; 01245 } 01246 else 01247 { 01248 mode = kMCG_ModeFEI ; 01249 } 01250 break; 01251 case kMCG_ClkOutStatInt: 01252 if (lp) 01253 { 01254 mode = kMCG_ModeBLPI ; 01255 } 01256 else 01257 { 01258 { 01259 mode = kMCG_ModeFBI ; 01260 } 01261 } 01262 break; 01263 case kMCG_ClkOutStatExt: 01264 if (lp) 01265 { 01266 mode = kMCG_ModeBLPE ; 01267 } 01268 else 01269 { 01270 if (kMCG_PllstPll == pllst) 01271 { 01272 mode = kMCG_ModePBE ; 01273 } 01274 else 01275 { 01276 mode = kMCG_ModeFBE ; 01277 } 01278 } 01279 break; 01280 case kMCG_ClkOutStatPll: 01281 { 01282 mode = kMCG_ModePEE ; 01283 } 01284 break; 01285 default: 01286 break; 01287 } 01288 01289 return mode; 01290 } 01291 01292 status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) 01293 { 01294 uint8_t mcg_c4; 01295 bool change_drs = false; 01296 01297 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01298 mcg_mode_t mode = CLOCK_GetMode(); 01299 if (!((kMCG_ModeFEI == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEE == mode))) 01300 { 01301 return kStatus_MCG_ModeUnreachable ; 01302 } 01303 #endif 01304 mcg_c4 = MCG->C4; 01305 01306 /* 01307 Errata: ERR007993 01308 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before 01309 reference clock source changes, then reset to previous value after 01310 reference clock changes. 01311 */ 01312 if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) 01313 { 01314 change_drs = true; 01315 /* Change the LSB of DRST_DRS. */ 01316 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT); 01317 } 01318 01319 /* Set CLKS and IREFS. */ 01320 MCG->C1 = 01321 ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | (MCG_C1_CLKS(kMCG_ClkOutSrcOut ) /* CLKS = 0 */ 01322 | MCG_C1_IREFS(kMCG_FllSrcInternal )); /* IREFS = 1 */ 01323 01324 /* Wait and check status. */ 01325 while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) 01326 { 01327 } 01328 01329 /* Errata: ERR007993 */ 01330 if (change_drs) 01331 { 01332 MCG->C4 = mcg_c4; 01333 } 01334 01335 /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ 01336 MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); 01337 01338 /* Check MCG_S[CLKST] */ 01339 while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) 01340 { 01341 } 01342 01343 /* Wait for FLL stable time. */ 01344 if (fllStableDelay) 01345 { 01346 fllStableDelay(); 01347 } 01348 01349 return kStatus_Success; 01350 } 01351 01352 status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) 01353 { 01354 uint8_t mcg_c4; 01355 bool change_drs = false; 01356 01357 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01358 mcg_mode_t mode = CLOCK_GetMode(); 01359 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode))) 01360 { 01361 return kStatus_MCG_ModeUnreachable ; 01362 } 01363 #endif 01364 mcg_c4 = MCG->C4; 01365 01366 /* 01367 Errata: ERR007993 01368 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before 01369 reference clock source changes, then reset to previous value after 01370 reference clock changes. 01371 */ 01372 if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) 01373 { 01374 change_drs = true; 01375 /* Change the LSB of DRST_DRS. */ 01376 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT); 01377 } 01378 01379 /* Set CLKS and IREFS. */ 01380 MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | 01381 (MCG_C1_CLKS(kMCG_ClkOutSrcOut ) /* CLKS = 0 */ 01382 | MCG_C1_FRDIV(frdiv) /* FRDIV */ 01383 | MCG_C1_IREFS(kMCG_FllSrcExternal ))); /* IREFS = 0 */ 01384 01385 /* Wait and check status. */ 01386 while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) 01387 { 01388 } 01389 01390 /* Errata: ERR007993 */ 01391 if (change_drs) 01392 { 01393 MCG->C4 = mcg_c4; 01394 } 01395 01396 /* Set DRS and DMX32. */ 01397 mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); 01398 MCG->C4 = mcg_c4; 01399 01400 /* Wait for DRST_DRS update. */ 01401 while (MCG->C4 != mcg_c4) 01402 { 01403 } 01404 01405 /* Check MCG_S[CLKST] */ 01406 while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) 01407 { 01408 } 01409 01410 /* Wait for FLL stable time. */ 01411 if (fllStableDelay) 01412 { 01413 fllStableDelay(); 01414 } 01415 01416 return kStatus_Success; 01417 } 01418 01419 status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) 01420 { 01421 uint8_t mcg_c4; 01422 bool change_drs = false; 01423 01424 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01425 mcg_mode_t mode = CLOCK_GetMode(); 01426 01427 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode) || 01428 (kMCG_ModeBLPI == mode))) 01429 01430 { 01431 return kStatus_MCG_ModeUnreachable ; 01432 } 01433 #endif 01434 01435 mcg_c4 = MCG->C4; 01436 01437 MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ 01438 01439 /* 01440 Errata: ERR007993 01441 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before 01442 reference clock source changes, then reset to previous value after 01443 reference clock changes. 01444 */ 01445 if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) 01446 { 01447 change_drs = true; 01448 /* Change the LSB of DRST_DRS. */ 01449 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT); 01450 } 01451 01452 /* Set CLKS and IREFS. */ 01453 MCG->C1 = 01454 ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcInternal ) /* CLKS = 1 */ 01455 | MCG_C1_IREFS(kMCG_FllSrcInternal ))); /* IREFS = 1 */ 01456 01457 /* Wait and check status. */ 01458 while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) 01459 { 01460 } 01461 01462 /* Errata: ERR007993 */ 01463 if (change_drs) 01464 { 01465 MCG->C4 = mcg_c4; 01466 } 01467 01468 while (kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) 01469 { 01470 } 01471 01472 MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); 01473 01474 /* Wait for FLL stable time. */ 01475 if (fllStableDelay) 01476 { 01477 fllStableDelay(); 01478 } 01479 01480 return kStatus_Success; 01481 } 01482 01483 status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) 01484 { 01485 uint8_t mcg_c4; 01486 bool change_drs = false; 01487 01488 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01489 mcg_mode_t mode = CLOCK_GetMode(); 01490 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode) || 01491 (kMCG_ModePBE == mode) || (kMCG_ModeBLPE == mode))) 01492 { 01493 return kStatus_MCG_ModeUnreachable ; 01494 } 01495 #endif 01496 01497 /* Change to FLL mode. */ 01498 MCG->C6 &= ~MCG_C6_PLLS_MASK; 01499 while (MCG->S & MCG_S_PLLST_MASK) 01500 { 01501 } 01502 01503 /* Set LP bit to enable the FLL */ 01504 MCG->C2 &= ~MCG_C2_LP_MASK; 01505 01506 mcg_c4 = MCG->C4; 01507 01508 /* 01509 Errata: ERR007993 01510 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before 01511 reference clock source changes, then reset to previous value after 01512 reference clock changes. 01513 */ 01514 if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) 01515 { 01516 change_drs = true; 01517 /* Change the LSB of DRST_DRS. */ 01518 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT); 01519 } 01520 01521 /* Set CLKS and IREFS. */ 01522 MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | 01523 (MCG_C1_CLKS(kMCG_ClkOutSrcExternal ) /* CLKS = 2 */ 01524 | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ 01525 | MCG_C1_IREFS(kMCG_FllSrcExternal ))); /* IREFS = 0 */ 01526 01527 /* Wait for Reference clock Status bit to clear */ 01528 while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) 01529 { 01530 } 01531 01532 /* Errata: ERR007993 */ 01533 if (change_drs) 01534 { 01535 MCG->C4 = mcg_c4; 01536 } 01537 01538 /* Set DRST_DRS and DMX32. */ 01539 mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); 01540 01541 /* Wait for clock status bits to show clock source is ext ref clk */ 01542 while (kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) 01543 { 01544 } 01545 01546 /* Wait for fll stable time. */ 01547 if (fllStableDelay) 01548 { 01549 fllStableDelay(); 01550 } 01551 01552 return kStatus_Success; 01553 } 01554 01555 status_t CLOCK_SetBlpiMode(void) 01556 { 01557 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01558 if (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) 01559 { 01560 return kStatus_MCG_ModeUnreachable ; 01561 } 01562 #endif /* MCG_CONFIG_CHECK_PARAM */ 01563 01564 /* Set LP. */ 01565 MCG->C2 |= MCG_C2_LP_MASK; 01566 01567 return kStatus_Success; 01568 } 01569 01570 status_t CLOCK_SetBlpeMode(void) 01571 { 01572 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01573 if (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) 01574 { 01575 return kStatus_MCG_ModeUnreachable ; 01576 } 01577 #endif 01578 01579 /* Set LP bit to enter BLPE mode. */ 01580 MCG->C2 |= MCG_C2_LP_MASK; 01581 01582 return kStatus_Success; 01583 } 01584 01585 status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) 01586 { 01587 /* 01588 This function is designed to change MCG to PBE mode from PEE/BLPE/FBE, 01589 but with this workflow, the source mode could be all modes except PEI/PBI. 01590 */ 01591 MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ 01592 01593 /* Change to use external clock first. */ 01594 MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal )); 01595 01596 /* Wait for CLKST clock status bits to show clock source is ext ref clk */ 01597 while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != 01598 (MCG_S_IREFST(kMCG_FllSrcExternal ) | MCG_S_CLKST(kMCG_ClkOutStatExt))) 01599 { 01600 } 01601 01602 /* Disable PLL first, then configure PLL. */ 01603 MCG->C6 &= ~MCG_C6_PLLS_MASK; 01604 while (MCG->S & MCG_S_PLLST_MASK) 01605 { 01606 } 01607 01608 /* Configure the PLL. */ 01609 if (kMCG_PllClkSelPll0 == pllcs) 01610 { 01611 CLOCK_EnablePll0(config); 01612 } 01613 01614 MCG->C11 = ((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs); 01615 while (pllcs != MCG_S2_PLLCST_VAL) 01616 { 01617 } 01618 01619 /* Change to PLL mode. */ 01620 MCG->C6 |= MCG_C6_PLLS_MASK; 01621 while (!(MCG->S & MCG_S_PLLST_MASK)) 01622 { 01623 } 01624 01625 return kStatus_Success; 01626 } 01627 01628 status_t CLOCK_SetPeeMode(void) 01629 { 01630 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01631 mcg_mode_t mode = CLOCK_GetMode(); 01632 if (kMCG_ModePBE != mode) 01633 { 01634 return kStatus_MCG_ModeUnreachable ; 01635 } 01636 #endif 01637 01638 /* Change to use PLL/FLL output clock first. */ 01639 MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut ); 01640 01641 /* Wait for clock status bits to update */ 01642 while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) 01643 { 01644 } 01645 01646 return kStatus_Success; 01647 } 01648 01649 status_t CLOCK_ExternalModeToFbeModeQuick(void) 01650 { 01651 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01652 if (MCG->S & MCG_S_IREFST_MASK) 01653 { 01654 return kStatus_MCG_ModeInvalid ; 01655 } 01656 #endif /* MCG_CONFIG_CHECK_PARAM */ 01657 01658 /* Disable low power */ 01659 MCG->C2 &= ~MCG_C2_LP_MASK; 01660 01661 MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal )); 01662 while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) 01663 { 01664 } 01665 01666 /* Disable PLL. */ 01667 MCG->C6 &= ~MCG_C6_PLLS_MASK; 01668 while (MCG->S & MCG_S_PLLST_MASK) 01669 { 01670 } 01671 01672 return kStatus_Success; 01673 } 01674 01675 status_t CLOCK_InternalModeToFbiModeQuick(void) 01676 { 01677 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) 01678 if (!(MCG->S & MCG_S_IREFST_MASK)) 01679 { 01680 return kStatus_MCG_ModeInvalid ; 01681 } 01682 #endif 01683 01684 /* Disable low power */ 01685 MCG->C2 &= ~MCG_C2_LP_MASK; 01686 01687 MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal )); 01688 while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) 01689 { 01690 } 01691 01692 return kStatus_Success; 01693 } 01694 01695 status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) 01696 { 01697 return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); 01698 } 01699 01700 status_t CLOCK_BootToFeeMode( 01701 mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) 01702 { 01703 CLOCK_SetExternalRefClkConfig(oscsel); 01704 01705 return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); 01706 } 01707 01708 status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) 01709 { 01710 /* If reset mode is FEI mode, set MCGIRCLK and always success. */ 01711 CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); 01712 01713 /* If reset mode is not BLPI, first enter FBI mode. */ 01714 MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal ); 01715 while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) 01716 { 01717 } 01718 01719 /* Enter BLPI mode. */ 01720 MCG->C2 |= MCG_C2_LP_MASK; 01721 01722 return kStatus_Success; 01723 } 01724 01725 status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) 01726 { 01727 CLOCK_SetExternalRefClkConfig(oscsel); 01728 01729 /* Set to FBE mode. */ 01730 MCG->C1 = 01731 ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal ) /* CLKS = 2 */ 01732 | MCG_C1_IREFS(kMCG_FllSrcExternal ))); /* IREFS = 0 */ 01733 01734 /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ 01735 while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != 01736 (MCG_S_IREFST(kMCG_FllSrcExternal ) | MCG_S_CLKST(kMCG_ClkOutStatExt))) 01737 { 01738 } 01739 01740 /* In FBE now, start to enter BLPE. */ 01741 MCG->C2 |= MCG_C2_LP_MASK; 01742 01743 return kStatus_Success; 01744 } 01745 01746 status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) 01747 { 01748 assert(config); 01749 01750 CLOCK_SetExternalRefClkConfig(oscsel); 01751 01752 CLOCK_SetPbeMode(pllcs, config); 01753 01754 /* Change to use PLL output clock. */ 01755 MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut ); 01756 while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) 01757 { 01758 } 01759 01760 return kStatus_Success; 01761 } 01762 01763 /* 01764 The transaction matrix. It defines the path for mode switch, the row is for 01765 current mode and the column is target mode. 01766 For example, switch from FEI to PEE: 01767 1. Current mode FEI, next mode is mcgModeMatrix[FEI][PEE] = FBE, so swith to FBE. 01768 2. Current mode FBE, next mode is mcgModeMatrix[FBE][PEE] = PBE, so swith to PBE. 01769 3. Current mode PBE, next mode is mcgModeMatrix[PBE][PEE] = PEE, so swith to PEE. 01770 Thus the MCG mode has changed from FEI to PEE. 01771 */ 01772 static const mcg_mode_t mcgModeMatrix[8][8] = { 01773 {kMCG_ModeFEI , kMCG_ModeFBI , kMCG_ModeFBI , kMCG_ModeFEE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , 01774 kMCG_ModeFBE}, /* FEI */ 01775 {kMCG_ModeFEI , kMCG_ModeFBI , kMCG_ModeBLPI , kMCG_ModeFEE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , 01776 kMCG_ModeFBE}, /* FBI */ 01777 {kMCG_ModeFBI , kMCG_ModeFBI , kMCG_ModeBLPI , kMCG_ModeFBI , kMCG_ModeFBI , kMCG_ModeFBI , kMCG_ModeFBI , 01778 kMCG_ModeFBI}, /* BLPI */ 01779 {kMCG_ModeFEI , kMCG_ModeFBI , kMCG_ModeFBI , kMCG_ModeFEE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , 01780 kMCG_ModeFBE}, /* FEE */ 01781 {kMCG_ModeFEI , kMCG_ModeFBI , kMCG_ModeFBI , kMCG_ModeFEE , kMCG_ModeFBE , kMCG_ModeBLPE , kMCG_ModePBE , 01782 kMCG_ModePBE}, /* FBE */ 01783 {kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeBLPE , kMCG_ModePBE , 01784 kMCG_ModePBE}, /* BLPE */ 01785 {kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeFBE , kMCG_ModeBLPE , kMCG_ModePBE , 01786 kMCG_ModePEE }, /* PBE */ 01787 {kMCG_ModePBE , kMCG_ModePBE , kMCG_ModePBE , kMCG_ModePBE , kMCG_ModePBE , kMCG_ModePBE , kMCG_ModePBE , 01788 kMCG_ModePBE} /* PEE */ 01789 /* FEI FBI BLPI FEE FBE BLPE PBE PEE */ 01790 }; 01791 01792 status_t CLOCK_SetMcgConfig(const mcg_config_t *config) 01793 { 01794 mcg_mode_t next_mode; 01795 status_t status = kStatus_Success; 01796 01797 mcg_pll_clk_select_t pllcs = config->pllcs ; 01798 01799 /* If need to change external clock, MCG_C7[OSCSEL]. */ 01800 if (MCG_C7_OSCSEL_VAL != config->oscsel ) 01801 { 01802 /* If external clock is in use, change to FEI first. */ 01803 if (!(MCG->S & MCG_S_IRCST_MASK)) 01804 { 01805 CLOCK_ExternalModeToFbeModeQuick(); 01806 CLOCK_SetFeiMode(config->dmx32 , config->drs , (void (*)(void))0); 01807 } 01808 01809 CLOCK_SetExternalRefClkConfig(config->oscsel ); 01810 } 01811 01812 /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */ 01813 if (MCG_S_CLKST_VAL == kMCG_ClkOutStatInt) 01814 { 01815 MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ 01816 01817 { 01818 CLOCK_SetFeiMode(config->dmx32 , config->drs , CLOCK_FllStableDelay); 01819 } 01820 } 01821 01822 /* Configure MCGIRCLK. */ 01823 CLOCK_SetInternalRefClkConfig(config->irclkEnableMode , config->ircs , config->fcrdiv ); 01824 01825 next_mode = CLOCK_GetMode(); 01826 01827 do 01828 { 01829 next_mode = mcgModeMatrix[next_mode][config->mcgMode ]; 01830 01831 switch (next_mode) 01832 { 01833 case kMCG_ModeFEI : 01834 status = CLOCK_SetFeiMode(config->dmx32 , config->drs , CLOCK_FllStableDelay); 01835 break; 01836 case kMCG_ModeFEE : 01837 status = CLOCK_SetFeeMode(config->frdiv , config->dmx32 , config->drs , CLOCK_FllStableDelay); 01838 break; 01839 case kMCG_ModeFBI : 01840 status = CLOCK_SetFbiMode(config->dmx32 , config->drs , (void (*)(void))0); 01841 break; 01842 case kMCG_ModeFBE : 01843 status = CLOCK_SetFbeMode(config->frdiv , config->dmx32 , config->drs , (void (*)(void))0); 01844 break; 01845 case kMCG_ModeBLPI : 01846 status = CLOCK_SetBlpiMode(); 01847 break; 01848 case kMCG_ModeBLPE : 01849 status = CLOCK_SetBlpeMode(); 01850 break; 01851 case kMCG_ModePBE : 01852 /* If target mode is not PBE or PEE, then only need to set CLKS = EXT here. */ 01853 if ((kMCG_ModePEE == config->mcgMode ) || (kMCG_ModePBE == config->mcgMode )) 01854 { 01855 if (kMCG_PllClkSelPll0 == pllcs) 01856 { 01857 status = CLOCK_SetPbeMode(pllcs, &config->pll0Config ); 01858 } 01859 else if (kMCG_PllClkSelExtPll == pllcs) 01860 { 01861 status = CLOCK_SetPbeMode(pllcs, NULL); 01862 } 01863 else 01864 { 01865 } 01866 } 01867 else 01868 { 01869 MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal )); 01870 while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) 01871 { 01872 } 01873 } 01874 break; 01875 case kMCG_ModePEE : 01876 status = CLOCK_SetPeeMode(); 01877 break; 01878 default: 01879 break; 01880 } 01881 if (kStatus_Success != status) 01882 { 01883 return status; 01884 } 01885 } while (next_mode != config->mcgMode ); 01886 01887 if (config->pll0Config .enableMode & kMCG_PllEnableIndependent ) 01888 { 01889 CLOCK_EnablePll0(&config->pll0Config ); 01890 } 01891 else 01892 { 01893 MCG->C5 &= ~(uint32_t)kMCG_PllEnableIndependent ; 01894 } 01895 return kStatus_Success; 01896 }
Generated on Tue Jul 12 2022 15:37:17 by
