From 24efeb84fe437aadf97cad58c72db83afa6e10cc Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Fri, 28 Jun 2019 09:55:50 -0500 Subject: [PATCH] Kinetis MCUXpresso: Update the clock drivers Updated driver includes 1. Bug fixes 2. Formatting updates. 3. Fix for warnings 4. Better code commenting Signed-off-by: Mahesh Mahadevan --- .../TARGET_K66F/drivers/fsl_clock.c | 1069 +++++++++++++---- .../TARGET_K66F/drivers/fsl_clock.h | 294 ++--- .../TARGET_K82F/drivers/fsl_clock.c | 1031 ++++++++++++---- .../TARGET_K82F/drivers/fsl_clock.h | 287 +++-- .../TARGET_KL27Z/drivers/fsl_clock.c | 169 ++- .../TARGET_KL27Z/drivers/fsl_clock.h | 260 ++-- .../TARGET_KL43Z/drivers/fsl_clock.c | 169 ++- .../TARGET_KL43Z/drivers/fsl_clock.h | 264 ++-- .../TARGET_KL82Z/drivers/fsl_clock.c | 1014 ++++++++++++---- .../TARGET_KL82Z/drivers/fsl_clock.h | 294 +++-- .../TARGET_KW24D/drivers/fsl_clock.c | 1021 ++++++++++++---- .../TARGET_KW24D/drivers/fsl_clock.h | 273 +++-- .../TARGET_KW41Z/drivers/fsl_clock.c | 829 +++++++++---- .../TARGET_KW41Z/drivers/fsl_clock.h | 238 ++-- .../TARGET_MCU_K22F/drivers/fsl_clock.c | 1053 ++++++++++++---- .../TARGET_MCU_K22F/drivers/fsl_clock.h | 735 +++++++----- .../TARGET_MCU_K24F/drivers/fsl_clock.c | 968 +++++++++++---- .../TARGET_MCU_K24F/drivers/fsl_clock.h | 249 ++-- .../TARGET_MCU_K64F/drivers/fsl_clock.c | 604 +++++++++- .../TARGET_MCU_K64F/drivers/fsl_clock.h | 77 +- 20 files changed, 7847 insertions(+), 3051 deletions(-) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c index d75d97ff4f..b832757768 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c @@ -1,32 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright (c) 2016 - 2017 , NXP + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_clock.h" @@ -35,6 +12,11 @@ * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + /* Macro definition remap workaround. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) #define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK @@ -65,11 +47,11 @@ #define TRIM_SIRC_MIN (31250U) #define MCG_S_IRCST_VAL ((MCG->S & MCG_S_IRCST_MASK) >> MCG_S_IRCST_SHIFT) -#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) -#define MCG_S_IREFST_VAL ((MCG->S & MCG_S_IREFST_MASK) >> MCG_S_IREFST_SHIFT) +#define MCG_S_CLKST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_CLKST_MASK) >> (uint32_t)MCG_S_CLKST_SHIFT) +#define MCG_S_IREFST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IREFST_MASK) >> (uint32_t)MCG_S_IREFST_SHIFT) #define MCG_S_PLLST_VAL ((MCG->S & MCG_S_PLLST_MASK) >> MCG_S_PLLST_SHIFT) #define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT) -#define MCG_C2_LP_VAL ((MCG->C2 & MCG_C2_LP_MASK) >> MCG_C2_LP_SHIFT) +#define MCG_C2_LP_VAL (((uint32_t)MCG->C2 & (uint32_t)MCG_C2_LP_MASK) >> (uint32_t)MCG_C2_LP_SHIFT) #define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT) #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) #define MCG_S2_PLLCST_VAL ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT) @@ -123,9 +105,9 @@ static uint32_t s_fastIrcFreq = 4000000U; static uint32_t s_extPllFreq = 0U; /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -194,10 +176,6 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); -/******************************************************************************* - * Code - ******************************************************************************/ - #ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. @@ -205,14 +183,22 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ -void CLOCK_FllStableDelay(void) +static void CLOCK_FllStableDelay(void); +#endif + +/******************************************************************************* + * Code + ******************************************************************************/ + +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN +static void CLOCK_FllStableDelay(void) { /* Should wait at least 1ms. Because in these modes, the core clock is 100MHz at most, so this function could obtain the 1ms delay. */ volatile uint32_t i = 30000U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -220,7 +206,7 @@ void CLOCK_FllStableDelay(void) #else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ /* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this - * file would call the CLOCK_FllStableDelay() regardness how it is defined. + * file would call the CLOCK_FllStableDelay() regardless how it is defined. */ extern void CLOCK_FllStableDelay(void); #endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ @@ -233,12 +219,12 @@ static uint32_t CLOCK_GetMcgExtClkFreq(void) { case 0U: /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ - assert(g_xtal0Freq); + assert(0U != g_xtal0Freq); freq = g_xtal0Freq; break; case 1U: /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ - assert(g_xtal32Freq); + assert(0U != g_xtal32Freq); freq = g_xtal32Freq; break; case 2U: @@ -261,7 +247,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) uint32_t freq = CLOCK_GetMcgExtClkFreq(); - if (!freq) + if (0U == freq) { return freq; } @@ -269,7 +255,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) frdiv = MCG_C1_FRDIV_VAL; freq >>= frdiv; - range = MCG_C2_RANGE_VAL; + range = MCG_C2_RANGE_VAL; oscsel = MCG_C7_OSCSEL_VAL; /* @@ -277,7 +263,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) 1. MCG_C7[OSCSEL] selects IRC48M. 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0. */ - if (((0U != range) && (kMCG_OscselOsc == oscsel)) || (kMCG_OscselIrc == oscsel)) + if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel)) || ((uint8_t)kMCG_OscselIrc == oscsel)) { switch (frdiv) { @@ -308,7 +294,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) { - if (kMCG_IrcSlow == MCG_S_IRCST_VAL) + if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL) { /* Slow internal reference clock selected*/ return s_slowIrcFreq; @@ -323,7 +309,7 @@ static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) static uint32_t CLOCK_GetFllRefClkFreq(void) { /* If use external reference clock. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { return CLOCK_GetFllExtRefClkFreq(); } @@ -360,6 +346,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } +/*! + * brief Get the OSC0 external reference undivided clock frequency (OSC0ERCLK_UNDIV). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -374,6 +365,11 @@ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) } } +/*! + * brief Get the OSC0 external reference divided clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkDivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -388,6 +384,11 @@ uint32_t CLOCK_GetOsc0ErClkDivFreq(void) } } +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -412,6 +413,11 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the output clock frequency selected by SIM[PLLFLLSEL]. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPllFllSelClkFreq(void) { uint32_t freq; @@ -438,36 +444,76 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) return freq * (SIM_CLKDIV3_PLLFLLFRAC_VAL + 1U) / (SIM_CLKDIV3_PLLFLLDIV_VAL + 1U); } +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { return CLOCK_GetOsc0ErClkDivFreq(); } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); } +/*! + * brief Get the flexbus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlexBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1); } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -525,6 +571,13 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; @@ -532,6 +585,13 @@ void CLOCK_SetSimConfig(sim_clock_config_t const *config) CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { /* In current implementation, USBPFDCLK is not used for USB FS. */ @@ -579,10 +639,21 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! brief Enable USB HS clock. + * + * This function only enables the access to USB HS prepheral, upper layer + * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY + * clock to use USB HS. + * + * param src USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused. + * param freq USB HS does not care about the clock source, so this parameter is ignored. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB HS clock. + */ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) { /* Source and freq are not used for USB HS. */ - src = src; + src = src; freq = freq; SIM->SCGC3 |= SIM_SCGC3_USBHS_MASK; @@ -595,12 +666,26 @@ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) return true; } +/*! brief Disable USB HS clock. + * + * Disable USB HS clock, this function should not be called after + * ref CLOCK_DisableUsbhs0PhyPllClock. + */ void CLOCK_DisableUsbhs0Clock(void) { USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* Disable USB clock output from USB PHY PLL */ SIM->SCGC3 &= ~SIM_SCGC3_USBHS_MASK; } +/*! brief Enable USB HS PHY PLL clock. + * + * This function enables the internal 480MHz USB PHY PLL clock. + * + * param src USB HS PHY PLL clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB HS clock. + */ bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq) { volatile uint32_t i; @@ -659,6 +744,10 @@ bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq) return true; } +/*! brief Disable USB HS PHY PLL clock. + * + * This function disables USB HS PHY PLL clock. + */ void CLOCK_DisableUsbhs0PhyPllClock(void) { USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */ @@ -667,6 +756,19 @@ void CLOCK_DisableUsbhs0PhyPllClock(void) SIM->SCGC3 &= ~SIM_SCGC3_USBHSPHY_MASK; } +/*! brief Enable USB HS PFD clock. + * + * This function enables USB HS PFD clock. It should be called after function + * ref CLOCK_EnableUsbhs0PhyPllClock. + * The PFD output clock is selected by the parameter p src. When the p src is + * ref kCLOCK_UsbPfdSrcExt, then the PFD outout is from external crystal + * directly, in this case, the p frac is not used. In other cases, the PFD_FRAC + * output clock frequency is 480MHz*18/frac, the PFD output frequency is based + * on the PFD_FRAC output. + * + * param frac The value set to PFD_FRAC, it must be in the range of 18 to 35. + * param src Source of the USB HS PFD clock (USB1PFDCLK). + */ void CLOCK_EnableUsbhs0PfdClock(uint8_t frac, clock_usb_pfd_src_t src) { assert((frac <= 35U) && (frac >= 18U)); @@ -698,21 +800,34 @@ void CLOCK_EnableUsbhs0PfdClock(uint8_t frac, clock_usb_pfd_src_t src) } } +/*! brief Disable USB HS PFD clock. + * + * This function disables USB HS PFD clock. It should be called before function + * ref CLOCK_DisableUsbhs0PhyPllClock. + */ void CLOCK_DisableUsbhs0PfdClock(void) { USBPHY->ANACTRL |= USBPHY_ANACTRL_PFD_CLKGATE_MASK; s_extPllFreq = 0U; } +/*! + * brief Gets the MCG output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG output clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; - uint32_t clkst = MCG_S_CLKST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; uint32_t pllcst = MCG_S2_PLLCST_VAL; switch (clkst) { - case kMCG_ClkOutStatPll: + case (uint32_t)kMCG_ClkOutStatPll: switch (pllcst) { case kMCG_PllClkSelExtPll: @@ -726,13 +841,13 @@ uint32_t CLOCK_GetOutClkFreq(void) break; } break; - case kMCG_ClkOutStatFll: + case (uint32_t)kMCG_ClkOutStatFll: mcgoutclk = CLOCK_GetFllFreq(); break; - case kMCG_ClkOutStatInt: + case (uint32_t)kMCG_ClkOutStatInt: mcgoutclk = CLOCK_GetInternalRefClkSelectFreq(); break; - case kMCG_ClkOutStatExt: + case (uint32_t)kMCG_ClkOutStatExt: mcgoutclk = CLOCK_GetMcgExtClkFreq(); break; default: @@ -742,6 +857,15 @@ uint32_t CLOCK_GetOutClkFreq(void) return mcgoutclk; } +/*! + * brief Gets the MCG FLL clock (MCGFLLCLK) frequency. + * + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. + * + * return The frequency of MCGFLLCLK. + */ uint32_t CLOCK_GetFllFreq(void) { static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; @@ -750,28 +874,36 @@ uint32_t CLOCK_GetFllFreq(void) uint32_t freq; /* If FLL is not enabled currently, then return 0U. */ - if ((MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) + if (0U != (MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) { return 0U; } /* Get FLL reference clock frequency. */ freq = CLOCK_GetFllRefClkFreq(); - if (!freq) + if (0U == freq) { return freq; } - drs = MCG_C4_DRST_DRS_VAL; + drs = MCG_C4_DRST_DRS_VAL; dmx32 = MCG_C4_DMX32_VAL; return freq * fllFactorTable[drs][dmx32]; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { /* If MCGIRCLK is gated. */ - if (!(MCG->C1 & MCG_C1_IRCLKEN_MASK)) + if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK)) { return 0U; } @@ -779,12 +911,20 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetInternalRefClkSelectFreq(); } +/*! + * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. + * + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGFFCLK. + */ uint32_t CLOCK_GetFixedFreqClkFreq(void) { uint32_t freq = CLOCK_GetFllRefClkFreq(); /* MCGFFCLK must be no more than MCGOUTCLK/8. */ - if ((freq) && (freq <= (CLOCK_GetOutClkFreq() / 8U))) + if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq)) { return freq; } @@ -794,6 +934,14 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void) } } +/*! + * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. + * + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGPLL0CLK. + */ uint32_t CLOCK_GetPll0Freq(void) { uint32_t mcgpll0clk; @@ -819,16 +967,45 @@ uint32_t CLOCK_GetPll0Freq(void) return mcgpll0clk; } +/*! + * brief Gets the MCG external PLL frequency. + * + * This function gets the MCG external PLL frequency in Hz. + * + * return The frequency of the MCG external PLL. + */ uint32_t CLOCK_GetExtPllFreq(void) { return s_extPllFreq; } +/*! + * brief Sets the MCG external PLL frequency. + * + * This function sets the MCG external PLL frequency in Hz. The MCG external PLL + * frequency is passed to the MCG driver using this function. Call this + * function after the external PLL frequency is changed. Otherwise, the APIs, which are used to get + * the frequency, may return an incorrect value. + * + * param The frequency of MCG external PLL. + */ void CLOCK_SetExtPllFreq(uint32_t freq) { s_extPllFreq = freq; } +/*! + * brief Selects the MCG external reference clock. + * + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. + * + * param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. + * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success External reference clock set successfully. + */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) { bool needDelay; @@ -842,7 +1019,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } #endif /* MCG_CONFIG_CHECK_PARAM */ - if (MCG_C7_OSCSEL_VAL != oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel) { /* If change OSCSEL, need to delay, ERR009878. */ needDelay = true; @@ -852,12 +1029,12 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) needDelay = false; } - MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); + MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ i = 1500U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -866,15 +1043,31 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Configures the Internal Reference clock (MCGIRCLK). + * + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. + * + * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * param ircs MCGIRCLK clock source, choose fast or slow. + * param fcrdiv Fast IRC divider setting (\c FCRDIV). + * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success MCGIRCLK configuration finished successfully. + */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) { - uint32_t mcgOutClkState = MCG_S_CLKST_VAL; - mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; - uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; + uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL; + mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; + uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) /* If MCGIRCLK is used as system clock source. */ - if (kMCG_ClkOutStatInt == mcgOutClkState) + if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState) { /* If need to change MCGIRCLK source or driver, return error. */ if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs)) @@ -888,25 +1081,27 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, if (fcrdiv != curFcrdiv) { /* If fast IRC is in use currently, change to slow IRC. */ - if ((kMCG_IrcFast == curIrcs) && ((mcgOutClkState == kMCG_ClkOutStatInt) || (MCG->C1 & MCG_C1_IRCLKEN_MASK))) + if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) && + (kMCG_IrcFast == curIrcs)) { - MCG->C2 = ((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); - while (MCG_S_IRCST_VAL != kMCG_IrcSlow) + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); + while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow) { } } /* Update FCRDIV. */ - MCG->SC = (MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); + MCG->SC = + (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); } /* Set internal reference clock selection. */ - MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)); - MCG->C1 = (MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode; + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs))); + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode); /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */ - if ((mcgOutClkState == kMCG_ClkOutStatInt) || (enableMode & kMCG_IrclkEnable)) + if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable))) { - while (MCG_S_IRCST_VAL != ircs) + while (MCG_S_IRCST_VAL != (uint8_t)ircs) { } } @@ -914,17 +1109,32 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, return kStatus_Success; } +/*! + * brief Calculates the PLL divider setting for a desired output frequency. + * + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function + * returns 0. + * + * param refFreq PLL reference clock frequency. + * param desireFreq Desired PLL output frequency. + * param prdiv PRDIV value to generate desired PLL frequency. + * param vdiv VDIV value to generate desired PLL frequency. + * return Closest frequency match that the PLL was able generate. + */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv) { - uint8_t ret_prdiv; /* PRDIV to return. */ - uint8_t ret_vdiv; /* VDIV to return. */ - uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_cur; /* PRDIV value for iteration. */ - uint8_t vdiv_cur; /* VDIV value for iteration. */ - uint32_t ret_freq = 0U; /* PLL output fequency to return. */ - uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ - uint32_t ref_div; /* Reference frequency after PRDIV. */ + uint8_t ret_prdiv; /* PRDIV to return. */ + uint8_t ret_vdiv; /* VDIV to return. */ + uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_cur; /* PRDIV value for iteration. */ + uint8_t vdiv_cur; /* VDIV value for iteration. */ + uint32_t ret_freq = 0U; /* PLL output frequency to return. */ + uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ + uint32_t ref_div; /* Reference frequency after PRDIV. */ /* Steps: @@ -973,15 +1183,15 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (ret_freq == desireFreq) /* If desire frequency is got. */ { *prdiv = prdiv_cur - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; return ret_freq / 2U; } /* New PRDIV/VDIV is closer. */ if (diff > desireFreq - ret_freq) { - diff = desireFreq - ret_freq; + diff = desireFreq - ret_freq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } vdiv_cur++; @@ -991,9 +1201,9 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, /* New PRDIV/VDIV is closer. */ if (diff > ret_freq - desireFreq) { - diff = ret_freq - desireFreq; + diff = ret_freq - desireFreq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } } @@ -1001,8 +1211,8 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (0xFFFFFFFFU != diff) { /* PRDIV/VDIV found. */ - *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; + *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; ret_freq = (refFreq / ret_prdiv) * ret_vdiv; return ret_freq / 2U; } @@ -1013,6 +1223,17 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, } } +/*! + * brief Enables the PLL0 in FLL mode. + * + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL + * divider values. + * + * param config Pointer to the configuration structure. + */ void CLOCK_EnablePll0(mcg_pll_config_t const *config) { assert(config); @@ -1033,6 +1254,14 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +/*! + * brief Set the PLL selection. + * + * This function sets the PLL selection between PLL0/PLL1/EXTPLL, and waits for + * change finished. + * + * param pllcs The PLL to select. + */ void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs) { MCG->C11 = ((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs); @@ -1041,20 +1270,27 @@ void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs) } } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ - MCG->SC &= ~MCG_SC_ATMF_MASK; + MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK; if (kMCG_MonitorNone == mode) { - MCG->C6 &= ~MCG_C6_CME0_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK; } else { if (kMCG_MonitorInt == mode) { - MCG->C2 &= ~MCG_C2_LOCRE0_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK; } else { @@ -1064,11 +1300,18 @@ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the RTC OSC clock monitor mode. + * + * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8 = MCG->C8; - mcg_c8 &= ~(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); + mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); if (kMCG_MonitorNone != mode) { @@ -1081,6 +1324,13 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) MCG->C8 = mcg_c8; } +/*! + * brief Sets the PLL0 clock monitor mode. + * + * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8; @@ -1111,6 +1361,14 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the external PLL clock monitor mode. + * + * This function ets the external PLL clock monitor mode. See ref mcg_monitor_mode_t + * for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c9 = MCG->C9; @@ -1128,38 +1386,80 @@ void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode) MCG->C9 = mcg_c9; } +/*! + * brief Gets the MCG status flags. + * + * This function gets the MCG clock status flags. All status flags are + * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To + * check a specific flag, compare the return value with the flag. + * + * Example: + * code + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * endcode + * + * return Logical OR value of the ref _mcg_status_flags_t. + */ uint32_t CLOCK_GetStatusFlags(void) { - uint32_t ret = 0U; + uint32_t ret = 0U; uint8_t mcg_s = MCG->S; if (MCG->SC & MCG_SC_LOCS0_MASK) { - ret |= kMCG_Osc0LostFlag; + ret |= (uint32_t)kMCG_Osc0LostFlag; } if (mcg_s & MCG_S_OSCINIT0_MASK) { - ret |= kMCG_Osc0InitFlag; + ret |= (uint32_t)kMCG_Osc0InitFlag; } - if (MCG->C8 & MCG_C8_LOCS1_MASK) + if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK)) { - ret |= kMCG_RtcOscLostFlag; + ret |= (uint32_t)kMCG_RtcOscLostFlag; } if (mcg_s & MCG_S_LOLS0_MASK) { - ret |= kMCG_Pll0LostFlag; + ret |= (uint32_t)kMCG_Pll0LostFlag; } if (mcg_s & MCG_S_LOCK0_MASK) { - ret |= kMCG_Pll0LockFlag; + ret |= (uint32_t)kMCG_Pll0LockFlag; } if (MCG->C9 & MCG_C9_EXT_PLL_LOCS_MASK) { - ret |= kMCG_ExtPllLostFlag; + ret |= (uint32_t)kMCG_ExtPllLostFlag; } return ret; } +/*! + * brief Clears the MCG status flags. + * + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See ref _mcg_status_flags_t. + * + * Example: + * code + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * endcode + * + * param mask The status flags to clear. This is a logical OR of members of the + * enumeration ref _mcg_status_flags_t. + */ void CLOCK_ClearStatusFlags(uint32_t mask) { uint8_t reg; @@ -1168,9 +1468,9 @@ void CLOCK_ClearStatusFlags(uint32_t mask) { MCG->SC &= ~MCG_SC_ATMF_MASK; } - if (mask & kMCG_RtcOscLostFlag) + if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag)) { - reg = MCG->C8; + reg = MCG->C8; MCG->C8 = reg; } if (mask & kMCG_Pll0LostFlag) @@ -1179,35 +1479,65 @@ void CLOCK_ClearStatusFlags(uint32_t mask) } if (mask & kMCG_ExtPllLostFlag) { - reg = MCG->C9; + reg = MCG->C9; MCG->C9 = reg; } } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); OSC_SetCapLoad(OSC0, config->capLoad); - OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); - MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) { /* Wait for stable. */ - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; - MCG->C2 &= ~OSC_MODE_MASK; + MCG->C2 &= ~(uint8_t)OSC_MODE_MASK; } +/*! + * brief Auto trims the internal reference clock. + * + * This function trims the internal reference clock by using the external clock. If + * successful, it returns the kStatus_Success and the frequency after + * trimming is received in the parameter p actualFreq. If an error occurs, + * the error code is returned. + * + * param extFreq External clock frequency, which should be a bus clock. + * param desireFreq Frequency to trim to. + * param actualFreq Actual frequency after trimming. + * param atms Trim fast or slow internal reference clock. + * retval kStatus_Success ATM success. + * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. + * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. + * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. + */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) { uint32_t multi; /* extFreq / desireFreq */ @@ -1241,7 +1571,7 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ } multi = extFreq / desireFreq; - actv = multi * 21U; + actv = multi * 21U; if (kMCG_AtmSel4m == atms) { @@ -1253,17 +1583,17 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ MCG->ATCVH = (uint8_t)(actv >> 8U); mcg_sc = MCG->SC; - mcg_sc &= ~(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); + mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms)); MCG->SC = (mcg_sc | MCG_SC_ATME_MASK); /* Wait for finished. */ - while (MCG->SC & MCG_SC_ATME_MASK) + while (0U != (MCG->SC & MCG_SC_ATME_MASK)) { } /* Error occurs? */ - if (MCG->SC & MCG_SC_ATMF_MASK) + if (0U != (MCG->SC & MCG_SC_ATMF_MASK)) { /* Clear the failed flag. */ MCG->SC = mcg_sc; @@ -1284,13 +1614,20 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ return kStatus_Success; } +/*! + * brief Gets the current MCG mode. + * + * This function checks the MCG registers and determines the current MCG mode. + * + * return Current MCG mode or error code; See ref mcg_mode_t. + */ mcg_mode_t CLOCK_GetMode(void) { mcg_mode_t mode = kMCG_ModeError; - uint32_t clkst = MCG_S_CLKST_VAL; - uint32_t irefst = MCG_S_IREFST_VAL; - uint32_t lp = MCG_C2_LP_VAL; - uint32_t pllst = MCG_S_PLLST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; + uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL; + uint32_t lp = (uint32_t)MCG_C2_LP_VAL; + uint32_t pllst = MCG_S_PLLST_VAL; /*------------------------------------------------------------------ Mode and Registers @@ -1331,59 +1668,77 @@ mcg_mode_t CLOCK_GetMode(void) ----------------------------------------------------------------------*/ - switch (clkst) + if (clkst == (uint32_t)kMCG_ClkOutStatFll) { - case kMCG_ClkOutStatFll: - if (kMCG_FllSrcExternal == irefst) + if ((uint32_t)kMCG_FllSrcExternal == irefst) + { + mode = kMCG_ModeFEE; + } + else + { + mode = kMCG_ModeFEI; + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatInt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPI; + } + else + { { - mode = kMCG_ModeFEE; + mode = kMCG_ModeFBI; + } + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatExt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPE; + } + else + { + if (kMCG_PllstPll == pllst) + { + mode = kMCG_ModePBE; } else { - mode = kMCG_ModeFEI; + mode = kMCG_ModeFBE; } - break; - case kMCG_ClkOutStatInt: - if (lp) - { - mode = kMCG_ModeBLPI; - } - else - { - { - mode = kMCG_ModeFBI; - } - } - break; - case kMCG_ClkOutStatExt: - if (lp) - { - mode = kMCG_ModeBLPE; - } - else - { - if (kMCG_PllstPll == pllst) - { - mode = kMCG_ModePBE; - } - else - { - mode = kMCG_ModeFBE; - } - } - break; - case kMCG_ClkOutStatPll: + } + } + if (clkst == (uint32_t)kMCG_ClkOutStatPll) + { { mode = kMCG_ModePEE; } - break; - default: - break; + } + else + { + /*do nothing*/ } return mode; } +/*! + * brief Sets the MCG to FEI mode. + * + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. + */ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1404,7 +1759,7 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1412,12 +1767,12 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal)); /* IREFS = 1 */ + MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1428,15 +1783,16 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1444,6 +1800,21 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FEE mode. + * + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1464,7 +1835,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1472,24 +1843,24 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ /* If use external crystal as clock source, wait for it stable. */ if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) { - if (MCG->C2 & MCG_C2_EREFS_MASK) + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } /* Wait and check status. */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1500,7 +1871,8 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); MCG->C4 = mcg_c4; /* Wait for DRST_DRS update. */ @@ -1509,12 +1881,12 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1522,6 +1894,22 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to FBI mode. + * + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FBI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1540,7 +1928,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela mcg_c4 = MCG->C4; - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ /* Errata: ERR007993 @@ -1548,7 +1936,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1556,12 +1944,12 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1571,14 +1959,15 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela MCG->C4 = mcg_c4; } - while (kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1586,6 +1975,21 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FBE mode. + * + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FBE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1601,13 +2005,13 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void #endif /* Change to FLL mode. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } /* Set LP bit to enable the FLL */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; mcg_c4 = MCG->C4; @@ -1617,7 +2021,7 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1625,24 +2029,24 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ /* If use external crystal as clock source, wait for it stable. */ if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) { - if (MCG->C2 & MCG_C2_EREFS_MASK) + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } /* Wait for Reference clock Status bit to clear */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1653,15 +2057,16 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRST_DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for clock status bits to show clock source is ext ref clk */ - while (kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) { } /* Wait for fll stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1669,10 +2074,19 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to BLPI mode. + * + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpiMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { return kStatus_MCG_ModeUnreachable; } @@ -1684,10 +2098,19 @@ status_t CLOCK_SetBlpiMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode. + * + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { return kStatus_MCG_ModeUnreachable; } @@ -1699,6 +2122,25 @@ status_t CLOCK_SetBlpeMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to PBE mode. + * + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. + * + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. + * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); + */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { /* If external PLL is used, then the config could be NULL. */ @@ -1750,6 +2192,18 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode. + * + * This function sets the MCG to PEE mode. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. + */ status_t CLOCK_SetPeeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1764,13 +2218,29 @@ status_t CLOCK_SetPeeMode(void) MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); /* Wait for clock status bits to update */ - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } return kStatus_Success; } +/*! + * brief Switches the MCG to FBE mode from the external mode. + * + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: + * + * code + * CLOCK_ExternalModeToFbeModeQuick(); + * CLOCK_SetFeiMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. + */ status_t CLOCK_ExternalModeToFbeModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1781,15 +2251,15 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) #endif /* MCG_CONFIG_CHECK_PARAM */ /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } /* Disable PLL. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } @@ -1797,6 +2267,22 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBI mode from internal modes. + * + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: + * + * code + * CLOCK_InternalModeToFbiModeQuick(); + * CLOCK_SetFeeMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. + */ status_t CLOCK_InternalModeToFbiModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1807,37 +2293,80 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) #endif /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } return kStatus_Success; } +/*! + * brief Sets the MCG to FEI mode during system boot up. + * + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to FEE mode during system bootup. + * + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, OSCSEL. + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to BLPI mode during system boot up. + * + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param fcrdiv Fast IRC divider, FCRDIV. + * param ircs The internal reference clock to select, IRCS. + * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * + * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) { /* If reset mode is FEI mode, set MCGIRCLK and always success. */ - CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); /* If reset mode is not BLPI, first enter FBI mode. */ - MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } @@ -1847,21 +2376,32 @@ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEn return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode during system boot up. + * + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); /* Set to FBE mode. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ /* If use external crystal as clock source, wait for it stable. */ if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) { - if (MCG->C2 & MCG_C2_EREFS_MASK) + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } @@ -1879,6 +2419,19 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode during system boot up. + * + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { /* If external PLL is used, then the config could be NULL. */ @@ -1893,7 +2446,7 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc /* Change to use PLL output clock. */ MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } @@ -1929,6 +2482,20 @@ static const mcg_mode_t mcgModeMatrix[8][8] = { /* FEI FBI BLPI FEE FBE BLPE PBE PEE */ }; +/*! + * brief Sets the MCG to a target mode. + * + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. + * + * param config Pointer to the target MCG mode configuration structure. + * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. + * + * note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. + */ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) { mcg_mode_t next_mode; @@ -1937,30 +2504,30 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) mcg_pll_clk_select_t pllcs = config->pllcs; /* If need to change external clock, MCG_C7[OSCSEL]. */ - if (MCG_C7_OSCSEL_VAL != config->oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel)) { /* If external clock is in use, change to FEI first. */ - if (!(MCG->S & MCG_S_IRCST_MASK)) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { - CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); + (void)CLOCK_ExternalModeToFbeModeQuick(); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL); } - CLOCK_SetExternalRefClkConfig(config->oscsel); + (void)CLOCK_SetExternalRefClkConfig(config->oscsel); } /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */ - if (MCG_S_CLKST_VAL == kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt) { - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } /* Configure MCGIRCLK. */ - CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); next_mode = CLOCK_GetMode(); @@ -1977,10 +2544,10 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL); break; case kMCG_ModeFBE: - status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL); break; case kMCG_ModeBLPI: status = CLOCK_SetBlpiMode(); @@ -2007,7 +2574,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) else { MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } } @@ -2030,7 +2597,55 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) } else { - MCG->C5 &= ~(uint32_t)kMCG_PllEnableIndependent; + MCG->C5 &= ~(uint8_t)kMCG_PllEnableIndependent; } return kStatus_Success; } + +/*! + * brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + uint64_t count = 0U; + uint32_t period = SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 1000000; + + /* Make sure the DWT trace fucntion is enabled. */ + if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR)) + { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + } + + /* CYCCNT not supported on this device. */ + assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk)); + + /* If CYCCENT has already been enabled, read directly, otherwise, need enable it. */ + if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL)) + { + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + /* Calculate the count ticks. */ + count = DWT->CYCCNT; + count += (uint64_t)period * delay_us; + + if (count > 0xFFFFFFFFUL) + { + count -= 0xFFFFFFFFUL; + /* wait for cyccnt overflow. */ + while (count < DWT->CYCCNT) + { + } + } + + /* Wait for cyccnt reach count value. */ + while (count > DWT->CYCCNT) + { + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h index 3f343f5cc9..ebdc3efe4e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h @@ -1,32 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright (c) 2016 - 2017 , NXP + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ @@ -65,7 +42,7 @@ * * When set to 0, peripheral drivers will enable clock in initialize function * and disable clock in de-initialize function. When set to 1, peripheral - * driver will not control the clock, application could contol the clock out of + * driver will not control the clock, application could control the clock out of * the driver. * * @note All drivers share this feature switcher. If it is set to 1, application @@ -81,25 +58,32 @@ /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.2. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*! @brief CLOCK driver version 2.3.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) /*@}*/ +/* Definition for delay API in clock driver, users can redefine it to the real application. */ +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (180000000UL) +#endif + /*! @brief External XTAL0 (OSC0) clock frequency. * * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Set up the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. + * Set up the OSC0 + * CLOCK_InitOsc0(...); + * Set the XTAL0 value to the clock driver. + * CLOCK_SetXtal0Freq(80000000); * @endcode * * This is important for the multicore platforms where only one core needs to set up the * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * @@ -110,7 +94,7 @@ extern uint32_t g_xtal0Freq; * the clock. All other cores need to call the CLOCK_SetXtal32Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; /*! @brief IRC48M clock frequency in Hz. */ #define MCG_INTERNAL_IRC_48M 48000000U @@ -358,12 +342,12 @@ typedef enum _clock_name /*! @brief USB clock source definition. */ typedef enum _clock_usb_src { - kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ + kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ kCLOCK_UsbSrcUsbPfd = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(2U), /*!< Use USBPFDCLK. */ kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(3U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U), /*!< Use USB_CLKIN. */ - kCLOCK_UsbSrcUnused = 0xFFFFFFFFU, /*!< Used when the function does not - care the clock source. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U), /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcUnused = (int)0xFFFFFFFFU, /*!< Used when the function does not + care the clock source. */ } clock_usb_src_t; /*! @brief Source of the USB HS PHY. */ @@ -375,10 +359,10 @@ typedef enum _clock_usb_phy_src /*! @brief Source of the USB HS PFD clock (USB1PFDCLK) */ typedef enum _clock_usb_pfd_src { - kCLOCK_UsbPfdSrcExt = 0U, /*!< Use external crystal. */ + kCLOCK_UsbPfdSrcExt = 0U, /*!< Use external crystal. */ kCLOCK_UsbPfdSrcFracDivBy4 = 1U, /*!< Use PFD_FRAC output divided by 4. */ kCLOCK_UsbPfdSrcFracDivBy2 = 2U, /*!< Use PFD_FRAC output divided by 2. */ - kCLOCK_UsbPfdSrcFrac = 3U, /*!< Use PFD_FRAC output. */ + kCLOCK_UsbPfdSrcFrac = 3U, /*!< Use PFD_FRAC output. */ } clock_usb_pfd_src_t; /*------------------------------------------------------------------------------ @@ -413,70 +397,70 @@ typedef enum _clock_usb_pfd_src typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_I2c2 = CLK_GATE_DEFINE(0x1028U, 6U), - kCLOCK_I2c3 = CLK_GATE_DEFINE(0x1028U, 7U), - kCLOCK_Uart4 = CLK_GATE_DEFINE(0x1028U, 10U), + kCLOCK_I2c2 = CLK_GATE_DEFINE(0x1028U, 6U), + kCLOCK_I2c3 = CLK_GATE_DEFINE(0x1028U, 7U), + kCLOCK_Uart4 = CLK_GATE_DEFINE(0x1028U, 10U), - kCLOCK_Enet0 = CLK_GATE_DEFINE(0x102CU, 0U), + kCLOCK_Enet0 = CLK_GATE_DEFINE(0x102CU, 0U), kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x102CU, 4U), - kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x102CU, 9U), - kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x102CU, 10U), - kCLOCK_Dac0 = CLK_GATE_DEFINE(0x102CU, 12U), - kCLOCK_Dac1 = CLK_GATE_DEFINE(0x102CU, 13U), + kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x102CU, 9U), + kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x102CU, 10U), + kCLOCK_Dac0 = CLK_GATE_DEFINE(0x102CU, 12U), + kCLOCK_Dac1 = CLK_GATE_DEFINE(0x102CU, 13U), - kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x1030U, 0U), - kCLOCK_Usbhs0 = CLK_GATE_DEFINE(0x1030U, 1U), + kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x1030U, 0U), + kCLOCK_Usbhs0 = CLK_GATE_DEFINE(0x1030U, 1U), kCLOCK_UsbhsPhy0 = CLK_GATE_DEFINE(0x1030U, 2U), kCLOCK_UsbhsDcd0 = CLK_GATE_DEFINE(0x1030U, 3U), - kCLOCK_Flexcan1 = CLK_GATE_DEFINE(0x1030U, 4U), - kCLOCK_Spi2 = CLK_GATE_DEFINE(0x1030U, 12U), - kCLOCK_Sdhc0 = CLK_GATE_DEFINE(0x1030U, 17U), - kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x1030U, 25U), - kCLOCK_Adc1 = CLK_GATE_DEFINE(0x1030U, 27U), + kCLOCK_Flexcan1 = CLK_GATE_DEFINE(0x1030U, 4U), + kCLOCK_Spi2 = CLK_GATE_DEFINE(0x1030U, 12U), + kCLOCK_Sdhc0 = CLK_GATE_DEFINE(0x1030U, 17U), + kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x1030U, 25U), + kCLOCK_Adc1 = CLK_GATE_DEFINE(0x1030U, 27U), - kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), - kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), - kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U), - kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U), - kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), - kCLOCK_Uart3 = CLK_GATE_DEFINE(0x1034U, 13U), + kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), + kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U), + kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U), + kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), + kCLOCK_Uart3 = CLK_GATE_DEFINE(0x1034U, 13U), kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp3 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp3 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), - kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), - kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), - kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), + kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), + kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), - kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), - kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), + kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), kCLOCK_Flexcan0 = CLK_GATE_DEFINE(0x103CU, 4U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), - kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), - kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), - kCLOCK_Usbdcd0 = CLK_GATE_DEFINE(0x103CU, 21U), - kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), + kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), + kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), + kCLOCK_Usbdcd0 = CLK_GATE_DEFINE(0x103CU, 21U), + kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), kCLOCK_Flexbus0 = CLK_GATE_DEFINE(0x1040U, 0U), - kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), - kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), - kCLOCK_Sdramc0 = CLK_GATE_DEFINE(0x1040U, 3U), + kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), + kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), + kCLOCK_Sdramc0 = CLK_GATE_DEFINE(0x1040U, 3U), } clock_ip_name_t; /*!@brief SIM configuration structure for clock setting. */ @@ -500,34 +484,30 @@ typedef enum _osc_mode #endif kOSC_ModeOscHighGain = 0U #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) - | - MCG_C2_EREFS_MASK + | MCG_C2_EREFS_MASK #else - | - MCG_C2_EREFS0_MASK + | MCG_C2_EREFS0_MASK #endif #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK))) - | - MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ #else - | - MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ #endif } osc_mode_t; /*! @brief Oscillator capacitor load setting.*/ enum _osc_cap_load { - kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ - kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ - kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */ }; /*! @brief OSCERCLK enable mode. */ enum _oscer_enable_mode { - kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ + kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */ }; @@ -635,31 +615,31 @@ typedef enum _mcg_monitor_mode enum _mcg_status { kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0), /*!< Can't switch to target mode. */ - kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific + kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific function. */ - kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ + kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ - kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ - kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ + kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because it is in use. */ }; /*! @brief MCG status flags. */ enum _mcg_status_flags_t { - kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ - kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ + kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ + kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ kMCG_RtcOscLostFlag = (1U << 4U), /*!< RTC OSC lost. */ - kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ - kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ + kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ + kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ kMCG_ExtPllLostFlag = (1U << 9U), /*!< External PLL lost. */ }; /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcg_irclk_enable_mode { - kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; @@ -827,18 +807,20 @@ static inline void CLOCK_SetTpmClock(uint32_t src) */ static inline void CLOCK_SetTraceClock(uint32_t src, uint32_t divValue, uint32_t fracValue) { - SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TRACECLKSEL_MASK) | SIM_SOPT2_TRACECLKSEL(src)); + SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TRACECLKSEL_MASK) | SIM_SOPT2_TRACECLKSEL(src)); SIM->CLKDIV4 = SIM_CLKDIV4_TRACEDIV(divValue) | SIM_CLKDIV4_TRACEFRAC(fracValue); } /*! * @brief Set PLLFLLSEL clock source. * - * @param src The value to set PLLFLLSEL clock source. + * @param src The value to set PLLFLLSEL clock source. + * @param divValue PLLFLL clock divider divisor. + * @param fracValue PLLFLL clock divider fraction. */ static inline void CLOCK_SetPllFllSelClock(uint32_t src, uint32_t divValue, uint32_t fracValue) { - SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_PLLFLLSEL_MASK) | SIM_SOPT2_PLLFLLSEL(src)); + SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_PLLFLLSEL_MASK) | SIM_SOPT2_PLLFLLSEL(src)); SIM->CLKDIV3 = SIM_CLKDIV3_PLLFLLDIV(divValue) | SIM_CLKDIV3_PLLFLLFRAC(fracValue); } @@ -1026,6 +1008,13 @@ uint32_t CLOCK_GetEr32kClkFreq(void); */ uint32_t CLOCK_GetOsc0ErClkFreq(void); +/*! + * @brief Get the OSC0 external reference divided clock frequency. + * + * @return Clock frequency in Hz. + */ +uint32_t CLOCK_GetOsc0ErClkDivFreq(void); + /*! * @brief Get the OSC0 external reference undivided clock frequency (OSC0ERCLK_UNDIV). * @@ -1156,7 +1145,7 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } else { - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; } } @@ -1172,8 +1161,8 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); @@ -1187,7 +1176,7 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); @@ -1201,7 +1190,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); */ static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) { - MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv); + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); } /*! @@ -1255,6 +1244,15 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, */ void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs); +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ +void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); + /*@}*/ /*! @name MCG clock lock monitor functions. */ @@ -1306,20 +1304,20 @@ void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode); * * Example: * @code - // To check the clock lost lock status of OSC0 and PLL0. - uint32_t mcgFlags; - - mcgFlags = CLOCK_GetStatusFlags(); - - if (mcgFlags & kMCG_Osc0LostFlag) - { - // OSC0 clock lock lost. Do something. - } - if (mcgFlags & kMCG_Pll0LostFlag) - { - // PLL0 clock lock lost. Do something. - } - @endcode + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * @endcode * * @return Logical OR value of the @ref _mcg_status_flags_t. */ @@ -1333,10 +1331,10 @@ uint32_t CLOCK_GetStatusFlags(void); * * Example: * @code - // To clear the clock lost lock status flags of OSC0 and PLL0. - - CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); - @endcode + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * @endcode * * @param mask The status flags to clear. This is a logical OR of members of the * enumeration @ref _mcg_status_flags_t. @@ -1394,7 +1392,7 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * * * Example: @code - // To enable only 2 pF and 8 pF capacitor load, please use like this. + To enable only 2 pF and 8 pF capacitor load, please use like this. OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P); @endcode */ @@ -1620,7 +1618,7 @@ status_t CLOCK_SetPeeMode(void); * @brief Switches the MCG to FBE mode from the external mode. * * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. - * The external clock is used as the system clock souce and PLL is disabled. However, + * The external clock is used as the system clock source and PLL is disabled. However, * the FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEE mode to FEI mode: * @@ -1638,7 +1636,7 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void); * @brief Switches the MCG to FBI mode from internal modes. * * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. - * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, * FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEI mode to FEE mode: * @@ -1691,7 +1689,7 @@ status_t CLOCK_BootToFeeMode( * @brief Sets the MCG to BLPI mode during system boot up. * * This function sets the MCG to BLPI mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. @@ -1703,10 +1701,10 @@ status_t CLOCK_BootToFeeMode( status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Sets the MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during system boot up. * * This function sets the MCG to BLPE mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @@ -1746,6 +1744,16 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); +/*! + * @brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + /*@}*/ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_clock.c index b70bff9fb3..318c30c330 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_clock.c @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_clock.h" @@ -34,6 +12,11 @@ * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + /* Macro definition remap workaround. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) #define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK @@ -64,11 +47,11 @@ #define TRIM_SIRC_MIN (31250U) #define MCG_S_IRCST_VAL ((MCG->S & MCG_S_IRCST_MASK) >> MCG_S_IRCST_SHIFT) -#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) -#define MCG_S_IREFST_VAL ((MCG->S & MCG_S_IREFST_MASK) >> MCG_S_IREFST_SHIFT) +#define MCG_S_CLKST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_CLKST_MASK) >> (uint32_t)MCG_S_CLKST_SHIFT) +#define MCG_S_IREFST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IREFST_MASK) >> (uint32_t)MCG_S_IREFST_SHIFT) #define MCG_S_PLLST_VAL ((MCG->S & MCG_S_PLLST_MASK) >> MCG_S_PLLST_SHIFT) #define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT) -#define MCG_C2_LP_VAL ((MCG->C2 & MCG_C2_LP_MASK) >> MCG_C2_LP_SHIFT) +#define MCG_C2_LP_VAL (((uint32_t)MCG->C2 & (uint32_t)MCG_C2_LP_MASK) >> (uint32_t)MCG_C2_LP_SHIFT) #define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT) #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) #define MCG_S2_PLLCST_VAL ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT) @@ -120,9 +103,9 @@ static uint32_t s_slowIrcFreq = 32768U; static uint32_t s_fastIrcFreq = 4000000U; /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -191,6 +174,7 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * @@ -198,11 +182,33 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ static void CLOCK_FllStableDelay(void); +#endif /******************************************************************************* * Code ******************************************************************************/ +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN +static void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (0U != (i--)) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardless how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ + static uint32_t CLOCK_GetMcgExtClkFreq(void) { uint32_t freq; @@ -211,12 +217,12 @@ static uint32_t CLOCK_GetMcgExtClkFreq(void) { case 0U: /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ - assert(g_xtal0Freq); + assert(0U != g_xtal0Freq); freq = g_xtal0Freq; break; case 1U: /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ - assert(g_xtal32Freq); + assert(0U != g_xtal32Freq); freq = g_xtal32Freq; break; case 2U: @@ -239,7 +245,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) uint32_t freq = CLOCK_GetMcgExtClkFreq(); - if (!freq) + if (0U == freq) { return freq; } @@ -247,7 +253,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) frdiv = MCG_C1_FRDIV_VAL; freq >>= frdiv; - range = MCG_C2_RANGE_VAL; + range = MCG_C2_RANGE_VAL; oscsel = MCG_C7_OSCSEL_VAL; /* @@ -255,7 +261,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) 1. MCG_C7[OSCSEL] selects IRC48M. 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0. */ - if (((0U != range) && (kMCG_OscselOsc == oscsel)) || (kMCG_OscselIrc == oscsel)) + if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel)) || ((uint8_t)kMCG_OscselIrc == oscsel)) { switch (frdiv) { @@ -286,7 +292,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) { - if (kMCG_IrcSlow == MCG_S_IRCST_VAL) + if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL) { /* Slow internal reference clock selected*/ return s_slowIrcFreq; @@ -301,7 +307,7 @@ static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) static uint32_t CLOCK_GetFllRefClkFreq(void) { /* If use external reference clock. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { return CLOCK_GetFllExtRefClkFreq(); } @@ -338,19 +344,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - +/*! + * brief Get the OSC0 external reference undivided clock frequency (OSC0ERCLK_UNDIV). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -365,6 +363,11 @@ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) } } +/*! + * brief Get the OSC0 external reference divided clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkDivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -379,6 +382,11 @@ uint32_t CLOCK_GetOsc0ErClkDivFreq(void) } } +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -403,6 +411,11 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the output clock frequency selected by SIM[PLLFLLSEL]. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPllFllSelClkFreq(void) { uint32_t freq; @@ -428,36 +441,76 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) return freq; } +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { return CLOCK_GetOsc0ErClkUndivFreq(); } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); } +/*! + * brief Get the flexbus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlexBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1); } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -515,6 +568,13 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; @@ -522,6 +582,13 @@ void CLOCK_SetSimConfig(sim_clock_config_t const *config) CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { bool ret = true; @@ -566,23 +633,31 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! + * brief Gets the MCG output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG output clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; - uint32_t clkst = MCG_S_CLKST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; switch (clkst) { - case kMCG_ClkOutStatPll: + case (uint32_t)kMCG_ClkOutStatPll: mcgoutclk = CLOCK_GetPll0Freq(); break; - case kMCG_ClkOutStatFll: + case (uint32_t)kMCG_ClkOutStatFll: mcgoutclk = CLOCK_GetFllFreq(); break; - case kMCG_ClkOutStatInt: + case (uint32_t)kMCG_ClkOutStatInt: mcgoutclk = CLOCK_GetInternalRefClkSelectFreq(); break; - case kMCG_ClkOutStatExt: + case (uint32_t)kMCG_ClkOutStatExt: mcgoutclk = CLOCK_GetMcgExtClkFreq(); break; default: @@ -592,6 +667,15 @@ uint32_t CLOCK_GetOutClkFreq(void) return mcgoutclk; } +/*! + * brief Gets the MCG FLL clock (MCGFLLCLK) frequency. + * + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. + * + * return The frequency of MCGFLLCLK. + */ uint32_t CLOCK_GetFllFreq(void) { static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; @@ -600,28 +684,36 @@ uint32_t CLOCK_GetFllFreq(void) uint32_t freq; /* If FLL is not enabled currently, then return 0U. */ - if ((MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) + if (0U != (MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) { return 0U; } /* Get FLL reference clock frequency. */ freq = CLOCK_GetFllRefClkFreq(); - if (!freq) + if (0U == freq) { return freq; } - drs = MCG_C4_DRST_DRS_VAL; + drs = MCG_C4_DRST_DRS_VAL; dmx32 = MCG_C4_DMX32_VAL; return freq * fllFactorTable[drs][dmx32]; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { /* If MCGIRCLK is gated. */ - if (!(MCG->C1 & MCG_C1_IRCLKEN_MASK)) + if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK)) { return 0U; } @@ -629,12 +721,20 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetInternalRefClkSelectFreq(); } +/*! + * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. + * + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGFFCLK. + */ uint32_t CLOCK_GetFixedFreqClkFreq(void) { uint32_t freq = CLOCK_GetFllRefClkFreq(); /* MCGFFCLK must be no more than MCGOUTCLK/8. */ - if ((freq) && (freq <= (CLOCK_GetOutClkFreq() / 8U))) + if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq)) { return freq; } @@ -644,6 +744,14 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void) } } +/*! + * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. + * + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGPLL0CLK. + */ uint32_t CLOCK_GetPll0Freq(void) { uint32_t mcgpll0clk; @@ -669,6 +777,18 @@ uint32_t CLOCK_GetPll0Freq(void) return mcgpll0clk; } +/*! + * brief Selects the MCG external reference clock. + * + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. + * + * param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. + * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success External reference clock set successfully. + */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) { bool needDelay; @@ -682,7 +802,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } #endif /* MCG_CONFIG_CHECK_PARAM */ - if (MCG_C7_OSCSEL_VAL != oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel) { /* If change OSCSEL, need to delay, ERR009878. */ needDelay = true; @@ -692,22 +812,12 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) needDelay = false; } - MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - + MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ i = 1500U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -716,15 +826,31 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Configures the Internal Reference clock (MCGIRCLK). + * + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. + * + * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * param ircs MCGIRCLK clock source, choose fast or slow. + * param fcrdiv Fast IRC divider setting (\c FCRDIV). + * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success MCGIRCLK configuration finished successfully. + */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) { - uint32_t mcgOutClkState = MCG_S_CLKST_VAL; - mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; - uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; + uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL; + mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; + uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) /* If MCGIRCLK is used as system clock source. */ - if (kMCG_ClkOutStatInt == mcgOutClkState) + if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState) { /* If need to change MCGIRCLK source or driver, return error. */ if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs)) @@ -738,25 +864,27 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, if (fcrdiv != curFcrdiv) { /* If fast IRC is in use currently, change to slow IRC. */ - if ((kMCG_IrcFast == curIrcs) && ((mcgOutClkState == kMCG_ClkOutStatInt) || (MCG->C1 & MCG_C1_IRCLKEN_MASK))) + if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) && + (kMCG_IrcFast == curIrcs)) { - MCG->C2 = ((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); - while (MCG_S_IRCST_VAL != kMCG_IrcSlow) + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); + while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow) { } } /* Update FCRDIV. */ - MCG->SC = (MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); + MCG->SC = + (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); } /* Set internal reference clock selection. */ - MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)); - MCG->C1 = (MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode; + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs))); + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode); /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */ - if ((mcgOutClkState == kMCG_ClkOutStatInt) || (enableMode & kMCG_IrclkEnable)) + if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable))) { - while (MCG_S_IRCST_VAL != ircs) + while (MCG_S_IRCST_VAL != (uint8_t)ircs) { } } @@ -764,17 +892,32 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, return kStatus_Success; } +/*! + * brief Calculates the PLL divider setting for a desired output frequency. + * + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function + * returns 0. + * + * param refFreq PLL reference clock frequency. + * param desireFreq Desired PLL output frequency. + * param prdiv PRDIV value to generate desired PLL frequency. + * param vdiv VDIV value to generate desired PLL frequency. + * return Closest frequency match that the PLL was able generate. + */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv) { - uint8_t ret_prdiv; /* PRDIV to return. */ - uint8_t ret_vdiv; /* VDIV to return. */ - uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_cur; /* PRDIV value for iteration. */ - uint8_t vdiv_cur; /* VDIV value for iteration. */ - uint32_t ret_freq = 0U; /* PLL output fequency to return. */ - uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ - uint32_t ref_div; /* Reference frequency after PRDIV. */ + uint8_t ret_prdiv; /* PRDIV to return. */ + uint8_t ret_vdiv; /* VDIV to return. */ + uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_cur; /* PRDIV value for iteration. */ + uint8_t vdiv_cur; /* VDIV value for iteration. */ + uint32_t ret_freq = 0U; /* PLL output frequency to return. */ + uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ + uint32_t ref_div; /* Reference frequency after PRDIV. */ /* Steps: @@ -823,15 +966,15 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (ret_freq == desireFreq) /* If desire frequency is got. */ { *prdiv = prdiv_cur - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; return ret_freq / 2U; } /* New PRDIV/VDIV is closer. */ if (diff > desireFreq - ret_freq) { - diff = desireFreq - ret_freq; + diff = desireFreq - ret_freq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } vdiv_cur++; @@ -841,9 +984,9 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, /* New PRDIV/VDIV is closer. */ if (diff > ret_freq - desireFreq) { - diff = ret_freq - desireFreq; + diff = ret_freq - desireFreq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } } @@ -851,8 +994,8 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (0xFFFFFFFFU != diff) { /* PRDIV/VDIV found. */ - *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; + *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; ret_freq = (refFreq / ret_prdiv) * ret_vdiv; return ret_freq / 2U; } @@ -863,6 +1006,17 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, } } +/*! + * brief Enables the PLL0 in FLL mode. + * + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL + * divider values. + * + * param config Pointer to the configuration structure. + */ void CLOCK_EnablePll0(mcg_pll_config_t const *config) { assert(config); @@ -883,20 +1037,27 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ - MCG->SC &= ~MCG_SC_ATMF_MASK; + MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK; if (kMCG_MonitorNone == mode) { - MCG->C6 &= ~MCG_C6_CME0_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK; } else { if (kMCG_MonitorInt == mode) { - MCG->C2 &= ~MCG_C2_LOCRE0_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK; } else { @@ -906,11 +1067,18 @@ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the RTC OSC clock monitor mode. + * + * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8 = MCG->C8; - mcg_c8 &= ~(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); + mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); if (kMCG_MonitorNone != mode) { @@ -923,6 +1091,13 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) MCG->C8 = mcg_c8; } +/*! + * brief Sets the PLL0 clock monitor mode. + * + * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8; @@ -953,34 +1128,76 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Gets the MCG status flags. + * + * This function gets the MCG clock status flags. All status flags are + * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To + * check a specific flag, compare the return value with the flag. + * + * Example: + * code + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * endcode + * + * return Logical OR value of the ref _mcg_status_flags_t. + */ uint32_t CLOCK_GetStatusFlags(void) { - uint32_t ret = 0U; + uint32_t ret = 0U; uint8_t mcg_s = MCG->S; if (MCG->SC & MCG_SC_LOCS0_MASK) { - ret |= kMCG_Osc0LostFlag; + ret |= (uint32_t)kMCG_Osc0LostFlag; } if (mcg_s & MCG_S_OSCINIT0_MASK) { - ret |= kMCG_Osc0InitFlag; + ret |= (uint32_t)kMCG_Osc0InitFlag; } - if (MCG->C8 & MCG_C8_LOCS1_MASK) + if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK)) { - ret |= kMCG_RtcOscLostFlag; + ret |= (uint32_t)kMCG_RtcOscLostFlag; } if (mcg_s & MCG_S_LOLS0_MASK) { - ret |= kMCG_Pll0LostFlag; + ret |= (uint32_t)kMCG_Pll0LostFlag; } if (mcg_s & MCG_S_LOCK0_MASK) { - ret |= kMCG_Pll0LockFlag; + ret |= (uint32_t)kMCG_Pll0LockFlag; } return ret; } +/*! + * brief Clears the MCG status flags. + * + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See ref _mcg_status_flags_t. + * + * Example: + * code + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * endcode + * + * param mask The status flags to clear. This is a logical OR of members of the + * enumeration ref _mcg_status_flags_t. + */ void CLOCK_ClearStatusFlags(uint32_t mask) { uint8_t reg; @@ -989,9 +1206,9 @@ void CLOCK_ClearStatusFlags(uint32_t mask) { MCG->SC &= ~MCG_SC_ATMF_MASK; } - if (mask & kMCG_RtcOscLostFlag) + if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag)) { - reg = MCG->C8; + reg = MCG->C8; MCG->C8 = reg; } if (mask & kMCG_Pll0LostFlag) @@ -1000,30 +1217,60 @@ void CLOCK_ClearStatusFlags(uint32_t mask) } } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); OSC_SetCapLoad(OSC0, config->capLoad); - OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); - MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) { /* Wait for stable. */ - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; - MCG->C2 &= ~OSC_MODE_MASK; + MCG->C2 &= ~(uint8_t)OSC_MODE_MASK; } +/*! + * brief Auto trims the internal reference clock. + * + * This function trims the internal reference clock by using the external clock. If + * successful, it returns the kStatus_Success and the frequency after + * trimming is received in the parameter p actualFreq. If an error occurs, + * the error code is returned. + * + * param extFreq External clock frequency, which should be a bus clock. + * param desireFreq Frequency to trim to. + * param actualFreq Actual frequency after trimming. + * param atms Trim fast or slow internal reference clock. + * retval kStatus_Success ATM success. + * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. + * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. + * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. + */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) { uint32_t multi; /* extFreq / desireFreq */ @@ -1057,7 +1304,7 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ } multi = extFreq / desireFreq; - actv = multi * 21U; + actv = multi * 21U; if (kMCG_AtmSel4m == atms) { @@ -1069,17 +1316,17 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ MCG->ATCVH = (uint8_t)(actv >> 8U); mcg_sc = MCG->SC; - mcg_sc &= ~(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); + mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms)); MCG->SC = (mcg_sc | MCG_SC_ATME_MASK); /* Wait for finished. */ - while (MCG->SC & MCG_SC_ATME_MASK) + while (0U != (MCG->SC & MCG_SC_ATME_MASK)) { } /* Error occurs? */ - if (MCG->SC & MCG_SC_ATMF_MASK) + if (0U != (MCG->SC & MCG_SC_ATMF_MASK)) { /* Clear the failed flag. */ MCG->SC = mcg_sc; @@ -1100,13 +1347,20 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ return kStatus_Success; } +/*! + * brief Gets the current MCG mode. + * + * This function checks the MCG registers and determines the current MCG mode. + * + * return Current MCG mode or error code; See ref mcg_mode_t. + */ mcg_mode_t CLOCK_GetMode(void) { mcg_mode_t mode = kMCG_ModeError; - uint32_t clkst = MCG_S_CLKST_VAL; - uint32_t irefst = MCG_S_IREFST_VAL; - uint32_t lp = MCG_C2_LP_VAL; - uint32_t pllst = MCG_S_PLLST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; + uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL; + uint32_t lp = (uint32_t)MCG_C2_LP_VAL; + uint32_t pllst = MCG_S_PLLST_VAL; /*------------------------------------------------------------------ Mode and Registers @@ -1147,59 +1401,77 @@ mcg_mode_t CLOCK_GetMode(void) ----------------------------------------------------------------------*/ - switch (clkst) + if (clkst == (uint32_t)kMCG_ClkOutStatFll) { - case kMCG_ClkOutStatFll: - if (kMCG_FllSrcExternal == irefst) + if ((uint32_t)kMCG_FllSrcExternal == irefst) + { + mode = kMCG_ModeFEE; + } + else + { + mode = kMCG_ModeFEI; + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatInt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPI; + } + else + { { - mode = kMCG_ModeFEE; + mode = kMCG_ModeFBI; + } + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatExt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPE; + } + else + { + if (kMCG_PllstPll == pllst) + { + mode = kMCG_ModePBE; } else { - mode = kMCG_ModeFEI; + mode = kMCG_ModeFBE; } - break; - case kMCG_ClkOutStatInt: - if (lp) - { - mode = kMCG_ModeBLPI; - } - else - { - { - mode = kMCG_ModeFBI; - } - } - break; - case kMCG_ClkOutStatExt: - if (lp) - { - mode = kMCG_ModeBLPE; - } - else - { - if (kMCG_PllstPll == pllst) - { - mode = kMCG_ModePBE; - } - else - { - mode = kMCG_ModeFBE; - } - } - break; - case kMCG_ClkOutStatPll: + } + } + if (clkst == (uint32_t)kMCG_ClkOutStatPll) + { { mode = kMCG_ModePEE; } - break; - default: - break; + } + else + { + /*do nothing*/ } return mode; } +/*! + * brief Sets the MCG to FEI mode. + * + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. + */ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1220,7 +1492,7 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1228,12 +1500,12 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal)); /* IREFS = 1 */ + MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1244,15 +1516,16 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1260,6 +1533,21 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FEE mode. + * + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1280,7 +1568,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1288,13 +1576,24 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait and check status. */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1305,7 +1604,8 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); MCG->C4 = mcg_c4; /* Wait for DRST_DRS update. */ @@ -1314,12 +1614,12 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1327,6 +1627,22 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to FBI mode. + * + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FBI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1345,7 +1661,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela mcg_c4 = MCG->C4; - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ /* Errata: ERR007993 @@ -1353,7 +1669,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1361,12 +1677,12 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1376,14 +1692,15 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela MCG->C4 = mcg_c4; } - while (kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1391,6 +1708,21 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FBE mode. + * + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FBE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1406,13 +1738,13 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void #endif /* Change to FLL mode. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } /* Set LP bit to enable the FLL */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; mcg_c4 = MCG->C4; @@ -1422,7 +1754,7 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1430,13 +1762,24 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for Reference clock Status bit to clear */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1447,15 +1790,16 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRST_DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for clock status bits to show clock source is ext ref clk */ - while (kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) { } /* Wait for fll stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1463,10 +1807,19 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to BLPI mode. + * + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpiMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { return kStatus_MCG_ModeUnreachable; } @@ -1478,10 +1831,19 @@ status_t CLOCK_SetBlpiMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode. + * + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { return kStatus_MCG_ModeUnreachable; } @@ -1493,6 +1855,25 @@ status_t CLOCK_SetBlpeMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to PBE mode. + * + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. + * + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. + * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); + */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1534,6 +1915,18 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode. + * + * This function sets the MCG to PEE mode. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. + */ status_t CLOCK_SetPeeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1548,13 +1941,29 @@ status_t CLOCK_SetPeeMode(void) MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); /* Wait for clock status bits to update */ - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } return kStatus_Success; } +/*! + * brief Switches the MCG to FBE mode from the external mode. + * + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: + * + * code + * CLOCK_ExternalModeToFbeModeQuick(); + * CLOCK_SetFeiMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. + */ status_t CLOCK_ExternalModeToFbeModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1565,15 +1974,15 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) #endif /* MCG_CONFIG_CHECK_PARAM */ /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } /* Disable PLL. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } @@ -1581,6 +1990,22 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBI mode from internal modes. + * + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: + * + * code + * CLOCK_InternalModeToFbiModeQuick(); + * CLOCK_SetFeeMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. + */ status_t CLOCK_InternalModeToFbiModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1591,37 +2016,80 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) #endif /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } return kStatus_Success; } +/*! + * brief Sets the MCG to FEI mode during system boot up. + * + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to FEE mode during system bootup. + * + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, OSCSEL. + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to BLPI mode during system boot up. + * + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param fcrdiv Fast IRC divider, FCRDIV. + * param ircs The internal reference clock to select, IRCS. + * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * + * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) { /* If reset mode is FEI mode, set MCGIRCLK and always success. */ - CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); /* If reset mode is not BLPI, first enter FBI mode. */ - MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } @@ -1631,14 +2099,36 @@ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEn return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode during system boot up. + * + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); /* Set to FBE mode. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != @@ -1652,6 +2142,19 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode during system boot up. + * + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1662,7 +2165,7 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc /* Change to use PLL output clock. */ MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } @@ -1698,6 +2201,20 @@ static const mcg_mode_t mcgModeMatrix[8][8] = { /* FEI FBI BLPI FEE FBE BLPE PBE PEE */ }; +/*! + * brief Sets the MCG to a target mode. + * + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. + * + * param config Pointer to the target MCG mode configuration structure. + * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. + * + * note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. + */ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) { mcg_mode_t next_mode; @@ -1706,30 +2223,30 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) mcg_pll_clk_select_t pllcs = kMCG_PllClkSelPll0; /* If need to change external clock, MCG_C7[OSCSEL]. */ - if (MCG_C7_OSCSEL_VAL != config->oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel)) { /* If external clock is in use, change to FEI first. */ - if (!(MCG->S & MCG_S_IRCST_MASK)) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { - CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); + (void)CLOCK_ExternalModeToFbeModeQuick(); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL); } - CLOCK_SetExternalRefClkConfig(config->oscsel); + (void)CLOCK_SetExternalRefClkConfig(config->oscsel); } /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */ - if (MCG_S_CLKST_VAL == kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt) { - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } /* Configure MCGIRCLK. */ - CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); next_mode = CLOCK_GetMode(); @@ -1746,10 +2263,10 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL); break; case kMCG_ModeFBE: - status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL); break; case kMCG_ModeBLPI: status = CLOCK_SetBlpiMode(); @@ -1768,7 +2285,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) else { MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } } @@ -1791,7 +2308,55 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) } else { - MCG->C5 &= ~(uint32_t)kMCG_PllEnableIndependent; + MCG->C5 &= ~(uint8_t)kMCG_PllEnableIndependent; } return kStatus_Success; } + +/*! + * brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + uint64_t count = 0U; + uint32_t period = SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 1000000; + + /* Make sure the DWT trace fucntion is enabled. */ + if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR)) + { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + } + + /* CYCCNT not supported on this device. */ + assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk)); + + /* If CYCCENT has already been enabled, read directly, otherwise, need enable it. */ + if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL)) + { + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + /* Calculate the count ticks. */ + count = DWT->CYCCNT; + count += (uint64_t)period * delay_us; + + if (count > 0xFFFFFFFFUL) + { + count -= 0xFFFFFFFFUL; + /* wait for cyccnt overflow. */ + while (count < DWT->CYCCNT) + { + } + } + + /* Wait for cyccnt reach count value. */ + while (count > DWT->CYCCNT) + { + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_clock.h index 1dbfa263a4..11ce953ece 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_clock.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ @@ -39,14 +17,32 @@ /*! @file */ /******************************************************************************* - * Definitions + * Configurations ******************************************************************************/ +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + /*! @brief Configure whether driver controls clock * * When set to 0, peripheral drivers will enable clock in initialize function * and disable clock in de-initialize function. When set to 1, peripheral - * driver will not control the clock, application could contol the clock out of + * driver will not control the clock, application could control the clock out of * the driver. * * @note All drivers share this feature switcher. If it is set to 1, application @@ -56,27 +52,38 @@ #define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 #endif +/******************************************************************************* + * Definitions + ******************************************************************************/ + /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.0. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief CLOCK driver version 2.3.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) /*@}*/ +/* Definition for delay API in clock driver, users can redefine it to the real application. */ +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (120000000UL) +#endif + /*! @brief External XTAL0 (OSC0) clock frequency. * * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Set up the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. + * Set up the OSC0 + * CLOCK_InitOsc0(...); + * Set the XTAL0 value to the clock driver. + * CLOCK_SetXtal0Freq(80000000); * @endcode * * This is important for the multicore platforms where only one core needs to set up the * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * @@ -87,7 +94,7 @@ extern uint32_t g_xtal0Freq; * the clock. All other cores need to call the CLOCK_SetXtal32Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; /*! @brief IRC48M clock frequency in Hz. */ #define MCG_INTERNAL_IRC_48M 48000000U @@ -211,9 +218,9 @@ extern uint32_t g_xtal32Freq; } /*! @brief Clock ip name array for MPU. */ -#define MPU_CLOCKS \ - { \ - kCLOCK_Mpu0 \ +#define MPU_CLOCKS \ + { \ + kCLOCK_Sysmpu0 \ } /*! @brief Clock ip name array for FLEXIO. */ @@ -336,9 +343,9 @@ typedef enum _clock_name /*! @brief USB clock source definition. */ typedef enum _clock_usb_src { - kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ + kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(3U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ } clock_usb_src_t; /*------------------------------------------------------------------------------ @@ -372,65 +379,65 @@ typedef enum _clock_usb_src typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_I2c2 = CLK_GATE_DEFINE(0x1028U, 6U), - kCLOCK_I2c3 = CLK_GATE_DEFINE(0x1028U, 7U), + kCLOCK_I2c2 = CLK_GATE_DEFINE(0x1028U, 6U), + kCLOCK_I2c3 = CLK_GATE_DEFINE(0x1028U, 7U), kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x102CU, 4U), kCLOCK_Lpuart1 = CLK_GATE_DEFINE(0x102CU, 5U), kCLOCK_Lpuart2 = CLK_GATE_DEFINE(0x102CU, 6U), kCLOCK_Lpuart3 = CLK_GATE_DEFINE(0x102CU, 7U), - kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x102CU, 9U), - kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x102CU, 10U), - kCLOCK_Dac0 = CLK_GATE_DEFINE(0x102CU, 12U), - kCLOCK_Ltc0 = CLK_GATE_DEFINE(0x102CU, 17U), + kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x102CU, 9U), + kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x102CU, 10U), + kCLOCK_Dac0 = CLK_GATE_DEFINE(0x102CU, 12U), + kCLOCK_Ltc0 = CLK_GATE_DEFINE(0x102CU, 17U), kCLOCK_Emvsim0 = CLK_GATE_DEFINE(0x102CU, 20U), kCLOCK_Emvsim1 = CLK_GATE_DEFINE(0x102CU, 21U), kCLOCK_Lpuart4 = CLK_GATE_DEFINE(0x102CU, 22U), - kCLOCK_Qspi0 = CLK_GATE_DEFINE(0x102CU, 26U), + kCLOCK_Qspi0 = CLK_GATE_DEFINE(0x102CU, 26U), kCLOCK_Flexio0 = CLK_GATE_DEFINE(0x102CU, 31U), kCLOCK_Trng0 = CLK_GATE_DEFINE(0x1030U, 0U), - kCLOCK_Spi2 = CLK_GATE_DEFINE(0x1030U, 12U), + kCLOCK_Spi2 = CLK_GATE_DEFINE(0x1030U, 12U), kCLOCK_Sdhc0 = CLK_GATE_DEFINE(0x1030U, 17U), - kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x1030U, 25U), + kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x1030U, 25U), - kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), - kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), + kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), kCLOCK_Lptmr1 = CLK_GATE_DEFINE(0x1038U, 4U), - kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), - kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), - kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), + kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), + kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), - kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), - kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), - kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), + kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), + kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), kCLOCK_Usbdcd0 = CLK_GATE_DEFINE(0x103CU, 21U), - kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), kCLOCK_Flexbus0 = CLK_GATE_DEFINE(0x1040U, 0U), - kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), - kCLOCK_Mpu0 = CLK_GATE_DEFINE(0x1040U, 2U), - kCLOCK_Sdramc0 = CLK_GATE_DEFINE(0x1040U, 3U), + kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), + kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), + kCLOCK_Sdramc0 = CLK_GATE_DEFINE(0x1040U, 3U), } clock_ip_name_t; /*!@brief SIM configuration structure for clock setting. */ @@ -454,34 +461,30 @@ typedef enum _osc_mode #endif kOSC_ModeOscHighGain = 0U #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) - | - MCG_C2_EREFS_MASK + | MCG_C2_EREFS_MASK #else - | - MCG_C2_EREFS0_MASK + | MCG_C2_EREFS0_MASK #endif #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK))) - | - MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ #else - | - MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ #endif } osc_mode_t; /*! @brief Oscillator capacitor load setting.*/ enum _osc_cap_load { - kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ - kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ - kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */ }; /*! @brief OSCERCLK enable mode. */ enum _oscer_enable_mode { - kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ + kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */ }; @@ -589,30 +592,30 @@ typedef enum _mcg_monitor_mode enum _mcg_status { kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0), /*!< Can't switch to target mode. */ - kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific + kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific function. */ - kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ + kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ - kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ - kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ + kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because it is in use. */ }; /*! @brief MCG status flags. */ enum _mcg_status_flags_t { - kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ - kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ + kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ + kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ kMCG_RtcOscLostFlag = (1U << 4U), /*!< RTC OSC lost. */ - kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ - kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ + kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ + kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ }; /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcg_irclk_enable_mode { - kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; @@ -778,18 +781,20 @@ static inline void CLOCK_SetFlexio0Clock(uint32_t src) */ static inline void CLOCK_SetTraceClock(uint32_t src, uint32_t divValue, uint32_t fracValue) { - SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TRACECLKSEL_MASK) | SIM_SOPT2_TRACECLKSEL(src)); + SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TRACECLKSEL_MASK) | SIM_SOPT2_TRACECLKSEL(src)); SIM->CLKDIV4 = SIM_CLKDIV4_TRACEDIV(divValue) | SIM_CLKDIV4_TRACEFRAC(fracValue); } /*! * @brief Set PLLFLLSEL clock source. * - * @param src The value to set PLLFLLSEL clock source. + * @param src The value to set PLLFLLSEL clock source. + * @param divValue PLLFLL clock divider divisor. + * @param fracValue PLLFLL clock divider fraction. */ static inline void CLOCK_SetPllFllSelClock(uint32_t src, uint32_t divValue, uint32_t fracValue) { - SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_PLLFLLSEL_MASK) | SIM_SOPT2_PLLFLLSEL(src)); + SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_PLLFLLSEL_MASK) | SIM_SOPT2_PLLFLLSEL(src)); SIM->CLKDIV3 = SIM_CLKDIV3_PLLFLLDIV(divValue) | SIM_CLKDIV3_PLLFLLFRAC(fracValue); } @@ -925,6 +930,13 @@ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void); */ uint32_t CLOCK_GetOsc0ErClkFreq(void); +/*! + * @brief Get the OSC0 external reference divided clock frequency. + * + * @return Clock frequency in Hz. + */ +uint32_t CLOCK_GetOsc0ErClkDivFreq(void); + /*! * @brief Set the clock configure in SIM module. * @@ -1027,7 +1039,7 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } else { - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; } } @@ -1043,8 +1055,8 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); @@ -1058,7 +1070,7 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); @@ -1072,7 +1084,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); */ static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) { - MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv); + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); } /*! @@ -1116,6 +1128,15 @@ static inline void CLOCK_DisablePll0(void) */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv); +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ +void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); + /*@}*/ /*! @name MCG clock lock monitor functions. */ @@ -1157,20 +1178,20 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode); * * Example: * @code - // To check the clock lost lock status of OSC0 and PLL0. - uint32_t mcgFlags; - - mcgFlags = CLOCK_GetStatusFlags(); - - if (mcgFlags & kMCG_Osc0LostFlag) - { - // OSC0 clock lock lost. Do something. - } - if (mcgFlags & kMCG_Pll0LostFlag) - { - // PLL0 clock lock lost. Do something. - } - @endcode + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * @endcode * * @return Logical OR value of the @ref _mcg_status_flags_t. */ @@ -1184,10 +1205,10 @@ uint32_t CLOCK_GetStatusFlags(void); * * Example: * @code - // To clear the clock lost lock status flags of OSC0 and PLL0. - - CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); - @endcode + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * @endcode * * @param mask The status flags to clear. This is a logical OR of members of the * enumeration @ref _mcg_status_flags_t. @@ -1245,7 +1266,7 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * * * Example: @code - // To enable only 2 pF and 8 pF capacitor load, please use like this. + To enable only 2 pF and 8 pF capacitor load, please use like this. OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P); @endcode */ @@ -1471,7 +1492,7 @@ status_t CLOCK_SetPeeMode(void); * @brief Switches the MCG to FBE mode from the external mode. * * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. - * The external clock is used as the system clock souce and PLL is disabled. However, + * The external clock is used as the system clock source and PLL is disabled. However, * the FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEE mode to FEI mode: * @@ -1489,7 +1510,7 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void); * @brief Switches the MCG to FBI mode from internal modes. * * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. - * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, * FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEI mode to FEE mode: * @@ -1542,7 +1563,7 @@ status_t CLOCK_BootToFeeMode( * @brief Sets the MCG to BLPI mode during system boot up. * * This function sets the MCG to BLPI mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. @@ -1554,10 +1575,10 @@ status_t CLOCK_BootToFeeMode( status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Sets the MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during system boot up. * * This function sets the MCG to BLPE mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @@ -1597,6 +1618,16 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); +/*! + * @brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + /*@}*/ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_clock.c index 5f0eba1d37..b6173fca93 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_clock.c @@ -1,40 +1,22 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include "fsl_common.h" #include "fsl_clock.h" /******************************************************************************* * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + #if (defined(OSC) && !(defined(OSC0))) #define OSC0 OSC #endif @@ -57,10 +39,9 @@ ******************************************************************************/ /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; - +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -126,6 +107,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -140,6 +126,11 @@ uint32_t CLOCK_GetOsc0ErClkFreq(void) } } +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -164,11 +155,21 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { uint32_t freq; @@ -179,6 +180,11 @@ uint32_t CLOCK_GetFlashClkFreq(void) return freq; } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { uint32_t freq; @@ -189,11 +195,26 @@ uint32_t CLOCK_GetBusClkFreq(void) return freq; } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -233,12 +254,26 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { bool ret = true; @@ -265,6 +300,14 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG_Lite internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { uint8_t divider1 = MCG_SC_FCRDIV_VAL; @@ -273,6 +316,14 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetLircClkFreq() >> (divider1 + divider2); } +/* + * brief Gets the current MCGPCLK frequency. + * + * This function gets the MCGPCLK frequency in Hz based on the current MCG_Lite + * register settings. + * + * return The frequency of MCGPCLK. + */ uint32_t CLOCK_GetPeriphClkFreq(void) { /* Check whether the HIRC is enabled. */ @@ -286,6 +337,14 @@ uint32_t CLOCK_GetPeriphClkFreq(void) } } +/*! + * brief Gets the MCG_Lite output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG_Lite output clock frequency in Hz based on the current + * MCG_Lite register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t freq; @@ -311,6 +370,13 @@ uint32_t CLOCK_GetOutClkFreq(void) return freq; } +/*! + * brief Gets the current MCG_Lite mode. + * + * This function checks the MCG_Lite registers and determines the current MCG_Lite mode. + * + * return The current MCG_Lite mode or error code. + */ mcglite_mode_t CLOCK_GetMode(void) { mcglite_mode_t mode; @@ -341,6 +407,15 @@ mcglite_mode_t CLOCK_GetMode(void) return mode; } +/*! + * brief Sets the MCG_Lite configuration. + * + * This function configures the MCG_Lite, includes the output clock source, MCGIRCLK + * settings, HIRC settings, and so on. See ref mcglite_config_t for details. + * + * param targetConfig Pointer to the target MCG_Lite mode configuration structure. + * return Error code. + */ status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig) { assert(targetConfig); @@ -383,6 +458,13 @@ status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig) return kStatus_Success; } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); @@ -401,8 +483,39 @@ void CLOCK_InitOsc0(osc_config_t const *config) } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; MCG->C2 &= MCG_C2_IRCS_MASK; } + +/*! + * brief Delay at least for several microseconds. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + + uint32_t count = (uint32_t)USEC_TO_COUNT(delay_us, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); + + /* + * Calculate the real delay count depend on the excute instructions cycles, + * users can change the divider value to adapt to the real IDE optimise level. + */ + count = (count / 4U); + + for (; count > 0UL; count--) + { + __NOP(); + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_clock.h index b1f95fd521..f6220a4b0d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_clock.h @@ -1,77 +1,80 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include -#include -#include +#include "fsl_common.h" /*! @addtogroup clock */ /*! @{ */ +/*! @file */ + +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could control the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + /******************************************************************************* * Definitions ******************************************************************************/ -/*! @brief Clock driver version. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ +/*! @name Driver version */ +/*@{*/ +/*! @brief CLOCK driver version 2.2.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*@}*/ + +/* Definition for delay API in clock driver, users can redefine it to the real application. */ +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (48000000UL) +#endif /*! @brief External XTAL0 (OSC0) clock frequency. * - * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal0Freq to set the value in to clock driver. For example, - * if XTAL0 is 8MHz, + * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, + * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Setup the OSC0 + * CLOCK_InitOsc0(...); // Set up the OSC0 * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to clock driver. * @endcode * - * This is important for the multicore platforms, only one core needs to setup - * OSC0 using CLOCK_InitOsc0, all other cores need to call CLOCK_SetXtal0Freq - * to get valid clock frequency. + * This is important for the multicore platforms where one core needs to set up the + * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq + * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; -/*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. +/*! @brief The external XTAL32/EXTAL32/RTC_CLKIN clock frequency. * - * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal32Freq to set the value in to clock driver. + * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal32Freq to set the value in the clock driver. * - * This is important for the multicore platforms, only one core needs to setup - * the clock, all other cores need to call CLOCK_SetXtal32Freq - * to get valid clock frequency. + * This is important for the multicore platforms where one core needs to set up + * the clock. All other cores need to call the CLOCK_SetXtal32Freq + * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; /*! @brief Clock ip name array for DMAMUX. */ #define DMAMUX_CLOCKS \ @@ -170,9 +173,9 @@ extern uint32_t g_xtal32Freq; } /*! @brief Clock ip name array for CMP. */ -#define CMP_CLOCKS \ - { \ - kCLOCK_Cmp0, kCLOCK_Cmp1, kCLOCK_Cmp2 \ +#define CMP_CLOCKS \ + { \ + kCLOCK_Cmp0 \ } /*! @@ -228,7 +231,7 @@ typedef enum _clock_name typedef enum _clock_usb_src { kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ } clock_usb_src_t; /*------------------------------------------------------------------------------ @@ -262,36 +265,34 @@ typedef enum _clock_usb_src typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), - kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), - kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x1034U, 22U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x1034U, 23U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), + kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x1034U, 22U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x1034U, 23U), - kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), - kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), - kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), + kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), + kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x1038U, 20U), kCLOCK_Lpuart1 = CLK_GATE_DEFINE(0x1038U, 21U), kCLOCK_Flexio0 = CLK_GATE_DEFINE(0x1038U, 31U), - kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), - kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 8U), } clock_ip_name_t; @@ -306,30 +307,30 @@ typedef struct _sim_clock_config /*! @brief Oscillator capacitor load setting.*/ enum _osc_cap_load { - kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ - kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ - kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */ }; /*! @brief OSCERCLK enable mode. */ enum _oscer_enable_mode { - kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ + kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */ }; -/*! @brief OSC configuration for OSCERCLK. */ +/*! @brief The OSC configuration for OSCERCLK. */ typedef struct _oscer_config { uint8_t enableMode; /*!< OSCERCLK enable mode. OR'ed value of \ref _oscer_enable_mode. */ } oscer_config_t; -/*! @brief OSC work mode. */ +/*! @brief The OSC work mode. */ typedef enum _osc_mode { - kOSC_ModeExt = 0U, /*!< Use external clock. */ + kOSC_ModeExt = 0U, /*!< Use external clock. */ kOSC_ModeOscLowPower = MCG_C2_EREFS0_MASK, /*!< Oscillator low power. */ kOSC_ModeOscHighGain = MCG_C2_EREFS0_MASK | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ } osc_mode_t; @@ -339,7 +340,7 @@ typedef enum _osc_mode * * Defines the configuration data structure to initialize the OSC. * When porting to a new board, set the following members - * according to board settings: + * according to the board settings: * 1. freq: The external frequency. * 2. workMode: The OSC module mode. */ @@ -363,8 +364,8 @@ typedef enum _mcglite_clkout_src /*! @brief MCG_Lite LIRC select. */ typedef enum _mcglite_lirc_mode { - kMCGLITE_Lirc2M, /*!< Slow internal reference(LIRC) 2MHz clock selected */ - kMCGLITE_Lirc8M, /*!< Slow internal reference(LIRC) 8MHz clock selected */ + kMCGLITE_Lirc2M, /*!< Slow internal reference(LIRC) 2 MHz clock selected */ + kMCGLITE_Lirc8M, /*!< Slow internal reference(LIRC) 8 MHz clock selected */ } mcglite_lirc_mode_t; /*! @brief MCG_Lite divider factor selection for clock source*/ @@ -393,7 +394,7 @@ typedef enum _mcglite_mode /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcglite_irclk_enable_mode { - kMCGLITE_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCGLITE_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCGLITE_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; @@ -416,26 +417,6 @@ typedef struct _mcglite_config extern "C" { #endif /* __cplusplus */ -/*! - * @brief Set the XTAL0 frequency based on board setting. - * - * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal0Freq(uint32_t freq) -{ - g_xtal0Freq = freq; -} - -/*! - * @brief Set the XTAL32/RTC_CLKIN frequency based on board setting. - * - * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal32Freq(uint32_t freq) -{ - g_xtal32Freq = freq; -} - /*! * @brief Enable the clock for specific IP. * @@ -647,7 +628,7 @@ static inline void CLOCK_SetSimSafeDivs(void) /*! * @brief Gets the MCG_Lite output clock (MCGOUTCLK) frequency. * - * This function gets the MCG_Lite output clock frequency (Hz) based on the current + * This function gets the MCG_Lite output clock frequency in Hz based on the current * MCG_Lite register value. * * @return The frequency of MCGOUTCLK. @@ -657,7 +638,7 @@ uint32_t CLOCK_GetOutClkFreq(void); /*! * @brief Gets the MCG internal reference clock (MCGIRCLK) frequency. * - * This function gets the MCG_Lite internal reference clock frequency (Hz) based + * This function gets the MCG_Lite internal reference clock frequency in Hz based * on the current MCG register value. * * @return The frequency of MCGIRCLK. @@ -665,13 +646,13 @@ uint32_t CLOCK_GetOutClkFreq(void); uint32_t CLOCK_GetInternalRefClkFreq(void); /*! -* @brief Gets the current MCGPCLK frequency. -* -* This function gets the MCGPCLK frequency (Hertz) based on the current MCG_Lite -* register settings. -* -* @return The frequency of MCGPCLK. -*/ + * @brief Gets the current MCGPCLK frequency. + * + * This function gets the MCGPCLK frequency in Hz based on the current MCG_Lite + * register settings. + * + * @return The frequency of MCGPCLK. + */ uint32_t CLOCK_GetPeriphClkFreq(void); /*! @}*/ @@ -686,15 +667,15 @@ uint32_t CLOCK_GetPeriphClkFreq(void); * * This function checks the MCG_Lite registers and determines the current MCG_Lite mode. * - * @return Current MCG_Lite mode or error code. + * @return The current MCG_Lite mode or error code. */ mcglite_mode_t CLOCK_GetMode(void); /*! * @brief Sets the MCG_Lite configuration. * - * This function configures the MCG_Lite, include output clock source, MCGIRCLK - * setting, HIRC setting and so on, see @ref mcglite_config_t for details. + * This function configures the MCG_Lite, includes the output clock source, MCGIRCLK + * settings, HIRC settings, and so on. See @ref mcglite_config_t for details. * * @param targetConfig Pointer to the target MCG_Lite mode configuration structure. * @return Error code. @@ -712,8 +693,8 @@ status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig); * @brief Configures the OSC external reference clock (OSCERCLK). * * This function configures the OSC external reference clock (OSCERCLK). - * For example, to enable the OSCERCLK in normal mode and stop mode, and also set - * the output divider to 1, as follows: + * This is an example to enable the OSCERCLK in normal mode and stop mode, and set + * the output divider to 1. * @code oscer_config_t config = @@ -741,12 +722,12 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * /*! * @brief Sets the capacitor load configuration for the oscillator. * - * This function sets the specified capacitors configuration for the oscillator. + * This function sets the specified capacitor configuration for the oscillator. * This should be done in the early system level initialization function call * based on the system configuration. * * @param base OSC peripheral address. - * @param capLoad OR'ed value for the capacitor load option, see \ref _osc_cap_load. + * @param capLoad OR'ed value for the capacitor load option.See \ref _osc_cap_load. * * Example: @code @@ -766,7 +747,7 @@ static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad) } /*! - * @brief Initialize OSC0. + * @brief Initializes the OSC0. * * This function initializes the OSC0 according to the board configuration. * @@ -783,6 +764,43 @@ void CLOCK_DeinitOsc0(void); /*! @}*/ +/*! + * @name External clock frequency + * @{ + */ + +/*! + * @brief Sets the XTAL0 frequency based on board settings. + * + * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal0Freq(uint32_t freq) +{ + g_xtal0Freq = freq; +} + +/*! + * @brief Sets the XTAL32/RTC_CLKIN frequency based on board settings. + * + * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal32Freq(uint32_t freq) +{ + g_xtal32Freq = freq; +} + +/*! + * @brief Delay at least for several microseconds. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + +/* @} */ + #if defined(__cplusplus) } #endif /* __cplusplus */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_clock.c index 5f0eba1d37..b6173fca93 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_clock.c @@ -1,40 +1,22 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include "fsl_common.h" #include "fsl_clock.h" /******************************************************************************* * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + #if (defined(OSC) && !(defined(OSC0))) #define OSC0 OSC #endif @@ -57,10 +39,9 @@ ******************************************************************************/ /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; - +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -126,6 +107,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -140,6 +126,11 @@ uint32_t CLOCK_GetOsc0ErClkFreq(void) } } +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -164,11 +155,21 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { uint32_t freq; @@ -179,6 +180,11 @@ uint32_t CLOCK_GetFlashClkFreq(void) return freq; } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { uint32_t freq; @@ -189,11 +195,26 @@ uint32_t CLOCK_GetBusClkFreq(void) return freq; } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -233,12 +254,26 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { bool ret = true; @@ -265,6 +300,14 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG_Lite internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { uint8_t divider1 = MCG_SC_FCRDIV_VAL; @@ -273,6 +316,14 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetLircClkFreq() >> (divider1 + divider2); } +/* + * brief Gets the current MCGPCLK frequency. + * + * This function gets the MCGPCLK frequency in Hz based on the current MCG_Lite + * register settings. + * + * return The frequency of MCGPCLK. + */ uint32_t CLOCK_GetPeriphClkFreq(void) { /* Check whether the HIRC is enabled. */ @@ -286,6 +337,14 @@ uint32_t CLOCK_GetPeriphClkFreq(void) } } +/*! + * brief Gets the MCG_Lite output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG_Lite output clock frequency in Hz based on the current + * MCG_Lite register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t freq; @@ -311,6 +370,13 @@ uint32_t CLOCK_GetOutClkFreq(void) return freq; } +/*! + * brief Gets the current MCG_Lite mode. + * + * This function checks the MCG_Lite registers and determines the current MCG_Lite mode. + * + * return The current MCG_Lite mode or error code. + */ mcglite_mode_t CLOCK_GetMode(void) { mcglite_mode_t mode; @@ -341,6 +407,15 @@ mcglite_mode_t CLOCK_GetMode(void) return mode; } +/*! + * brief Sets the MCG_Lite configuration. + * + * This function configures the MCG_Lite, includes the output clock source, MCGIRCLK + * settings, HIRC settings, and so on. See ref mcglite_config_t for details. + * + * param targetConfig Pointer to the target MCG_Lite mode configuration structure. + * return Error code. + */ status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig) { assert(targetConfig); @@ -383,6 +458,13 @@ status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig) return kStatus_Success; } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); @@ -401,8 +483,39 @@ void CLOCK_InitOsc0(osc_config_t const *config) } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; MCG->C2 &= MCG_C2_IRCS_MASK; } + +/*! + * brief Delay at least for several microseconds. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + + uint32_t count = (uint32_t)USEC_TO_COUNT(delay_us, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); + + /* + * Calculate the real delay count depend on the excute instructions cycles, + * users can change the divider value to adapt to the real IDE optimise level. + */ + count = (count / 4U); + + for (; count > 0UL; count--) + { + __NOP(); + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_clock.h index dd5594b0be..c0fb08c807 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_clock.h @@ -1,77 +1,79 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include -#include -#include +#include "fsl_common.h" -/*! @addtogroup mcglite */ +/*! @addtogroup clock */ /*! @{ */ +/*! @file */ + +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could control the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + /******************************************************************************* * Definitions ******************************************************************************/ -/*! @brief Clock driver version. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ +/*! @name Driver version */ +/*@{*/ +/*! @brief CLOCK driver version 2.2.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*@}*/ + +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY 48000000 +#endif /*! @brief External XTAL0 (OSC0) clock frequency. * - * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal0Freq to set the value in to clock driver. For example, - * if XTAL0 is 8MHz, + * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, + * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Setup the OSC0 + * CLOCK_InitOsc0(...); // Set up the OSC0 * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to clock driver. * @endcode * - * This is important for the multicore platforms, only one core needs to setup - * OSC0 using CLOCK_InitOsc0, all other cores need to call CLOCK_SetXtal0Freq - * to get valid clock frequency. + * This is important for the multicore platforms where one core needs to set up the + * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq + * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; -/*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. +/*! @brief The external XTAL32/EXTAL32/RTC_CLKIN clock frequency. * - * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal32Freq to set the value in to clock driver. + * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal32Freq to set the value in the clock driver. * - * This is important for the multicore platforms, only one core needs to setup - * the clock, all other cores need to call CLOCK_SetXtal32Freq - * to get valid clock frequency. + * This is important for the multicore platforms where one core needs to set up + * the clock. All other cores need to call the CLOCK_SetXtal32Freq + * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; /*! @brief Clock ip name array for DMAMUX. */ #define DMAMUX_CLOCKS \ @@ -182,9 +184,9 @@ extern uint32_t g_xtal32Freq; } /*! @brief Clock ip name array for CMP. */ -#define CMP_CLOCKS \ - { \ - kCLOCK_Cmp0, kCLOCK_Cmp1, kCLOCK_Cmp2 \ +#define CMP_CLOCKS \ + { \ + kCLOCK_Cmp0 \ } /*! @@ -240,7 +242,7 @@ typedef enum _clock_name typedef enum _clock_usb_src { kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ } clock_usb_src_t; /*------------------------------------------------------------------------------ @@ -274,38 +276,36 @@ typedef enum _clock_usb_src typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), - kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), - kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x1034U, 22U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x1034U, 23U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), + kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x1034U, 22U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x1034U, 23U), - kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), - kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), - kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), - kCLOCK_Slcd0 = CLK_GATE_DEFINE(0x1038U, 19U), + kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), + kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), + kCLOCK_Slcd0 = CLK_GATE_DEFINE(0x1038U, 19U), kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x1038U, 20U), kCLOCK_Lpuart1 = CLK_GATE_DEFINE(0x1038U, 21U), kCLOCK_Flexio0 = CLK_GATE_DEFINE(0x1038U, 31U), - kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), - kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), - kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), + kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 8U), } clock_ip_name_t; @@ -320,30 +320,30 @@ typedef struct _sim_clock_config /*! @brief Oscillator capacitor load setting.*/ enum _osc_cap_load { - kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ - kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ - kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */ }; /*! @brief OSCERCLK enable mode. */ enum _oscer_enable_mode { - kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ + kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */ }; -/*! @brief OSC configuration for OSCERCLK. */ +/*! @brief The OSC configuration for OSCERCLK. */ typedef struct _oscer_config { uint8_t enableMode; /*!< OSCERCLK enable mode. OR'ed value of \ref _oscer_enable_mode. */ } oscer_config_t; -/*! @brief OSC work mode. */ +/*! @brief The OSC work mode. */ typedef enum _osc_mode { - kOSC_ModeExt = 0U, /*!< Use external clock. */ + kOSC_ModeExt = 0U, /*!< Use external clock. */ kOSC_ModeOscLowPower = MCG_C2_EREFS0_MASK, /*!< Oscillator low power. */ kOSC_ModeOscHighGain = MCG_C2_EREFS0_MASK | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ } osc_mode_t; @@ -353,7 +353,7 @@ typedef enum _osc_mode * * Defines the configuration data structure to initialize the OSC. * When porting to a new board, set the following members - * according to board settings: + * according to the board settings: * 1. freq: The external frequency. * 2. workMode: The OSC module mode. */ @@ -377,8 +377,8 @@ typedef enum _mcglite_clkout_src /*! @brief MCG_Lite LIRC select. */ typedef enum _mcglite_lirc_mode { - kMCGLITE_Lirc2M, /*!< Slow internal reference(LIRC) 2MHz clock selected */ - kMCGLITE_Lirc8M, /*!< Slow internal reference(LIRC) 8MHz clock selected */ + kMCGLITE_Lirc2M, /*!< Slow internal reference(LIRC) 2 MHz clock selected */ + kMCGLITE_Lirc8M, /*!< Slow internal reference(LIRC) 8 MHz clock selected */ } mcglite_lirc_mode_t; /*! @brief MCG_Lite divider factor selection for clock source*/ @@ -407,7 +407,7 @@ typedef enum _mcglite_mode /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcglite_irclk_enable_mode { - kMCGLITE_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCGLITE_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCGLITE_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; @@ -430,26 +430,6 @@ typedef struct _mcglite_config extern "C" { #endif /* __cplusplus */ -/*! - * @brief Set the XTAL0 frequency based on board setting. - * - * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal0Freq(uint32_t freq) -{ - g_xtal0Freq = freq; -} - -/*! - * @brief Set the XTAL32/RTC_CLKIN frequency based on board setting. - * - * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal32Freq(uint32_t freq) -{ - g_xtal32Freq = freq; -} - /*! * @brief Enable the clock for specific IP. * @@ -661,7 +641,7 @@ static inline void CLOCK_SetSimSafeDivs(void) /*! * @brief Gets the MCG_Lite output clock (MCGOUTCLK) frequency. * - * This function gets the MCG_Lite output clock frequency (Hz) based on the current + * This function gets the MCG_Lite output clock frequency in Hz based on the current * MCG_Lite register value. * * @return The frequency of MCGOUTCLK. @@ -671,7 +651,7 @@ uint32_t CLOCK_GetOutClkFreq(void); /*! * @brief Gets the MCG internal reference clock (MCGIRCLK) frequency. * - * This function gets the MCG_Lite internal reference clock frequency (Hz) based + * This function gets the MCG_Lite internal reference clock frequency in Hz based * on the current MCG register value. * * @return The frequency of MCGIRCLK. @@ -679,13 +659,13 @@ uint32_t CLOCK_GetOutClkFreq(void); uint32_t CLOCK_GetInternalRefClkFreq(void); /*! -* @brief Gets the current MCGPCLK frequency. -* -* This function gets the MCGPCLK frequency (Hertz) based on the current MCG_Lite -* register settings. -* -* @return The frequency of MCGPCLK. -*/ + * @brief Gets the current MCGPCLK frequency. + * + * This function gets the MCGPCLK frequency in Hz based on the current MCG_Lite + * register settings. + * + * @return The frequency of MCGPCLK. + */ uint32_t CLOCK_GetPeriphClkFreq(void); /*! @}*/ @@ -700,15 +680,15 @@ uint32_t CLOCK_GetPeriphClkFreq(void); * * This function checks the MCG_Lite registers and determines the current MCG_Lite mode. * - * @return Current MCG_Lite mode or error code. + * @return The current MCG_Lite mode or error code. */ mcglite_mode_t CLOCK_GetMode(void); /*! * @brief Sets the MCG_Lite configuration. * - * This function configures the MCG_Lite, include output clock source, MCGIRCLK - * setting, HIRC setting and so on, see @ref mcglite_config_t for details. + * This function configures the MCG_Lite, includes the output clock source, MCGIRCLK + * settings, HIRC settings, and so on. See @ref mcglite_config_t for details. * * @param targetConfig Pointer to the target MCG_Lite mode configuration structure. * @return Error code. @@ -726,8 +706,8 @@ status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig); * @brief Configures the OSC external reference clock (OSCERCLK). * * This function configures the OSC external reference clock (OSCERCLK). - * For example, to enable the OSCERCLK in normal mode and stop mode, and also set - * the output divider to 1, as follows: + * This is an example to enable the OSCERCLK in normal mode and stop mode, and set + * the output divider to 1. * @code oscer_config_t config = @@ -755,12 +735,12 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * /*! * @brief Sets the capacitor load configuration for the oscillator. * - * This function sets the specified capacitors configuration for the oscillator. + * This function sets the specified capacitor configuration for the oscillator. * This should be done in the early system level initialization function call * based on the system configuration. * * @param base OSC peripheral address. - * @param capLoad OR'ed value for the capacitor load option, see \ref _osc_cap_load. + * @param capLoad OR'ed value for the capacitor load option.See \ref _osc_cap_load. * * Example: @code @@ -780,7 +760,7 @@ static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad) } /*! - * @brief Initialize OSC0. + * @brief Initializes the OSC0. * * This function initializes the OSC0 according to the board configuration. * @@ -797,6 +777,42 @@ void CLOCK_DeinitOsc0(void); /*! @}*/ +/*! + * @name External clock frequency + * @{ + */ + +/*! + * @brief Sets the XTAL0 frequency based on board settings. + * + * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal0Freq(uint32_t freq) +{ + g_xtal0Freq = freq; +} + +/*! + * @brief Sets the XTAL32/RTC_CLKIN frequency based on board settings. + * + * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal32Freq(uint32_t freq) +{ + g_xtal32Freq = freq; +} +/* @} */ + +/*! + * @brief Delay at least for several microseconds. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + #if defined(__cplusplus) } #endif /* __cplusplus */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_clock.c index 6861c4db54..79545b6028 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_clock.c @@ -1,40 +1,22 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include "fsl_common.h" #include "fsl_clock.h" /******************************************************************************* * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + /* Macro definition remap workaround. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) #define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK @@ -65,11 +47,11 @@ #define TRIM_SIRC_MIN (31250U) #define MCG_S_IRCST_VAL ((MCG->S & MCG_S_IRCST_MASK) >> MCG_S_IRCST_SHIFT) -#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) -#define MCG_S_IREFST_VAL ((MCG->S & MCG_S_IREFST_MASK) >> MCG_S_IREFST_SHIFT) +#define MCG_S_CLKST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_CLKST_MASK) >> (uint32_t)MCG_S_CLKST_SHIFT) +#define MCG_S_IREFST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IREFST_MASK) >> (uint32_t)MCG_S_IREFST_SHIFT) #define MCG_S_PLLST_VAL ((MCG->S & MCG_S_PLLST_MASK) >> MCG_S_PLLST_SHIFT) #define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT) -#define MCG_C2_LP_VAL ((MCG->C2 & MCG_C2_LP_MASK) >> MCG_C2_LP_SHIFT) +#define MCG_C2_LP_VAL (((uint32_t)MCG->C2 & (uint32_t)MCG_C2_LP_MASK) >> (uint32_t)MCG_C2_LP_SHIFT) #define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT) #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) #define MCG_S2_PLLCST_VAL ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT) @@ -121,9 +103,9 @@ static uint32_t s_slowIrcFreq = 32768U; static uint32_t s_fastIrcFreq = 4000000U; /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -192,6 +174,7 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * @@ -199,11 +182,33 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ static void CLOCK_FllStableDelay(void); +#endif /******************************************************************************* * Code ******************************************************************************/ +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN +static void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (0U != (i--)) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardless how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ + static uint32_t CLOCK_GetMcgExtClkFreq(void) { uint32_t freq; @@ -212,12 +217,12 @@ static uint32_t CLOCK_GetMcgExtClkFreq(void) { case 0U: /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ - assert(g_xtal0Freq); + assert(0U != g_xtal0Freq); freq = g_xtal0Freq; break; case 1U: /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ - assert(g_xtal32Freq); + assert(0U != g_xtal32Freq); freq = g_xtal32Freq; break; case 2U: @@ -240,7 +245,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) uint32_t freq = CLOCK_GetMcgExtClkFreq(); - if (!freq) + if (0U == freq) { return freq; } @@ -248,7 +253,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) frdiv = MCG_C1_FRDIV_VAL; freq >>= frdiv; - range = MCG_C2_RANGE_VAL; + range = MCG_C2_RANGE_VAL; oscsel = MCG_C7_OSCSEL_VAL; /* @@ -256,7 +261,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) 1. MCG_C7[OSCSEL] selects IRC48M. 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0. */ - if (((0U != range) && (kMCG_OscselOsc == oscsel)) || (kMCG_OscselIrc == oscsel)) + if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel)) || ((uint8_t)kMCG_OscselIrc == oscsel)) { switch (frdiv) { @@ -287,7 +292,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) { - if (kMCG_IrcSlow == MCG_S_IRCST_VAL) + if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL) { /* Slow internal reference clock selected*/ return s_slowIrcFreq; @@ -302,7 +307,7 @@ static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) static uint32_t CLOCK_GetFllRefClkFreq(void) { /* If use external reference clock. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { return CLOCK_GetFllExtRefClkFreq(); } @@ -339,19 +344,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - +/*! + * brief Get the OSC0 external reference undivided clock frequency (OSC0ERCLK_UNDIV). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -366,6 +363,11 @@ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) } } +/*! + * brief Get the OSC0 external reference divided clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkDivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -380,6 +382,11 @@ uint32_t CLOCK_GetOsc0ErClkDivFreq(void) } } +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -404,6 +411,11 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the output clock frequency selected by SIM[PLLFLLSEL]. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPllFllSelClkFreq(void) { uint32_t freq; @@ -429,36 +441,76 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) return freq; } +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { return CLOCK_GetOsc0ErClkDivFreq(); } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); } +/*! + * brief Get the QSPI bus interface clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetQspiBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV5_VAL + 1); } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -516,6 +568,13 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; @@ -523,6 +582,13 @@ void CLOCK_SetSimConfig(sim_clock_config_t const *config) CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { bool ret = true; @@ -567,23 +633,31 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! + * brief Gets the MCG output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG output clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; - uint32_t clkst = MCG_S_CLKST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; switch (clkst) { - case kMCG_ClkOutStatPll: + case (uint32_t)kMCG_ClkOutStatPll: mcgoutclk = CLOCK_GetPll0Freq(); break; - case kMCG_ClkOutStatFll: + case (uint32_t)kMCG_ClkOutStatFll: mcgoutclk = CLOCK_GetFllFreq(); break; - case kMCG_ClkOutStatInt: + case (uint32_t)kMCG_ClkOutStatInt: mcgoutclk = CLOCK_GetInternalRefClkSelectFreq(); break; - case kMCG_ClkOutStatExt: + case (uint32_t)kMCG_ClkOutStatExt: mcgoutclk = CLOCK_GetMcgExtClkFreq(); break; default: @@ -593,6 +667,15 @@ uint32_t CLOCK_GetOutClkFreq(void) return mcgoutclk; } +/*! + * brief Gets the MCG FLL clock (MCGFLLCLK) frequency. + * + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. + * + * return The frequency of MCGFLLCLK. + */ uint32_t CLOCK_GetFllFreq(void) { static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; @@ -601,28 +684,36 @@ uint32_t CLOCK_GetFllFreq(void) uint32_t freq; /* If FLL is not enabled currently, then return 0U. */ - if ((MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) + if (0U != (MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) { return 0U; } /* Get FLL reference clock frequency. */ freq = CLOCK_GetFllRefClkFreq(); - if (!freq) + if (0U == freq) { return freq; } - drs = MCG_C4_DRST_DRS_VAL; + drs = MCG_C4_DRST_DRS_VAL; dmx32 = MCG_C4_DMX32_VAL; return freq * fllFactorTable[drs][dmx32]; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { /* If MCGIRCLK is gated. */ - if (!(MCG->C1 & MCG_C1_IRCLKEN_MASK)) + if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK)) { return 0U; } @@ -630,12 +721,20 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetInternalRefClkSelectFreq(); } +/*! + * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. + * + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGFFCLK. + */ uint32_t CLOCK_GetFixedFreqClkFreq(void) { uint32_t freq = CLOCK_GetFllRefClkFreq(); /* MCGFFCLK must be no more than MCGOUTCLK/8. */ - if ((freq) && (freq <= (CLOCK_GetOutClkFreq() / 8U))) + if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq)) { return freq; } @@ -645,6 +744,14 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void) } } +/*! + * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. + * + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGPLL0CLK. + */ uint32_t CLOCK_GetPll0Freq(void) { uint32_t mcgpll0clk; @@ -670,6 +777,18 @@ uint32_t CLOCK_GetPll0Freq(void) return mcgpll0clk; } +/*! + * brief Selects the MCG external reference clock. + * + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. + * + * param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. + * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success External reference clock set successfully. + */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) { bool needDelay; @@ -683,7 +802,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } #endif /* MCG_CONFIG_CHECK_PARAM */ - if (MCG_C7_OSCSEL_VAL != oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel) { /* If change OSCSEL, need to delay, ERR009878. */ needDelay = true; @@ -693,22 +812,12 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) needDelay = false; } - MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - + MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ i = 1500U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -717,15 +826,31 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Configures the Internal Reference clock (MCGIRCLK). + * + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. + * + * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * param ircs MCGIRCLK clock source, choose fast or slow. + * param fcrdiv Fast IRC divider setting (\c FCRDIV). + * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success MCGIRCLK configuration finished successfully. + */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) { - uint32_t mcgOutClkState = MCG_S_CLKST_VAL; - mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; - uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; + uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL; + mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; + uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) /* If MCGIRCLK is used as system clock source. */ - if (kMCG_ClkOutStatInt == mcgOutClkState) + if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState) { /* If need to change MCGIRCLK source or driver, return error. */ if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs)) @@ -739,25 +864,27 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, if (fcrdiv != curFcrdiv) { /* If fast IRC is in use currently, change to slow IRC. */ - if ((kMCG_IrcFast == curIrcs) && ((mcgOutClkState == kMCG_ClkOutStatInt) || (MCG->C1 & MCG_C1_IRCLKEN_MASK))) + if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) && + (kMCG_IrcFast == curIrcs)) { - MCG->C2 = ((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); - while (MCG_S_IRCST_VAL != kMCG_IrcSlow) + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); + while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow) { } } /* Update FCRDIV. */ - MCG->SC = (MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); + MCG->SC = + (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); } /* Set internal reference clock selection. */ - MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)); - MCG->C1 = (MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode; + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs))); + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode); /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */ - if ((mcgOutClkState == kMCG_ClkOutStatInt) || (enableMode & kMCG_IrclkEnable)) + if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable))) { - while (MCG_S_IRCST_VAL != ircs) + while (MCG_S_IRCST_VAL != (uint8_t)ircs) { } } @@ -765,17 +892,32 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, return kStatus_Success; } +/*! + * brief Calculates the PLL divider setting for a desired output frequency. + * + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function + * returns 0. + * + * param refFreq PLL reference clock frequency. + * param desireFreq Desired PLL output frequency. + * param prdiv PRDIV value to generate desired PLL frequency. + * param vdiv VDIV value to generate desired PLL frequency. + * return Closest frequency match that the PLL was able generate. + */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv) { - uint8_t ret_prdiv; /* PRDIV to return. */ - uint8_t ret_vdiv; /* VDIV to return. */ - uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_cur; /* PRDIV value for iteration. */ - uint8_t vdiv_cur; /* VDIV value for iteration. */ - uint32_t ret_freq = 0U; /* PLL output fequency to return. */ - uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ - uint32_t ref_div; /* Reference frequency after PRDIV. */ + uint8_t ret_prdiv; /* PRDIV to return. */ + uint8_t ret_vdiv; /* VDIV to return. */ + uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_cur; /* PRDIV value for iteration. */ + uint8_t vdiv_cur; /* VDIV value for iteration. */ + uint32_t ret_freq = 0U; /* PLL output frequency to return. */ + uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ + uint32_t ref_div; /* Reference frequency after PRDIV. */ /* Steps: @@ -824,15 +966,15 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (ret_freq == desireFreq) /* If desire frequency is got. */ { *prdiv = prdiv_cur - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; return ret_freq / 2U; } /* New PRDIV/VDIV is closer. */ if (diff > desireFreq - ret_freq) { - diff = desireFreq - ret_freq; + diff = desireFreq - ret_freq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } vdiv_cur++; @@ -842,9 +984,9 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, /* New PRDIV/VDIV is closer. */ if (diff > ret_freq - desireFreq) { - diff = ret_freq - desireFreq; + diff = ret_freq - desireFreq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } } @@ -852,8 +994,8 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (0xFFFFFFFFU != diff) { /* PRDIV/VDIV found. */ - *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; + *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; ret_freq = (refFreq / ret_prdiv) * ret_vdiv; return ret_freq / 2U; } @@ -864,6 +1006,17 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, } } +/*! + * brief Enables the PLL0 in FLL mode. + * + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL + * divider values. + * + * param config Pointer to the configuration structure. + */ void CLOCK_EnablePll0(mcg_pll_config_t const *config) { assert(config); @@ -884,20 +1037,27 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ - MCG->SC &= ~MCG_SC_ATMF_MASK; + MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK; if (kMCG_MonitorNone == mode) { - MCG->C6 &= ~MCG_C6_CME0_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK; } else { if (kMCG_MonitorInt == mode) { - MCG->C2 &= ~MCG_C2_LOCRE0_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK; } else { @@ -907,11 +1067,18 @@ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the RTC OSC clock monitor mode. + * + * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8 = MCG->C8; - mcg_c8 &= ~(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); + mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); if (kMCG_MonitorNone != mode) { @@ -924,6 +1091,13 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) MCG->C8 = mcg_c8; } +/*! + * brief Sets the PLL0 clock monitor mode. + * + * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8; @@ -954,34 +1128,76 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Gets the MCG status flags. + * + * This function gets the MCG clock status flags. All status flags are + * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To + * check a specific flag, compare the return value with the flag. + * + * Example: + * code + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * endcode + * + * return Logical OR value of the ref _mcg_status_flags_t. + */ uint32_t CLOCK_GetStatusFlags(void) { - uint32_t ret = 0U; + uint32_t ret = 0U; uint8_t mcg_s = MCG->S; if (MCG->SC & MCG_SC_LOCS0_MASK) { - ret |= kMCG_Osc0LostFlag; + ret |= (uint32_t)kMCG_Osc0LostFlag; } if (mcg_s & MCG_S_OSCINIT0_MASK) { - ret |= kMCG_Osc0InitFlag; + ret |= (uint32_t)kMCG_Osc0InitFlag; } - if (MCG->C8 & MCG_C8_LOCS1_MASK) + if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK)) { - ret |= kMCG_RtcOscLostFlag; + ret |= (uint32_t)kMCG_RtcOscLostFlag; } if (mcg_s & MCG_S_LOLS0_MASK) { - ret |= kMCG_Pll0LostFlag; + ret |= (uint32_t)kMCG_Pll0LostFlag; } if (mcg_s & MCG_S_LOCK0_MASK) { - ret |= kMCG_Pll0LockFlag; + ret |= (uint32_t)kMCG_Pll0LockFlag; } return ret; } +/*! + * brief Clears the MCG status flags. + * + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See ref _mcg_status_flags_t. + * + * Example: + * code + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * endcode + * + * param mask The status flags to clear. This is a logical OR of members of the + * enumeration ref _mcg_status_flags_t. + */ void CLOCK_ClearStatusFlags(uint32_t mask) { uint8_t reg; @@ -990,9 +1206,9 @@ void CLOCK_ClearStatusFlags(uint32_t mask) { MCG->SC &= ~MCG_SC_ATMF_MASK; } - if (mask & kMCG_RtcOscLostFlag) + if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag)) { - reg = MCG->C8; + reg = MCG->C8; MCG->C8 = reg; } if (mask & kMCG_Pll0LostFlag) @@ -1001,30 +1217,60 @@ void CLOCK_ClearStatusFlags(uint32_t mask) } } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); OSC_SetCapLoad(OSC0, config->capLoad); - OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); - MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) { /* Wait for stable. */ - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; - MCG->C2 &= ~OSC_MODE_MASK; + MCG->C2 &= ~(uint8_t)OSC_MODE_MASK; } +/*! + * brief Auto trims the internal reference clock. + * + * This function trims the internal reference clock by using the external clock. If + * successful, it returns the kStatus_Success and the frequency after + * trimming is received in the parameter p actualFreq. If an error occurs, + * the error code is returned. + * + * param extFreq External clock frequency, which should be a bus clock. + * param desireFreq Frequency to trim to. + * param actualFreq Actual frequency after trimming. + * param atms Trim fast or slow internal reference clock. + * retval kStatus_Success ATM success. + * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. + * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. + * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. + */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) { uint32_t multi; /* extFreq / desireFreq */ @@ -1058,7 +1304,7 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ } multi = extFreq / desireFreq; - actv = multi * 21U; + actv = multi * 21U; if (kMCG_AtmSel4m == atms) { @@ -1070,17 +1316,17 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ MCG->ATCVH = (uint8_t)(actv >> 8U); mcg_sc = MCG->SC; - mcg_sc &= ~(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); + mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms)); MCG->SC = (mcg_sc | MCG_SC_ATME_MASK); /* Wait for finished. */ - while (MCG->SC & MCG_SC_ATME_MASK) + while (0U != (MCG->SC & MCG_SC_ATME_MASK)) { } /* Error occurs? */ - if (MCG->SC & MCG_SC_ATMF_MASK) + if (0U != (MCG->SC & MCG_SC_ATMF_MASK)) { /* Clear the failed flag. */ MCG->SC = mcg_sc; @@ -1101,13 +1347,20 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ return kStatus_Success; } +/*! + * brief Gets the current MCG mode. + * + * This function checks the MCG registers and determines the current MCG mode. + * + * return Current MCG mode or error code; See ref mcg_mode_t. + */ mcg_mode_t CLOCK_GetMode(void) { mcg_mode_t mode = kMCG_ModeError; - uint32_t clkst = MCG_S_CLKST_VAL; - uint32_t irefst = MCG_S_IREFST_VAL; - uint32_t lp = MCG_C2_LP_VAL; - uint32_t pllst = MCG_S_PLLST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; + uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL; + uint32_t lp = (uint32_t)MCG_C2_LP_VAL; + uint32_t pllst = MCG_S_PLLST_VAL; /*------------------------------------------------------------------ Mode and Registers @@ -1148,59 +1401,77 @@ mcg_mode_t CLOCK_GetMode(void) ----------------------------------------------------------------------*/ - switch (clkst) + if (clkst == (uint32_t)kMCG_ClkOutStatFll) { - case kMCG_ClkOutStatFll: - if (kMCG_FllSrcExternal == irefst) + if ((uint32_t)kMCG_FllSrcExternal == irefst) + { + mode = kMCG_ModeFEE; + } + else + { + mode = kMCG_ModeFEI; + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatInt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPI; + } + else + { { - mode = kMCG_ModeFEE; + mode = kMCG_ModeFBI; + } + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatExt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPE; + } + else + { + if (kMCG_PllstPll == pllst) + { + mode = kMCG_ModePBE; } else { - mode = kMCG_ModeFEI; + mode = kMCG_ModeFBE; } - break; - case kMCG_ClkOutStatInt: - if (lp) - { - mode = kMCG_ModeBLPI; - } - else - { - { - mode = kMCG_ModeFBI; - } - } - break; - case kMCG_ClkOutStatExt: - if (lp) - { - mode = kMCG_ModeBLPE; - } - else - { - if (kMCG_PllstPll == pllst) - { - mode = kMCG_ModePBE; - } - else - { - mode = kMCG_ModeFBE; - } - } - break; - case kMCG_ClkOutStatPll: + } + } + if (clkst == (uint32_t)kMCG_ClkOutStatPll) + { { mode = kMCG_ModePEE; } - break; - default: - break; + } + else + { + /*do nothing*/ } return mode; } +/*! + * brief Sets the MCG to FEI mode. + * + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. + */ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1221,7 +1492,7 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1229,12 +1500,12 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal)); /* IREFS = 1 */ + MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1245,15 +1516,16 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1261,6 +1533,21 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FEE mode. + * + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1281,7 +1568,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1289,13 +1576,24 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait and check status. */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1306,7 +1604,8 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); MCG->C4 = mcg_c4; /* Wait for DRST_DRS update. */ @@ -1315,12 +1614,12 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1328,6 +1627,22 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to FBI mode. + * + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FBI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1346,7 +1661,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela mcg_c4 = MCG->C4; - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ /* Errata: ERR007993 @@ -1354,7 +1669,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1362,12 +1677,12 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1377,14 +1692,15 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela MCG->C4 = mcg_c4; } - while (kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1392,6 +1708,21 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FBE mode. + * + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FBE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1407,13 +1738,13 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void #endif /* Change to FLL mode. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } /* Set LP bit to enable the FLL */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; mcg_c4 = MCG->C4; @@ -1423,7 +1754,7 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1431,13 +1762,24 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for Reference clock Status bit to clear */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1448,15 +1790,16 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRST_DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for clock status bits to show clock source is ext ref clk */ - while (kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) { } /* Wait for fll stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1464,10 +1807,19 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to BLPI mode. + * + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpiMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { return kStatus_MCG_ModeUnreachable; } @@ -1479,10 +1831,19 @@ status_t CLOCK_SetBlpiMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode. + * + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { return kStatus_MCG_ModeUnreachable; } @@ -1494,8 +1855,29 @@ status_t CLOCK_SetBlpeMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to PBE mode. + * + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. + * + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. + * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); + */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { + assert(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. @@ -1524,6 +1906,8 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co /* Change to PLL mode. */ MCG->C6 |= MCG_C6_PLLS_MASK; + + /* Wait for PLL mode changed. */ while (!(MCG->S & MCG_S_PLLST_MASK)) { } @@ -1531,6 +1915,18 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode. + * + * This function sets the MCG to PEE mode. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. + */ status_t CLOCK_SetPeeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1545,13 +1941,29 @@ status_t CLOCK_SetPeeMode(void) MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); /* Wait for clock status bits to update */ - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } return kStatus_Success; } +/*! + * brief Switches the MCG to FBE mode from the external mode. + * + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: + * + * code + * CLOCK_ExternalModeToFbeModeQuick(); + * CLOCK_SetFeiMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. + */ status_t CLOCK_ExternalModeToFbeModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1562,15 +1974,15 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) #endif /* MCG_CONFIG_CHECK_PARAM */ /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } /* Disable PLL. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } @@ -1578,6 +1990,22 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBI mode from internal modes. + * + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: + * + * code + * CLOCK_InternalModeToFbiModeQuick(); + * CLOCK_SetFeeMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. + */ status_t CLOCK_InternalModeToFbiModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1588,37 +2016,80 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) #endif /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } return kStatus_Success; } +/*! + * brief Sets the MCG to FEI mode during system boot up. + * + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to FEE mode during system bootup. + * + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, OSCSEL. + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to BLPI mode during system boot up. + * + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param fcrdiv Fast IRC divider, FCRDIV. + * param ircs The internal reference clock to select, IRCS. + * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * + * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) { /* If reset mode is FEI mode, set MCGIRCLK and always success. */ - CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); /* If reset mode is not BLPI, first enter FBI mode. */ - MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } @@ -1628,14 +2099,36 @@ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEn return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode during system boot up. + * + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); /* Set to FBE mode. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != @@ -1649,6 +2142,19 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode during system boot up. + * + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1659,7 +2165,7 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc /* Change to use PLL output clock. */ MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } @@ -1695,6 +2201,20 @@ static const mcg_mode_t mcgModeMatrix[8][8] = { /* FEI FBI BLPI FEE FBE BLPE PBE PEE */ }; +/*! + * brief Sets the MCG to a target mode. + * + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. + * + * param config Pointer to the target MCG mode configuration structure. + * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. + * + * note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. + */ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) { mcg_mode_t next_mode; @@ -1703,30 +2223,30 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) mcg_pll_clk_select_t pllcs = kMCG_PllClkSelPll0; /* If need to change external clock, MCG_C7[OSCSEL]. */ - if (MCG_C7_OSCSEL_VAL != config->oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel)) { /* If external clock is in use, change to FEI first. */ - if (!(MCG->S & MCG_S_IRCST_MASK)) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { - CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); + (void)CLOCK_ExternalModeToFbeModeQuick(); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL); } - CLOCK_SetExternalRefClkConfig(config->oscsel); + (void)CLOCK_SetExternalRefClkConfig(config->oscsel); } /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */ - if (MCG_S_CLKST_VAL == kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt) { - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } /* Configure MCGIRCLK. */ - CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); next_mode = CLOCK_GetMode(); @@ -1743,10 +2263,10 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL); break; case kMCG_ModeFBE: - status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL); break; case kMCG_ModeBLPI: status = CLOCK_SetBlpiMode(); @@ -1765,7 +2285,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) else { MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } } @@ -1788,7 +2308,33 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) } else { - MCG->C5 &= ~(uint32_t)kMCG_PllEnableIndependent; + MCG->C5 &= ~(uint8_t)kMCG_PllEnableIndependent; } return kStatus_Success; } + +/*! + * brief Delay at least for several microseconds. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + + uint32_t count = (uint32_t)USEC_TO_COUNT(delay_us, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); + + /* + * Calculate the real delay count depend on the excute instructions cycles, + * users can change the divider value to adapt to the real IDE optimise level. + */ + count = (count / 4U); + + for (; count > 0UL; count--) + { + __NOP(); + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_clock.h index ba7428f4c2..60639b541c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_clock.h @@ -1,71 +1,89 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include -#include -#include +#include "fsl_common.h" /*! @addtogroup clock */ /*! @{ */ /*! @file */ +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could control the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.0. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief CLOCK driver version 2.3.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) /*@}*/ +/* Definition for delay API in clock driver, users can redefine it to the real application. */ +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (48000000UL) +#endif + /*! @brief External XTAL0 (OSC0) clock frequency. * * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Set up the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. + * Set up the OSC0 + * CLOCK_InitOsc0(...); + * Set the XTAL0 value to the clock driver. + * CLOCK_SetXtal0Freq(80000000); * @endcode * * This is important for the multicore platforms where only one core needs to set up the * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * @@ -76,7 +94,7 @@ extern uint32_t g_xtal0Freq; * the clock. All other cores need to call the CLOCK_SetXtal32Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; /*! @brief IRC48M clock frequency in Hz. */ #define MCG_INTERNAL_IRC_48M 48000000U @@ -170,9 +188,9 @@ extern uint32_t g_xtal32Freq; } /*! @brief Clock ip name array for MPU. */ -#define MPU_CLOCKS \ - { \ - kCLOCK_Mpu0 \ +#define MPU_CLOCKS \ + { \ + kCLOCK_Sysmpu0 \ } /*! @brief Clock ip name array for FLEXIO. */ @@ -280,9 +298,9 @@ typedef enum _clock_name /*! @brief USB clock source definition. */ typedef enum _clock_usb_src { - kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ + kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(3U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ } clock_usb_src_t; /*------------------------------------------------------------------------------ @@ -318,49 +336,49 @@ typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), - kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), + kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), kCLOCK_Secreg0 = CLK_GATE_DEFINE(0x1038U, 3U), - kCLOCK_Lptmr1 = CLK_GATE_DEFINE(0x1038U, 4U), - kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), - kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), - kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), + kCLOCK_Lptmr1 = CLK_GATE_DEFINE(0x1038U, 4U), + kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), + kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), kCLOCK_Emvsim0 = CLK_GATE_DEFINE(0x1038U, 14U), kCLOCK_Emvsim1 = CLK_GATE_DEFINE(0x1038U, 15U), - kCLOCK_Ltc0 = CLK_GATE_DEFINE(0x1038U, 17U), + kCLOCK_Ltc0 = CLK_GATE_DEFINE(0x1038U, 17U), kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x1038U, 20U), kCLOCK_Lpuart1 = CLK_GATE_DEFINE(0x1038U, 21U), kCLOCK_Lpuart2 = CLK_GATE_DEFINE(0x1038U, 22U), - kCLOCK_Qspi0 = CLK_GATE_DEFINE(0x1038U, 26U), + kCLOCK_Qspi0 = CLK_GATE_DEFINE(0x1038U, 26U), kCLOCK_Flexio0 = CLK_GATE_DEFINE(0x1038U, 31U), - kCLOCK_Nvm0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Nvm0 = CLK_GATE_DEFINE(0x103CU, 0U), kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), kCLOCK_Intmux0 = CLK_GATE_DEFINE(0x103CU, 4U), - kCLOCK_Trng0 = CLK_GATE_DEFINE(0x103CU, 5U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), - kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Trng0 = CLK_GATE_DEFINE(0x103CU, 5U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), + kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), kCLOCK_Rtc_Rf0 = CLK_GATE_DEFINE(0x103CU, 30U), - kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), + kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), - kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), - kCLOCK_Mpu0 = CLK_GATE_DEFINE(0x1040U, 2U), + kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), + kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), } clock_ip_name_t; /*!@brief SIM configuration structure for clock setting. */ @@ -384,34 +402,30 @@ typedef enum _osc_mode #endif kOSC_ModeOscHighGain = 0U #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) - | - MCG_C2_EREFS_MASK + | MCG_C2_EREFS_MASK #else - | - MCG_C2_EREFS0_MASK + | MCG_C2_EREFS0_MASK #endif #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK))) - | - MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ #else - | - MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ #endif } osc_mode_t; /*! @brief Oscillator capacitor load setting.*/ enum _osc_cap_load { - kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ - kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ - kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */ }; /*! @brief OSCERCLK enable mode. */ enum _oscer_enable_mode { - kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ + kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */ }; @@ -519,30 +533,30 @@ typedef enum _mcg_monitor_mode enum _mcg_status { kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0), /*!< Can't switch to target mode. */ - kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific + kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific function. */ - kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ + kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ - kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ - kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ + kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because it is in use. */ }; /*! @brief MCG status flags. */ enum _mcg_status_flags_t { - kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ - kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ + kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ + kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ kMCG_RtcOscLostFlag = (1U << 4U), /*!< RTC OSC lost. */ - kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ - kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ + kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ + kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ }; /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcg_irclk_enable_mode { - kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; @@ -694,11 +708,13 @@ static inline void CLOCK_SetFlexio0Clock(uint32_t src) /*! * @brief Set PLLFLLSEL clock source. * - * @param src The value to set PLLFLLSEL clock source. + * @param src The value to set PLLFLLSEL clock source. + * @param divValue PLLFLL clock divider divisor. + * @param fracValue PLLFLL clock divider fraction. */ static inline void CLOCK_SetPllFllSelClock(uint32_t src, uint32_t divValue, uint32_t fracValue) { - SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_PLLFLLSEL_MASK) | SIM_SOPT2_PLLFLLSEL(src)); + SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_PLLFLLSEL_MASK) | SIM_SOPT2_PLLFLLSEL(src)); SIM->CLKDIV3 = SIM_CLKDIV3_PLLFLLDIV(divValue) | SIM_CLKDIV3_PLLFLLFRAC(fracValue); } @@ -834,6 +850,13 @@ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void); */ uint32_t CLOCK_GetOsc0ErClkFreq(void); +/*! + * @brief Get the OSC0 external reference divided clock frequency. + * + * @return Clock frequency in Hz. + */ +uint32_t CLOCK_GetOsc0ErClkDivFreq(void); + /*! * @brief Set the clock configure in SIM module. * @@ -936,7 +959,7 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } else { - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; } } @@ -952,8 +975,8 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); @@ -967,11 +990,23 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); +/*! + * @brief Set the FLL external reference clock divider value. + * + * Sets the FLL external reference clock divider value, the register MCG_C1[FRDIV]. + * + * @param frdiv The FLL external reference clock divider value, MCG_C1[FRDIV]. + */ +static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) +{ + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); +} + /*! * @brief Enables the PLL0 in FLL mode. * @@ -1013,6 +1048,15 @@ static inline void CLOCK_DisablePll0(void) */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv); +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ +void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); + /*@}*/ /*! @name MCG clock lock monitor functions. */ @@ -1054,20 +1098,20 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode); * * Example: * @code - // To check the clock lost lock status of OSC0 and PLL0. - uint32_t mcgFlags; - - mcgFlags = CLOCK_GetStatusFlags(); - - if (mcgFlags & kMCG_Osc0LostFlag) - { - // OSC0 clock lock lost. Do something. - } - if (mcgFlags & kMCG_Pll0LostFlag) - { - // PLL0 clock lock lost. Do something. - } - @endcode + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * @endcode * * @return Logical OR value of the @ref _mcg_status_flags_t. */ @@ -1081,10 +1125,10 @@ uint32_t CLOCK_GetStatusFlags(void); * * Example: * @code - // To clear the clock lost lock status flags of OSC0 and PLL0. - - CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); - @endcode + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * @endcode * * @param mask The status flags to clear. This is a logical OR of members of the * enumeration @ref _mcg_status_flags_t. @@ -1142,7 +1186,7 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * * * Example: @code - // To enable only 2 pF and 8 pF capacitor load, please use like this. + To enable only 2 pF and 8 pF capacitor load, please use like this. OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P); @endcode */ @@ -1368,7 +1412,7 @@ status_t CLOCK_SetPeeMode(void); * @brief Switches the MCG to FBE mode from the external mode. * * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. - * The external clock is used as the system clock souce and PLL is disabled. However, + * The external clock is used as the system clock source and PLL is disabled. However, * the FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEE mode to FEI mode: * @@ -1386,7 +1430,7 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void); * @brief Switches the MCG to FBI mode from internal modes. * * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. - * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, * FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEI mode to FEE mode: * @@ -1439,7 +1483,7 @@ status_t CLOCK_BootToFeeMode( * @brief Sets the MCG to BLPI mode during system boot up. * * This function sets the MCG to BLPI mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. @@ -1451,10 +1495,10 @@ status_t CLOCK_BootToFeeMode( status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Sets the MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during system boot up. * * This function sets the MCG to BLPE mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @@ -1494,6 +1538,16 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); +/*! + * @brief Delay at least for several microseconds. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + /*@}*/ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_clock.c index f5afd3f800..da51adcbcc 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_clock.c @@ -1,40 +1,22 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include "fsl_common.h" #include "fsl_clock.h" /******************************************************************************* * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + /* Macro definition remap workaround. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) #define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK @@ -65,11 +47,11 @@ #define TRIM_SIRC_MIN (31250U) #define MCG_S_IRCST_VAL ((MCG->S & MCG_S_IRCST_MASK) >> MCG_S_IRCST_SHIFT) -#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) -#define MCG_S_IREFST_VAL ((MCG->S & MCG_S_IREFST_MASK) >> MCG_S_IREFST_SHIFT) +#define MCG_S_CLKST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_CLKST_MASK) >> (uint32_t)MCG_S_CLKST_SHIFT) +#define MCG_S_IREFST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IREFST_MASK) >> (uint32_t)MCG_S_IREFST_SHIFT) #define MCG_S_PLLST_VAL ((MCG->S & MCG_S_PLLST_MASK) >> MCG_S_PLLST_SHIFT) #define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT) -#define MCG_C2_LP_VAL ((MCG->C2 & MCG_C2_LP_MASK) >> MCG_C2_LP_SHIFT) +#define MCG_C2_LP_VAL (((uint32_t)MCG->C2 & (uint32_t)MCG_C2_LP_MASK) >> (uint32_t)MCG_C2_LP_SHIFT) #define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT) #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) #define MCG_S2_PLLCST_VAL ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT) @@ -118,9 +100,9 @@ static uint32_t s_slowIrcFreq = 32768U; static uint32_t s_fastIrcFreq = 4000000U; /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -189,6 +171,7 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * @@ -196,11 +179,33 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ static void CLOCK_FllStableDelay(void); +#endif /******************************************************************************* * Code ******************************************************************************/ +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN +static void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (0U != (i--)) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardless how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ + static uint32_t CLOCK_GetMcgExtClkFreq(void) { uint32_t freq; @@ -209,12 +214,12 @@ static uint32_t CLOCK_GetMcgExtClkFreq(void) { case 0U: /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ - assert(g_xtal0Freq); + assert(0U != g_xtal0Freq); freq = g_xtal0Freq; break; case 1U: /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ - assert(g_xtal32Freq); + assert(0U != g_xtal32Freq); freq = g_xtal32Freq; break; default: @@ -234,7 +239,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) uint32_t freq = CLOCK_GetMcgExtClkFreq(); - if (!freq) + if (0U == freq) { return freq; } @@ -242,7 +247,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) frdiv = MCG_C1_FRDIV_VAL; freq >>= frdiv; - range = MCG_C2_RANGE_VAL; + range = MCG_C2_RANGE_VAL; oscsel = MCG_C7_OSCSEL_VAL; /* @@ -250,7 +255,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) 1. MCG_C7[OSCSEL] selects IRC48M. 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0. */ - if (((0U != range) && (kMCG_OscselOsc == oscsel))) + if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel))) { switch (frdiv) { @@ -281,7 +286,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) { - if (kMCG_IrcSlow == MCG_S_IRCST_VAL) + if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL) { /* Slow internal reference clock selected*/ return s_slowIrcFreq; @@ -296,7 +301,7 @@ static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) static uint32_t CLOCK_GetFllRefClkFreq(void) { /* If use external reference clock. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { return CLOCK_GetFllExtRefClkFreq(); } @@ -333,19 +338,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -360,6 +357,11 @@ uint32_t CLOCK_GetOsc0ErClkFreq(void) } } +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -384,6 +386,11 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the output clock frequency selected by SIM[PLLFLLSEL]. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPllFllSelClkFreq(void) { uint32_t freq; @@ -404,26 +411,56 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) return freq; } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -472,6 +509,13 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; @@ -479,6 +523,13 @@ void CLOCK_SetSimConfig(sim_clock_config_t const *config) CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { bool ret = true; @@ -518,23 +569,31 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! + * brief Gets the MCG output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG output clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; - uint32_t clkst = MCG_S_CLKST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; switch (clkst) { - case kMCG_ClkOutStatPll: + case (uint32_t)kMCG_ClkOutStatPll: mcgoutclk = CLOCK_GetPll0Freq(); break; - case kMCG_ClkOutStatFll: + case (uint32_t)kMCG_ClkOutStatFll: mcgoutclk = CLOCK_GetFllFreq(); break; - case kMCG_ClkOutStatInt: + case (uint32_t)kMCG_ClkOutStatInt: mcgoutclk = CLOCK_GetInternalRefClkSelectFreq(); break; - case kMCG_ClkOutStatExt: + case (uint32_t)kMCG_ClkOutStatExt: mcgoutclk = CLOCK_GetMcgExtClkFreq(); break; default: @@ -544,6 +603,15 @@ uint32_t CLOCK_GetOutClkFreq(void) return mcgoutclk; } +/*! + * brief Gets the MCG FLL clock (MCGFLLCLK) frequency. + * + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. + * + * return The frequency of MCGFLLCLK. + */ uint32_t CLOCK_GetFllFreq(void) { static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; @@ -552,28 +620,36 @@ uint32_t CLOCK_GetFllFreq(void) uint32_t freq; /* If FLL is not enabled currently, then return 0U. */ - if ((MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) + if (0U != (MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) { return 0U; } /* Get FLL reference clock frequency. */ freq = CLOCK_GetFllRefClkFreq(); - if (!freq) + if (0U == freq) { return freq; } - drs = MCG_C4_DRST_DRS_VAL; + drs = MCG_C4_DRST_DRS_VAL; dmx32 = MCG_C4_DMX32_VAL; return freq * fllFactorTable[drs][dmx32]; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { /* If MCGIRCLK is gated. */ - if (!(MCG->C1 & MCG_C1_IRCLKEN_MASK)) + if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK)) { return 0U; } @@ -581,12 +657,20 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetInternalRefClkSelectFreq(); } +/*! + * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. + * + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGFFCLK. + */ uint32_t CLOCK_GetFixedFreqClkFreq(void) { uint32_t freq = CLOCK_GetFllRefClkFreq(); /* MCGFFCLK must be no more than MCGOUTCLK/8. */ - if ((freq) && (freq <= (CLOCK_GetOutClkFreq() / 8U))) + if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq)) { return freq; } @@ -596,6 +680,14 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void) } } +/*! + * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. + * + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGPLL0CLK. + */ uint32_t CLOCK_GetPll0Freq(void) { uint32_t mcgpll0clk; @@ -620,6 +712,18 @@ uint32_t CLOCK_GetPll0Freq(void) return mcgpll0clk; } +/*! + * brief Selects the MCG external reference clock. + * + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. + * + * param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. + * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success External reference clock set successfully. + */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) { bool needDelay; @@ -633,7 +737,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } #endif /* MCG_CONFIG_CHECK_PARAM */ - if (MCG_C7_OSCSEL_VAL != oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel) { /* If change OSCSEL, need to delay, ERR009878. */ needDelay = true; @@ -643,22 +747,12 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) needDelay = false; } - MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - + MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ i = 1500U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -667,15 +761,31 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Configures the Internal Reference clock (MCGIRCLK). + * + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. + * + * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * param ircs MCGIRCLK clock source, choose fast or slow. + * param fcrdiv Fast IRC divider setting (\c FCRDIV). + * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success MCGIRCLK configuration finished successfully. + */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) { - uint32_t mcgOutClkState = MCG_S_CLKST_VAL; - mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; - uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; + uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL; + mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; + uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) /* If MCGIRCLK is used as system clock source. */ - if (kMCG_ClkOutStatInt == mcgOutClkState) + if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState) { /* If need to change MCGIRCLK source or driver, return error. */ if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs)) @@ -689,25 +799,27 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, if (fcrdiv != curFcrdiv) { /* If fast IRC is in use currently, change to slow IRC. */ - if ((kMCG_IrcFast == curIrcs) && ((mcgOutClkState == kMCG_ClkOutStatInt) || (MCG->C1 & MCG_C1_IRCLKEN_MASK))) + if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) && + (kMCG_IrcFast == curIrcs)) { - MCG->C2 = ((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); - while (MCG_S_IRCST_VAL != kMCG_IrcSlow) + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); + while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow) { } } /* Update FCRDIV. */ - MCG->SC = (MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); + MCG->SC = + (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); } /* Set internal reference clock selection. */ - MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)); - MCG->C1 = (MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode; + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs))); + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode); /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */ - if ((mcgOutClkState == kMCG_ClkOutStatInt) || (enableMode & kMCG_IrclkEnable)) + if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable))) { - while (MCG_S_IRCST_VAL != ircs) + while (MCG_S_IRCST_VAL != (uint8_t)ircs) { } } @@ -715,17 +827,32 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, return kStatus_Success; } +/*! + * brief Calculates the PLL divider setting for a desired output frequency. + * + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function + * returns 0. + * + * param refFreq PLL reference clock frequency. + * param desireFreq Desired PLL output frequency. + * param prdiv PRDIV value to generate desired PLL frequency. + * param vdiv VDIV value to generate desired PLL frequency. + * return Closest frequency match that the PLL was able generate. + */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv) { - uint8_t ret_prdiv; /* PRDIV to return. */ - uint8_t ret_vdiv; /* VDIV to return. */ - uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_cur; /* PRDIV value for iteration. */ - uint8_t vdiv_cur; /* VDIV value for iteration. */ - uint32_t ret_freq = 0U; /* PLL output fequency to return. */ - uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ - uint32_t ref_div; /* Reference frequency after PRDIV. */ + uint8_t ret_prdiv; /* PRDIV to return. */ + uint8_t ret_vdiv; /* VDIV to return. */ + uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_cur; /* PRDIV value for iteration. */ + uint8_t vdiv_cur; /* VDIV value for iteration. */ + uint32_t ret_freq = 0U; /* PLL output frequency to return. */ + uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ + uint32_t ref_div; /* Reference frequency after PRDIV. */ /* Steps: @@ -772,15 +899,15 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (ret_freq == desireFreq) /* If desire frequency is got. */ { *prdiv = prdiv_cur - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; return ret_freq; } /* New PRDIV/VDIV is closer. */ if (diff > desireFreq - ret_freq) { - diff = desireFreq - ret_freq; + diff = desireFreq - ret_freq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } vdiv_cur++; @@ -790,9 +917,9 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, /* New PRDIV/VDIV is closer. */ if (diff > ret_freq - desireFreq) { - diff = ret_freq - desireFreq; + diff = ret_freq - desireFreq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } } @@ -800,8 +927,8 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (0xFFFFFFFFU != diff) { /* PRDIV/VDIV found. */ - *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; + *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; ret_freq = (refFreq / ret_prdiv) * ret_vdiv; return ret_freq; } @@ -812,6 +939,17 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, } } +/*! + * brief Enables the PLL0 in FLL mode. + * + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL + * divider values. + * + * param config Pointer to the configuration structure. + */ void CLOCK_EnablePll0(mcg_pll_config_t const *config) { assert(config); @@ -832,20 +970,27 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ - MCG->SC &= ~MCG_SC_ATMF_MASK; + MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK; if (kMCG_MonitorNone == mode) { - MCG->C6 &= ~MCG_C6_CME0_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK; } else { if (kMCG_MonitorInt == mode) { - MCG->C2 &= ~MCG_C2_LOCRE0_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK; } else { @@ -855,11 +1000,18 @@ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the RTC OSC clock monitor mode. + * + * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8 = MCG->C8; - mcg_c8 &= ~(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); + mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); if (kMCG_MonitorNone != mode) { @@ -872,6 +1024,13 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) MCG->C8 = mcg_c8; } +/*! + * brief Sets the PLL0 clock monitor mode. + * + * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8; @@ -902,34 +1061,76 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Gets the MCG status flags. + * + * This function gets the MCG clock status flags. All status flags are + * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To + * check a specific flag, compare the return value with the flag. + * + * Example: + * code + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * endcode + * + * return Logical OR value of the ref _mcg_status_flags_t. + */ uint32_t CLOCK_GetStatusFlags(void) { - uint32_t ret = 0U; + uint32_t ret = 0U; uint8_t mcg_s = MCG->S; if (MCG->SC & MCG_SC_LOCS0_MASK) { - ret |= kMCG_Osc0LostFlag; + ret |= (uint32_t)kMCG_Osc0LostFlag; } if (mcg_s & MCG_S_OSCINIT0_MASK) { - ret |= kMCG_Osc0InitFlag; + ret |= (uint32_t)kMCG_Osc0InitFlag; } - if (MCG->C8 & MCG_C8_LOCS1_MASK) + if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK)) { - ret |= kMCG_RtcOscLostFlag; + ret |= (uint32_t)kMCG_RtcOscLostFlag; } if (mcg_s & MCG_S_LOLS0_MASK) { - ret |= kMCG_Pll0LostFlag; + ret |= (uint32_t)kMCG_Pll0LostFlag; } if (mcg_s & MCG_S_LOCK0_MASK) { - ret |= kMCG_Pll0LockFlag; + ret |= (uint32_t)kMCG_Pll0LockFlag; } return ret; } +/*! + * brief Clears the MCG status flags. + * + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See ref _mcg_status_flags_t. + * + * Example: + * code + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * endcode + * + * param mask The status flags to clear. This is a logical OR of members of the + * enumeration ref _mcg_status_flags_t. + */ void CLOCK_ClearStatusFlags(uint32_t mask) { uint8_t reg; @@ -938,9 +1139,9 @@ void CLOCK_ClearStatusFlags(uint32_t mask) { MCG->SC &= ~MCG_SC_ATMF_MASK; } - if (mask & kMCG_RtcOscLostFlag) + if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag)) { - reg = MCG->C8; + reg = MCG->C8; MCG->C8 = reg; } if (mask & kMCG_Pll0LostFlag) @@ -949,30 +1150,60 @@ void CLOCK_ClearStatusFlags(uint32_t mask) } } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); OSC_SetCapLoad(OSC0, config->capLoad); - OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); - MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) { /* Wait for stable. */ - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; - MCG->C2 &= ~OSC_MODE_MASK; + MCG->C2 &= ~(uint8_t)OSC_MODE_MASK; } +/*! + * brief Auto trims the internal reference clock. + * + * This function trims the internal reference clock by using the external clock. If + * successful, it returns the kStatus_Success and the frequency after + * trimming is received in the parameter p actualFreq. If an error occurs, + * the error code is returned. + * + * param extFreq External clock frequency, which should be a bus clock. + * param desireFreq Frequency to trim to. + * param actualFreq Actual frequency after trimming. + * param atms Trim fast or slow internal reference clock. + * retval kStatus_Success ATM success. + * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. + * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. + * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. + */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) { uint32_t multi; /* extFreq / desireFreq */ @@ -1006,7 +1237,7 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ } multi = extFreq / desireFreq; - actv = multi * 21U; + actv = multi * 21U; if (kMCG_AtmSel4m == atms) { @@ -1018,17 +1249,17 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ MCG->ATCVH = (uint8_t)(actv >> 8U); mcg_sc = MCG->SC; - mcg_sc &= ~(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); + mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms)); MCG->SC = (mcg_sc | MCG_SC_ATME_MASK); /* Wait for finished. */ - while (MCG->SC & MCG_SC_ATME_MASK) + while (0U != (MCG->SC & MCG_SC_ATME_MASK)) { } /* Error occurs? */ - if (MCG->SC & MCG_SC_ATMF_MASK) + if (0U != (MCG->SC & MCG_SC_ATMF_MASK)) { /* Clear the failed flag. */ MCG->SC = mcg_sc; @@ -1049,13 +1280,20 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ return kStatus_Success; } +/*! + * brief Gets the current MCG mode. + * + * This function checks the MCG registers and determines the current MCG mode. + * + * return Current MCG mode or error code; See ref mcg_mode_t. + */ mcg_mode_t CLOCK_GetMode(void) { mcg_mode_t mode = kMCG_ModeError; - uint32_t clkst = MCG_S_CLKST_VAL; - uint32_t irefst = MCG_S_IREFST_VAL; - uint32_t lp = MCG_C2_LP_VAL; - uint32_t pllst = MCG_S_PLLST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; + uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL; + uint32_t lp = (uint32_t)MCG_C2_LP_VAL; + uint32_t pllst = MCG_S_PLLST_VAL; /*------------------------------------------------------------------ Mode and Registers @@ -1096,59 +1334,77 @@ mcg_mode_t CLOCK_GetMode(void) ----------------------------------------------------------------------*/ - switch (clkst) + if (clkst == (uint32_t)kMCG_ClkOutStatFll) { - case kMCG_ClkOutStatFll: - if (kMCG_FllSrcExternal == irefst) + if ((uint32_t)kMCG_FllSrcExternal == irefst) + { + mode = kMCG_ModeFEE; + } + else + { + mode = kMCG_ModeFEI; + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatInt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPI; + } + else + { { - mode = kMCG_ModeFEE; + mode = kMCG_ModeFBI; + } + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatExt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPE; + } + else + { + if (kMCG_PllstPll == pllst) + { + mode = kMCG_ModePBE; } else { - mode = kMCG_ModeFEI; + mode = kMCG_ModeFBE; } - break; - case kMCG_ClkOutStatInt: - if (lp) - { - mode = kMCG_ModeBLPI; - } - else - { - { - mode = kMCG_ModeFBI; - } - } - break; - case kMCG_ClkOutStatExt: - if (lp) - { - mode = kMCG_ModeBLPE; - } - else - { - if (kMCG_PllstPll == pllst) - { - mode = kMCG_ModePBE; - } - else - { - mode = kMCG_ModeFBE; - } - } - break; - case kMCG_ClkOutStatPll: + } + } + if (clkst == (uint32_t)kMCG_ClkOutStatPll) + { { mode = kMCG_ModePEE; } - break; - default: - break; + } + else + { + /*do nothing*/ } return mode; } +/*! + * brief Sets the MCG to FEI mode. + * + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. + */ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1169,7 +1425,7 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1177,12 +1433,12 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal)); /* IREFS = 1 */ + MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1193,15 +1449,16 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1209,6 +1466,21 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FEE mode. + * + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1229,7 +1501,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1237,13 +1509,24 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait and check status. */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1254,7 +1537,8 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); MCG->C4 = mcg_c4; /* Wait for DRST_DRS update. */ @@ -1263,12 +1547,12 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1276,6 +1560,22 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to FBI mode. + * + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FBI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1294,7 +1594,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela mcg_c4 = MCG->C4; - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ /* Errata: ERR007993 @@ -1302,7 +1602,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1310,12 +1610,12 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1325,14 +1625,15 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela MCG->C4 = mcg_c4; } - while (kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1340,6 +1641,21 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FBE mode. + * + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FBE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1355,13 +1671,13 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void #endif /* Change to FLL mode. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } /* Set LP bit to enable the FLL */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; mcg_c4 = MCG->C4; @@ -1371,7 +1687,7 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1379,13 +1695,24 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for Reference clock Status bit to clear */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1396,15 +1723,16 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRST_DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for clock status bits to show clock source is ext ref clk */ - while (kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) { } /* Wait for fll stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1412,10 +1740,19 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to BLPI mode. + * + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpiMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { return kStatus_MCG_ModeUnreachable; } @@ -1427,10 +1764,19 @@ status_t CLOCK_SetBlpiMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode. + * + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { return kStatus_MCG_ModeUnreachable; } @@ -1442,8 +1788,29 @@ status_t CLOCK_SetBlpeMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to PBE mode. + * + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. + * + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. + * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); + */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { + assert(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. @@ -1472,6 +1839,8 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co /* Change to PLL mode. */ MCG->C6 |= MCG_C6_PLLS_MASK; + + /* Wait for PLL mode changed. */ while (!(MCG->S & MCG_S_PLLST_MASK)) { } @@ -1479,6 +1848,18 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode. + * + * This function sets the MCG to PEE mode. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. + */ status_t CLOCK_SetPeeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1493,13 +1874,29 @@ status_t CLOCK_SetPeeMode(void) MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); /* Wait for clock status bits to update */ - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } return kStatus_Success; } +/*! + * brief Switches the MCG to FBE mode from the external mode. + * + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: + * + * code + * CLOCK_ExternalModeToFbeModeQuick(); + * CLOCK_SetFeiMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. + */ status_t CLOCK_ExternalModeToFbeModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1510,15 +1907,15 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) #endif /* MCG_CONFIG_CHECK_PARAM */ /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } /* Disable PLL. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } @@ -1526,6 +1923,22 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBI mode from internal modes. + * + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: + * + * code + * CLOCK_InternalModeToFbiModeQuick(); + * CLOCK_SetFeeMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. + */ status_t CLOCK_InternalModeToFbiModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1536,37 +1949,80 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) #endif /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } return kStatus_Success; } +/*! + * brief Sets the MCG to FEI mode during system boot up. + * + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to FEE mode during system bootup. + * + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, OSCSEL. + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to BLPI mode during system boot up. + * + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param fcrdiv Fast IRC divider, FCRDIV. + * param ircs The internal reference clock to select, IRCS. + * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * + * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) { /* If reset mode is FEI mode, set MCGIRCLK and always success. */ - CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); /* If reset mode is not BLPI, first enter FBI mode. */ - MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } @@ -1576,14 +2032,36 @@ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEn return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode during system boot up. + * + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); /* Set to FBE mode. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != @@ -1597,6 +2075,19 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode during system boot up. + * + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1607,7 +2098,7 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc /* Change to use PLL output clock. */ MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } @@ -1643,6 +2134,20 @@ static const mcg_mode_t mcgModeMatrix[8][8] = { /* FEI FBI BLPI FEE FBE BLPE PBE PEE */ }; +/*! + * brief Sets the MCG to a target mode. + * + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. + * + * param config Pointer to the target MCG mode configuration structure. + * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. + * + * note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. + */ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) { mcg_mode_t next_mode; @@ -1651,30 +2156,30 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) mcg_pll_clk_select_t pllcs = kMCG_PllClkSelPll0; /* If need to change external clock, MCG_C7[OSCSEL]. */ - if (MCG_C7_OSCSEL_VAL != config->oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel)) { /* If external clock is in use, change to FEI first. */ - if (!(MCG->S & MCG_S_IRCST_MASK)) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { - CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); + (void)CLOCK_ExternalModeToFbeModeQuick(); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL); } - CLOCK_SetExternalRefClkConfig(config->oscsel); + (void)CLOCK_SetExternalRefClkConfig(config->oscsel); } /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */ - if (MCG_S_CLKST_VAL == kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt) { - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } /* Configure MCGIRCLK. */ - CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); next_mode = CLOCK_GetMode(); @@ -1691,10 +2196,10 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL); break; case kMCG_ModeFBE: - status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL); break; case kMCG_ModeBLPI: status = CLOCK_SetBlpiMode(); @@ -1713,7 +2218,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) else { MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } } @@ -1736,7 +2241,55 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) } else { - MCG->C5 &= ~(uint32_t)kMCG_PllEnableIndependent; + MCG->C5 &= ~(uint8_t)kMCG_PllEnableIndependent; } return kStatus_Success; } + +/*! + * brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + uint64_t count = 0U; + uint32_t period = SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 1000000; + + /* Make sure the DWT trace fucntion is enabled. */ + if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR)) + { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + } + + /* CYCCNT not supported on this device. */ + assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk)); + + /* If CYCCENT has already been enabled, read directly, otherwise, need enable it. */ + if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL)) + { + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + /* Calculate the count ticks. */ + count = DWT->CYCCNT; + count += (uint64_t)period * delay_us; + + if (count > 0xFFFFFFFFUL) + { + count -= 0xFFFFFFFFUL; + /* wait for cyccnt overflow. */ + while (count < DWT->CYCCNT) + { + } + } + + /* Wait for cyccnt reach count value. */ + while (count > DWT->CYCCNT) + { + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_clock.h index 839eefcd90..f1c93875c2 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_clock.h @@ -1,71 +1,89 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include -#include -#include +#include "fsl_common.h" /*! @addtogroup clock */ /*! @{ */ /*! @file */ +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could control the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.0. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief CLOCK driver version 2.3.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) /*@}*/ +/* Definition for delay API in clock driver, users can redefine it to the real application. */ +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (120000000UL) +#endif + /*! @brief External XTAL0 (OSC0) clock frequency. * * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Set up the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. + * Set up the OSC0 + * CLOCK_InitOsc0(...); + * Set the XTAL0 value to the clock driver. + * CLOCK_SetXtal0Freq(80000000); * @endcode * * This is important for the multicore platforms where only one core needs to set up the * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * @@ -76,7 +94,7 @@ extern uint32_t g_xtal0Freq; * the clock. All other cores need to call the CLOCK_SetXtal32Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; #if (defined(OSC) && !(defined(OSC0))) #define OSC0 OSC @@ -247,7 +265,7 @@ typedef enum _clock_name typedef enum _clock_usb_src { kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ } clock_usb_src_t; /*------------------------------------------------------------------------------ @@ -282,41 +300,41 @@ typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), - kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), - kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U), - kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U), - kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), + kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), + kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U), + kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U), + kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), - kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), - kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), + kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), - kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), - kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x103CU, 9U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), - kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), - kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), + kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x103CU, 9U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), + kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), + kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), kCLOCK_Usbdcd0 = CLK_GATE_DEFINE(0x103CU, 21U), - kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), - kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), + kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), } clock_ip_name_t; @@ -340,34 +358,30 @@ typedef enum _osc_mode #endif kOSC_ModeOscHighGain = 0U #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) - | - MCG_C2_EREFS_MASK + | MCG_C2_EREFS_MASK #else - | - MCG_C2_EREFS0_MASK + | MCG_C2_EREFS0_MASK #endif #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK))) - | - MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ #else - | - MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ #endif } osc_mode_t; /*! @brief Oscillator capacitor load setting.*/ enum _osc_cap_load { - kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ - kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ - kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */ }; /*! @brief OSCERCLK enable mode. */ enum _oscer_enable_mode { - kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ + kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */ }; @@ -473,30 +487,30 @@ typedef enum _mcg_monitor_mode enum _mcg_status { kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0), /*!< Can't switch to target mode. */ - kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific + kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific function. */ - kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ + kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ - kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ - kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ + kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because it is in use. */ }; /*! @brief MCG status flags. */ enum _mcg_status_flags_t { - kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ - kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ + kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ + kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ kMCG_RtcOscLostFlag = (1U << 4U), /*!< RTC OSC lost. */ - kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ - kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ + kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ + kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ }; /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcg_irclk_enable_mode { - kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; @@ -842,7 +856,7 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } else { - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; } } @@ -858,8 +872,8 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); @@ -873,11 +887,23 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); +/*! + * @brief Set the FLL external reference clock divider value. + * + * Sets the FLL external reference clock divider value, the register MCG_C1[FRDIV]. + * + * @param frdiv The FLL external reference clock divider value, MCG_C1[FRDIV]. + */ +static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) +{ + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); +} + /*! * @brief Enables the PLL0 in FLL mode. * @@ -919,6 +945,15 @@ static inline void CLOCK_DisablePll0(void) */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv); +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ +void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); + /*@}*/ /*! @name MCG clock lock monitor functions. */ @@ -960,20 +995,20 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode); * * Example: * @code - // To check the clock lost lock status of OSC0 and PLL0. - uint32_t mcgFlags; - - mcgFlags = CLOCK_GetStatusFlags(); - - if (mcgFlags & kMCG_Osc0LostFlag) - { - // OSC0 clock lock lost. Do something. - } - if (mcgFlags & kMCG_Pll0LostFlag) - { - // PLL0 clock lock lost. Do something. - } - @endcode + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * @endcode * * @return Logical OR value of the @ref _mcg_status_flags_t. */ @@ -987,10 +1022,10 @@ uint32_t CLOCK_GetStatusFlags(void); * * Example: * @code - // To clear the clock lost lock status flags of OSC0 and PLL0. - - CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); - @endcode + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * @endcode * * @param mask The status flags to clear. This is a logical OR of members of the * enumeration @ref _mcg_status_flags_t. @@ -1046,7 +1081,7 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * * * Example: @code - // To enable only 2 pF and 8 pF capacitor load, please use like this. + To enable only 2 pF and 8 pF capacitor load, please use like this. OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P); @endcode */ @@ -1272,7 +1307,7 @@ status_t CLOCK_SetPeeMode(void); * @brief Switches the MCG to FBE mode from the external mode. * * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. - * The external clock is used as the system clock souce and PLL is disabled. However, + * The external clock is used as the system clock source and PLL is disabled. However, * the FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEE mode to FEI mode: * @@ -1290,7 +1325,7 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void); * @brief Switches the MCG to FBI mode from internal modes. * * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. - * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, * FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEI mode to FEE mode: * @@ -1343,7 +1378,7 @@ status_t CLOCK_BootToFeeMode( * @brief Sets the MCG to BLPI mode during system boot up. * * This function sets the MCG to BLPI mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. @@ -1355,10 +1390,10 @@ status_t CLOCK_BootToFeeMode( status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Sets the MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during system boot up. * * This function sets the MCG to BLPE mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @@ -1398,6 +1433,16 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); +/*! + * @brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + /*@}*/ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_clock.c index 969e94c54e..a62ad2167e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_clock.c @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_clock.h" @@ -34,6 +12,11 @@ * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + /* Macro definition remap workaround. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) #define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK @@ -64,11 +47,11 @@ #define TRIM_SIRC_MIN (31250U) #define MCG_S_IRCST_VAL ((MCG->S & MCG_S_IRCST_MASK) >> MCG_S_IRCST_SHIFT) -#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) -#define MCG_S_IREFST_VAL ((MCG->S & MCG_S_IREFST_MASK) >> MCG_S_IREFST_SHIFT) +#define MCG_S_CLKST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_CLKST_MASK) >> (uint32_t)MCG_S_CLKST_SHIFT) +#define MCG_S_IREFST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IREFST_MASK) >> (uint32_t)MCG_S_IREFST_SHIFT) #define MCG_S_PLLST_VAL ((MCG->S & MCG_S_PLLST_MASK) >> MCG_S_PLLST_SHIFT) #define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT) -#define MCG_C2_LP_VAL ((MCG->C2 & MCG_C2_LP_MASK) >> MCG_C2_LP_SHIFT) +#define MCG_C2_LP_VAL (((uint32_t)MCG->C2 & (uint32_t)MCG_C2_LP_MASK) >> (uint32_t)MCG_C2_LP_SHIFT) #define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT) #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) #define MCG_S2_PLLCST_VAL ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT) @@ -115,9 +98,9 @@ static uint32_t s_slowIrcFreq = 32768U; static uint32_t s_fastIrcFreq = 4000000U; /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -176,6 +159,7 @@ static uint32_t CLOCK_GetInternalRefClkSelectFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * @@ -183,11 +167,33 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ static void CLOCK_FllStableDelay(void); +#endif /******************************************************************************* * Code ******************************************************************************/ +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN +static void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (0U != (i--)) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardless how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ + static uint32_t CLOCK_GetMcgExtClkFreq(void) { uint32_t freq; @@ -196,12 +202,12 @@ static uint32_t CLOCK_GetMcgExtClkFreq(void) { case 0U: /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ - assert(g_xtal0Freq); + assert(0U != g_xtal0Freq); freq = g_xtal0Freq; break; case 1U: /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ - assert(g_xtal32Freq); + assert(0U != g_xtal32Freq); freq = g_xtal32Freq; break; default: @@ -221,7 +227,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) uint32_t freq = CLOCK_GetMcgExtClkFreq(); - if (!freq) + if (0U == freq) { return freq; } @@ -229,7 +235,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) frdiv = MCG_C1_FRDIV_VAL; freq >>= frdiv; - range = MCG_C2_RANGE_VAL; + range = MCG_C2_RANGE_VAL; oscsel = MCG_C7_OSCSEL_VAL; /* @@ -237,7 +243,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) 1. MCG_C7[OSCSEL] selects IRC48M. 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0. */ - if (((0U != range) && (kMCG_OscselOsc == oscsel))) + if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel))) { switch (frdiv) { @@ -268,7 +274,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) { - if (kMCG_IrcSlow == MCG_S_IRCST_VAL) + if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL) { /* Slow internal reference clock selected*/ return s_slowIrcFreq; @@ -283,7 +289,7 @@ static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) static uint32_t CLOCK_GetFllRefClkFreq(void) { /* If use external reference clock. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { return CLOCK_GetFllExtRefClkFreq(); } @@ -314,19 +320,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -334,8 +332,6 @@ uint32_t CLOCK_GetEr32kClkFreq(void) switch (SIM_SOPT1_OSC32KSEL_VAL) { case 0U: /* OSC 32k clock */ - freq = (g_xtal0Freq == 32768U) ? 32768U : 0U; - break; case 2U: /* RTC 32k clock */ /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ assert(g_xtal32Freq); @@ -351,6 +347,11 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ @@ -358,11 +359,21 @@ uint32_t CLOCK_GetOsc0ErClkFreq(void) return g_xtal0Freq; } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { uint32_t freq; @@ -373,6 +384,11 @@ uint32_t CLOCK_GetFlashClkFreq(void) return freq; } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { uint32_t freq; @@ -383,11 +399,26 @@ uint32_t CLOCK_GetBusClkFreq(void) return freq; } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -406,9 +437,6 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) case kCLOCK_Er32kClk: freq = CLOCK_GetEr32kClkFreq(); break; - case kCLOCK_McgFixedFreqClk: - freq = CLOCK_GetFixedFreqClkFreq(); - break; case kCLOCK_McgInternalRefClk: freq = CLOCK_GetInternalRefClkFreq(); break; @@ -431,26 +459,41 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; CLOCK_SetEr32kClock(config->er32kSrc); } +/*! + * brief Gets the MCG output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG output clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; - uint32_t clkst = MCG_S_CLKST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; switch (clkst) { - case kMCG_ClkOutStatFll: + case (uint32_t)kMCG_ClkOutStatFll: mcgoutclk = CLOCK_GetFllFreq(); break; - case kMCG_ClkOutStatInt: + case (uint32_t)kMCG_ClkOutStatInt: mcgoutclk = CLOCK_GetInternalRefClkSelectFreq(); break; - case kMCG_ClkOutStatExt: + case (uint32_t)kMCG_ClkOutStatExt: mcgoutclk = CLOCK_GetMcgExtClkFreq(); break; default: @@ -460,6 +503,15 @@ uint32_t CLOCK_GetOutClkFreq(void) return mcgoutclk; } +/*! + * brief Gets the MCG FLL clock (MCGFLLCLK) frequency. + * + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. + * + * return The frequency of MCGFLLCLK. + */ uint32_t CLOCK_GetFllFreq(void) { static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; @@ -468,28 +520,36 @@ uint32_t CLOCK_GetFllFreq(void) uint32_t freq; /* If FLL is not enabled currently, then return 0U. */ - if ((MCG->C2 & MCG_C2_LP_MASK)) + if (0U != (MCG->C2 & MCG_C2_LP_MASK)) { return 0U; } /* Get FLL reference clock frequency. */ freq = CLOCK_GetFllRefClkFreq(); - if (!freq) + if (0U == freq) { return freq; } - drs = MCG_C4_DRST_DRS_VAL; + drs = MCG_C4_DRST_DRS_VAL; dmx32 = MCG_C4_DMX32_VAL; return freq * fllFactorTable[drs][dmx32]; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { /* If MCGIRCLK is gated. */ - if (!(MCG->C1 & MCG_C1_IRCLKEN_MASK)) + if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK)) { return 0U; } @@ -497,12 +557,20 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetInternalRefClkSelectFreq(); } +/*! + * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. + * + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGFFCLK. + */ uint32_t CLOCK_GetFixedFreqClkFreq(void) { uint32_t freq = CLOCK_GetFllRefClkFreq(); /* MCGFFCLK must be no more than MCGOUTCLK/8. */ - if ((freq) && (freq <= (CLOCK_GetOutClkFreq() / 8U))) + if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq)) { return freq; } @@ -512,6 +580,18 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void) } } +/*! + * brief Selects the MCG external reference clock. + * + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. + * + * param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. + * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success External reference clock set successfully. + */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) { bool needDelay; @@ -525,7 +605,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } #endif /* MCG_CONFIG_CHECK_PARAM */ - if (MCG_C7_OSCSEL_VAL != oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel) { /* If change OSCSEL, need to delay, ERR009878. */ needDelay = true; @@ -535,22 +615,12 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) needDelay = false; } - MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - + MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ i = 1500U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -559,15 +629,31 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Configures the Internal Reference clock (MCGIRCLK). + * + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. + * + * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * param ircs MCGIRCLK clock source, choose fast or slow. + * param fcrdiv Fast IRC divider setting (\c FCRDIV). + * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success MCGIRCLK configuration finished successfully. + */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) { - uint32_t mcgOutClkState = MCG_S_CLKST_VAL; - mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; - uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; + uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL; + mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; + uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) /* If MCGIRCLK is used as system clock source. */ - if (kMCG_ClkOutStatInt == mcgOutClkState) + if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState) { /* If need to change MCGIRCLK source or driver, return error. */ if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs)) @@ -581,25 +667,27 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, if (fcrdiv != curFcrdiv) { /* If fast IRC is in use currently, change to slow IRC. */ - if ((kMCG_IrcFast == curIrcs) && ((mcgOutClkState == kMCG_ClkOutStatInt) || (MCG->C1 & MCG_C1_IRCLKEN_MASK))) + if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) && + (kMCG_IrcFast == curIrcs)) { - MCG->C2 = ((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); - while (MCG_S_IRCST_VAL != kMCG_IrcSlow) + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); + while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow) { } } /* Update FCRDIV. */ - MCG->SC = (MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); + MCG->SC = + (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); } /* Set internal reference clock selection. */ - MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)); - MCG->C1 = (MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode; + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs))); + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode); /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */ - if ((mcgOutClkState == kMCG_ClkOutStatInt) || (enableMode & kMCG_IrclkEnable)) + if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable))) { - while (MCG_S_IRCST_VAL != ircs) + while (MCG_S_IRCST_VAL != (uint8_t)ircs) { } } @@ -607,20 +695,27 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, return kStatus_Success; } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ - MCG->SC &= ~MCG_SC_ATMF_MASK; + MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK; if (kMCG_MonitorNone == mode) { - MCG->C6 &= ~MCG_C6_CME0_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK; } else { if (kMCG_MonitorInt == mode) { - MCG->C2 &= ~MCG_C2_LOCRE0_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK; } else { @@ -630,11 +725,18 @@ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the RTC OSC clock monitor mode. + * + * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8 = MCG->C8; - mcg_c8 &= ~(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); + mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); if (kMCG_MonitorNone != mode) { @@ -647,48 +749,120 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) MCG->C8 = mcg_c8; } +/*! + * brief Gets the MCG status flags. + * + * This function gets the MCG clock status flags. All status flags are + * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To + * check a specific flag, compare the return value with the flag. + * + * Example: + * code + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * endcode + * + * return Logical OR value of the ref _mcg_status_flags_t. + */ uint32_t CLOCK_GetStatusFlags(void) { uint32_t ret = 0U; - if (MCG->C8 & MCG_C8_LOCS1_MASK) + if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK)) { - ret |= kMCG_RtcOscLostFlag; + ret |= (uint32_t)kMCG_RtcOscLostFlag; } return ret; } +/*! + * brief Clears the MCG status flags. + * + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See ref _mcg_status_flags_t. + * + * Example: + * code + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * endcode + * + * param mask The status flags to clear. This is a logical OR of members of the + * enumeration ref _mcg_status_flags_t. + */ void CLOCK_ClearStatusFlags(uint32_t mask) { uint8_t reg; - if (mask & kMCG_RtcOscLostFlag) + if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag)) { - reg = MCG->C8; + reg = MCG->C8; MCG->C8 = reg; } } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); - MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); if ((kOSC_ModeExt != config->workMode)) { /* Wait for stable. */ - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { - MCG->C2 &= ~OSC_MODE_MASK; + MCG->C2 &= ~(uint8_t)OSC_MODE_MASK; } +/*! + * brief Auto trims the internal reference clock. + * + * This function trims the internal reference clock by using the external clock. If + * successful, it returns the kStatus_Success and the frequency after + * trimming is received in the parameter p actualFreq. If an error occurs, + * the error code is returned. + * + * param extFreq External clock frequency, which should be a bus clock. + * param desireFreq Frequency to trim to. + * param actualFreq Actual frequency after trimming. + * param atms Trim fast or slow internal reference clock. + * retval kStatus_Success ATM success. + * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. + * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. + * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. + */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) { uint32_t multi; /* extFreq / desireFreq */ @@ -722,7 +896,7 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ } multi = extFreq / desireFreq; - actv = multi * 21U; + actv = multi * 21U; if (kMCG_AtmSel4m == atms) { @@ -734,17 +908,17 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ MCG->ATCVH = (uint8_t)(actv >> 8U); mcg_sc = MCG->SC; - mcg_sc &= ~(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); + mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms)); MCG->SC = (mcg_sc | MCG_SC_ATME_MASK); /* Wait for finished. */ - while (MCG->SC & MCG_SC_ATME_MASK) + while (0U != (MCG->SC & MCG_SC_ATME_MASK)) { } /* Error occurs? */ - if (MCG->SC & MCG_SC_ATMF_MASK) + if (0U != (MCG->SC & MCG_SC_ATMF_MASK)) { /* Clear the failed flag. */ MCG->SC = mcg_sc; @@ -765,12 +939,19 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ return kStatus_Success; } +/*! + * brief Gets the current MCG mode. + * + * This function checks the MCG registers and determines the current MCG mode. + * + * return Current MCG mode or error code; See ref mcg_mode_t. + */ mcg_mode_t CLOCK_GetMode(void) { mcg_mode_t mode = kMCG_ModeError; - uint32_t clkst = MCG_S_CLKST_VAL; - uint32_t irefst = MCG_S_IREFST_VAL; - uint32_t lp = MCG_C2_LP_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; + uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL; + uint32_t lp = (uint32_t)MCG_C2_LP_VAL; /*------------------------------------------------------------------ Mode and Registers @@ -811,49 +992,66 @@ mcg_mode_t CLOCK_GetMode(void) ----------------------------------------------------------------------*/ - switch (clkst) + if (clkst == (uint32_t)kMCG_ClkOutStatFll) { - case kMCG_ClkOutStatFll: - if (kMCG_FllSrcExternal == irefst) + if ((uint32_t)kMCG_FllSrcExternal == irefst) + { + mode = kMCG_ModeFEE; + } + else + { + mode = kMCG_ModeFEI; + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatInt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPI; + } + else + { { - mode = kMCG_ModeFEE; + mode = kMCG_ModeFBI; } - else + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatExt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPE; + } + else + { { - mode = kMCG_ModeFEI; + mode = kMCG_ModeFBE; } - break; - case kMCG_ClkOutStatInt: - if (lp) - { - mode = kMCG_ModeBLPI; - } - else - { - { - mode = kMCG_ModeFBI; - } - } - break; - case kMCG_ClkOutStatExt: - if (lp) - { - mode = kMCG_ModeBLPE; - } - else - { - { - mode = kMCG_ModeFBE; - } - } - break; - default: - break; + } + } + else + { + /*do nothing*/ } return mode; } +/*! + * brief Sets the MCG to FEI mode. + * + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. + */ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -874,7 +1072,7 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -882,12 +1080,12 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal)); /* IREFS = 1 */ + MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -898,15 +1096,16 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -914,6 +1113,21 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FEE mode. + * + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -934,7 +1148,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -942,13 +1156,24 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait and check status. */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -959,7 +1184,8 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); MCG->C4 = mcg_c4; /* Wait for DRST_DRS update. */ @@ -968,12 +1194,12 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -981,6 +1207,22 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to FBI mode. + * + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FBI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -999,7 +1241,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela mcg_c4 = MCG->C4; - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ /* Errata: ERR007993 @@ -1007,7 +1249,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1015,12 +1257,12 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1030,14 +1272,15 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela MCG->C4 = mcg_c4; } - while (kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1045,6 +1288,21 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FBE mode. + * + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FBE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1060,7 +1318,7 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void #endif /* Set LP bit to enable the FLL */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; mcg_c4 = MCG->C4; @@ -1070,7 +1328,7 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1078,13 +1336,24 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for Reference clock Status bit to clear */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1095,15 +1364,16 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRST_DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for clock status bits to show clock source is ext ref clk */ - while (kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) { } /* Wait for fll stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1111,10 +1381,19 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to BLPI mode. + * + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpiMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { return kStatus_MCG_ModeUnreachable; } @@ -1126,10 +1405,19 @@ status_t CLOCK_SetBlpiMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode. + * + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { return kStatus_MCG_ModeUnreachable; } @@ -1141,6 +1429,22 @@ status_t CLOCK_SetBlpeMode(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBE mode from the external mode. + * + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: + * + * code + * CLOCK_ExternalModeToFbeModeQuick(); + * CLOCK_SetFeiMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. + */ status_t CLOCK_ExternalModeToFbeModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1151,16 +1455,32 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) #endif /* MCG_CONFIG_CHECK_PARAM */ /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } return kStatus_Success; } +/*! + * brief Switches the MCG to FBI mode from internal modes. + * + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: + * + * code + * CLOCK_InternalModeToFbiModeQuick(); + * CLOCK_SetFeeMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. + */ status_t CLOCK_InternalModeToFbiModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1171,37 +1491,80 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) #endif /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } return kStatus_Success; } +/*! + * brief Sets the MCG to FEI mode during system boot up. + * + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to FEE mode during system bootup. + * + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, OSCSEL. + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to BLPI mode during system boot up. + * + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param fcrdiv Fast IRC divider, FCRDIV. + * param ircs The internal reference clock to select, IRCS. + * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * + * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) { /* If reset mode is FEI mode, set MCGIRCLK and always success. */ - CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); /* If reset mode is not BLPI, first enter FBI mode. */ - MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } @@ -1211,14 +1574,36 @@ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEn return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode during system boot up. + * + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); /* Set to FBE mode. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != @@ -1251,36 +1636,50 @@ static const mcg_mode_t mcgModeMatrix[6][6] = { /* FEI FBI BLPI FEE FBE BLPE */ }; +/*! + * brief Sets the MCG to a target mode. + * + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. + * + * param config Pointer to the target MCG mode configuration structure. + * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. + * + * note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. + */ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) { mcg_mode_t next_mode; status_t status = kStatus_Success; /* If need to change external clock, MCG_C7[OSCSEL]. */ - if (MCG_C7_OSCSEL_VAL != config->oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel)) { /* If external clock is in use, change to FEI first. */ - if (!(MCG->S & MCG_S_IRCST_MASK)) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { - CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); + (void)CLOCK_ExternalModeToFbeModeQuick(); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL); } - CLOCK_SetExternalRefClkConfig(config->oscsel); + (void)CLOCK_SetExternalRefClkConfig(config->oscsel); } /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */ - if (MCG_S_CLKST_VAL == kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt) { - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } /* Configure MCGIRCLK. */ - CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); next_mode = CLOCK_GetMode(); @@ -1297,10 +1696,10 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL); break; case kMCG_ModeFBE: - status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL); break; case kMCG_ModeBLPI: status = CLOCK_SetBlpiMode(); @@ -1319,3 +1718,29 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) return kStatus_Success; } + +/*! + * brief Delay at least for several microseconds. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + + uint32_t count = (uint32_t)USEC_TO_COUNT(delay_us, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); + + /* + * Calculate the real delay count depend on the excute instructions cycles, + * users can change the divider value to adapt to the real IDE optimise level. + */ + count = (count / 4U); + + for (; count > 0UL; count--) + { + __NOP(); + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_clock.h index daec7ab7bc..e9bccc02ea 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_clock.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ @@ -38,31 +16,74 @@ /*! @file */ +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could control the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.0. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief CLOCK driver version 2.3.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) /*@}*/ +/* Definition for delay API in clock driver, users can redefine it to the real application. */ +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (120000000UL) +#endif + /*! @brief External XTAL0 (OSC0) clock frequency. * * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Set up the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. + * Set up the OSC0 + * CLOCK_InitOsc0(...); + * Set the XTAL0 value to the clock driver. + * CLOCK_SetXtal0Freq(80000000); * @endcode * * This is important for the multicore platforms where only one core needs to set up the * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * @@ -73,7 +94,7 @@ extern uint32_t g_xtal0Freq; * the clock. All other cores need to call the CLOCK_SetXtal32Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; #if (defined(OSC) && !(defined(OSC0))) #define OSC0 OSC @@ -221,10 +242,8 @@ typedef enum _clock_name kCLOCK_Osc0ErClk, /*!< OSC0 external reference clock (OSC0ERCLK) */ /* ----------------------------- MCG and MCG-Lite clock ---------------------------*/ - kCLOCK_McgFixedFreqClk, /*!< MCG fixed frequency clock (MCGFFCLK) */ kCLOCK_McgInternalRefClk, /*!< MCG internal reference clock (MCGIRCLK) */ kCLOCK_McgFllClk, /*!< MCGFLLCLK */ - kCLOCK_McgPeriphClk, /*!< MCG peripheral clock (MCGPCLK) */ /* --------------------------------- Other clock ----------------------------------*/ kCLOCK_LpoClk, /*!< LPO clock */ @@ -264,39 +283,39 @@ typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), - kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), - kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), + kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x1038U, 20U), - kCLOCK_Aesa = CLK_GATE_DEFINE(0x1038U, 24U), - kCLOCK_Ltc0 = CLK_GATE_DEFINE(0x1038U, 24U), - kCLOCK_Rsim = CLK_GATE_DEFINE(0x1038U, 25U), - kCLOCK_Dcdc0 = CLK_GATE_DEFINE(0x1038U, 26U), - kCLOCK_Btll = CLK_GATE_DEFINE(0x1038U, 27U), - kCLOCK_PhyDig = CLK_GATE_DEFINE(0x1038U, 28U), - kCLOCK_ZigBee = CLK_GATE_DEFINE(0x1038U, 29U), - kCLOCK_GenFsk = CLK_GATE_DEFINE(0x1038U, 31U), + kCLOCK_Aesa = CLK_GATE_DEFINE(0x1038U, 24U), + kCLOCK_Ltc0 = CLK_GATE_DEFINE(0x1038U, 24U), + kCLOCK_Rsim = CLK_GATE_DEFINE(0x1038U, 25U), + kCLOCK_Dcdc0 = CLK_GATE_DEFINE(0x1038U, 26U), + kCLOCK_Btll = CLK_GATE_DEFINE(0x1038U, 27U), + kCLOCK_PhyDig = CLK_GATE_DEFINE(0x1038U, 28U), + kCLOCK_ZigBee = CLK_GATE_DEFINE(0x1038U, 29U), + kCLOCK_GenFsk = CLK_GATE_DEFINE(0x1038U, 31U), - kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), - kCLOCK_Trng0 = CLK_GATE_DEFINE(0x103CU, 9U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), - kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), + kCLOCK_Trng0 = CLK_GATE_DEFINE(0x103CU, 9U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 8U), } clock_ip_name_t; @@ -322,18 +341,14 @@ typedef enum _osc_mode #endif kOSC_ModeOscHighGain = 0U #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) - | - MCG_C2_EREFS_MASK + | MCG_C2_EREFS_MASK #else - | - MCG_C2_EREFS0_MASK + | MCG_C2_EREFS0_MASK #endif #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK))) - | - MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ #else - | - MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ #endif } osc_mode_t; @@ -430,13 +445,13 @@ typedef enum _mcg_monitor_mode enum _mcg_status { kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0), /*!< Can't switch to target mode. */ - kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific + kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific function. */ - kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ + kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ - kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ - kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ + kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because it is in use. */ }; @@ -449,7 +464,7 @@ enum _mcg_status_flags_t /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcg_irclk_enable_mode { - kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; @@ -724,7 +739,7 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } else { - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; } } @@ -740,8 +755,8 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); @@ -755,7 +770,7 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); @@ -769,9 +784,18 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); */ static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) { - MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv); + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ +void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); + /*@}*/ /*! @name MCG clock lock monitor functions. */ @@ -795,20 +819,20 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode); * * Example: * @code - // To check the clock lost lock status of OSC0 and PLL0. - uint32_t mcgFlags; - - mcgFlags = CLOCK_GetStatusFlags(); - - if (mcgFlags & kMCG_Osc0LostFlag) - { - // OSC0 clock lock lost. Do something. - } - if (mcgFlags & kMCG_Pll0LostFlag) - { - // PLL0 clock lock lost. Do something. - } - @endcode + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * @endcode * * @return Logical OR value of the @ref _mcg_status_flags_t. */ @@ -822,10 +846,10 @@ uint32_t CLOCK_GetStatusFlags(void); * * Example: * @code - // To clear the clock lost lock status flags of OSC0 and PLL0. - - CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); - @endcode + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * @endcode * * @param mask The status flags to clear. This is a logical OR of members of the * enumeration @ref _mcg_status_flags_t. @@ -1016,7 +1040,7 @@ status_t CLOCK_SetBlpeMode(void); * @brief Switches the MCG to FBE mode from the external mode. * * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. - * The external clock is used as the system clock souce and PLL is disabled. However, + * The external clock is used as the system clock source and PLL is disabled. However, * the FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEE mode to FEI mode: * @@ -1034,7 +1058,7 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void); * @brief Switches the MCG to FBI mode from internal modes. * * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. - * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, * FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEI mode to FEE mode: * @@ -1087,7 +1111,7 @@ status_t CLOCK_BootToFeeMode( * @brief Sets the MCG to BLPI mode during system boot up. * * This function sets the MCG to BLPI mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. @@ -1099,10 +1123,10 @@ status_t CLOCK_BootToFeeMode( status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Sets the MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during system boot up. * * This function sets the MCG to BLPE mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @@ -1127,6 +1151,16 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel); */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); +/*! + * @brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + /*@}*/ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_clock.c index 476eeb3cd1..e205d3a613 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_clock.c @@ -1,40 +1,22 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include "fsl_common.h" #include "fsl_clock.h" /******************************************************************************* * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + /* Macro definition remap workaround. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) #define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK @@ -65,11 +47,11 @@ #define TRIM_SIRC_MIN (31250U) #define MCG_S_IRCST_VAL ((MCG->S & MCG_S_IRCST_MASK) >> MCG_S_IRCST_SHIFT) -#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) -#define MCG_S_IREFST_VAL ((MCG->S & MCG_S_IREFST_MASK) >> MCG_S_IREFST_SHIFT) +#define MCG_S_CLKST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_CLKST_MASK) >> (uint32_t)MCG_S_CLKST_SHIFT) +#define MCG_S_IREFST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IREFST_MASK) >> (uint32_t)MCG_S_IREFST_SHIFT) #define MCG_S_PLLST_VAL ((MCG->S & MCG_S_PLLST_MASK) >> MCG_S_PLLST_SHIFT) #define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT) -#define MCG_C2_LP_VAL ((MCG->C2 & MCG_C2_LP_MASK) >> MCG_C2_LP_SHIFT) +#define MCG_C2_LP_VAL (((uint32_t)MCG->C2 & (uint32_t)MCG_C2_LP_MASK) >> (uint32_t)MCG_C2_LP_SHIFT) #define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT) #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) #define MCG_S2_PLLCST_VAL ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT) @@ -119,10 +101,9 @@ static uint32_t s_slowIrcFreq = 32768U; static uint32_t s_fastIrcFreq = 4000000U; /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; - +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -191,6 +172,7 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * @@ -198,11 +180,33 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ static void CLOCK_FllStableDelay(void); +#endif /******************************************************************************* * Code ******************************************************************************/ +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN +static void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (0U != (i--)) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardless how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ + static uint32_t CLOCK_GetMcgExtClkFreq(void) { uint32_t freq; @@ -211,12 +215,12 @@ static uint32_t CLOCK_GetMcgExtClkFreq(void) { case 0U: /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ - assert(g_xtal0Freq); + assert(0U != g_xtal0Freq); freq = g_xtal0Freq; break; case 1U: /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ - assert(g_xtal32Freq); + assert(0U != g_xtal32Freq); freq = g_xtal32Freq; break; case 2U: @@ -239,7 +243,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) uint32_t freq = CLOCK_GetMcgExtClkFreq(); - if (!freq) + if (0U == freq) { return freq; } @@ -247,7 +251,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) frdiv = MCG_C1_FRDIV_VAL; freq >>= frdiv; - range = MCG_C2_RANGE_VAL; + range = MCG_C2_RANGE_VAL; oscsel = MCG_C7_OSCSEL_VAL; /* @@ -255,7 +259,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) 1. MCG_C7[OSCSEL] selects IRC48M. 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0. */ - if (((0U != range) && (kMCG_OscselOsc == oscsel)) || (kMCG_OscselIrc == oscsel)) + if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel)) || ((uint8_t)kMCG_OscselIrc == oscsel)) { switch (frdiv) { @@ -286,7 +290,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) { - if (kMCG_IrcSlow == MCG_S_IRCST_VAL) + if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL) { /* Slow internal reference clock selected*/ return s_slowIrcFreq; @@ -301,7 +305,7 @@ static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) static uint32_t CLOCK_GetFllRefClkFreq(void) { /* If use external reference clock. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { return CLOCK_GetFllExtRefClkFreq(); } @@ -338,19 +342,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - +/*! + * brief Get the OSC0 external reference undivided clock frequency (OSC0ERCLK_UNDIV). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -365,6 +361,11 @@ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) } } +/*! + * brief Get the OSC0 external reference divided clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkDivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -379,6 +380,11 @@ uint32_t CLOCK_GetOsc0ErClkDivFreq(void) } } +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -403,6 +409,11 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the output clock frequency selected by SIM[PLLFLLSEL]. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPllFllSelClkFreq(void) { uint32_t freq; @@ -426,36 +437,76 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) return freq; } +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { return CLOCK_GetOsc0ErClkDivFreq(); } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); } +/*! + * brief Get the flexbus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlexBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1); } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -513,6 +564,13 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; @@ -520,6 +578,13 @@ void CLOCK_SetSimConfig(sim_clock_config_t const *config) CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { bool ret = true; @@ -564,23 +629,31 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! + * brief Gets the MCG output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG output clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; - uint32_t clkst = MCG_S_CLKST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; switch (clkst) { - case kMCG_ClkOutStatPll: + case (uint32_t)kMCG_ClkOutStatPll: mcgoutclk = CLOCK_GetPll0Freq(); break; - case kMCG_ClkOutStatFll: + case (uint32_t)kMCG_ClkOutStatFll: mcgoutclk = CLOCK_GetFllFreq(); break; - case kMCG_ClkOutStatInt: + case (uint32_t)kMCG_ClkOutStatInt: mcgoutclk = CLOCK_GetInternalRefClkSelectFreq(); break; - case kMCG_ClkOutStatExt: + case (uint32_t)kMCG_ClkOutStatExt: mcgoutclk = CLOCK_GetMcgExtClkFreq(); break; default: @@ -590,6 +663,15 @@ uint32_t CLOCK_GetOutClkFreq(void) return mcgoutclk; } +/*! + * brief Gets the MCG FLL clock (MCGFLLCLK) frequency. + * + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. + * + * return The frequency of MCGFLLCLK. + */ uint32_t CLOCK_GetFllFreq(void) { static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; @@ -598,28 +680,36 @@ uint32_t CLOCK_GetFllFreq(void) uint32_t freq; /* If FLL is not enabled currently, then return 0U. */ - if ((MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) + if (0U != (MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) { return 0U; } /* Get FLL reference clock frequency. */ freq = CLOCK_GetFllRefClkFreq(); - if (!freq) + if (0U == freq) { return freq; } - drs = MCG_C4_DRST_DRS_VAL; + drs = MCG_C4_DRST_DRS_VAL; dmx32 = MCG_C4_DMX32_VAL; return freq * fllFactorTable[drs][dmx32]; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { /* If MCGIRCLK is gated. */ - if (!(MCG->C1 & MCG_C1_IRCLKEN_MASK)) + if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK)) { return 0U; } @@ -627,12 +717,20 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetInternalRefClkSelectFreq(); } +/*! + * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. + * + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGFFCLK. + */ uint32_t CLOCK_GetFixedFreqClkFreq(void) { uint32_t freq = CLOCK_GetFllRefClkFreq(); /* MCGFFCLK must be no more than MCGOUTCLK/8. */ - if ((freq) && (freq <= (CLOCK_GetOutClkFreq() / 8U))) + if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq)) { return freq; } @@ -642,6 +740,14 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void) } } +/*! + * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. + * + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGPLL0CLK. + */ uint32_t CLOCK_GetPll0Freq(void) { uint32_t mcgpll0clk; @@ -654,12 +760,30 @@ uint32_t CLOCK_GetPll0Freq(void) mcgpll0clk = CLOCK_GetPll0RefFreq(); + /* + * Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. + * Please call CLOCK_SetXtal1Freq base on board setting before using OSC1 clock. + */ + assert(mcgpll0clk); + mcgpll0clk /= (FSL_FEATURE_MCG_PLL_PRDIV_BASE + MCG_C5_PRDIV0_VAL); mcgpll0clk *= (FSL_FEATURE_MCG_PLL_VDIV_BASE + MCG_C6_VDIV0_VAL); return mcgpll0clk; } +/*! + * brief Selects the MCG external reference clock. + * + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. + * + * param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. + * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success External reference clock set successfully. + */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) { bool needDelay; @@ -673,7 +797,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } #endif /* MCG_CONFIG_CHECK_PARAM */ - if (MCG_C7_OSCSEL_VAL != oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel) { /* If change OSCSEL, need to delay, ERR009878. */ needDelay = true; @@ -683,22 +807,12 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) needDelay = false; } - MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - + MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ i = 1500U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -707,15 +821,31 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Configures the Internal Reference clock (MCGIRCLK). + * + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. + * + * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * param ircs MCGIRCLK clock source, choose fast or slow. + * param fcrdiv Fast IRC divider setting (\c FCRDIV). + * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success MCGIRCLK configuration finished successfully. + */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) { - uint32_t mcgOutClkState = MCG_S_CLKST_VAL; - mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; - uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; + uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL; + mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; + uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) /* If MCGIRCLK is used as system clock source. */ - if (kMCG_ClkOutStatInt == mcgOutClkState) + if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState) { /* If need to change MCGIRCLK source or driver, return error. */ if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs)) @@ -729,25 +859,27 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, if (fcrdiv != curFcrdiv) { /* If fast IRC is in use currently, change to slow IRC. */ - if ((kMCG_IrcFast == curIrcs) && ((mcgOutClkState == kMCG_ClkOutStatInt) || (MCG->C1 & MCG_C1_IRCLKEN_MASK))) + if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) && + (kMCG_IrcFast == curIrcs)) { - MCG->C2 = ((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); - while (MCG_S_IRCST_VAL != kMCG_IrcSlow) + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); + while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow) { } } /* Update FCRDIV. */ - MCG->SC = (MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); + MCG->SC = + (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); } /* Set internal reference clock selection. */ - MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)); - MCG->C1 = (MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode; + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs))); + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode); /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */ - if ((mcgOutClkState == kMCG_ClkOutStatInt) || (enableMode & kMCG_IrclkEnable)) + if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable))) { - while (MCG_S_IRCST_VAL != ircs) + while (MCG_S_IRCST_VAL != (uint8_t)ircs) { } } @@ -755,17 +887,32 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, return kStatus_Success; } +/*! + * brief Calculates the PLL divider setting for a desired output frequency. + * + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function + * returns 0. + * + * param refFreq PLL reference clock frequency. + * param desireFreq Desired PLL output frequency. + * param prdiv PRDIV value to generate desired PLL frequency. + * param vdiv VDIV value to generate desired PLL frequency. + * return Closest frequency match that the PLL was able generate. + */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv) { - uint8_t ret_prdiv; /* PRDIV to return. */ - uint8_t ret_vdiv; /* VDIV to return. */ - uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_cur; /* PRDIV value for iteration. */ - uint8_t vdiv_cur; /* VDIV value for iteration. */ - uint32_t ret_freq = 0U; /* PLL output fequency to return. */ - uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ - uint32_t ref_div; /* Reference frequency after PRDIV. */ + uint8_t ret_prdiv; /* PRDIV to return. */ + uint8_t ret_vdiv; /* VDIV to return. */ + uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_cur; /* PRDIV value for iteration. */ + uint8_t vdiv_cur; /* VDIV value for iteration. */ + uint32_t ret_freq = 0U; /* PLL output frequency to return. */ + uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ + uint32_t ref_div; /* Reference frequency after PRDIV. */ /* Steps: @@ -812,15 +959,15 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (ret_freq == desireFreq) /* If desire frequency is got. */ { *prdiv = prdiv_cur - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; return ret_freq; } /* New PRDIV/VDIV is closer. */ if (diff > desireFreq - ret_freq) { - diff = desireFreq - ret_freq; + diff = desireFreq - ret_freq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } vdiv_cur++; @@ -830,9 +977,9 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, /* New PRDIV/VDIV is closer. */ if (diff > ret_freq - desireFreq) { - diff = ret_freq - desireFreq; + diff = ret_freq - desireFreq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } } @@ -840,8 +987,8 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (0xFFFFFFFFU != diff) { /* PRDIV/VDIV found. */ - *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; + *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; ret_freq = (refFreq / ret_prdiv) * ret_vdiv; return ret_freq; } @@ -852,6 +999,17 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, } } +/*! + * brief Enables the PLL0 in FLL mode. + * + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL + * divider values. + * + * param config Pointer to the configuration structure. + */ void CLOCK_EnablePll0(mcg_pll_config_t const *config) { assert(config); @@ -872,20 +1030,27 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ - MCG->SC &= ~MCG_SC_ATMF_MASK; + MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK; if (kMCG_MonitorNone == mode) { - MCG->C6 &= ~MCG_C6_CME0_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK; } else { if (kMCG_MonitorInt == mode) { - MCG->C2 &= ~MCG_C2_LOCRE0_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK; } else { @@ -895,11 +1060,18 @@ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the RTC OSC clock monitor mode. + * + * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8 = MCG->C8; - mcg_c8 &= ~(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); + mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); if (kMCG_MonitorNone != mode) { @@ -912,6 +1084,13 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) MCG->C8 = mcg_c8; } +/*! + * brief Sets the PLL0 clock monitor mode. + * + * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8; @@ -942,34 +1121,76 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Gets the MCG status flags. + * + * This function gets the MCG clock status flags. All status flags are + * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To + * check a specific flag, compare the return value with the flag. + * + * Example: + * code + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * endcode + * + * return Logical OR value of the ref _mcg_status_flags_t. + */ uint32_t CLOCK_GetStatusFlags(void) { - uint32_t ret = 0U; + uint32_t ret = 0U; uint8_t mcg_s = MCG->S; if (MCG->SC & MCG_SC_LOCS0_MASK) { - ret |= kMCG_Osc0LostFlag; + ret |= (uint32_t)kMCG_Osc0LostFlag; } if (mcg_s & MCG_S_OSCINIT0_MASK) { - ret |= kMCG_Osc0InitFlag; + ret |= (uint32_t)kMCG_Osc0InitFlag; } - if (MCG->C8 & MCG_C8_LOCS1_MASK) + if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK)) { - ret |= kMCG_RtcOscLostFlag; + ret |= (uint32_t)kMCG_RtcOscLostFlag; } if (mcg_s & MCG_S_LOLS0_MASK) { - ret |= kMCG_Pll0LostFlag; + ret |= (uint32_t)kMCG_Pll0LostFlag; } if (mcg_s & MCG_S_LOCK0_MASK) { - ret |= kMCG_Pll0LockFlag; + ret |= (uint32_t)kMCG_Pll0LockFlag; } return ret; } +/*! + * brief Clears the MCG status flags. + * + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See ref _mcg_status_flags_t. + * + * Example: + * code + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * endcode + * + * param mask The status flags to clear. This is a logical OR of members of the + * enumeration ref _mcg_status_flags_t. + */ void CLOCK_ClearStatusFlags(uint32_t mask) { uint8_t reg; @@ -978,9 +1199,9 @@ void CLOCK_ClearStatusFlags(uint32_t mask) { MCG->SC &= ~MCG_SC_ATMF_MASK; } - if (mask & kMCG_RtcOscLostFlag) + if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag)) { - reg = MCG->C8; + reg = MCG->C8; MCG->C8 = reg; } if (mask & kMCG_Pll0LostFlag) @@ -989,30 +1210,60 @@ void CLOCK_ClearStatusFlags(uint32_t mask) } } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); OSC_SetCapLoad(OSC0, config->capLoad); - OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); - MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) { /* Wait for stable. */ - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; - MCG->C2 &= ~OSC_MODE_MASK; + MCG->C2 &= ~(uint8_t)OSC_MODE_MASK; } +/*! + * brief Auto trims the internal reference clock. + * + * This function trims the internal reference clock by using the external clock. If + * successful, it returns the kStatus_Success and the frequency after + * trimming is received in the parameter p actualFreq. If an error occurs, + * the error code is returned. + * + * param extFreq External clock frequency, which should be a bus clock. + * param desireFreq Frequency to trim to. + * param actualFreq Actual frequency after trimming. + * param atms Trim fast or slow internal reference clock. + * retval kStatus_Success ATM success. + * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. + * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. + * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. + */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) { uint32_t multi; /* extFreq / desireFreq */ @@ -1046,7 +1297,7 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ } multi = extFreq / desireFreq; - actv = multi * 21U; + actv = multi * 21U; if (kMCG_AtmSel4m == atms) { @@ -1058,17 +1309,17 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ MCG->ATCVH = (uint8_t)(actv >> 8U); mcg_sc = MCG->SC; - mcg_sc &= ~(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); + mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms)); MCG->SC = (mcg_sc | MCG_SC_ATME_MASK); /* Wait for finished. */ - while (MCG->SC & MCG_SC_ATME_MASK) + while (0U != (MCG->SC & MCG_SC_ATME_MASK)) { } /* Error occurs? */ - if (MCG->SC & MCG_SC_ATMF_MASK) + if (0U != (MCG->SC & MCG_SC_ATMF_MASK)) { /* Clear the failed flag. */ MCG->SC = mcg_sc; @@ -1089,13 +1340,20 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ return kStatus_Success; } +/*! + * brief Gets the current MCG mode. + * + * This function checks the MCG registers and determines the current MCG mode. + * + * return Current MCG mode or error code; See ref mcg_mode_t. + */ mcg_mode_t CLOCK_GetMode(void) { mcg_mode_t mode = kMCG_ModeError; - uint32_t clkst = MCG_S_CLKST_VAL; - uint32_t irefst = MCG_S_IREFST_VAL; - uint32_t lp = MCG_C2_LP_VAL; - uint32_t pllst = MCG_S_PLLST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; + uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL; + uint32_t lp = (uint32_t)MCG_C2_LP_VAL; + uint32_t pllst = MCG_S_PLLST_VAL; /*------------------------------------------------------------------ Mode and Registers @@ -1136,60 +1394,78 @@ mcg_mode_t CLOCK_GetMode(void) ----------------------------------------------------------------------*/ - switch (clkst) + if (clkst == (uint32_t)kMCG_ClkOutStatFll) { - case kMCG_ClkOutStatFll: - if (kMCG_FllSrcExternal == irefst) + if ((uint32_t)kMCG_FllSrcExternal == irefst) + { + mode = kMCG_ModeFEE; + } + else + { + mode = kMCG_ModeFEI; + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatInt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPI; + } + else + { { - mode = kMCG_ModeFEE; + mode = kMCG_ModeFBI; + } + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatExt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPE; + } + else + { + if (kMCG_PllstPll == pllst) + { + mode = kMCG_ModePBE; } else { - mode = kMCG_ModeFEI; + mode = kMCG_ModeFBE; } - break; - case kMCG_ClkOutStatInt: - if (lp) - { - mode = kMCG_ModeBLPI; - } - else - { - { - mode = kMCG_ModeFBI; - } - } - break; - case kMCG_ClkOutStatExt: - if (lp) - { - mode = kMCG_ModeBLPE; - } - else - { - if (kMCG_PllstPll == pllst) - { - mode = kMCG_ModePBE; - } - else - { - mode = kMCG_ModeFBE; - } - } - break; - case kMCG_ClkOutStatPll: + } + } + if (clkst == (uint32_t)kMCG_ClkOutStatPll) + { { mode = kMCG_ModePEE; } - break; - default: - break; + } + else + { + /*do nothing*/ } return mode; } -status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +/*! + * brief Sets the MCG to FEI mode. + * + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. + */ +status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; bool change_drs = false; @@ -1209,7 +1485,7 @@ status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1217,12 +1493,12 @@ status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal)); /* IREFS = 1 */ + MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1233,15 +1509,16 @@ status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1249,6 +1526,21 @@ status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) return kStatus_Success; } +/*! + * brief Sets the MCG to FEE mode. + * + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1269,7 +1561,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1277,13 +1569,24 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait and check status. */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1294,7 +1597,8 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); MCG->C4 = mcg_c4; /* Wait for DRST_DRS update. */ @@ -1303,12 +1607,12 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1316,7 +1620,23 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } -status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +/*! + * brief Sets the MCG to FBI mode. + * + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FBI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ +status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; bool change_drs = false; @@ -1334,7 +1654,7 @@ status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) mcg_c4 = MCG->C4; - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ /* Errata: ERR007993 @@ -1342,7 +1662,7 @@ status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1350,12 +1670,12 @@ status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1365,14 +1685,15 @@ status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) MCG->C4 = mcg_c4; } - while (kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1380,6 +1701,21 @@ status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) return kStatus_Success; } +/*! + * brief Sets the MCG to FBE mode. + * + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FBE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1395,13 +1731,13 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void #endif /* Change to FLL mode. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } /* Set LP bit to enable the FLL */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; mcg_c4 = MCG->C4; @@ -1411,7 +1747,7 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1419,13 +1755,24 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for Reference clock Status bit to clear */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1436,15 +1783,16 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRST_DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for clock status bits to show clock source is ext ref clk */ - while (kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) { } /* Wait for fll stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1452,10 +1800,19 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to BLPI mode. + * + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpiMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { return kStatus_MCG_ModeUnreachable; } @@ -1467,10 +1824,19 @@ status_t CLOCK_SetBlpiMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode. + * + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { return kStatus_MCG_ModeUnreachable; } @@ -1482,8 +1848,29 @@ status_t CLOCK_SetBlpeMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to PBE mode. + * + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. + * + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. + * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); + */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { + assert(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. @@ -1512,6 +1899,8 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co /* Change to PLL mode. */ MCG->C6 |= MCG_C6_PLLS_MASK; + + /* Wait for PLL mode changed. */ while (!(MCG->S & MCG_S_PLLST_MASK)) { } @@ -1519,6 +1908,18 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode. + * + * This function sets the MCG to PEE mode. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. + */ status_t CLOCK_SetPeeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1533,13 +1934,29 @@ status_t CLOCK_SetPeeMode(void) MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); /* Wait for clock status bits to update */ - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } return kStatus_Success; } +/*! + * brief Switches the MCG to FBE mode from the external mode. + * + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: + * + * code + * CLOCK_ExternalModeToFbeModeQuick(); + * CLOCK_SetFeiMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. + */ status_t CLOCK_ExternalModeToFbeModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1550,15 +1967,15 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) #endif /* MCG_CONFIG_CHECK_PARAM */ /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } /* Disable PLL. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } @@ -1566,6 +1983,22 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBI mode from internal modes. + * + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: + * + * code + * CLOCK_InternalModeToFbiModeQuick(); + * CLOCK_SetFeeMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. + */ status_t CLOCK_InternalModeToFbiModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1576,37 +2009,80 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) #endif /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } return kStatus_Success; } -status_t CLOCK_BootToFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +/*! + * brief Sets the MCG to FEI mode during system boot up. + * + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ +status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - return CLOCK_SetFeiMode(drs, fllStableDelay); + return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to FEE mode during system bootup. + * + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, OSCSEL. + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to BLPI mode during system boot up. + * + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param fcrdiv Fast IRC divider, FCRDIV. + * param ircs The internal reference clock to select, IRCS. + * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * + * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) { /* If reset mode is FEI mode, set MCGIRCLK and always success. */ - CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); /* If reset mode is not BLPI, first enter FBI mode. */ - MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } @@ -1616,14 +2092,36 @@ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEn return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode during system boot up. + * + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); /* Set to FBE mode. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) + { + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != @@ -1637,6 +2135,19 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode during system boot up. + * + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1647,7 +2158,7 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc /* Change to use PLL output clock. */ MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } @@ -1683,6 +2194,20 @@ static const mcg_mode_t mcgModeMatrix[8][8] = { /* FEI FBI BLPI FEE FBE BLPE PBE PEE */ }; +/*! + * brief Sets the MCG to a target mode. + * + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. + * + * param config Pointer to the target MCG mode configuration structure. + * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. + * + * note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. + */ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) { mcg_mode_t next_mode; @@ -1691,30 +2216,30 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) mcg_pll_clk_select_t pllcs = kMCG_PllClkSelPll0; /* If need to change external clock, MCG_C7[OSCSEL]. */ - if (MCG_C7_OSCSEL_VAL != config->oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel)) { /* If external clock is in use, change to FEI first. */ - if (!(MCG->S & MCG_S_IRCST_MASK)) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { - CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->drs, (void (*)(void))0); + (void)CLOCK_ExternalModeToFbeModeQuick(); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL); } - CLOCK_SetExternalRefClkConfig(config->oscsel); + (void)CLOCK_SetExternalRefClkConfig(config->oscsel); } /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */ - if (MCG_S_CLKST_VAL == kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt) { - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->drs, CLOCK_FllStableDelay); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } /* Configure MCGIRCLK. */ - CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); next_mode = CLOCK_GetMode(); @@ -1725,16 +2250,16 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) switch (next_mode) { case kMCG_ModeFEI: - status = CLOCK_SetFeiMode(config->drs, CLOCK_FllStableDelay); + status = CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFEE: status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL); break; case kMCG_ModeFBE: - status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL); break; case kMCG_ModeBLPI: status = CLOCK_SetBlpiMode(); @@ -1753,7 +2278,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) else { MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } } @@ -1776,7 +2301,55 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) } else { - MCG->C5 &= ~(uint32_t)kMCG_PllEnableIndependent; + MCG->C5 &= ~(uint8_t)kMCG_PllEnableIndependent; } return kStatus_Success; } + +/*! + * brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + uint64_t count = 0U; + uint32_t period = SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 1000000; + + /* Make sure the DWT trace fucntion is enabled. */ + if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR)) + { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + } + + /* CYCCNT not supported on this device. */ + assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk)); + + /* If CYCCENT has already been enabled, read directly, otherwise, need enable it. */ + if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL)) + { + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + /* Calculate the count ticks. */ + count = DWT->CYCCNT; + count += (uint64_t)period * delay_us; + + if (count > 0xFFFFFFFFUL) + { + count -= 0xFFFFFFFFUL; + /* wait for cyccnt overflow. */ + while (count < DWT->CYCCNT) + { + } + } + + /* Wait for cyccnt reach count value. */ + while (count > DWT->CYCCNT) + { + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_clock.h index b6040ff75d..c59be50ab6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_clock.h @@ -1,77 +1,100 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include -#include -#include +#include "fsl_common.h" /*! @addtogroup clock */ /*! @{ */ +/*! @file */ + +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could control the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + /******************************************************************************* * Definitions ******************************************************************************/ -/*! @brief Clock driver version. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ +/*! @name Driver version */ +/*@{*/ +/*! @brief CLOCK driver version 2.3.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) +/*@}*/ + +/* Definition for delay API in clock driver, users can redefine it to the real application. */ +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (120000000UL) +#endif /*! @brief External XTAL0 (OSC0) clock frequency. * - * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal0Freq to set the value in to clock driver. For example, - * if XTAL0 is 8MHz, + * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, + * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Setup the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to clock driver. + * Set up the OSC0 + * CLOCK_InitOsc0(...); + * Set the XTAL0 value to the clock driver. + * CLOCK_SetXtal0Freq(80000000); * @endcode * - * This is important for the multicore platforms, only one core needs to setup - * OSC0 using CLOCK_InitOsc0, all other cores need to call CLOCK_SetXtal0Freq - * to get valid clock frequency. + * This is important for the multicore platforms where only one core needs to set up the + * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq + * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * - * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal32Freq to set the value in to clock driver. + * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal32Freq to set the value in the clock driver. * - * This is important for the multicore platforms, only one core needs to setup - * the clock, all other cores need to call CLOCK_SetXtal32Freq - * to get valid clock frequency. + * This is important for the multicore platforms where only one core needs to set up + * the clock. All other cores need to call the CLOCK_SetXtal32Freq + * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; /*! @brief IRC48M clock frequency in Hz. */ #define MCG_INTERNAL_IRC_48M 48000000U @@ -207,9 +230,9 @@ extern uint32_t g_xtal32Freq; } /*! @brief Clock ip name array for CMP. */ -#define CMP_CLOCKS \ - { \ - kCLOCK_Cmp0, kCLOCK_Cmp1, kCLOCK_Cmp2 \ +#define CMP_CLOCKS \ + { \ + kCLOCK_Cmp0, kCLOCK_Cmp1 \ } /*! @@ -267,9 +290,9 @@ typedef enum _clock_name /*! @brief USB clock source definition. */ typedef enum _clock_usb_src { - kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ + kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(3U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ } clock_usb_src_t; /*------------------------------------------------------------------------------ @@ -304,47 +327,46 @@ typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), - kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U), - kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U), - kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), + kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U), + kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U), + kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), - kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), - kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), + kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), - kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), - kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x103CU, 6U), - kCLOCK_Adc1 = CLK_GATE_DEFINE(0x103CU, 7U), - kCLOCK_Dac1 = CLK_GATE_DEFINE(0x103CU, 8U), - kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x103CU, 9U), + kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x103CU, 6U), + kCLOCK_Adc1 = CLK_GATE_DEFINE(0x103CU, 7U), + kCLOCK_Dac1 = CLK_GATE_DEFINE(0x103CU, 8U), + kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x103CU, 9U), kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x103CU, 10U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), - kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), - kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), - kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), - kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), + kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), + kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), + kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U), kCLOCK_Flexbus0 = CLK_GATE_DEFINE(0x1040U, 0U), - kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), + kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), } clock_ip_name_t; /*!@brief SIM configuration structure for clock setting. */ @@ -358,7 +380,7 @@ typedef struct _sim_clock_config /*! @brief OSC work mode. */ typedef enum _osc_mode { - kOSC_ModeExt = 0U, /*!< Use external clock. */ + kOSC_ModeExt = 0U, /*!< Use an external clock. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) kOSC_ModeOscLowPower = MCG_C2_EREFS_MASK, /*!< Oscillator low power. */ #else @@ -366,34 +388,30 @@ typedef enum _osc_mode #endif kOSC_ModeOscHighGain = 0U #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) - | - MCG_C2_EREFS_MASK + | MCG_C2_EREFS_MASK #else - | - MCG_C2_EREFS0_MASK + | MCG_C2_EREFS0_MASK #endif #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK))) - | - MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ #else - | - MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ #endif } osc_mode_t; /*! @brief Oscillator capacitor load setting.*/ enum _osc_cap_load { - kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ - kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ - kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */ }; /*! @brief OSCERCLK enable mode. */ enum _oscer_enable_mode { - kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ + kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */ }; @@ -409,8 +427,8 @@ typedef struct _oscer_config * @brief OSC Initialization Configuration Structure * * Defines the configuration data structure to initialize the OSC. - * When porting to a new board, please set the following members - * according to board setting: + * When porting to a new board, set the following members + * according to the board setting: * 1. freq: The external frequency. * 2. workMode: The OSC module mode. */ @@ -501,41 +519,41 @@ typedef enum _mcg_monitor_mode enum _mcg_status { kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0), /*!< Can't switch to target mode. */ - kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific + kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific function. */ - kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ + kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ - kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ - kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Could not change clock source because - it is used currently. */ + kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ + kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + it is in use. */ }; /*! @brief MCG status flags. */ enum _mcg_status_flags_t { - kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ - kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ + kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ + kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ kMCG_RtcOscLostFlag = (1U << 4U), /*!< RTC OSC lost. */ - kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ - kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ + kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ + kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ }; /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcg_irclk_enable_mode { - kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; /*! @brief MCG PLL clock enable mode definition. */ enum _mcg_pll_enable_mode { - kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable indepencent of - MCG clock mode. Generally, PLL + kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable independent of the + MCG clock mode. Generally, the PLL is disabled in FLL modes - (FEI/FBI/FEE/FBE), set PLL clock - enable independent will enable + (FEI/FBI/FEE/FBE). Setting the PLL clock + enable independent, enables the PLL in the FLL modes. */ kMCG_PllEnableInStop = MCG_C5_PLLSTEN0_MASK /*!< MCGPLLCLK enable in STOP mode. */ }; @@ -562,16 +580,16 @@ typedef struct _mcg_pll_config uint8_t vdiv; /*!< VCO divider VDIV. */ } mcg_pll_config_t; -/*! @brief MCG configure structure for mode change. +/*! @brief MCG mode change configuration structure * - * When porting to a new board, please set the following members - * according to board setting: - * 1. frdiv: If FLL uses the external reference clock, please set this - * value to make sure external reference clock divided by frdiv is - * in the range 31.25kHz to 39.0625kHz. + * When porting to a new board, set the following members + * according to the board setting: + * 1. frdiv: If the FLL uses the external reference clock, set this + * value to ensure that the external reference clock divided by frdiv is + * in the 31.25 kHz to 39.0625 kHz range. * 2. The PLL reference clock divider PRDIV: PLL reference clock frequency after - * PRDIV should be in the range of FSL_FEATURE_MCG_PLL_REF_MIN to - * FSL_FEATURE_MCG_PLL_REF_MAX. + * PRDIV should be in the FSL_FEATURE_MCG_PLL_REF_MIN to + * FSL_FEATURE_MCG_PLL_REF_MAX range. */ typedef struct _mcg_config { @@ -601,26 +619,6 @@ typedef struct _mcg_config extern "C" { #endif /* __cplusplus */ -/*! - * @brief Set the XTAL0 frequency based on board setting. - * - * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal0Freq(uint32_t freq) -{ - g_xtal0Freq = freq; -} - -/*! - * @brief Set the XTAL32/RTC_CLKIN frequency based on board setting. - * - * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal32Freq(uint32_t freq) -{ - g_xtal32Freq = freq; -} - /*! * @brief Enable the clock for specific IP. * @@ -815,6 +813,13 @@ uint32_t CLOCK_GetOsc0ErClkUndivFreq(void); */ uint32_t CLOCK_GetOsc0ErClkFreq(void); +/*! + * @brief Get the OSC0 external reference divided clock frequency. + * + * @return Clock frequency in Hz. + */ +uint32_t CLOCK_GetOsc0ErClkDivFreq(void); + /*! * @brief Set the clock configure in SIM module. * @@ -844,9 +849,9 @@ static inline void CLOCK_SetSimSafeDivs(void) /*@{*/ /*! - * @brief Get the MCG output clock(MCGOUTCLK) frequency. + * @brief Gets the MCG output clock (MCGOUTCLK) frequency. * - * This function gets the MCG output clock frequency (Hz) based on current MCG + * This function gets the MCG output clock frequency in Hz based on the current MCG * register value. * * @return The frequency of MCGOUTCLK. @@ -854,40 +859,40 @@ static inline void CLOCK_SetSimSafeDivs(void) uint32_t CLOCK_GetOutClkFreq(void); /*! - * @brief Get the MCG FLL clock(MCGFLLCLK) frequency. + * @brief Gets the MCG FLL clock (MCGFLLCLK) frequency. * - * This function gets the MCG FLL clock frequency (Hz) based on current MCG - * register value. The FLL is only enabled in FEI/FBI/FEE/FBE mode, in other - * modes, FLL is disabled in low power state. + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. * * @return The frequency of MCGFLLCLK. */ uint32_t CLOCK_GetFllFreq(void); /*! - * @brief Get the MCG internal reference clock(MCGIRCLK) frequency. + * @brief Gets the MCG internal reference clock (MCGIRCLK) frequency. * - * This function gets the MCG internal reference clock frequency (Hz) based - * on current MCG register value. + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. * * @return The frequency of MCGIRCLK. */ uint32_t CLOCK_GetInternalRefClkFreq(void); /*! - * @brief Get the MCG fixed frequency clock(MCGFFCLK) frequency. + * @brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. * - * This function gets the MCG fixed frequency clock frequency (Hz) based - * on current MCG register value. + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. * * @return The frequency of MCGFFCLK. */ uint32_t CLOCK_GetFixedFreqClkFreq(void); /*! - * @brief Get the MCG PLL0 clock(MCGPLL0CLK) frequency. + * @brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. * - * This function gets the MCG PLL0 clock frequency (Hz) based on current MCG + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG * register value. * * @return The frequency of MCGPLL0CLK. @@ -900,12 +905,12 @@ uint32_t CLOCK_GetPll0Freq(void); /*@{*/ /*! - * @brief Enable or disable MCG low power. + * @brief Enables or disables the MCG low power. * - * Enable MCG low power will disable the PLL and FLL in bypass modes. That is, - * in FBE and PBE modes, enable low power will set MCG to BLPE mode, in FBI and - * PBI mode, enable low power will set MCG to BLPI mode. - * When disable MCG low power, the PLL or FLL will be enabled based on MCG setting. + * Enabling the MCG low power disables the PLL and FLL in bypass modes. In other words, + * in FBE and PBE modes, enabling low power sets the MCG to BLPE mode. In FBI and + * PBI modes, enabling low power sets the MCG to BLPI mode. + * When disabling the MCG low power, the PLL or FLL are enabled based on MCG settings. * * @param enable True to enable MCG low power, false to disable MCG low power. */ @@ -917,47 +922,61 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } else { - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; } } /*! - * @brief Configure the Internal Reference clock (MCGIRCLK) + * @brief Configures the Internal Reference clock (MCGIRCLK). * - * This function setups the \c MCGIRCLK base on parameters. It selects the IRC - * source, if fast IRC is used, this function also sets the fast IRC divider. - * This function also sets whether enable \c MCGIRCLK in stop mode. - * Calling this function in FBI/PBI/BLPI modes may change the system clock, so - * it is not allowed to use this in these modes. + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. * * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed MCGIRCLK is used as system clock, should not configure MCGIRCLK. + * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); /*! - * @brief Select the MCG external reference clock. + * @brief Selects the MCG external reference clock. * - * Select the MCG external reference clock source, it changes the MCG_C7[OSCSEL] - * and wait for the clock source stable. Should not change external reference - * clock in FEE/FBE/BLPE/PBE/PEE mdes, so don't call this function in these modes. + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. - * @retval kStatus_MCG_SourceUsed External reference clock is used, should not change. + * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); +/*! + * @brief Set the FLL external reference clock divider value. + * + * Sets the FLL external reference clock divider value, the register MCG_C1[FRDIV]. + * + * @param frdiv The FLL external reference clock divider value, MCG_C1[FRDIV]. + */ +static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) +{ + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); +} + /*! * @brief Enables the PLL0 in FLL mode. * - * This function setups the PLL0 in FLL mode, make sure the PLL reference - * clock is enabled before calling this function. This function reconfigures - * the PLL0, make sure the PLL0 is not used as a clock source while calling - * this function. The function CLOCK_CalcPllDiv can help to get the proper PLL + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL * divider values. * * @param config Pointer to the configuration structure. @@ -967,7 +986,7 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config); /*! * @brief Disables the PLL0 in FLL mode. * - * This function disables the PLL0 in FLL mode, it should be used together with + * This function disables the PLL0 in FLL mode. It should be used together with the * @ref CLOCK_EnablePll0. */ static inline void CLOCK_DisablePll0(void) @@ -976,77 +995,86 @@ static inline void CLOCK_DisablePll0(void) } /*! - * @brief Calculates the PLL divider setting for desired output frequency. + * @brief Calculates the PLL divider setting for a desired output frequency. * - * This function calculates the proper reference clock divider (\c PRDIV) and - * VCO divider (\c VDIV) to generate desired PLL output frequency. It returns the - * closest frequency PLL could generate, the corresponding \c PRDIV/VDIV are - * returned from parameters. If desired frequency is not valid, this function + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function * returns 0. * * @param refFreq PLL reference clock frequency. * @param desireFreq Desired PLL output frequency. * @param prdiv PRDIV value to generate desired PLL frequency. * @param vdiv VDIV value to generate desired PLL frequency. - * @return Closest frequency PLL could generate. + * @return Closest frequency match that the PLL was able generate. */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv); +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ +void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); + /*@}*/ /*! @name MCG clock lock monitor functions. */ /*@{*/ /*! - * @brief Set the OSC0 clock monitor mode. + * @brief Sets the OSC0 clock monitor mode. * - * Set the OSC0 clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the OSC0 clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the RTC OSC clock monitor mode. + * @brief Sets the RTC OSC clock monitor mode. * - * Set the RTC OSC clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the RTC OSC clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the PLL0 clock monitor mode. + * @brief Sets the PLL0 clock monitor mode. * - * Set the PLL0 clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the PLL0 clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Get the MCG status flags. + * @brief Gets the MCG status flags. * - * This function gets the MCG clock status flags, all the status flags are + * This function gets the MCG clock status flags. All status flags are * returned as a logical OR of the enumeration @ref _mcg_status_flags_t. To - * check specific flags, compare the return value with the flags. + * check a specific flag, compare the return value with the flag. * * Example: * @code - // To check the clock lost lock status of OSC0 and PLL0. - uint32_t mcgFlags; - - mcgFlags = CLOCK_GetStatusFlags(); - - if (mcgFlags & kMCG_Osc0LostFlag) - { - // OSC0 clock lock lost. Do something. - } - if (mcgFlags & kMCG_Pll0LostFlag) - { - // PLL0 clock lock lost. Do something. - } - @endcode + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * @endcode * * @return Logical OR value of the @ref _mcg_status_flags_t. */ @@ -1055,15 +1083,15 @@ uint32_t CLOCK_GetStatusFlags(void); /*! * @brief Clears the MCG status flags. * - * This function clears the MCG clock lock lost status. The parameter is logical - * OR value of the flags to clear, see @ref _mcg_status_flags_t. + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See @ref _mcg_status_flags_t. * * Example: * @code - // To clear the clock lost lock status flags of OSC0 and PLL0. - - CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); - @endcode + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * @endcode * * @param mask The status flags to clear. This is a logical OR of members of the * enumeration @ref _mcg_status_flags_t. @@ -1081,8 +1109,8 @@ void CLOCK_ClearStatusFlags(uint32_t mask); * @brief Configures the OSC external reference clock (OSCERCLK). * * This function configures the OSC external reference clock (OSCERCLK). - * For example, to enable the OSCERCLK in normal mode and stop mode, and also set - * the output divider to 1, as follows: + * This is an example to enable the OSCERCLK in normal and stop modes and also set + * the output divider to 1: * @code oscer_config_t config = @@ -1121,7 +1149,7 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * * * Example: @code - // To enable only 2 pF and 8 pF capacitor load, please use like this. + To enable only 2 pF and 8 pF capacitor load, please use like this. OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P); @endcode */ @@ -1136,45 +1164,71 @@ static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad) } /*! - * @brief Initialize OSC0. + * @brief Initializes the OSC0. * - * This function initializes OSC0 according to board configuration. + * This function initializes the OSC0 according to the board configuration. * * @param config Pointer to the OSC0 configuration structure. */ void CLOCK_InitOsc0(osc_config_t const *config); /*! - * @brief Deinitialize OSC0. + * @brief Deinitializes the OSC0. * - * This function deinitializes OSC0. + * This function deinitializes the OSC0. */ void CLOCK_DeinitOsc0(void); /* @} */ +/*! + * @name External clock frequency + * @{ + */ + +/*! + * @brief Sets the XTAL0 frequency based on board settings. + * + * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal0Freq(uint32_t freq) +{ + g_xtal0Freq = freq; +} + +/*! + * @brief Sets the XTAL32/RTC_CLKIN frequency based on board settings. + * + * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal32Freq(uint32_t freq) +{ + g_xtal32Freq = freq; +} +/* @} */ + /*! * @name MCG auto-trim machine. * @{ */ /*! - * @brief Auto trim the internal reference clock. + * @brief Auto trims the internal reference clock. * - * This function trims the internal reference clock using external clock. If + * This function trims the internal reference clock by using the external clock. If * successful, it returns the kStatus_Success and the frequency after * trimming is received in the parameter @p actualFreq. If an error occurs, * the error code is returned. * - * @param extFreq External clock frequency, should be bus clock. - * @param desireFreq Frequency want to trim to. - * @param actualFreq Actual frequency after trim. + * @param extFreq External clock frequency, which should be a bus clock. + * @param desireFreq Frequency to trim to. + * @param actualFreq Actual frequency after trimming. * @param atms Trim fast or slow internal reference clock. * @retval kStatus_Success ATM success. - * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for ATM. + * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. * @retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. - * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as bus clock source. - * @retval kStatus_MCG_AtmHardwareFail Hardware fails during trim. + * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * @retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms); /* @} */ @@ -1185,263 +1239,278 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ /*! * @brief Gets the current MCG mode. * - * This function checks the MCG registers and determine current MCG mode. + * This function checks the MCG registers and determines the current MCG mode. * - * @return Current MCG mode or error code, see @ref mcg_mode_t. + * @return Current MCG mode or error code; See @ref mcg_mode_t. */ mcg_mode_t CLOCK_GetMode(void); /*! - * @brief Set MCG to FEI mode. + * @brief Sets the MCG to FEI mode. * - * This function sets MCG to FEI mode. If could not set to FEI mode directly - * from current mode, this function returns error. @ref kMCG_Dmx32Default is used in this - * mode because using kMCG_Dmx32Fine with internal reference clock source - * might damage hardware. + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. * + * @param dmx32 DMX32 in FEI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable, if pass - * in NULL, then does not delay. + * @param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. */ -status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FEE mode. + * @brief Sets the MCG to FEE mode. * - * This function sets MCG to FEE mode. If could not set to FEE mode directly - * from current mode, this function returns error. + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. * * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FEE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable, if pass - * in NULL, then does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FBI mode. + * @brief Sets the MCG to FBI mode. * - * This function sets MCG to FBI mode. If could not set to FBI mode directly - * from current mode, this function returns error. + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. * + * @param dmx32 DMX32 in FBI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. If FLL - * is not used in FBI mode, this parameter could be NULL. Pass in - * NULL does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. */ -status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FBE mode. + * @brief Sets the MCG to FBE mode. * - * This function sets MCG to FBE mode. If could not set to FBE mode directly - * from current mode, this function returns error. + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. * * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FBE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. If FLL - * is not used in FBE mode, this parameter could be NULL. Pass in NULL - * does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to BLPI mode. + * @brief Sets the MCG to BLPI mode. * - * This function sets MCG to BLPI mode. If could not set to BLPI mode directly - * from current mode, this function returns error. + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetBlpiMode(void); /*! - * @brief Set MCG to BLPE mode. + * @brief Sets the MCG to BLPE mode. * - * This function sets MCG to BLPE mode. If could not set to BLPE mode directly - * from current mode, this function returns error. + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetBlpeMode(void); /*! - * @brief Set MCG to PBE mode. + * @brief Sets the MCG to PBE mode. * - * This function sets MCG to PBE mode. If could not set to PBE mode directly - * from current mode, this function returns error. + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. * * @param pllcs The PLL selection, PLLCS. * @param config Pointer to the PLL configuration. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * * @note - * 1. The parameter \c pllcs selects the PLL, for some platforms, there is - * only one PLL, the parameter pllcs is kept for interface compatible. - * 2. The parameter \c config is the PLL configuration structure, on some - * platforms, could choose the external PLL directly. This means that the - * configuration structure is not necessary, pass in NULL for this case. + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config); /*! - * @brief Set MCG to PEE mode. + * @brief Sets the MCG to PEE mode. * - * This function sets MCG to PEE mode. + * This function sets the MCG to PEE mode. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * - * @note This function only change CLKS to use PLL/FLL output. If the - * PRDIV/VDIV are different from PBE mode, please setup these - * settings in PBE mode and wait for stable then switch to PEE mode. + * @note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. */ status_t CLOCK_SetPeeMode(void); /*! - * @brief Switch MCG to FBE mode quickly from external mode. + * @brief Switches the MCG to FBE mode from the external mode. * - * This function changes MCG from external modes (PEE/PBE/BLPE/FEE) to FBE mode quickly. - * It only changes to use external clock as the system clock souce and disable PLL, but does not - * configure FLL settings. This is a lite function with small code size, it is useful - * during mode switch. For example, to switch from PEE mode to FEI mode: + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: * * @code * CLOCK_ExternalModeToFbeModeQuick(); * CLOCK_SetFeiMode(...); * @endcode * - * @retval kStatus_Success Change successfully. - * @retval kStatus_MCG_ModeInvalid Current mode is not external modes, should not call this function. + * @retval kStatus_Success Switched successfully. + * @retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. */ status_t CLOCK_ExternalModeToFbeModeQuick(void); /*! - * @brief Switch MCG to FBI mode quickly from internal modes. + * @brief Switches the MCG to FBI mode from internal modes. * - * This function changes MCG from internal modes (PEI/PBI/BLPI/FEI) to FBI mode quickly. - * It only changes to use MCGIRCLK as the system clock souce and disable PLL, but does not - * configure FLL settings. This is a lite function with small code size, it is useful - * during mode switch. For example, to switch from PEI mode to FEE mode: + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: * * @code * CLOCK_InternalModeToFbiModeQuick(); * CLOCK_SetFeeMode(...); * @endcode * - * @retval kStatus_Success Change successfully. - * @retval kStatus_MCG_ModeInvalid Current mode is not internal mode, should not call this function. + * @retval kStatus_Success Switched successfully. + * @retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. */ status_t CLOCK_InternalModeToFbiModeQuick(void); /*! - * @brief Set MCG to FEI mode during system boot up. + * @brief Sets the MCG to FEI mode during system boot up. * - * This function sets MCG to FEI mode from reset mode, it could be used to - * set up MCG during system boot up. @ref kMCG_Dmx32Default is used in this - * mode because using kMCG_Dmx32Fine with internal reference clock source - * might damage hardware. + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. * + * @param dmx32 DMX32 in FEI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. + * @param fllStableDelay Delay function to ensure that the FLL is stable. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. */ -status_t CLOCK_BootToFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FEE mode during system bootup. + * @brief Sets the MCG to FEE mode during system bootup. * - * This function sets MCG to FEE mode from reset mode, it could be used to - * set up MCG during system boot up. + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, OSCSEL. * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FEE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. + * @param fllStableDelay Delay function to ensure that the FLL is stable. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to BLPI mode during system boot up. + * @brief Sets the MCG to BLPI mode during system boot up. * - * This function sets MCG to BLPI mode from reset mode, it could be used to - * setup MCG during sytem boot up. + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. * @param ircEnableMode The MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * * @retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Set MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during system boot up. * - * This function sets MCG to BLPE mode from reset mode, it could be used to - * setup MCG during sytem boot up. + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel); /*! - * @brief Set MCG to PEE mode during system boot up. + * @brief Sets the MCG to PEE mode during system boot up. * - * This function sets MCG to PEE mode from reset mode, it could be used to - * setup MCG during system boot up. + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @param pllcs The PLL selection, PLLCS. * @param config Pointer to the PLL configuration. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config); /*! - * @brief Set MCG to some target mode. + * @brief Sets the MCG to a target mode. * - * This function sets MCG to some target mode defined by the configure - * structure, if cannot switch to target mode directly, this function will - * choose the proper path. + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. * * @param config Pointer to the target MCG mode configuration structure. - * @return Return kStatus_Success if switch successfully, otherwise return error code #_mcg_status. + * @return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. * - * @note If external clock is used in the target mode, please make sure it is - * enabled, for example, if the OSC0 is used, please setup OSC0 correctly before - * this funciton. + * @note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); +/*! + * @brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + /*@}*/ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_clock.c index 12048524dd..5d6b0b9740 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_clock.c @@ -1,32 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright (c) 2016 - 2017 , NXP + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_clock.h" @@ -35,6 +12,11 @@ * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif + /* Macro definition remap workaround. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) #define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK @@ -65,11 +47,11 @@ #define TRIM_SIRC_MIN (31250U) #define MCG_S_IRCST_VAL ((MCG->S & MCG_S_IRCST_MASK) >> MCG_S_IRCST_SHIFT) -#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) -#define MCG_S_IREFST_VAL ((MCG->S & MCG_S_IREFST_MASK) >> MCG_S_IREFST_SHIFT) +#define MCG_S_CLKST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_CLKST_MASK) >> (uint32_t)MCG_S_CLKST_SHIFT) +#define MCG_S_IREFST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IREFST_MASK) >> (uint32_t)MCG_S_IREFST_SHIFT) #define MCG_S_PLLST_VAL ((MCG->S & MCG_S_PLLST_MASK) >> MCG_S_PLLST_SHIFT) #define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT) -#define MCG_C2_LP_VAL ((MCG->C2 & MCG_C2_LP_MASK) >> MCG_C2_LP_SHIFT) +#define MCG_C2_LP_VAL (((uint32_t)MCG->C2 & (uint32_t)MCG_C2_LP_MASK) >> (uint32_t)MCG_C2_LP_SHIFT) #define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT) #define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT) #define MCG_S2_PLLCST_VAL ((MCG->S2 & MCG_S2_PLLCST_MASK) >> MCG_S2_PLLCST_SHIFT) @@ -119,9 +101,9 @@ static uint32_t s_slowIrcFreq = 32768U; static uint32_t s_fastIrcFreq = 4000000U; /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -190,10 +172,6 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); -/******************************************************************************* - * Code - ******************************************************************************/ - #ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. @@ -201,14 +179,22 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ -void CLOCK_FllStableDelay(void) +static void CLOCK_FllStableDelay(void); +#endif + +/******************************************************************************* + * Code + ******************************************************************************/ + +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN +static void CLOCK_FllStableDelay(void) { /* Should wait at least 1ms. Because in these modes, the core clock is 100MHz at most, so this function could obtain the 1ms delay. */ volatile uint32_t i = 30000U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -216,7 +202,7 @@ void CLOCK_FllStableDelay(void) #else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ /* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this - * file would call the CLOCK_FllStableDelay() regardness how it is defined. + * file would call the CLOCK_FllStableDelay() regardless how it is defined. */ extern void CLOCK_FllStableDelay(void); #endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ @@ -229,12 +215,12 @@ static uint32_t CLOCK_GetMcgExtClkFreq(void) { case 0U: /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */ - assert(g_xtal0Freq); + assert(0U != g_xtal0Freq); freq = g_xtal0Freq; break; case 1U: /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */ - assert(g_xtal32Freq); + assert(0U != g_xtal32Freq); freq = g_xtal32Freq; break; case 2U: @@ -257,7 +243,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) uint32_t freq = CLOCK_GetMcgExtClkFreq(); - if (!freq) + if (0U == freq) { return freq; } @@ -265,7 +251,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) frdiv = MCG_C1_FRDIV_VAL; freq >>= frdiv; - range = MCG_C2_RANGE_VAL; + range = MCG_C2_RANGE_VAL; oscsel = MCG_C7_OSCSEL_VAL; /* @@ -273,7 +259,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) 1. MCG_C7[OSCSEL] selects IRC48M. 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0. */ - if (((0U != range) && (kMCG_OscselOsc == oscsel)) || (kMCG_OscselIrc == oscsel)) + if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel)) || ((uint8_t)kMCG_OscselIrc == oscsel)) { switch (frdiv) { @@ -304,7 +290,7 @@ static uint32_t CLOCK_GetFllExtRefClkFreq(void) static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) { - if (kMCG_IrcSlow == MCG_S_IRCST_VAL) + if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL) { /* Slow internal reference clock selected*/ return s_slowIrcFreq; @@ -319,7 +305,7 @@ static uint32_t CLOCK_GetInternalRefClkSelectFreq(void) static uint32_t CLOCK_GetFllRefClkFreq(void) { /* If use external reference clock. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { return CLOCK_GetFllExtRefClkFreq(); } @@ -356,6 +342,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -371,6 +362,11 @@ uint32_t CLOCK_GetOsc0ErClkFreq(void) } /* Function Name : CLOCK_GetEr32kClkFreq */ +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -395,6 +391,11 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the output clock frequency selected by SIM[PLLFLLSEL]. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPllFllSelClkFreq(void) { uint32_t freq; @@ -418,26 +419,56 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) return freq; } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); } +/*! + * brief Get the flexbus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlexBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1); } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -491,6 +522,13 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; @@ -498,6 +536,13 @@ void CLOCK_SetSimConfig(sim_clock_config_t const *config) CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { bool ret = true; @@ -542,23 +587,31 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! + * brief Gets the MCG output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG output clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; - uint32_t clkst = MCG_S_CLKST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; switch (clkst) { - case kMCG_ClkOutStatPll: + case (uint32_t)kMCG_ClkOutStatPll: mcgoutclk = CLOCK_GetPll0Freq(); break; - case kMCG_ClkOutStatFll: + case (uint32_t)kMCG_ClkOutStatFll: mcgoutclk = CLOCK_GetFllFreq(); break; - case kMCG_ClkOutStatInt: + case (uint32_t)kMCG_ClkOutStatInt: mcgoutclk = CLOCK_GetInternalRefClkSelectFreq(); break; - case kMCG_ClkOutStatExt: + case (uint32_t)kMCG_ClkOutStatExt: mcgoutclk = CLOCK_GetMcgExtClkFreq(); break; default: @@ -568,6 +621,15 @@ uint32_t CLOCK_GetOutClkFreq(void) return mcgoutclk; } +/*! + * brief Gets the MCG FLL clock (MCGFLLCLK) frequency. + * + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. + * + * return The frequency of MCGFLLCLK. + */ uint32_t CLOCK_GetFllFreq(void) { static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; @@ -576,28 +638,36 @@ uint32_t CLOCK_GetFllFreq(void) uint32_t freq; /* If FLL is not enabled currently, then return 0U. */ - if ((MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) + if (0U != (MCG->C2 & MCG_C2_LP_MASK) || (MCG->S & MCG_S_PLLST_MASK)) { return 0U; } /* Get FLL reference clock frequency. */ freq = CLOCK_GetFllRefClkFreq(); - if (!freq) + if (0U == freq) { return freq; } - drs = MCG_C4_DRST_DRS_VAL; + drs = MCG_C4_DRST_DRS_VAL; dmx32 = MCG_C4_DMX32_VAL; return freq * fllFactorTable[drs][dmx32]; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { /* If MCGIRCLK is gated. */ - if (!(MCG->C1 & MCG_C1_IRCLKEN_MASK)) + if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK)) { return 0U; } @@ -605,12 +675,20 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetInternalRefClkSelectFreq(); } +/*! + * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. + * + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGFFCLK. + */ uint32_t CLOCK_GetFixedFreqClkFreq(void) { uint32_t freq = CLOCK_GetFllRefClkFreq(); /* MCGFFCLK must be no more than MCGOUTCLK/8. */ - if ((freq) && (freq <= (CLOCK_GetOutClkFreq() / 8U))) + if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq)) { return freq; } @@ -620,6 +698,14 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void) } } +/*! + * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. + * + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGPLL0CLK. + */ uint32_t CLOCK_GetPll0Freq(void) { uint32_t mcgpll0clk; @@ -644,6 +730,18 @@ uint32_t CLOCK_GetPll0Freq(void) return mcgpll0clk; } +/*! + * brief Selects the MCG external reference clock. + * + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. + * + * param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. + * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success External reference clock set successfully. + */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) { bool needDelay; @@ -657,7 +755,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } #endif /* MCG_CONFIG_CHECK_PARAM */ - if (MCG_C7_OSCSEL_VAL != oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel) { /* If change OSCSEL, need to delay, ERR009878. */ needDelay = true; @@ -667,12 +765,12 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) needDelay = false; } - MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); + MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ i = 1500U; - while (i--) + while (0U != (i--)) { __NOP(); } @@ -681,15 +779,31 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Configures the Internal Reference clock (MCGIRCLK). + * + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. + * + * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * param ircs MCGIRCLK clock source, choose fast or slow. + * param fcrdiv Fast IRC divider setting (\c FCRDIV). + * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success MCGIRCLK configuration finished successfully. + */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) { - uint32_t mcgOutClkState = MCG_S_CLKST_VAL; - mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; - uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; + uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL; + mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)MCG_S_IRCST_VAL; + uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL; #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) /* If MCGIRCLK is used as system clock source. */ - if (kMCG_ClkOutStatInt == mcgOutClkState) + if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState) { /* If need to change MCGIRCLK source or driver, return error. */ if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs)) @@ -703,25 +817,27 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, if (fcrdiv != curFcrdiv) { /* If fast IRC is in use currently, change to slow IRC. */ - if ((kMCG_IrcFast == curIrcs) && ((mcgOutClkState == kMCG_ClkOutStatInt) || (MCG->C1 & MCG_C1_IRCLKEN_MASK))) + if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) && + (kMCG_IrcFast == curIrcs)) { - MCG->C2 = ((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); - while (MCG_S_IRCST_VAL != kMCG_IrcSlow) + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow))); + while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow) { } } /* Update FCRDIV. */ - MCG->SC = (MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); + MCG->SC = + (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv); } /* Set internal reference clock selection. */ - MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)); - MCG->C1 = (MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode; + MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs))); + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode); /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */ - if ((mcgOutClkState == kMCG_ClkOutStatInt) || (enableMode & kMCG_IrclkEnable)) + if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable))) { - while (MCG_S_IRCST_VAL != ircs) + while (MCG_S_IRCST_VAL != (uint8_t)ircs) { } } @@ -729,17 +845,32 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, return kStatus_Success; } +/*! + * brief Calculates the PLL divider setting for a desired output frequency. + * + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function + * returns 0. + * + * param refFreq PLL reference clock frequency. + * param desireFreq Desired PLL output frequency. + * param prdiv PRDIV value to generate desired PLL frequency. + * param vdiv VDIV value to generate desired PLL frequency. + * return Closest frequency match that the PLL was able generate. + */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv) { - uint8_t ret_prdiv; /* PRDIV to return. */ - uint8_t ret_vdiv; /* VDIV to return. */ - uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ - uint8_t prdiv_cur; /* PRDIV value for iteration. */ - uint8_t vdiv_cur; /* VDIV value for iteration. */ - uint32_t ret_freq = 0U; /* PLL output fequency to return. */ - uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ - uint32_t ref_div; /* Reference frequency after PRDIV. */ + uint8_t ret_prdiv; /* PRDIV to return. */ + uint8_t ret_vdiv; /* VDIV to return. */ + uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ + uint8_t prdiv_cur; /* PRDIV value for iteration. */ + uint8_t vdiv_cur; /* VDIV value for iteration. */ + uint32_t ret_freq = 0U; /* PLL output frequency to return. */ + uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ + uint32_t ref_div; /* Reference frequency after PRDIV. */ /* Steps: @@ -786,15 +917,15 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (ret_freq == desireFreq) /* If desire frequency is got. */ { *prdiv = prdiv_cur - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *vdiv = vdiv_cur - FSL_FEATURE_MCG_PLL_VDIV_BASE; return ret_freq; } /* New PRDIV/VDIV is closer. */ if (diff > desireFreq - ret_freq) { - diff = desireFreq - ret_freq; + diff = desireFreq - ret_freq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } vdiv_cur++; @@ -804,9 +935,9 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, /* New PRDIV/VDIV is closer. */ if (diff > ret_freq - desireFreq) { - diff = ret_freq - desireFreq; + diff = ret_freq - desireFreq; ret_prdiv = prdiv_cur; - ret_vdiv = vdiv_cur; + ret_vdiv = vdiv_cur; } } } @@ -814,8 +945,8 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, if (0xFFFFFFFFU != diff) { /* PRDIV/VDIV found. */ - *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; - *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; + *prdiv = ret_prdiv - FSL_FEATURE_MCG_PLL_PRDIV_BASE; + *vdiv = ret_vdiv - FSL_FEATURE_MCG_PLL_VDIV_BASE; ret_freq = (refFreq / ret_prdiv) * ret_vdiv; return ret_freq; } @@ -826,6 +957,17 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, } } +/*! + * brief Enables the PLL0 in FLL mode. + * + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL + * divider values. + * + * param config Pointer to the configuration structure. + */ void CLOCK_EnablePll0(mcg_pll_config_t const *config) { assert(config); @@ -846,20 +988,27 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ - MCG->SC &= ~MCG_SC_ATMF_MASK; + MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK; if (kMCG_MonitorNone == mode) { - MCG->C6 &= ~MCG_C6_CME0_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK; } else { if (kMCG_MonitorInt == mode) { - MCG->C2 &= ~MCG_C2_LOCRE0_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK; } else { @@ -869,11 +1018,18 @@ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the RTC OSC clock monitor mode. + * + * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8 = MCG->C8; - mcg_c8 &= ~(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); + mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK); if (kMCG_MonitorNone != mode) { @@ -886,6 +1042,13 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) MCG->C8 = mcg_c8; } +/*! + * brief Sets the PLL0 clock monitor mode. + * + * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8; @@ -916,34 +1079,76 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Gets the MCG status flags. + * + * This function gets the MCG clock status flags. All status flags are + * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To + * check a specific flag, compare the return value with the flag. + * + * Example: + * code + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * endcode + * + * return Logical OR value of the ref _mcg_status_flags_t. + */ uint32_t CLOCK_GetStatusFlags(void) { - uint32_t ret = 0U; + uint32_t ret = 0U; uint8_t mcg_s = MCG->S; if (MCG->SC & MCG_SC_LOCS0_MASK) { - ret |= kMCG_Osc0LostFlag; + ret |= (uint32_t)kMCG_Osc0LostFlag; } if (mcg_s & MCG_S_OSCINIT0_MASK) { - ret |= kMCG_Osc0InitFlag; + ret |= (uint32_t)kMCG_Osc0InitFlag; } - if (MCG->C8 & MCG_C8_LOCS1_MASK) + if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK)) { - ret |= kMCG_RtcOscLostFlag; + ret |= (uint32_t)kMCG_RtcOscLostFlag; } if (mcg_s & MCG_S_LOLS0_MASK) { - ret |= kMCG_Pll0LostFlag; + ret |= (uint32_t)kMCG_Pll0LostFlag; } if (mcg_s & MCG_S_LOCK0_MASK) { - ret |= kMCG_Pll0LockFlag; + ret |= (uint32_t)kMCG_Pll0LockFlag; } return ret; } +/*! + * brief Clears the MCG status flags. + * + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See ref _mcg_status_flags_t. + * + * Example: + * code + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * endcode + * + * param mask The status flags to clear. This is a logical OR of members of the + * enumeration ref _mcg_status_flags_t. + */ void CLOCK_ClearStatusFlags(uint32_t mask) { uint8_t reg; @@ -952,9 +1157,9 @@ void CLOCK_ClearStatusFlags(uint32_t mask) { MCG->SC &= ~MCG_SC_ATMF_MASK; } - if (mask & kMCG_RtcOscLostFlag) + if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag)) { - reg = MCG->C8; + reg = MCG->C8; MCG->C8 = reg; } if (mask & kMCG_Pll0LostFlag) @@ -963,30 +1168,60 @@ void CLOCK_ClearStatusFlags(uint32_t mask) } } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); OSC_SetCapLoad(OSC0, config->capLoad); - OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); - MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); + OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) { /* Wait for stable. */ - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; - MCG->C2 &= ~OSC_MODE_MASK; + MCG->C2 &= ~(uint8_t)OSC_MODE_MASK; } +/*! + * brief Auto trims the internal reference clock. + * + * This function trims the internal reference clock by using the external clock. If + * successful, it returns the kStatus_Success and the frequency after + * trimming is received in the parameter p actualFreq. If an error occurs, + * the error code is returned. + * + * param extFreq External clock frequency, which should be a bus clock. + * param desireFreq Frequency to trim to. + * param actualFreq Actual frequency after trimming. + * param atms Trim fast or slow internal reference clock. + * retval kStatus_Success ATM success. + * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. + * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. + * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. + */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) { uint32_t multi; /* extFreq / desireFreq */ @@ -1020,7 +1255,7 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ } multi = extFreq / desireFreq; - actv = multi * 21U; + actv = multi * 21U; if (kMCG_AtmSel4m == atms) { @@ -1032,17 +1267,17 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ MCG->ATCVH = (uint8_t)(actv >> 8U); mcg_sc = MCG->SC; - mcg_sc &= ~(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); + mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK); mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms)); MCG->SC = (mcg_sc | MCG_SC_ATME_MASK); /* Wait for finished. */ - while (MCG->SC & MCG_SC_ATME_MASK) + while (0U != (MCG->SC & MCG_SC_ATME_MASK)) { } /* Error occurs? */ - if (MCG->SC & MCG_SC_ATMF_MASK) + if (0U != (MCG->SC & MCG_SC_ATMF_MASK)) { /* Clear the failed flag. */ MCG->SC = mcg_sc; @@ -1063,13 +1298,20 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ return kStatus_Success; } +/*! + * brief Gets the current MCG mode. + * + * This function checks the MCG registers and determines the current MCG mode. + * + * return Current MCG mode or error code; See ref mcg_mode_t. + */ mcg_mode_t CLOCK_GetMode(void) { mcg_mode_t mode = kMCG_ModeError; - uint32_t clkst = MCG_S_CLKST_VAL; - uint32_t irefst = MCG_S_IREFST_VAL; - uint32_t lp = MCG_C2_LP_VAL; - uint32_t pllst = MCG_S_PLLST_VAL; + uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL; + uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL; + uint32_t lp = (uint32_t)MCG_C2_LP_VAL; + uint32_t pllst = MCG_S_PLLST_VAL; /*------------------------------------------------------------------ Mode and Registers @@ -1110,59 +1352,77 @@ mcg_mode_t CLOCK_GetMode(void) ----------------------------------------------------------------------*/ - switch (clkst) + if (clkst == (uint32_t)kMCG_ClkOutStatFll) { - case kMCG_ClkOutStatFll: - if (kMCG_FllSrcExternal == irefst) + if ((uint32_t)kMCG_FllSrcExternal == irefst) + { + mode = kMCG_ModeFEE; + } + else + { + mode = kMCG_ModeFEI; + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatInt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPI; + } + else + { { - mode = kMCG_ModeFEE; + mode = kMCG_ModeFBI; + } + } + } + else if (clkst == (uint32_t)kMCG_ClkOutStatExt) + { + if (0U != lp) + { + mode = kMCG_ModeBLPE; + } + else + { + if (kMCG_PllstPll == pllst) + { + mode = kMCG_ModePBE; } else { - mode = kMCG_ModeFEI; + mode = kMCG_ModeFBE; } - break; - case kMCG_ClkOutStatInt: - if (lp) - { - mode = kMCG_ModeBLPI; - } - else - { - { - mode = kMCG_ModeFBI; - } - } - break; - case kMCG_ClkOutStatExt: - if (lp) - { - mode = kMCG_ModeBLPE; - } - else - { - if (kMCG_PllstPll == pllst) - { - mode = kMCG_ModePBE; - } - else - { - mode = kMCG_ModeFBE; - } - } - break; - case kMCG_ClkOutStatPll: + } + } + if (clkst == (uint32_t)kMCG_ClkOutStatPll) + { { mode = kMCG_ModePEE; } - break; - default: - break; + } + else + { + /*do nothing*/ } return mode; } +/*! + * brief Sets the MCG to FEI mode. + * + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. + */ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1183,7 +1443,7 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1191,12 +1451,12 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal)); /* IREFS = 1 */ + MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1207,15 +1467,16 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1223,6 +1484,21 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FEE mode. + * + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1243,7 +1519,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1251,24 +1527,24 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ /* If use external crystal as clock source, wait for it stable. */ if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) { - if (MCG->C2 & MCG_C2_EREFS_MASK) + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } /* Wait and check status. */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1279,7 +1555,8 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); MCG->C4 = mcg_c4; /* Wait for DRST_DRS update. */ @@ -1288,12 +1565,12 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Check MCG_S[CLKST] */ - while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) { } /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1301,6 +1578,22 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to FBI mode. + * + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FBI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1319,7 +1612,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela mcg_c4 = MCG->C4; - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ /* Errata: ERR007993 @@ -1327,7 +1620,7 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1335,12 +1628,12 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela } /* Set CLKS and IREFS. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ - | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */ + | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */ /* Wait and check status. */ - while (kMCG_FllSrcInternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL) { } @@ -1350,14 +1643,15 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela MCG->C4 = mcg_c4; } - while (kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); + MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for FLL stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1365,6 +1659,21 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FBE mode. + * + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FBE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1380,13 +1689,13 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void #endif /* Change to FLL mode. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } /* Set LP bit to enable the FLL */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; mcg_c4 = MCG->C4; @@ -1396,7 +1705,7 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void reference clock source changes, then reset to previous value after reference clock changes. */ - if (kMCG_FllSrcInternal == MCG_S_IREFST_VAL) + if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL) { change_drs = true; /* Change the LSB of DRST_DRS. */ @@ -1404,24 +1713,24 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set CLKS and IREFS. */ - MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | - (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ /* If use external crystal as clock source, wait for it stable. */ if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) { - if (MCG->C2 & MCG_C2_EREFS_MASK) + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } } /* Wait for Reference clock Status bit to clear */ - while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) + while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { } @@ -1432,15 +1741,16 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void } /* Set DRST_DRS and DMX32. */ - mcg_c4 = ((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); + mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | + (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs))); /* Wait for clock status bits to show clock source is ext ref clk */ - while (kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) + while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL) { } /* Wait for fll stable time. */ - if (fllStableDelay) + if (NULL != fllStableDelay) { fllStableDelay(); } @@ -1448,10 +1758,19 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to BLPI mode. + * + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpiMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { return kStatus_MCG_ModeUnreachable; } @@ -1463,10 +1782,19 @@ status_t CLOCK_SetBlpiMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode. + * + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) - if (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { return kStatus_MCG_ModeUnreachable; } @@ -1478,6 +1806,25 @@ status_t CLOCK_SetBlpeMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to PBE mode. + * + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. + * + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. + * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); + */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1519,6 +1866,18 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode. + * + * This function sets the MCG to PEE mode. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. + */ status_t CLOCK_SetPeeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1533,13 +1892,29 @@ status_t CLOCK_SetPeeMode(void) MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); /* Wait for clock status bits to update */ - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } return kStatus_Success; } +/*! + * brief Switches the MCG to FBE mode from the external mode. + * + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: + * + * code + * CLOCK_ExternalModeToFbeModeQuick(); + * CLOCK_SetFeiMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. + */ status_t CLOCK_ExternalModeToFbeModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1550,15 +1925,15 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) #endif /* MCG_CONFIG_CHECK_PARAM */ /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } /* Disable PLL. */ - MCG->C6 &= ~MCG_C6_PLLS_MASK; + MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK; while (MCG->S & MCG_S_PLLST_MASK) { } @@ -1566,6 +1941,22 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBI mode from internal modes. + * + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: + * + * code + * CLOCK_InternalModeToFbiModeQuick(); + * CLOCK_SetFeeMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. + */ status_t CLOCK_InternalModeToFbiModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1576,37 +1967,80 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) #endif /* Disable low power */ - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; - MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } return kStatus_Success; } +/*! + * brief Sets the MCG to FEI mode during system boot up. + * + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to FEE mode during system bootup. + * + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, OSCSEL. + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to BLPI mode during system boot up. + * + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param fcrdiv Fast IRC divider, FCRDIV. + * param ircs The internal reference clock to select, IRCS. + * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * + * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) { /* If reset mode is FEI mode, set MCGIRCLK and always success. */ - CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv); /* If reset mode is not BLPI, first enter FBI mode. */ - MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatInt) + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal)); + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt) { } @@ -1616,21 +2050,32 @@ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEn return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode during system boot up. + * + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) { - CLOCK_SetExternalRefClkConfig(oscsel); + (void)CLOCK_SetExternalRefClkConfig(oscsel); /* Set to FBE mode. */ - MCG->C1 = - ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ - | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | + (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ + | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ /* If use external crystal as clock source, wait for it stable. */ if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) { - if (MCG->C2 & MCG_C2_EREFS_MASK) + if (0U != (MCG->C2 & MCG_C2_EREFS_MASK)) { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + while (0U == (MCG->S & MCG_S_OSCINIT0_MASK)) { } } @@ -1648,6 +2093,19 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode during system boot up. + * + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1658,7 +2116,7 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc /* Change to use PLL output clock. */ MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatPll) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll) { } @@ -1694,6 +2152,20 @@ static const mcg_mode_t mcgModeMatrix[8][8] = { /* FEI FBI BLPI FEE FBE BLPE PBE PEE */ }; +/*! + * brief Sets the MCG to a target mode. + * + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. + * + * param config Pointer to the target MCG mode configuration structure. + * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. + * + * note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. + */ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) { mcg_mode_t next_mode; @@ -1702,30 +2174,30 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) mcg_pll_clk_select_t pllcs = kMCG_PllClkSelPll0; /* If need to change external clock, MCG_C7[OSCSEL]. */ - if (MCG_C7_OSCSEL_VAL != config->oscsel) + if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel)) { /* If external clock is in use, change to FEI first. */ - if (!(MCG->S & MCG_S_IRCST_MASK)) + if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { - CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); + (void)CLOCK_ExternalModeToFbeModeQuick(); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL); } - CLOCK_SetExternalRefClkConfig(config->oscsel); + (void)CLOCK_SetExternalRefClkConfig(config->oscsel); } /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */ - if (MCG_S_CLKST_VAL == kMCG_ClkOutStatInt) + if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt) { - MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); + (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } /* Configure MCGIRCLK. */ - CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); + (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv); next_mode = CLOCK_GetMode(); @@ -1742,10 +2214,10 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL); break; case kMCG_ModeFBE: - status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL); break; case kMCG_ModeBLPI: status = CLOCK_SetBlpiMode(); @@ -1764,7 +2236,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) else { MCG->C1 = ((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal)); - while (MCG_S_CLKST_VAL != kMCG_ClkOutStatExt) + while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt) { } } @@ -1787,7 +2259,55 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) } else { - MCG->C5 &= ~(uint32_t)kMCG_PllEnableIndependent; + MCG->C5 &= ~(uint8_t)kMCG_PllEnableIndependent; } return kStatus_Success; } + +/*! + * brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + uint64_t count = 0U; + uint32_t period = SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 1000000; + + /* Make sure the DWT trace fucntion is enabled. */ + if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR)) + { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + } + + /* CYCCNT not supported on this device. */ + assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk)); + + /* If CYCCENT has already been enabled, read directly, otherwise, need enable it. */ + if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL)) + { + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + /* Calculate the count ticks. */ + count = DWT->CYCCNT; + count += (uint64_t)period * delay_us; + + if (count > 0xFFFFFFFFUL) + { + count -= 0xFFFFFFFFUL; + /* wait for cyccnt overflow. */ + while (count < DWT->CYCCNT) + { + } + } + + /* Wait for cyccnt reach count value. */ + while (count > DWT->CYCCNT) + { + } +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_clock.h index f08000c33f..4a9468052f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_clock.h @@ -1,32 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright (c) 2016 - 2017 , NXP + * Copyright 2016 - 2019, NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ @@ -65,7 +42,7 @@ * * When set to 0, peripheral drivers will enable clock in initialize function * and disable clock in de-initialize function. When set to 1, peripheral - * driver will not control the clock, application could contol the clock out of + * driver will not control the clock, application could control the clock out of * the driver. * * @note All drivers share this feature switcher. If it is set to 1, application @@ -81,25 +58,32 @@ /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.1. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 1)) +/*! @brief CLOCK driver version 2.3.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 0)) /*@}*/ +/* Definition for delay API in clock driver, users can redefine it to the real application. */ +#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY +#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (120000000UL) +#endif + /*! @brief External XTAL0 (OSC0) clock frequency. * * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Set up the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. + * Set up the OSC0 + * CLOCK_InitOsc0(...); + * Set the XTAL0 value to the clock driver. + * CLOCK_SetXtal0Freq(80000000); * @endcode * * This is important for the multicore platforms where only one core needs to set up the * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * @@ -110,7 +94,7 @@ extern uint32_t g_xtal0Freq; * the clock. All other cores need to call the CLOCK_SetXtal32Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; /*! @brief IRC48M clock frequency in Hz. */ #define MCG_INTERNAL_IRC_48M 48000000U @@ -328,9 +312,9 @@ typedef enum _clock_name /*! @brief USB clock source definition. */ typedef enum _clock_usb_src { - kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ + kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(3U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ } clock_usb_src_t; /*------------------------------------------------------------------------------ @@ -364,59 +348,59 @@ typedef enum _clock_usb_src typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_I2c2 = CLK_GATE_DEFINE(0x1028U, 6U), - kCLOCK_Uart4 = CLK_GATE_DEFINE(0x1028U, 10U), - kCLOCK_Uart5 = CLK_GATE_DEFINE(0x1028U, 11U), + kCLOCK_I2c2 = CLK_GATE_DEFINE(0x1028U, 6U), + kCLOCK_Uart4 = CLK_GATE_DEFINE(0x1028U, 10U), + kCLOCK_Uart5 = CLK_GATE_DEFINE(0x1028U, 11U), kCLOCK_Dac0 = CLK_GATE_DEFINE(0x102CU, 12U), kCLOCK_Dac1 = CLK_GATE_DEFINE(0x102CU, 13U), - kCLOCK_Spi2 = CLK_GATE_DEFINE(0x1030U, 12U), + kCLOCK_Spi2 = CLK_GATE_DEFINE(0x1030U, 12U), kCLOCK_Sdhc0 = CLK_GATE_DEFINE(0x1030U, 17U), - kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x1030U, 25U), - kCLOCK_Adc1 = CLK_GATE_DEFINE(0x1030U, 27U), + kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x1030U, 25U), + kCLOCK_Adc1 = CLK_GATE_DEFINE(0x1030U, 27U), - kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), - kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), - kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), - kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), - kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U), - kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U), - kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), - kCLOCK_Uart3 = CLK_GATE_DEFINE(0x1034U, 13U), + kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U), + kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U), + kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U), + kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U), + kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U), + kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U), + kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U), + kCLOCK_Uart3 = CLK_GATE_DEFINE(0x1034U, 13U), kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U), - kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), - kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), + kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), - kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), - kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), - kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), - kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), - kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), + kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U), + kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U), + kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U), + kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U), + kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U), - kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), - kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), + kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U), + kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U), kCLOCK_Flexcan0 = CLK_GATE_DEFINE(0x103CU, 4U), - kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x103CU, 9U), - kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), - kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), - kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), - kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), - kCLOCK_Usbdcd0 = CLK_GATE_DEFINE(0x103CU, 21U), - kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), - kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), - kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), - kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), - kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), - kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), - kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), + kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x103CU, 9U), + kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U), + kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U), + kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U), + kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U), + kCLOCK_Usbdcd0 = CLK_GATE_DEFINE(0x103CU, 21U), + kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U), + kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U), + kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U), + kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U), + kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U), + kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U), + kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U), kCLOCK_Flexbus0 = CLK_GATE_DEFINE(0x1040U, 0U), - kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), - kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), + kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), + kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), } clock_ip_name_t; /*!@brief SIM configuration structure for clock setting. */ @@ -438,34 +422,30 @@ typedef enum _osc_mode #endif kOSC_ModeOscHighGain = 0U #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) - | - MCG_C2_EREFS_MASK + | MCG_C2_EREFS_MASK #else - | - MCG_C2_EREFS0_MASK + | MCG_C2_EREFS0_MASK #endif #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK))) - | - MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO_MASK, /*!< Oscillator high gain. */ #else - | - MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ + | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */ #endif } osc_mode_t; /*! @brief Oscillator capacitor load setting.*/ enum _osc_cap_load { - kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ - kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ - kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */ }; /*! @brief OSCERCLK enable mode. */ enum _oscer_enable_mode { - kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ + kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */ kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */ }; @@ -572,30 +552,30 @@ typedef enum _mcg_monitor_mode enum _mcg_status { kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0), /*!< Can't switch to target mode. */ - kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific + kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1), /*!< Current mode invalid for the specific function. */ - kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ + kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2), /*!< Invalid bus clock for ATM. */ kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ - kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ - kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ + kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because it is in use. */ }; /*! @brief MCG status flags. */ enum _mcg_status_flags_t { - kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ - kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ + kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */ + kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */ kMCG_RtcOscLostFlag = (1U << 4U), /*!< RTC OSC lost. */ - kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ - kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ + kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */ + kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */ }; /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */ enum _mcg_irclk_enable_mode { - kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ + kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */ kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */ }; @@ -954,7 +934,7 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } else { - MCG->C2 &= ~MCG_C2_LP_MASK; + MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; } } @@ -970,8 +950,8 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); @@ -985,7 +965,7 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); @@ -999,7 +979,7 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); */ static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) { - MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv); + MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); } /*! @@ -1043,6 +1023,15 @@ static inline void CLOCK_DisablePll0(void) */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv); +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ +void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); + /*@}*/ /*! @name MCG clock lock monitor functions. */ @@ -1084,20 +1073,20 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode); * * Example: * @code - // To check the clock lost lock status of OSC0 and PLL0. - uint32_t mcgFlags; - - mcgFlags = CLOCK_GetStatusFlags(); - - if (mcgFlags & kMCG_Osc0LostFlag) - { - // OSC0 clock lock lost. Do something. - } - if (mcgFlags & kMCG_Pll0LostFlag) - { - // PLL0 clock lock lost. Do something. - } - @endcode + * To check the clock lost lock status of OSC0 and PLL0. + * uint32_t mcgFlags; + * + * mcgFlags = CLOCK_GetStatusFlags(); + * + * if (mcgFlags & kMCG_Osc0LostFlag) + * { + * OSC0 clock lock lost. Do something. + * } + * if (mcgFlags & kMCG_Pll0LostFlag) + * { + * PLL0 clock lock lost. Do something. + * } + * @endcode * * @return Logical OR value of the @ref _mcg_status_flags_t. */ @@ -1111,10 +1100,10 @@ uint32_t CLOCK_GetStatusFlags(void); * * Example: * @code - // To clear the clock lost lock status flags of OSC0 and PLL0. - - CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); - @endcode + * To clear the clock lost lock status flags of OSC0 and PLL0. + * + * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + * @endcode * * @param mask The status flags to clear. This is a logical OR of members of the * enumeration @ref _mcg_status_flags_t. @@ -1170,7 +1159,7 @@ static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const * * * Example: @code - // To enable only 2 pF and 8 pF capacitor load, please use like this. + To enable only 2 pF and 8 pF capacitor load, please use like this. OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P); @endcode */ @@ -1396,7 +1385,7 @@ status_t CLOCK_SetPeeMode(void); * @brief Switches the MCG to FBE mode from the external mode. * * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. - * The external clock is used as the system clock souce and PLL is disabled. However, + * The external clock is used as the system clock source and PLL is disabled. However, * the FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEE mode to FEI mode: * @@ -1414,7 +1403,7 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void); * @brief Switches the MCG to FBI mode from internal modes. * * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. - * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, * FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEI mode to FEE mode: * @@ -1467,7 +1456,7 @@ status_t CLOCK_BootToFeeMode( * @brief Sets the MCG to BLPI mode during system boot up. * * This function sets the MCG to BLPI mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. @@ -1479,10 +1468,10 @@ status_t CLOCK_BootToFeeMode( status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Sets the MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during system boot up. * * This function sets the MCG to BLPE mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @@ -1522,6 +1511,16 @@ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mc */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); +/*! + * @brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + /*@}*/ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_clock.c index 88c242710f..4fff390444 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_clock.c @@ -1,31 +1,10 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright (c) 2016 - 2017 , NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_clock.h" @@ -33,6 +12,10 @@ /******************************************************************************* * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif /* Macro definition remap workaround. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) @@ -118,9 +101,9 @@ static uint32_t s_slowIrcFreq = 32768U; static uint32_t s_fastIrcFreq = 4000000U; /* External XTAL0 (OSC0) clock frequency. */ -uint32_t g_xtal0Freq; +volatile uint32_t g_xtal0Freq; /* External XTAL32K clock frequency. */ -uint32_t g_xtal32Freq; +volatile uint32_t g_xtal32Freq; /******************************************************************************* * Prototypes @@ -189,6 +172,7 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * @@ -196,11 +180,33 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ static void CLOCK_FllStableDelay(void); +#endif /******************************************************************************* * Code ******************************************************************************/ +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN +static void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (i--) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardless how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ + static uint32_t CLOCK_GetMcgExtClkFreq(void) { uint32_t freq; @@ -336,19 +342,11 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - +/*! + * brief Get the OSC0 external reference clock frequency (OSC0ERCLK). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetOsc0ErClkFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -363,6 +361,11 @@ uint32_t CLOCK_GetOsc0ErClkFreq(void) } } +/*! + * brief Get the external reference 32K clock frequency (ERCLK32K). + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetEr32kClkFreq(void) { uint32_t freq; @@ -387,6 +390,11 @@ uint32_t CLOCK_GetEr32kClkFreq(void) return freq; } +/*! + * brief Get the output clock frequency selected by SIM[PLLFLLSEL]. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPllFllSelClkFreq(void) { uint32_t freq; @@ -410,31 +418,66 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) return freq; } +/*! + * brief Get the platform clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetPlatClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Get the flash clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlashClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1); } +/*! + * brief Get the flexbus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetFlexBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1); } +/*! + * brief Get the bus clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetBusClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1); } +/*! + * brief Get the core clock or system clock frequency. + * + * return Clock frequency in Hz. + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1); } +/*! + * brief Gets the clock frequency for a specific clock name. + * + * This function checks the current clock configurations and then calculates + * the clock frequency for a specific clock name defined in clock_name_t. + * The MCG must be properly configured before using this function. + * + * param clockName Clock names defined in clock_name_t + * return Clock frequency value in Hertz + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -489,6 +532,13 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) return freq; } +/*! + * brief Set the clock configure in SIM module. + * + * This function sets system layer clock settings in SIM module. + * + * param config Pointer to the configure structure. + */ void CLOCK_SetSimConfig(sim_clock_config_t const *config) { SIM->CLKDIV1 = config->clkdiv1; @@ -496,6 +546,13 @@ void CLOCK_SetSimConfig(sim_clock_config_t const *config) CLOCK_SetEr32kClock(config->er32kSrc); } +/*! brief Enable USB FS clock. + * + * param src USB FS clock source. + * param freq The frequency specified by src. + * retval true The clock is set successfully. + * retval false The clock source is invalid to get proper USB FS clock. + */ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) { bool ret = true; @@ -540,6 +597,14 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } +/*! + * brief Gets the MCG output clock (MCGOUTCLK) frequency. + * + * This function gets the MCG output clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGOUTCLK. + */ uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; @@ -566,6 +631,15 @@ uint32_t CLOCK_GetOutClkFreq(void) return mcgoutclk; } +/*! + * brief Gets the MCG FLL clock (MCGFLLCLK) frequency. + * + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. + * + * return The frequency of MCGFLLCLK. + */ uint32_t CLOCK_GetFllFreq(void) { static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}}; @@ -592,6 +666,14 @@ uint32_t CLOCK_GetFllFreq(void) return freq * fllFactorTable[drs][dmx32]; } +/*! + * brief Gets the MCG internal reference clock (MCGIRCLK) frequency. + * + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGIRCLK. + */ uint32_t CLOCK_GetInternalRefClkFreq(void) { /* If MCGIRCLK is gated. */ @@ -603,6 +685,14 @@ uint32_t CLOCK_GetInternalRefClkFreq(void) return CLOCK_GetInternalRefClkSelectFreq(); } +/*! + * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. + * + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. + * + * return The frequency of MCGFFCLK. + */ uint32_t CLOCK_GetFixedFreqClkFreq(void) { uint32_t freq = CLOCK_GetFllRefClkFreq(); @@ -618,6 +708,14 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void) } } +/*! + * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. + * + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG + * register value. + * + * return The frequency of MCGPLL0CLK. + */ uint32_t CLOCK_GetPll0Freq(void) { uint32_t mcgpll0clk; @@ -642,6 +740,18 @@ uint32_t CLOCK_GetPll0Freq(void) return mcgpll0clk; } +/*! + * brief Selects the MCG external reference clock. + * + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. + * + * param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. + * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success External reference clock set successfully. + */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) { bool needDelay; @@ -666,16 +776,6 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ @@ -689,6 +789,22 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Configures the Internal Reference clock (MCGIRCLK). + * + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. + * + * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * param ircs MCGIRCLK clock source, choose fast or slow. + * param fcrdiv Fast IRC divider setting (\c FCRDIV). + * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. + * retval kStatus_Success MCGIRCLK configuration finished successfully. + */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv) { uint32_t mcgOutClkState = MCG_S_CLKST_VAL; @@ -737,6 +853,21 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, return kStatus_Success; } +/*! + * brief Calculates the PLL divider setting for a desired output frequency. + * + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function + * returns 0. + * + * param refFreq PLL reference clock frequency. + * param desireFreq Desired PLL output frequency. + * param prdiv PRDIV value to generate desired PLL frequency. + * param vdiv VDIV value to generate desired PLL frequency. + * return Closest frequency match that the PLL was able generate. + */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv) { uint8_t ret_prdiv; /* PRDIV to return. */ @@ -745,7 +876,7 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */ uint8_t prdiv_cur; /* PRDIV value for iteration. */ uint8_t vdiv_cur; /* VDIV value for iteration. */ - uint32_t ret_freq = 0U; /* PLL output fequency to return. */ + uint32_t ret_freq = 0U; /* PLL output frequency to return. */ uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */ uint32_t ref_div; /* Reference frequency after PRDIV. */ @@ -834,6 +965,17 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, } } +/*! + * brief Enables the PLL0 in FLL mode. + * + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL + * divider values. + * + * param config Pointer to the configuration structure. + */ void CLOCK_EnablePll0(mcg_pll_config_t const *config) { assert(config); @@ -854,6 +996,13 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +/*! + * brief Sets the OSC0 clock monitor mode. + * + * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ @@ -877,6 +1026,13 @@ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Sets the RTC OSC clock monitor mode. + * + * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8 = MCG->C8; @@ -894,6 +1050,13 @@ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode) MCG->C8 = mcg_c8; } +/*! + * brief Sets the PLL0 clock monitor mode. + * + * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details. + * + * param mode Monitor mode to set. + */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) { uint8_t mcg_c8; @@ -924,6 +1087,32 @@ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode) } } +/*! + * brief Gets the MCG status flags. + * + * This function gets the MCG clock status flags. All status flags are + * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To + * check a specific flag, compare the return value with the flag. + * + * Example: + * code + // To check the clock lost lock status of OSC0 and PLL0. + uint32_t mcgFlags; + + mcgFlags = CLOCK_GetStatusFlags(); + + if (mcgFlags & kMCG_Osc0LostFlag) + { + // OSC0 clock lock lost. Do something. + } + if (mcgFlags & kMCG_Pll0LostFlag) + { + // PLL0 clock lock lost. Do something. + } + endcode + * + * return Logical OR value of the ref _mcg_status_flags_t. + */ uint32_t CLOCK_GetStatusFlags(void) { uint32_t ret = 0U; @@ -952,6 +1141,22 @@ uint32_t CLOCK_GetStatusFlags(void) return ret; } +/*! + * brief Clears the MCG status flags. + * + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See ref _mcg_status_flags_t. + * + * Example: + * code + // To clear the clock lost lock status flags of OSC0 and PLL0. + + CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag); + endcode + * + * param mask The status flags to clear. This is a logical OR of members of the + * enumeration ref _mcg_status_flags_t. + */ void CLOCK_ClearStatusFlags(uint32_t mask) { uint8_t reg; @@ -971,6 +1176,13 @@ void CLOCK_ClearStatusFlags(uint32_t mask) } } +/*! + * brief Initializes the OSC0. + * + * This function initializes the OSC0 according to the board configuration. + * + * param config Pointer to the OSC0 configuration structure. + */ void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); @@ -989,12 +1201,35 @@ void CLOCK_InitOsc0(osc_config_t const *config) } } +/*! + * brief Deinitializes the OSC0. + * + * This function deinitializes the OSC0. + */ void CLOCK_DeinitOsc0(void) { OSC0->CR = 0U; MCG->C2 &= ~OSC_MODE_MASK; } +/*! + * brief Auto trims the internal reference clock. + * + * This function trims the internal reference clock by using the external clock. If + * successful, it returns the kStatus_Success and the frequency after + * trimming is received in the parameter p actualFreq. If an error occurs, + * the error code is returned. + * + * param extFreq External clock frequency, which should be a bus clock. + * param desireFreq Frequency to trim to. + * param actualFreq Actual frequency after trimming. + * param atms Trim fast or slow internal reference clock. + * retval kStatus_Success ATM success. + * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. + * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. + * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. + */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms) { uint32_t multi; /* extFreq / desireFreq */ @@ -1071,6 +1306,13 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ return kStatus_Success; } +/*! + * brief Gets the current MCG mode. + * + * This function checks the MCG registers and determines the current MCG mode. + * + * return Current MCG mode or error code; See ref mcg_mode_t. + */ mcg_mode_t CLOCK_GetMode(void) { mcg_mode_t mode = kMCG_ModeError; @@ -1171,6 +1413,21 @@ mcg_mode_t CLOCK_GetMode(void) return mode; } +/*! + * brief Sets the MCG to FEI mode. + * + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. + */ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1231,6 +1488,21 @@ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FEE mode. + * + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1264,6 +1536,17 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void | MCG_C1_FRDIV(frdiv) /* FRDIV */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait and check status. */ while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { @@ -1298,6 +1581,22 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to FBI mode. + * + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. + * + * param dmx32 DMX32 in FBI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1362,6 +1661,21 @@ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDela return kStatus_Success; } +/*! + * brief Sets the MCG to FBE mode. + * + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. + * + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FBE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; @@ -1406,6 +1720,17 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait for Reference clock Status bit to clear */ while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { @@ -1434,6 +1759,15 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } +/*! + * brief Sets the MCG to BLPI mode. + * + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpiMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1449,6 +1783,15 @@ status_t CLOCK_SetBlpiMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode. + * + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_SetBlpeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1464,6 +1807,25 @@ status_t CLOCK_SetBlpeMode(void) return kStatus_Success; } +/*! + * brief Sets the MCG to PBE mode. + * + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. + * + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. + * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); + */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1505,6 +1867,18 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode. + * + * This function sets the MCG to PEE mode. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * + * note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. + */ status_t CLOCK_SetPeeMode(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1526,6 +1900,22 @@ status_t CLOCK_SetPeeMode(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBE mode from the external mode. + * + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock source and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: + * + * code + * CLOCK_ExternalModeToFbeModeQuick(); + * CLOCK_SetFeiMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. + */ status_t CLOCK_ExternalModeToFbeModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1552,6 +1942,22 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void) return kStatus_Success; } +/*! + * brief Switches the MCG to FBI mode from internal modes. + * + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: + * + * code + * CLOCK_InternalModeToFbiModeQuick(); + * CLOCK_SetFeeMode(...); + * endcode + * + * retval kStatus_Success Switched successfully. + * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. + */ status_t CLOCK_InternalModeToFbiModeQuick(void) { #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM) @@ -1572,11 +1978,41 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) return kStatus_Success; } +/*! + * brief Sets the MCG to FEI mode during system boot up. + * + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. + * + * param dmx32 DMX32 in FEI mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. + */ status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to FEE mode during system bootup. + * + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, OSCSEL. + * param frdiv FLL reference clock divider setting, FRDIV. + * param dmx32 DMX32 in FEE mode. + * param drs The DCO range selection. + * param fllStableDelay Delay function to ensure that the FLL is stable. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { @@ -1585,6 +2021,19 @@ status_t CLOCK_BootToFeeMode( return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay); } +/*! + * brief Sets the MCG to BLPI mode during system boot up. + * + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param fcrdiv Fast IRC divider, FCRDIV. + * param ircs The internal reference clock to select, IRCS. + * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode. + * + * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode) { /* If reset mode is FEI mode, set MCGIRCLK and always success. */ @@ -1602,6 +2051,17 @@ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEn return kStatus_Success; } +/*! + * brief Sets the MCG to BLPE mode during system boot up. + * + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) { CLOCK_SetExternalRefClkConfig(oscsel); @@ -1611,6 +2071,17 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt))) @@ -1623,6 +2094,19 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) return kStatus_Success; } +/*! + * brief Sets the MCG to PEE mode during system boot up. + * + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. + * + * param oscsel OSC clock select, MCG_C7[OSCSEL]. + * param pllcs The PLL selection, PLLCS. + * param config Pointer to the PLL configuration. + * + * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. + * retval kStatus_Success Switched to the target mode successfully. + */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { assert(config); @@ -1669,6 +2153,20 @@ static const mcg_mode_t mcgModeMatrix[8][8] = { /* FEI FBI BLPI FEE FBE BLPE PBE PEE */ }; +/*! + * brief Sets the MCG to a target mode. + * + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. + * + * param config Pointer to the target MCG mode configuration structure. + * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. + * + * note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. + */ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) { mcg_mode_t next_mode; @@ -1680,10 +2178,10 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) if (MCG_C7_OSCSEL_VAL != config->oscsel) { /* If external clock is in use, change to FEI first. */ - if (!(MCG->S & MCG_S_IRCST_MASK)) + if (kMCG_FllSrcExternal == MCG_S_IREFST_VAL) { CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); + CLOCK_SetFeiMode(config->dmx32, config->drs, NULL); } CLOCK_SetExternalRefClkConfig(config->oscsel); @@ -1717,10 +2215,10 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL); break; case kMCG_ModeFBE: - status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); + status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL); break; case kMCG_ModeBLPI: status = CLOCK_SetBlpiMode(); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_clock.h index b20629add1..13ac8fa98a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_clock.h @@ -1,31 +1,10 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright (c) 2016 - 2017 , NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ @@ -39,14 +18,32 @@ /*! @file */ /******************************************************************************* - * Definitions + * Configurations ******************************************************************************/ +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + /*! @brief Configure whether driver controls clock * * When set to 0, peripheral drivers will enable clock in initialize function * and disable clock in de-initialize function. When set to 1, peripheral - * driver will not control the clock, application could contol the clock out of + * driver will not control the clock, application could control the clock out of * the driver. * * @note All drivers share this feature switcher. If it is set to 1, application @@ -56,10 +53,14 @@ #define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 #endif +/******************************************************************************* + * Definitions + ******************************************************************************/ + /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.0. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief CLOCK driver version 2.2.1. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 1)) /*@}*/ /*! @brief External XTAL0 (OSC0) clock frequency. @@ -76,7 +77,7 @@ * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal0Freq; +extern volatile uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * @@ -87,7 +88,7 @@ extern uint32_t g_xtal0Freq; * the clock. All other cores need to call the CLOCK_SetXtal32Freq * to get a valid clock frequency. */ -extern uint32_t g_xtal32Freq; +extern volatile uint32_t g_xtal32Freq; /*! @brief IRC48M clock frequency in Hz. */ #define MCG_INTERNAL_IRC_48M 48000000U @@ -194,7 +195,7 @@ extern uint32_t g_xtal32Freq; /*! @brief Clock ip name array for MPU. */ #define SYSMPU_CLOCKS \ - { \ + { \ kCLOCK_Sysmpu0 \ } @@ -982,8 +983,8 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source, + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); @@ -997,7 +998,7 @@ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, - * the confuration should not be changed. Otherwise, a glitch occurs. + * the configuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); @@ -1408,7 +1409,7 @@ status_t CLOCK_SetPeeMode(void); * @brief Switches the MCG to FBE mode from the external mode. * * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. - * The external clock is used as the system clock souce and PLL is disabled. However, + * The external clock is used as the system clock source and PLL is disabled. However, * the FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEE mode to FEI mode: * @@ -1426,7 +1427,7 @@ status_t CLOCK_ExternalModeToFbeModeQuick(void); * @brief Switches the MCG to FBI mode from internal modes. * * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. - * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * The MCGIRCLK is used as the system clock source and PLL is disabled. However, * FLL settings are not configured. This is a lite function with a small code size, which is useful * during the mode switch. For example, to switch from PEI mode to FEE mode: * @@ -1479,7 +1480,7 @@ status_t CLOCK_BootToFeeMode( * @brief Sets the MCG to BLPI mode during system boot up. * * This function sets the MCG to BLPI mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. @@ -1491,10 +1492,10 @@ status_t CLOCK_BootToFeeMode( status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Sets the MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during system boot up. * * This function sets the MCG to BLPE mode from the reset mode. It can also be used to - * set up the MCG during sytem boot up. + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. *