added prescaler for 16 bit pwm in LPC1347 target
Fork of mbed-dev by
Diff: targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_cmu.c
- Revision:
- 50:a417edff4437
- Parent:
- 0:9b334a45a8ff
- Child:
- 144:ef7eb2e8f9f7
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_cmu.c Wed Jan 13 12:45:11 2016 +0000 +++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_cmu.c Fri Jan 15 07:45:16 2016 +0000 @@ -1,10 +1,10 @@ /***************************************************************************//** * @file em_cmu.c * @brief Clock management unit (CMU) Peripheral API - * @version 3.20.12 + * @version 4.2.1 ******************************************************************************* * @section License - * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b> + * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> ******************************************************************************* * * Permission is granted to anyone to use this software for any purpose, @@ -29,14 +29,15 @@ * arising from your use of this Software. * ******************************************************************************/ - - #include "em_cmu.h" #if defined( CMU_PRESENT ) +#include <stddef.h> +#include <limits.h> #include "em_assert.h" -#include "em_bitband.h" +#include "em_bus.h" #include "em_emu.h" +#include "em_system.h" /***************************************************************************//** * @addtogroup EM_Library @@ -55,30 +56,41 @@ /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ -/** Maximum allowed core frequency when using 0 wait states on flash access. */ +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) +/** Maximum allowed core frequency when using 0 wait-states on flash access. */ +#define CMU_MAX_FREQ_0WS 26000000 +/** Maximum allowed core frequency when using 1 wait-states on flash access */ +#define CMU_MAX_FREQ_1WS 40000000 +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) +/** Maximum allowed core frequency when using 0 wait-states on flash access. */ #define CMU_MAX_FREQ_0WS 16000000 -/** Maximum allowed core frequency when using 1 wait states on flash access */ +/** Maximum allowed core frequency when using 1 wait-states on flash access */ #define CMU_MAX_FREQ_1WS 32000000 +#else +#error "Unkown MCU platform." +#endif #if defined( CMU_CTRL_HFLE ) /** Maximum frequency for HFLE needs to be enabled on Giant, Leopard and Wonder. */ -#if defined ( _EFM32_WONDER_FAMILY ) || \ - defined ( _EZR32_LEOPARD_FAMILY ) || \ - defined ( _EZR32_WONDER_FAMILY ) -#define CMU_MAX_FREQ_HFLE 24000000 +#if defined( _EFM32_WONDER_FAMILY ) \ + || defined( _EZR32_LEOPARD_FAMILY ) \ + || defined( _EZR32_WONDER_FAMILY ) +#define CMU_MAX_FREQ_HFLE() 24000000 #elif defined ( _EFM32_GIANT_FAMILY ) -#define CMU_MAX_FREQ_HFLE (CMU_MaxFreqHfle()) +#define CMU_MAX_FREQ_HFLE() (maxFreqHfle()) #else #error Invalid part/device. #endif #endif -/** Low frequency A group identifier */ -#define CMU_LFA 0 - -/** Low frequency B group identifier */ -#define CMU_LFB 1 +/******************************************************************************* + ************************** LOCAL VARIABLES ******************************** + ******************************************************************************/ + +#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK ) +static CMU_AUXHFRCOFreq_TypeDef auxHfrcoFreq = cmuAUXHFRCOFreq_19M0Hz; +#endif /** @endcond */ @@ -88,50 +100,104 @@ /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ -#if defined( CMU_CTRL_HFLE ) && \ - !defined ( _EFM32_WONDER_FAMILY ) && \ - !defined ( _EZR32_LEOPARD_FAMILY ) && \ - !defined ( _EZR32_WONDER_FAMILY ) +/***************************************************************************//** + * @brief + * Get the AUX clock frequency. Used by MSC flash programming and LESENSE, + * by default also as debug clock. + * + * @return + * AUX Frequency in Hz + ******************************************************************************/ +static uint32_t auxClkGet(void) +{ + uint32_t ret; + +#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK ) + ret = auxHfrcoFreq; + +#elif defined( _CMU_AUXHFRCOCTRL_BAND_MASK ) + /* All Geckos from TG and newer */ + switch(CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK) + { + case CMU_AUXHFRCOCTRL_BAND_1MHZ: + ret = 1000000; + break; + + case CMU_AUXHFRCOCTRL_BAND_7MHZ: + ret = 7000000; + break; + + case CMU_AUXHFRCOCTRL_BAND_11MHZ: + ret = 11000000; + break; + + case CMU_AUXHFRCOCTRL_BAND_14MHZ: + ret = 14000000; + break; + + case CMU_AUXHFRCOCTRL_BAND_21MHZ: + ret = 21000000; + break; + +#if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ ) + case CMU_AUXHFRCOCTRL_BAND_28MHZ: + ret = 28000000; + break; +#endif + + default: + EFM_ASSERT(0); + ret = 0; + break; + } + +#else + /* Gecko has a fixed 14Mhz AUXHFRCO clock */ + ret = 14000000; + +#endif + + return ret; +} + /***************************************************************************//** * @brief - * Return max allowed frequency for low energy peripherals. + * Get the Debug Trace clock frequency + * + * @return + * Debug Trace frequency in Hz ******************************************************************************/ -static uint32_t CMU_MaxFreqHfle(void) +static uint32_t dbgClkGet(void) { - /* SYSTEM_GetFamily and SYSTEM_ChipRevisionGet could have been used here - but we want to minimize dependencies in em_cmu.c. */ - uint16_t majorMinorRev; - uint8_t deviceFamily = ((DEVINFO->PART & _DEVINFO_PART_DEVICE_FAMILY_MASK) - >> _DEVINFO_PART_DEVICE_FAMILY_SHIFT); - switch (deviceFamily) + uint32_t ret; + CMU_Select_TypeDef clk; + + /* Get selected clock source */ + clk = CMU_ClockSelectGet(cmuClock_DBG); + + switch(clk) { - case _DEVINFO_PART_DEVICE_FAMILY_LG: - /* CHIP MAJOR bit [3:0] */ - majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK) - >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8); - /* CHIP MINOR bit [7:4] */ - majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK) - >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4); - /* CHIP MINOR bit [3:0] */ - majorMinorRev |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK) - >> _ROMTABLE_PID3_REVMINORLSB_SHIFT); - - if (majorMinorRev >= 0x0204) - return 24000000; - else - return 32000000; - case _DEVINFO_PART_DEVICE_FAMILY_GG: - return 32000000; - case _DEVINFO_PART_DEVICE_FAMILY_WG: - return 24000000; - default: - /* Invalid device family. */ - EFM_ASSERT(false); - return 0; + case cmuSelect_HFCLK: + ret = SystemHFClockGet(); +#if defined( _CMU_CTRL_HFCLKDIV_MASK ) + /* Family with an additional divider. */ + ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) + >> _CMU_CTRL_HFCLKDIV_SHIFT)); +#endif + break; + + case cmuSelect_AUXHFRCO: + ret = auxClkGet(); + break; + + default: + EFM_ASSERT(0); + ret = 0; + break; } + return ret; } -#endif /***************************************************************************//** @@ -139,15 +205,15 @@ * Configure flash access wait states in order to support given core clock * frequency. * - * @param[in] hfcoreclk + * @param[in] coreFreq * Core clock frequency to configure flash wait-states for ******************************************************************************/ -static void CMU_FlashWaitStateControl(uint32_t hfcoreclk) +static void flashWaitStateControl(uint32_t coreFreq) { uint32_t mode; bool mscLocked; #if defined( MSC_READCTRL_MODE_WS0SCBTP ) - bool scbtpEn; + bool scbtpEn; /* Suppressed Conditional Branch Target Prefetch setting. */ #endif /* Make sure the MSC is unlocked */ @@ -180,12 +246,12 @@ { } #if defined( MSC_READCTRL_MODE_WS2 ) - else if (hfcoreclk > CMU_MAX_FREQ_1WS) + else if (coreFreq > CMU_MAX_FREQ_1WS) { mode = (scbtpEn ? MSC_READCTRL_MODE_WS2SCBTP : MSC_READCTRL_MODE_WS2); } #endif - else if ((hfcoreclk <= CMU_MAX_FREQ_1WS) && (hfcoreclk > CMU_MAX_FREQ_0WS)) + else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS)) { mode = (scbtpEn ? MSC_READCTRL_MODE_WS1SCBTP : MSC_READCTRL_MODE_WS1); } @@ -200,12 +266,12 @@ { } #if defined( MSC_READCTRL_MODE_WS2 ) - else if (hfcoreclk > CMU_MAX_FREQ_1WS) + else if (coreFreq > CMU_MAX_FREQ_1WS) { mode = MSC_READCTRL_MODE_WS2; } #endif - else if ((hfcoreclk <= CMU_MAX_FREQ_1WS) && (hfcoreclk > CMU_MAX_FREQ_0WS)) + else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS)) { mode = MSC_READCTRL_MODE_WS1; } @@ -229,62 +295,249 @@ /***************************************************************************//** * @brief * Configure flash access wait states to most conservative setting for - * this target. Retain SCBTP setting. + * this target. Retain SCBTP (Suppressed Conditional Branch Target Prefetch) + * setting. ******************************************************************************/ -static void CMU_FlashWaitStateMax(void) +static void flashWaitStateMax(void) { - uint32_t maxCoreClock; -#if defined (_EFM32_GECKO_FAMILY) - maxCoreClock = 32000000; -#elif defined (_EFM32_GIANT_FAMILY) - maxCoreClock = 48000000; -#elif defined (_EFM32_TINY_FAMILY) - maxCoreClock = 32000000; -#elif defined (_EFM32_LEOPARD_FAMILY) - maxCoreClock = 48000000; -#elif defined (_EFM32_WONDER_FAMILY) - maxCoreClock = 48000000; -#elif defined (_EFM32_ZERO_FAMILY) - maxCoreClock = 24000000; -#elif defined (_EFM32_HAPPY_FAMILY) - maxCoreClock = 25000000; -#else -#error "Max core clock frequency is not defined for this family" -#endif - - /* Use SystemMaxCoreClockGet() when available in CMSIS */ - CMU_FlashWaitStateControl(maxCoreClock); + flashWaitStateControl(SystemMaxCoreClockGet()); } /***************************************************************************//** - * @brief Convert dividend to prescaler logarithmic value. Only works for even - * numbers equal to 2^n - * @param[in] div Unscaled dividend, - * @return Base 2 logarithm of input, as used by fixed prescalers + * @brief + * Get the LFnCLK frequency based on current configuration. + * + * @param[in] lfClkBranch + * Selected LF branch + * + * @return + * The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is + * returned. ******************************************************************************/ -__STATIC_INLINE uint32_t CMU_DivToLog2(CMU_ClkDiv_TypeDef div) +static uint32_t lfClkGet(CMU_Clock_TypeDef lfClkBranch) { - uint32_t log2; - - /* Prescalers take argument of 32768 or less */ - EFM_ASSERT((div>0) && (div <= 32768)); - - /* Count leading zeroes and "reverse" result, Cortex-M3 intrinsic */ - log2 = (31 - __CLZ(div)); - - return log2; + uint32_t sel; + uint32_t ret = 0; + + switch (lfClkBranch) + { + case cmuClock_LFA: + case cmuClock_LFB: +#if defined( _CMU_LFCCLKEN0_MASK ) + case cmuClock_LFC: +#endif +#if defined( _CMU_LFECLKSEL_MASK ) + case cmuClock_LFE: +#endif + break; + + default: + EFM_ASSERT(0); + break; + } + + sel = CMU_ClockSelectGet(lfClkBranch); + + /* Get clock select field */ + switch (lfClkBranch) + { + case cmuClock_LFA: +#if defined( _CMU_LFCLKSEL_MASK ) + sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK) >> _CMU_LFCLKSEL_LFA_SHIFT; +#elif defined( _CMU_LFACLKSEL_MASK ) + sel = (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK) >> _CMU_LFACLKSEL_LFA_SHIFT; +#else + EFM_ASSERT(0); +#endif + break; + + case cmuClock_LFB: +#if defined( _CMU_LFCLKSEL_MASK ) + sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK) >> _CMU_LFCLKSEL_LFB_SHIFT; +#elif defined( _CMU_LFBCLKSEL_MASK ) + sel = (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK) >> _CMU_LFBCLKSEL_LFB_SHIFT; +#else + EFM_ASSERT(0); +#endif + break; + +#if defined( _CMU_LFCCLKEN0_MASK ) + case cmuClock_LFC: + sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK) >> _CMU_LFCLKSEL_LFC_SHIFT; + break; +#endif + +#if defined( _CMU_LFECLKSEL_MASK ) + case cmuClock_LFE: + sel = (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK) >> _CMU_LFECLKSEL_LFE_SHIFT; + break; +#endif + + default: + EFM_ASSERT(0); + break; + } + + /* Get clock frequency */ +#if defined( _CMU_LFCLKSEL_MASK ) + switch (sel) + { + case _CMU_LFCLKSEL_LFA_LFRCO: + ret = SystemLFRCOClockGet(); + break; + + case _CMU_LFCLKSEL_LFA_LFXO: + ret = SystemLFXOClockGet(); + break; + +#if defined( _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2 ) + case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2: +#if defined( CMU_CTRL_HFLE ) + /* Family which can use an extra div 4 divider */ + /* (and must if >32MHz) or HFLE is set. */ + if(((CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK) + == CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4) + || (CMU->CTRL & CMU_CTRL_HFLE)) + { + ret = SystemCoreClockGet() / 4U; + } + else + { + ret = SystemCoreClockGet() / 2U; + } +#else + ret = SystemCoreClockGet() / 2U; +#endif + break; +#endif + + case _CMU_LFCLKSEL_LFA_DISABLED: + ret = 0; +#if defined( CMU_LFCLKSEL_LFAE ) + /* Check LF Extended bit setting for LFA or LFB ULFRCO clock */ + if ((lfClkBranch == cmuClock_LFA) || (lfClkBranch == cmuClock_LFB)) + { + if (CMU->LFCLKSEL >> (lfClkBranch == cmuClock_LFA + ? _CMU_LFCLKSEL_LFAE_SHIFT + : _CMU_LFCLKSEL_LFBE_SHIFT)) + { + ret = SystemULFRCOClockGet(); + } + } +#endif + break; + + default: + EFM_ASSERT(0); + ret = 0U; + break; + } +#endif /* _CMU_LFCLKSEL_MASK */ + +#if defined( _CMU_LFACLKSEL_MASK ) + switch (sel) + { + case _CMU_LFACLKSEL_LFA_LFRCO: + ret = SystemLFRCOClockGet(); + break; + + case _CMU_LFACLKSEL_LFA_LFXO: + ret = SystemLFXOClockGet(); + break; + + case _CMU_LFACLKSEL_LFA_ULFRCO: + ret = SystemULFRCOClockGet(); + break; + +#if defined( _CMU_LFACLKSEL_LFA_HFCLKLE ) + case _CMU_LFACLKSEL_LFA_HFCLKLE: + ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK) + == CMU_HFPRESC_HFCLKLEPRESC_DIV4) + ? SystemCoreClockGet() / 4U + : SystemCoreClockGet() / 2U; + break; +#elif defined( _CMU_LFBCLKSEL_LFB_HFCLKLE ) + case _CMU_LFBCLKSEL_LFB_HFCLKLE: + ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK) + == CMU_HFPRESC_HFCLKLEPRESC_DIV4) + ? SystemCoreClockGet() / 4U + : SystemCoreClockGet() / 2U; + break; +#endif + + case _CMU_LFACLKSEL_LFA_DISABLED: + ret = 0; + break; + } +#endif + + return ret; } +#if defined( CMU_CTRL_HFLE ) \ + && !defined( _EFM32_WONDER_FAMILY ) \ + && !defined( _EZR32_LEOPARD_FAMILY ) \ + && !defined( _EZR32_WONDER_FAMILY ) +/***************************************************************************//** + * @brief + * Return max allowed frequency for low energy peripherals. + ******************************************************************************/ +static uint32_t maxFreqHfle(void) +{ + uint16_t majorMinorRev; + + switch (SYSTEM_GetFamily()) + { + case systemPartFamilyEfm32Leopard: + /* CHIP MAJOR bit [5:0] */ + majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK) + >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8); + /* CHIP MINOR bit [7:4] */ + majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK) + >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4); + /* CHIP MINOR bit [3:0] */ + majorMinorRev |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK) + >> _ROMTABLE_PID3_REVMINORLSB_SHIFT); + + if (majorMinorRev >= 0x0204) + return 24000000; + else + return 32000000; + + case systemPartFamilyEfm32Giant: + return 32000000; + + default: + /* Invalid device family. */ + EFM_ASSERT(false); + return 0; + } +} +#endif + + /***************************************************************************//** - * @brief Convert logarithm of 2 prescaler to division factor - * @param[in] log2 - * @return Dividend + * @brief + * Wait for ongoing sync of register(s) to low frequency domain to complete. + * + * @param[in] mask + * Bitmask corresponding to SYNCBUSY register defined bits, indicating + * registers that must complete any ongoing synchronization. ******************************************************************************/ -__STATIC_INLINE uint32_t CMU_Log2ToDiv(uint32_t log2) +__STATIC_INLINE void syncReg(uint32_t mask) { - return 1<<log2; + /* Avoid deadlock if modifying the same register twice when freeze mode is */ + /* activated. */ + if (CMU->FREEZE & CMU_FREEZE_REGFREEZE) + return; + + /* Wait for any pending previous write operation to have been completed */ + /* in low frequency domain */ + while (CMU->SYNCBUSY & mask) + { + } } @@ -296,7 +549,7 @@ * @return * USBC frequency in Hz ******************************************************************************/ -static uint32_t CMU_USBCClkGet(void) +static uint32_t usbCClkGet(void) { uint32_t ret; CMU_Select_TypeDef clk; @@ -306,215 +559,230 @@ switch(clk) { - case cmuSelect_LFXO: - ret = SystemLFXOClockGet(); - break; - case cmuSelect_LFRCO: - ret = SystemLFRCOClockGet(); - break; - case cmuSelect_HFCLK: - ret = SystemHFClockGet(); - break; - default: - /* Clock is not enabled */ - ret = 0; - break; + case cmuSelect_LFXO: + ret = SystemLFXOClockGet(); + break; + case cmuSelect_LFRCO: + ret = SystemLFRCOClockGet(); + break; + case cmuSelect_HFCLK: + ret = SystemHFClockGet(); + break; + default: + /* Clock is not enabled */ + ret = 0; + break; } return ret; } #endif -/***************************************************************************//** - * @brief - * Get the AUX clock frequency. Used by MSC flash programming and LESENSE, - * by default also as debug clock. - * - * @return - * AUX Frequency in Hz - ******************************************************************************/ -static uint32_t CMU_AUXClkGet(void) -{ - uint32_t ret; - -#if defined(_EFM32_GECKO_FAMILY) - /* Gecko has a fixed 14Mhz AUXHFRCO clock */ - ret = 14000000; -#else - switch(CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK) - { - case CMU_AUXHFRCOCTRL_BAND_1MHZ: - ret = 1000000; - break; - case CMU_AUXHFRCOCTRL_BAND_7MHZ: - ret = 7000000; - break; - case CMU_AUXHFRCOCTRL_BAND_11MHZ: - ret = 11000000; - break; - case CMU_AUXHFRCOCTRL_BAND_14MHZ: - ret = 14000000; - break; - case CMU_AUXHFRCOCTRL_BAND_21MHZ: - ret = 21000000; - break; -#if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ ) - case CMU_AUXHFRCOCTRL_BAND_28MHZ: - ret = 28000000; - break; -#endif - default: - ret = 0; - break; - } -#endif - return ret; -} - - -/***************************************************************************//** - * @brief - * Get the Debug Trace clock frequency - * - * @return - * Debug Trace frequency in Hz - ******************************************************************************/ -static uint32_t CMU_DBGClkGet(void) -{ - uint32_t ret; - CMU_Select_TypeDef clk; - - /* Get selected clock source */ - clk = CMU_ClockSelectGet(cmuClock_DBG); - - switch(clk) - { - case cmuSelect_HFCLK: - ret = SystemHFClockGet(); -#if defined( _CMU_CTRL_HFCLKDIV_MASK ) - /* Giant Gecko has an additional divider, not used by USBC */ - ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >> - _CMU_CTRL_HFCLKDIV_SHIFT)); -#endif - break; - - case cmuSelect_AUXHFRCO: - ret = CMU_AUXClkGet(); - break; - - default: - EFM_ASSERT(0); - ret = 0; - break; - } - return ret; -} - - -/***************************************************************************//** - * @brief - * Get the LFnCLK frequency based on current configuration. - * - * @param[in] lfClkBranch - * LF branch, 0 = LFA, 1 = LFB, ... - * - * @return - * The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is - * returned. - ******************************************************************************/ -static uint32_t CMU_LFClkGet(unsigned int lfClkBranch) -{ - uint32_t ret; - - EFM_ASSERT(lfClkBranch == CMU_LFA || lfClkBranch == CMU_LFB); - - switch ((CMU->LFCLKSEL >> (lfClkBranch * 2)) & 0x3) - { - case _CMU_LFCLKSEL_LFA_LFRCO: - ret = SystemLFRCOClockGet(); - break; - - case _CMU_LFCLKSEL_LFA_LFXO: - ret = SystemLFXOClockGet(); - break; - - case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2: -#if defined( CMU_CTRL_HFLE ) - /* Giant Gecko can use a /4 divider (and must if >32MHz) or HFLE is set */ - if(((CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK) == CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4)|| - (CMU->CTRL & CMU_CTRL_HFLE)) - { - ret = SystemCoreClockGet() / 4; - } - else - { - ret = SystemCoreClockGet() / 2; - } -#else - ret = SystemCoreClockGet() / 2; -#endif - break; - - case _CMU_LFCLKSEL_LFA_DISABLED: -#if defined( CMU_LFCLKSEL_LFAE ) - /* Check LF Extended bit setting for ULFRCO clock */ - if(CMU->LFCLKSEL >> (_CMU_LFCLKSEL_LFAE_SHIFT + lfClkBranch * 4)) - { - ret = SystemULFRCOClockGet(); - } - else - { - ret = 0; - } -#else - ret = 0; -#endif - break; - - default: - ret = 0; - break; - } - - return ret; -} - - -/***************************************************************************//** - * @brief - * Wait for ongoing sync of register(s) to low frequency domain to complete. - * - * @param[in] mask - * Bitmask corresponding to SYNCBUSY register defined bits, indicating - * registers that must complete any ongoing synchronization. - ******************************************************************************/ -__STATIC_INLINE void CMU_Sync(uint32_t mask) -{ - /* Avoid deadlock if modifying the same register twice when freeze mode is */ - /* activated. */ - if (CMU->FREEZE & CMU_FREEZE_REGFREEZE) - return; - - /* Wait for any pending previous write operation to have been completed */ - /* in low frequency domain */ - while (CMU->SYNCBUSY & mask) - ; -} - - /** @endcond */ /******************************************************************************* ************************** GLOBAL FUNCTIONS ******************************* ******************************************************************************/ +#if defined( _CMU_AUXHFRCOCTRL_BAND_MASK ) +/***************************************************************************//** + * @brief + * Get AUXHFRCO band in use. + * + * @return + * AUXHFRCO band in use. + ******************************************************************************/ +CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void) +{ + return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL + & _CMU_AUXHFRCOCTRL_BAND_MASK) + >> _CMU_AUXHFRCOCTRL_BAND_SHIFT); +} +#endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */ + + +#if defined( _CMU_AUXHFRCOCTRL_BAND_MASK ) +/***************************************************************************//** + * @brief + * Set AUXHFRCO band and the tuning value based on the value in the + * calibration table made during production. + * + * @param[in] band + * AUXHFRCO band to activate. + ******************************************************************************/ +void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band) +{ + uint32_t tuning; + + /* Read tuning value from calibration table */ + switch (band) + { + case cmuAUXHFRCOBand_1MHz: + tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK) + >> _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT; + break; + + case cmuAUXHFRCOBand_7MHz: + tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK) + >> _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT; + break; + + case cmuAUXHFRCOBand_11MHz: + tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK) + >> _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT; + break; + + case cmuAUXHFRCOBand_14MHz: + tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK) + >> _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT; + break; + + case cmuAUXHFRCOBand_21MHz: + tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK) + >> _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT; + break; + +#if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ ) + case cmuAUXHFRCOBand_28MHz: + tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK) + >> _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT; + break; +#endif + + default: + EFM_ASSERT(0); + return; + } + + /* Set band/tuning */ + CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & + ~(_CMU_AUXHFRCOCTRL_BAND_MASK + | _CMU_AUXHFRCOCTRL_TUNING_MASK)) + | (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT) + | (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT); + +} +#endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */ + + +#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK ) +/**************************************************************************//** + * @brief + * Get a pointer to the AUXHFRCO frequency calibration word in DEVINFO + * + * @param[in] freq + * Frequency in Hz + * + * @return + * AUXHFRCO calibration word for a given frequency + *****************************************************************************/ +static uint32_t CMU_AUXHFRCODevinfoGet(CMU_AUXHFRCOFreq_TypeDef freq) +{ + switch (freq) + { + /* 1, 2 and 4MHz share the same calibration word */ + case cmuAUXHFRCOFreq_1M0Hz: + case cmuAUXHFRCOFreq_2M0Hz: + case cmuAUXHFRCOFreq_4M0Hz: + return DEVINFO->AUXHFRCOCAL0; + + case cmuAUXHFRCOFreq_7M0Hz: + return DEVINFO->AUXHFRCOCAL3; + + case cmuAUXHFRCOFreq_13M0Hz: + return DEVINFO->AUXHFRCOCAL6; + + case cmuAUXHFRCOFreq_16M0Hz: + return DEVINFO->AUXHFRCOCAL7; + + case cmuAUXHFRCOFreq_19M0Hz: + return DEVINFO->AUXHFRCOCAL8; + + case cmuAUXHFRCOFreq_26M0Hz: + return DEVINFO->AUXHFRCOCAL10; + + case cmuAUXHFRCOFreq_32M0Hz: + return DEVINFO->AUXHFRCOCAL11; + + case cmuAUXHFRCOFreq_38M0Hz: + return DEVINFO->AUXHFRCOCAL12; + + default: /* cmuAUXHFRCOFreq_UserDefined */ + return 0; + } +} +#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */ + + +#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK ) +/***************************************************************************//** + * @brief + * Get AUXHFRCO frequency enumeration in use + * + * @return + * AUXHFRCO frequency enumeration in use + ******************************************************************************/ +CMU_AUXHFRCOFreq_TypeDef CMU_AUXHFRCOFreqGet(void) +{ + return auxHfrcoFreq; +} +#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */ + + +#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK ) +/***************************************************************************//** + * @brief + * Set AUXHFRCO calibration for the selected target frequency + * + * @param[in] frequency + * AUXHFRCO frequency to set + ******************************************************************************/ +void CMU_AUXHFRCOFreqSet(CMU_AUXHFRCOFreq_TypeDef freq) +{ + uint32_t freqCal; + + /* Get DEVINFO index, set global auxHfrcoFreq */ + freqCal = CMU_AUXHFRCODevinfoGet(freq); + EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX)); + auxHfrcoFreq = freq; + + /* Wait for any previous sync to complete, and then set calibration data + for the selected frequency. */ + while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT)); + + /* Set divider in AUXHFRCOCTRL for 1, 2 and 4MHz */ + switch(freq) + { + case cmuAUXHFRCOFreq_1M0Hz: + freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK) + | CMU_AUXHFRCOCTRL_CLKDIV_DIV4; + break; + + case cmuAUXHFRCOFreq_2M0Hz: + freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK) + | CMU_AUXHFRCOCTRL_CLKDIV_DIV2; + break; + + case cmuAUXHFRCOFreq_4M0Hz: + freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK) + | CMU_AUXHFRCOCTRL_CLKDIV_DIV1; + break; + + default: + break; + } + CMU->AUXHFRCOCTRL = freqCal; +} +#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */ + + /***************************************************************************//** * @brief * Calibrate clock. * * @details * Run a calibration for HFCLK against a selectable reference clock. Please - * refer to the EFM32 reference manual, CMU chapter, for further details. + * refer to the reference manual, CMU chapter, for further details. * * @note * This function will not return until calibration measurement is completed. @@ -537,29 +805,29 @@ /* Set reference clock source */ switch (ref) { - case cmuOsc_LFXO: - CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO; - break; - - case cmuOsc_LFRCO: - CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO; - break; - - case cmuOsc_HFXO: - CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO; - break; - - case cmuOsc_HFRCO: - CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO; - break; - - case cmuOsc_AUXHFRCO: - CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO; - break; - - default: - EFM_ASSERT(0); - return 0; + case cmuOsc_LFXO: + CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO; + break; + + case cmuOsc_LFRCO: + CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO; + break; + + case cmuOsc_HFXO: + CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO; + break; + + case cmuOsc_HFRCO: + CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO; + break; + + case cmuOsc_AUXHFRCO: + CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO; + break; + + default: + EFM_ASSERT(0); + return 0; } /* Set top value */ @@ -568,9 +836,17 @@ /* Start calibration */ CMU->CMD = CMU_CMD_CALSTART; +#if defined( CMU_STATUS_CALRDY ) /* Wait until calibration completes */ - while (CMU->STATUS & CMU_STATUS_CALBSY) - ; + while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT)) + { + } +#else + /* Wait until calibration completes */ + while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT)) + { + } +#endif return CMU->CALCNT; } @@ -584,7 +860,7 @@ * @details * Configure a calibration for a selectable clock source against another * selectable reference clock. - * Refer to the EFM32 reference manual, CMU chapter, for further details. + * Refer to the reference manual, CMU chapter, for further details. * * @note * After configuration, a call to CMU_CalibrateStart() is required, and @@ -607,7 +883,8 @@ CMU_Osc_TypeDef upSel) { /* Keep untouched configuration settings */ - uint32_t calCtrl = CMU->CALCTRL & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK); + uint32_t calCtrl = CMU->CALCTRL + & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK); /* 20 bits of precision to calibration count register */ EFM_ASSERT(downCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT)); @@ -615,29 +892,29 @@ /* Set down counting clock source - down counter */ switch (downSel) { - case cmuOsc_LFXO: - calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO; - break; - - case cmuOsc_LFRCO: - calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO; - break; - - case cmuOsc_HFXO: - calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO; - break; - - case cmuOsc_HFRCO: - calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO; - break; - - case cmuOsc_AUXHFRCO: - calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO; - break; - - default: - EFM_ASSERT(0); - break; + case cmuOsc_LFXO: + calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO; + break; + + case cmuOsc_LFRCO: + calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO; + break; + + case cmuOsc_HFXO: + calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO; + break; + + case cmuOsc_HFRCO: + calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO; + break; + + case cmuOsc_AUXHFRCO: + calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO; + break; + + default: + EFM_ASSERT(0); + break; } /* Set top value to be counted down by the downSel clock */ @@ -646,29 +923,29 @@ /* Set reference clock source - up counter */ switch (upSel) { - case cmuOsc_LFXO: - calCtrl |= CMU_CALCTRL_UPSEL_LFXO; - break; - - case cmuOsc_LFRCO: - calCtrl |= CMU_CALCTRL_UPSEL_LFRCO; - break; - - case cmuOsc_HFXO: - calCtrl |= CMU_CALCTRL_UPSEL_HFXO; - break; - - case cmuOsc_HFRCO: - calCtrl |= CMU_CALCTRL_UPSEL_HFRCO; - break; - - case cmuOsc_AUXHFRCO: - calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO; - break; - - default: - EFM_ASSERT(0); - break; + case cmuOsc_LFXO: + calCtrl |= CMU_CALCTRL_UPSEL_LFXO; + break; + + case cmuOsc_LFRCO: + calCtrl |= CMU_CALCTRL_UPSEL_LFRCO; + break; + + case cmuOsc_HFXO: + calCtrl |= CMU_CALCTRL_UPSEL_HFXO; + break; + + case cmuOsc_HFRCO: + calCtrl |= CMU_CALCTRL_UPSEL_HFRCO; + break; + + case cmuOsc_AUXHFRCO: + calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO; + break; + + default: + EFM_ASSERT(0); + break; } CMU->CALCTRL = calCtrl; @@ -678,6 +955,47 @@ /***************************************************************************//** * @brief + * Get calibration count register + * @note + * If continuous calibrartion mode is active, calibration busy will almost + * always be off, and we just need to read the value, where the normal case + * would be that this function call has been triggered by the CALRDY + * interrupt flag. + * @return + * Calibration count, the number of UPSEL clocks (see CMU_CalibrateConfig) + * in the period of DOWNSEL oscillator clock cycles configured by a previous + * write operation to CMU->CALCNT + ******************************************************************************/ +uint32_t CMU_CalibrateCountGet(void) +{ + /* Wait until calibration completes, UNLESS continuous calibration mode is */ + /* active */ +#if defined( CMU_CALCTRL_CONT ) + if (!BUS_RegBitRead(&CMU->CALCTRL, _CMU_CALCTRL_CONT_SHIFT)) + { +#if defined( CMU_STATUS_CALRDY ) + /* Wait until calibration completes */ + while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT)) + { + } +#else + /* Wait until calibration completes */ + while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT)) + { + } +#endif + } +#else + while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT)) + { + } +#endif + return CMU->CALCNT; +} + + +/***************************************************************************//** + * @brief * Get clock divisor/prescaler. * * @param[in] clock @@ -690,6 +1008,10 @@ ******************************************************************************/ CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock) { +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + return 1 + (uint32_t)CMU_ClockPrescGet(clock); + +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) uint32_t divReg; CMU_ClkDiv_TypeDef ret; @@ -699,99 +1021,101 @@ switch (divReg) { #if defined( _CMU_CTRL_HFCLKDIV_MASK ) - case CMU_HFCLKDIV_REG: - ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >> - _CMU_CTRL_HFCLKDIV_SHIFT); - break; + case CMU_HFCLKDIV_REG: + ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) + >> _CMU_CTRL_HFCLKDIV_SHIFT); + break; #endif - case CMU_HFPERCLKDIV_REG: - ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV & - _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >> - _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT); - ret = CMU_Log2ToDiv(ret); - break; - - case CMU_HFCORECLKDIV_REG: - ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV & - _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >> - _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT); - ret = CMU_Log2ToDiv(ret); - break; - - case CMU_LFAPRESC0_REG: - switch (clock) - { - case cmuClock_RTC: - ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) >> - _CMU_LFAPRESC0_RTC_SHIFT)); + case CMU_HFPERCLKDIV_REG: + ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV + & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) + >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT); ret = CMU_Log2ToDiv(ret); break; -#if defined(_CMU_LFAPRESC0_LETIMER0_MASK) - case cmuClock_LETIMER0: - ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) >> - _CMU_LFAPRESC0_LETIMER0_SHIFT)); + case CMU_HFCORECLKDIV_REG: + ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV + & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) + >> _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT); ret = CMU_Log2ToDiv(ret); break; + + case CMU_LFAPRESC0_REG: + switch (clock) + { + case cmuClock_RTC: + ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) + >> _CMU_LFAPRESC0_RTC_SHIFT); + ret = CMU_Log2ToDiv(ret); + break; + +#if defined(_CMU_LFAPRESC0_LETIMER0_MASK) + case cmuClock_LETIMER0: + ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) + >> _CMU_LFAPRESC0_LETIMER0_SHIFT); + ret = CMU_Log2ToDiv(ret); + break; #endif #if defined(_CMU_LFAPRESC0_LCD_MASK) - case cmuClock_LCDpre: - ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >> - _CMU_LFAPRESC0_LCD_SHIFT) + CMU_DivToLog2(cmuClkDiv_16)); - ret = CMU_Log2ToDiv(ret); - break; + case cmuClock_LCDpre: + ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) + >> _CMU_LFAPRESC0_LCD_SHIFT) + + CMU_DivToLog2(cmuClkDiv_16)); + ret = CMU_Log2ToDiv(ret); + break; #endif #if defined(_CMU_LFAPRESC0_LESENSE_MASK) - case cmuClock_LESENSE: - ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) >> - _CMU_LFAPRESC0_LESENSE_SHIFT)); - ret = CMU_Log2ToDiv(ret); + case cmuClock_LESENSE: + ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) + >> _CMU_LFAPRESC0_LESENSE_SHIFT); + ret = CMU_Log2ToDiv(ret); + break; +#endif + + default: + EFM_ASSERT(0); + ret = cmuClkDiv_1; + break; + } break; + + case CMU_LFBPRESC0_REG: + switch (clock) + { +#if defined(_CMU_LFBPRESC0_LEUART0_MASK) + case cmuClock_LEUART0: + ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) + >> _CMU_LFBPRESC0_LEUART0_SHIFT); + ret = CMU_Log2ToDiv(ret); + break; #endif +#if defined(_CMU_LFBPRESC0_LEUART1_MASK) + case cmuClock_LEUART1: + ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) + >> _CMU_LFBPRESC0_LEUART1_SHIFT); + ret = CMU_Log2ToDiv(ret); + break; +#endif + + default: + EFM_ASSERT(0); + ret = cmuClkDiv_1; + break; + } + break; + default: EFM_ASSERT(0); ret = cmuClkDiv_1; break; - } - break; - - case CMU_LFBPRESC0_REG: - switch (clock) - { -#if defined(_CMU_LFBPRESC0_LEUART0_MASK) - case cmuClock_LEUART0: - ret = (CMU_ClkDiv_TypeDef)(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) >> - _CMU_LFBPRESC0_LEUART0_SHIFT)); - ret = CMU_Log2ToDiv(ret); - break; + } + + return ret; #endif - -#if defined(_CMU_LFBPRESC0_LEUART1_MASK) - case cmuClock_LEUART1: - ret = (CMU_ClkDiv_TypeDef)(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) >> - _CMU_LFBPRESC0_LEUART1_SHIFT)); - ret = CMU_Log2ToDiv(ret); - break; -#endif - - default: - EFM_ASSERT(0); - ret = cmuClkDiv_1; - break; - } - break; - - default: - EFM_ASSERT(0); - ret = cmuClkDiv_1; - break; - } - - return(ret); } @@ -816,6 +1140,10 @@ ******************************************************************************/ void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div) { +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + CMU_ClockPrescSet(clock, (CMU_ClkPresc_TypeDef)(div - 1)); + +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) uint32_t freq; uint32_t divReg; @@ -825,186 +1153,189 @@ switch (divReg) { #if defined( _CMU_CTRL_HFCLKDIV_MASK ) - case CMU_HFCLKDIV_REG: - EFM_ASSERT((div>=cmuClkDiv_1) && (div<=cmuClkDiv_8)); - - /* Configure worst case wait states for flash access before setting divisor */ - CMU_FlashWaitStateMax(); - - /* Set divider */ - CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK) | - ((div-1) << _CMU_CTRL_HFCLKDIV_SHIFT); - - /* Update CMSIS core clock variable */ - /* (The function will update the global variable) */ - freq = SystemCoreClockGet(); - - /* Optimize flash access wait state setting for current core clk */ - CMU_FlashWaitStateControl(freq); - break; + case CMU_HFCLKDIV_REG: + EFM_ASSERT((div>=cmuClkDiv_1) && (div<=cmuClkDiv_8)); + + /* Configure worst case wait states for flash access before setting divisor */ + flashWaitStateMax(); + + /* Set divider */ + CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK) + | ((div-1) << _CMU_CTRL_HFCLKDIV_SHIFT); + + /* Update CMSIS core clock variable */ + /* (The function will update the global variable) */ + freq = SystemCoreClockGet(); + + /* Optimize flash access wait state setting for current core clk */ + flashWaitStateControl(freq); + break; #endif - case CMU_HFPERCLKDIV_REG: - EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512)); - /* Convert to correct scale */ - div = CMU_DivToLog2(div); - CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) | - (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT); - break; - - case CMU_HFCORECLKDIV_REG: - EFM_ASSERT(div <= cmuClkDiv_512); - - /* Configure worst case wait states for flash access before setting divisor */ - CMU_FlashWaitStateMax(); + case CMU_HFPERCLKDIV_REG: + EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512)); + /* Convert to correct scale */ + div = CMU_DivToLog2(div); + CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) + | (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT); + break; + + case CMU_HFCORECLKDIV_REG: + EFM_ASSERT(div <= cmuClkDiv_512); + + /* Configure worst case wait states for flash access before setting divisor */ + flashWaitStateMax(); #if defined( CMU_CTRL_HFLE ) - /* Clear HFLE and set DIV2 factor for peripheral clock - when running at frequencies lower than or equal to CMU_MAX_FREQ_HFLE. */ - if ((CMU_ClockFreqGet(cmuClock_HF) / div) <= CMU_MAX_FREQ_HFLE) - { - /* Clear CMU HFLE */ - BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 0); - - /* Set DIV2 factor for peripheral clock */ - BITBAND_Peripheral(&(CMU->HFCORECLKDIV), - _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 0); - } - else - { - /* Set CMU HFLE */ - BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1); - - /* Set DIV4 factor for peripheral clock */ - BITBAND_Peripheral(&(CMU->HFCORECLKDIV), - _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1); - } + /* Clear HFLE and set DIV2 factor for peripheral clock + when running at frequencies lower than or equal to CMU_MAX_FREQ_HFLE. */ + if ((CMU_ClockFreqGet(cmuClock_HF) / div) <= CMU_MAX_FREQ_HFLE()) + { + /* Clear CMU HFLE */ + BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 0); + + /* Set DIV2 factor for peripheral clock */ + BUS_RegBitWrite(&CMU->HFCORECLKDIV, + _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 0); + } + else + { + /* Set CMU HFLE */ + BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1); + + /* Set DIV4 factor for peripheral clock */ + BUS_RegBitWrite(&CMU->HFCORECLKDIV, + _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1); + } #endif - /* Convert to correct scale */ - div = CMU_DivToLog2(div); - - CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) | - (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT); - - /* Update CMSIS core clock variable */ - /* (The function will update the global variable) */ - freq = SystemCoreClockGet(); - - /* Optimize flash access wait state setting for current core clk */ - CMU_FlashWaitStateControl(freq); - break; - - case CMU_LFAPRESC0_REG: - switch (clock) - { - case cmuClock_RTC: - EFM_ASSERT(div <= cmuClkDiv_32768); - - /* LF register about to be modified require sync. busy check */ - CMU_Sync(CMU_SYNCBUSY_LFAPRESC0); - /* Convert to correct scale */ div = CMU_DivToLog2(div); - CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK) | - (div << _CMU_LFAPRESC0_RTC_SHIFT); + CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV + & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) + | (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT); + + /* Update CMSIS core clock variable */ + /* (The function will update the global variable) */ + freq = SystemCoreClockGet(); + + /* Optimize flash access wait state setting for current core clk */ + flashWaitStateControl(freq); break; + case CMU_LFAPRESC0_REG: + switch (clock) + { + case cmuClock_RTC: + EFM_ASSERT(div <= cmuClkDiv_32768); + + /* LF register about to be modified require sync. busy check */ + syncReg(CMU_SYNCBUSY_LFAPRESC0); + + /* Convert to correct scale */ + div = CMU_DivToLog2(div); + + CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK) + | (div << _CMU_LFAPRESC0_RTC_SHIFT); + break; + #if defined(_CMU_LFAPRESC0_LETIMER0_MASK) - case cmuClock_LETIMER0: - EFM_ASSERT(div <= cmuClkDiv_32768); - - /* LF register about to be modified require sync. busy check */ - CMU_Sync(CMU_SYNCBUSY_LFAPRESC0); - - /* Convert to correct scale */ - div = CMU_DivToLog2(div); - - CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK) | - (div << _CMU_LFAPRESC0_LETIMER0_SHIFT); - break; + case cmuClock_LETIMER0: + EFM_ASSERT(div <= cmuClkDiv_32768); + + /* LF register about to be modified require sync. busy check */ + syncReg(CMU_SYNCBUSY_LFAPRESC0); + + /* Convert to correct scale */ + div = CMU_DivToLog2(div); + + CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK) + | (div << _CMU_LFAPRESC0_LETIMER0_SHIFT); + break; #endif #if defined(LCD_PRESENT) - case cmuClock_LCDpre: - EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128)); - - /* LF register about to be modified require sync. busy check */ - CMU_Sync(CMU_SYNCBUSY_LFAPRESC0); - - /* Convert to correct scale */ - div = CMU_DivToLog2(div); - - CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK) | - ((div - CMU_DivToLog2(cmuClkDiv_16)) << _CMU_LFAPRESC0_LCD_SHIFT); - break; + case cmuClock_LCDpre: + EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128)); + + /* LF register about to be modified require sync. busy check */ + syncReg(CMU_SYNCBUSY_LFAPRESC0); + + /* Convert to correct scale */ + div = CMU_DivToLog2(div); + + CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK) + | ((div - CMU_DivToLog2(cmuClkDiv_16)) + << _CMU_LFAPRESC0_LCD_SHIFT); + break; #endif /* defined(LCD_PRESENT) */ #if defined(LESENSE_PRESENT) - case cmuClock_LESENSE: - EFM_ASSERT(div <= cmuClkDiv_8); - - /* LF register about to be modified require sync. busy check */ - CMU_Sync(CMU_SYNCBUSY_LFAPRESC0); - - /* Convert to correct scale */ - div = CMU_DivToLog2(div); - - CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK) | - (div << _CMU_LFAPRESC0_LESENSE_SHIFT); + case cmuClock_LESENSE: + EFM_ASSERT(div <= cmuClkDiv_8); + + /* LF register about to be modified require sync. busy check */ + syncReg(CMU_SYNCBUSY_LFAPRESC0); + + /* Convert to correct scale */ + div = CMU_DivToLog2(div); + + CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK) + | (div << _CMU_LFAPRESC0_LESENSE_SHIFT); + break; +#endif /* defined(LESENSE_PRESENT) */ + + default: + EFM_ASSERT(0); + break; + } break; -#endif /* defined(LESENSE_PRESENT) */ + + case CMU_LFBPRESC0_REG: + switch (clock) + { +#if defined(_CMU_LFBPRESC0_LEUART0_MASK) + case cmuClock_LEUART0: + EFM_ASSERT(div <= cmuClkDiv_8); + + /* LF register about to be modified require sync. busy check */ + syncReg(CMU_SYNCBUSY_LFBPRESC0); + + /* Convert to correct scale */ + div = CMU_DivToLog2(div); + + CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK) + | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT); + break; +#endif + +#if defined(_CMU_LFBPRESC0_LEUART1_MASK) + case cmuClock_LEUART1: + EFM_ASSERT(div <= cmuClkDiv_8); + + /* LF register about to be modified require sync. busy check */ + syncReg(CMU_SYNCBUSY_LFBPRESC0); + + /* Convert to correct scale */ + div = CMU_DivToLog2(div); + + CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK) + | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT); + break; +#endif + + default: + EFM_ASSERT(0); + break; + } + break; default: EFM_ASSERT(0); break; - } - break; - - case CMU_LFBPRESC0_REG: - switch (clock) - { -#if defined(_CMU_LFBPRESC0_LEUART0_MASK) - case cmuClock_LEUART0: - EFM_ASSERT(div <= cmuClkDiv_8); - - /* LF register about to be modified require sync. busy check */ - CMU_Sync(CMU_SYNCBUSY_LFBPRESC0); - - /* Convert to correct scale */ - div = CMU_DivToLog2(div); - - CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK) | - (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT); - break; + } #endif - -#if defined(_CMU_LFBPRESC0_LEUART1_MASK) - case cmuClock_LEUART1: - EFM_ASSERT(div <= cmuClkDiv_8); - - /* LF register about to be modified require sync. busy check */ - CMU_Sync(CMU_SYNCBUSY_LFBPRESC0); - - /* Convert to correct scale */ - div = CMU_DivToLog2(div); - - CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK) | - (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT); - break; -#endif - - default: - EFM_ASSERT(0); - break; - } - break; - - default: - EFM_ASSERT(0); - break; - } } @@ -1044,56 +1375,84 @@ /* Identify enable register */ switch ((clock >> CMU_EN_REG_POS) & CMU_EN_REG_MASK) { - case CMU_HFPERCLKDIV_EN_REG: - reg = &(CMU->HFPERCLKDIV); - break; - - case CMU_HFPERCLKEN0_EN_REG: - reg = &(CMU->HFPERCLKEN0); - break; - - case CMU_HFCORECLKEN0_EN_REG: - reg = &(CMU->HFCORECLKEN0); - +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + case CMU_CTRL_EN_REG: + reg = &CMU->CTRL; + break; +#endif + +#if defined( _SILICON_LABS_32B_PLATFORM_1 ) + case CMU_HFCORECLKEN0_EN_REG: + reg = &CMU->HFCORECLKEN0; #if defined( CMU_CTRL_HFLE ) - /* Set HFLE and DIV4 factor for peripheral clock when - running at frequencies higher than or equal to CMU_MAX_FREQ_HFLE. */ - if ( CMU_ClockFreqGet(cmuClock_CORE) > CMU_MAX_FREQ_HFLE ) - { - /* Enable CMU HFLE */ - BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1); - - /* Set DIV4 factor for peripheral clock */ - BITBAND_Peripheral(&(CMU->HFCORECLKDIV), - _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1); - } + /* Set HFLE and DIV4 factor for peripheral clock when + running at frequencies higher than or equal to CMU_MAX_FREQ_HFLE. */ + if ( CMU_ClockFreqGet(cmuClock_CORE) > CMU_MAX_FREQ_HFLE()) + { + /* Enable CMU HFLE */ + BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1); + + /* Set DIV4 factor for peripheral clock */ + BUS_RegBitWrite(&CMU->HFCORECLKDIV, + _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1); + } +#endif + break; +#endif + +#if defined( _CMU_HFBUSCLKEN0_MASK ) + case CMU_HFBUSCLKEN0_EN_REG: + reg = &CMU->HFBUSCLKEN0; + break; #endif - break; - - case CMU_LFACLKEN0_EN_REG: - reg = &(CMU->LFACLKEN0); - sync = CMU_SYNCBUSY_LFACLKEN0; - break; - - case CMU_LFBCLKEN0_EN_REG: - reg = &(CMU->LFBCLKEN0); - sync = CMU_SYNCBUSY_LFBCLKEN0; - break; - - case CMU_PCNT_EN_REG: - reg = &(CMU->PCNTCTRL); - break; + +#if defined( _CMU_HFRADIOCLKEN0_MASK ) + case CMU_HFRADIOCLKEN0_EN_REG: + reg = &CMU->HFRADIOCLKEN0; + break; +#endif + +#if defined( _CMU_HFPERCLKDIV_MASK ) + case CMU_HFPERCLKDIV_EN_REG: + reg = &CMU->HFPERCLKDIV; + break; +#endif + + case CMU_HFPERCLKEN0_EN_REG: + reg = &CMU->HFPERCLKEN0; + break; + + case CMU_LFACLKEN0_EN_REG: + reg = &CMU->LFACLKEN0; + sync = CMU_SYNCBUSY_LFACLKEN0; + break; + + case CMU_LFBCLKEN0_EN_REG: + reg = &CMU->LFBCLKEN0; + sync = CMU_SYNCBUSY_LFBCLKEN0; + break; #if defined( _CMU_LFCCLKEN0_MASK ) - case CMU_LFCCLKEN0_EN_REG: - reg = &(CMU->LFCCLKEN0); - sync = CMU_SYNCBUSY_LFCCLKEN0; - break; + case CMU_LFCCLKEN0_EN_REG: + reg = &CMU->LFCCLKEN0; + sync = CMU_SYNCBUSY_LFCCLKEN0; + break; #endif - default: /* Cannot enable/disable clock point */ - EFM_ASSERT(0); - return; +#if defined( _CMU_LFECLKEN0_MASK ) + case CMU_LFECLKEN0_EN_REG: + reg = &CMU->LFECLKEN0; + sync = CMU_SYNCBUSY_LFECLKEN0; + break; +#endif + + case CMU_PCNT_EN_REG: + reg = &CMU->PCNTCTRL; + break; + + default: /* Cannot enable/disable clock point */ + EFM_ASSERT(0); + return; } /* Get bit position used to enable/disable */ @@ -1102,11 +1461,11 @@ /* LF synchronization required? */ if (sync) { - CMU_Sync(sync); + syncReg(sync); } /* Set/clear bit as requested */ - BITBAND_Peripheral(reg, bit, (unsigned int)enable); + BUS_RegBitWrite(reg, bit, enable); } @@ -1127,150 +1486,545 @@ switch(clock & (CMU_CLK_BRANCH_MASK << CMU_CLK_BRANCH_POS)) { case (CMU_HF_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { ret = SystemHFClockGet(); #if defined( _CMU_CTRL_HFCLKDIV_MASK ) - /* Giant Gecko has an additional divider, not used by USBC */ - ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >> - _CMU_CTRL_HFCLKDIV_SHIFT)); + /* Family with an additional divider. */ + ret = ret / (1U + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) + >> _CMU_CTRL_HFCLKDIV_SHIFT)); +#endif +#if defined( _CMU_HFPRESC_MASK ) + ret = ret / (1U + ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK) + >> _CMU_HFPRESC_PRESC_SHIFT)); +#endif + break; + + case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS): + ret = SystemHFClockGet(); +#if defined( _SILICON_LABS_32B_PLATFORM_1 ) +#if defined( _CMU_CTRL_HFCLKDIV_MASK ) + /* Family with an additional divider. */ + ret = ret / (1U + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) + >> _CMU_CTRL_HFCLKDIV_SHIFT)); +#endif + ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) + >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT; +#elif defined( _SILICON_LABS_32B_PLATFORM_2 ) + ret /= 1U + ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK) + >> _CMU_HFPERPRESC_PRESC_SHIFT); #endif - } break; - -#if defined(_CMU_HFPERCLKEN0_USART0_MASK) || \ - defined(_CMU_HFPERCLKEN0_USART1_MASK) || \ - defined(_CMU_HFPERCLKEN0_USART2_MASK) || \ - defined(_CMU_HFPERCLKEN0_UART0_MASK) || \ - defined(_CMU_HFPERCLKEN0_UART1_MASK) || \ - defined(_CMU_HFPERCLKEN0_TIMER0_MASK) || \ - defined(_CMU_HFPERCLKEN0_TIMER1_MASK) || \ - defined(_CMU_HFPERCLKEN0_TIMER2_MASK) || \ - defined(_CMU_HFPERCLKEN0_TIMER3_MASK) || \ - defined(_CMU_HFPERCLKEN0_ACMP0_MASK) || \ - defined(_CMU_HFPERCLKEN0_ACMP1_MASK) || \ - defined(_CMU_HFPERCLKEN0_DAC0_MASK) || \ - defined(_CMU_HFPERCLKEN0_IDAC0_MASK) || \ - defined(_CMU_HFPERCLKEN0_ADC0_MASK) || \ - defined(_CMU_HFPERCLKEN0_I2C0_MASK) || \ - defined(_CMU_HFPERCLKEN0_I2C1_MASK) || \ - defined(PRS_PRESENT) || \ - defined(VCMP_PRESENT)|| \ - defined(GPIO_PRESENT) - case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = SystemHFClockGet(); -#if defined( _CMU_CTRL_HFCLKDIV_MASK ) - /* Leopard/Giant Gecko has an additional divider */ - ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >> - _CMU_CTRL_HFCLKDIV_SHIFT)); + break; + +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) +#if defined( _CMU_HFRADIOPRESC_PRESC_MASK ) + case (CMU_HFRADIO_CLK_BRANCH << CMU_CLK_BRANCH_POS): + ret = SystemHFClockGet(); + ret /= 1U + ((CMU->HFRADIOPRESC & _CMU_HFRADIOPRESC_PRESC_MASK) + >> _CMU_HFRADIOPRESC_PRESC_SHIFT); + break; +#endif + +#if defined( CRYPTO_PRESENT ) \ + || defined( LDMA_PRESENT ) \ + || defined( GPCRC_PRESENT ) \ + || defined( PRS_PRESENT ) \ + || defined( GPIO_PRESENT ) + case (CMU_HFBUS_CLK_BRANCH << CMU_CLK_BRANCH_POS): + ret = SystemHFClockGet(); + break; #endif - ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >> - _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT; - } break; + + case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS): + ret = SystemHFClockGet(); + ret /= 1U + ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK) + >> _CMU_HFCOREPRESC_PRESC_SHIFT); + break; + + case (CMU_HFEXP_CLK_BRANCH << CMU_CLK_BRANCH_POS): + ret = SystemHFClockGet(); + ret /= 1U + ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK) + >> _CMU_HFEXPPRESC_PRESC_SHIFT); + break; #endif -#if defined(AES_PRESENT) || \ - defined(DMA_PRESENT) || \ - defined(EBI_PRESENT) || \ - defined(USB_PRESENT) +#if defined( _SILICON_LABS_32B_PLATFORM_1 ) +#if defined(AES_PRESENT) \ + || defined(DMA_PRESENT) \ + || defined(EBI_PRESENT) \ + || defined(USB_PRESENT) case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS): { ret = SystemCoreClockGet(); } break; #endif +#endif case (CMU_LFA_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFA); - } break; -#if defined(_CMU_LFACLKEN0_RTC_MASK) + ret = lfClkGet(cmuClock_LFA); + break; + +#if defined( _CMU_LFACLKEN0_RTC_MASK ) case (CMU_RTC_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFA); - ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) >> - _CMU_LFAPRESC0_RTC_SHIFT; - } break; + ret = lfClkGet(cmuClock_LFA); + ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) + >> _CMU_LFAPRESC0_RTC_SHIFT; + break; +#endif + +#if defined( _CMU_LFECLKEN0_RTCC_MASK ) + case (CMU_RTCC_CLK_BRANCH << CMU_CLK_BRANCH_POS): + ret = lfClkGet(cmuClock_LFE); + break; #endif -#if defined(_CMU_LFACLKEN0_LETIMER0_MASK) - case (CMU_LETIMER_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFA); - ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) >> - _CMU_LFAPRESC0_LETIMER0_SHIFT; - } break; + +#if defined( _CMU_LFACLKEN0_LETIMER0_MASK ) + case (CMU_LETIMER0_CLK_BRANCH << CMU_CLK_BRANCH_POS): + ret = lfClkGet(cmuClock_LFA); +#if defined( _SILICON_LABS_32B_PLATFORM_1 ) + ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) + >> _CMU_LFAPRESC0_LETIMER0_SHIFT; +#elif defined( _SILICON_LABS_32B_PLATFORM_2 ) + ret /= CMU_Log2ToDiv((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) + >> _CMU_LFAPRESC0_LETIMER0_SHIFT); #endif + break; +#endif + #if defined(_CMU_LFACLKEN0_LCD_MASK) case (CMU_LCDPRE_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFA); - ret >>= ((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >> - _CMU_LFAPRESC0_LCD_SHIFT) + CMU_DivToLog2(cmuClkDiv_16); - } break; + ret = lfClkGet(cmuClock_LFA); + ret >>= ((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) + >> _CMU_LFAPRESC0_LCD_SHIFT) + + CMU_DivToLog2(cmuClkDiv_16); + break; case (CMU_LCD_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFA); - ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >> - _CMU_LFAPRESC0_LCD_SHIFT; - ret /= (1 + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> - _CMU_LCDCTRL_FDIV_SHIFT)); - } break; + ret = lfClkGet(cmuClock_LFA); + ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) + >> _CMU_LFAPRESC0_LCD_SHIFT; + ret /= 1U + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) + >> _CMU_LCDCTRL_FDIV_SHIFT); + break; #endif + #if defined(_CMU_LFACLKEN0_LESENSE_MASK) case (CMU_LESENSE_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFA); - ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) >> - _CMU_LFAPRESC0_LESENSE_SHIFT; - } break; + ret = lfClkGet(cmuClock_LFA); + ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) + >> _CMU_LFAPRESC0_LESENSE_SHIFT; + break; #endif + case (CMU_LFB_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFB); - } break; -#if defined(_CMU_LFBCLKEN0_LEUART0_MASK) + ret = lfClkGet(cmuClock_LFB); + break; + +#if defined( _CMU_LFBCLKEN0_LEUART0_MASK ) case (CMU_LEUART0_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFB); - ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) >> - _CMU_LFBPRESC0_LEUART0_SHIFT; - } break; + ret = lfClkGet(cmuClock_LFB); +#if defined( _SILICON_LABS_32B_PLATFORM_1 ) + ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) + >> _CMU_LFBPRESC0_LEUART0_SHIFT; +#elif defined( _SILICON_LABS_32B_PLATFORM_2 ) + ret /= CMU_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) + >> _CMU_LFBPRESC0_LEUART0_SHIFT); +#endif + break; #endif -#if defined(_CMU_LFBCLKEN0_LEUART1_MASK) + +#if defined( _CMU_LFBCLKEN0_LEUART1_MASK ) case (CMU_LEUART1_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_LFClkGet(CMU_LFB); - ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) >> - _CMU_LFBPRESC0_LEUART1_SHIFT; - } break; + ret = lfClkGet(cmuClock_LFB); +#if defined( _SILICON_LABS_32B_PLATFORM_1 ) + ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) + >> _CMU_LFBPRESC0_LEUART1_SHIFT; +#elif defined( _SILICON_LABS_32B_PLATFORM_2 ) + ret /= CMU_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) + >> _CMU_LFBPRESC0_LEUART1_SHIFT); +#endif + break; +#endif + +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + case (CMU_LFE_CLK_BRANCH << CMU_CLK_BRANCH_POS): + ret = lfClkGet(cmuClock_LFE); + break; #endif case (CMU_DBG_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_DBGClkGet(); - } break; + ret = dbgClkGet(); + break; case (CMU_AUX_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_AUXClkGet(); - } break; + ret = auxClkGet(); + break; #if defined(USB_PRESENT) case (CMU_USBC_CLK_BRANCH << CMU_CLK_BRANCH_POS): - { - ret = CMU_USBCClkGet(); - } break; + ret = usbCClkGet(); + break; #endif + default: - { EFM_ASSERT(0); ret = 0; - } break; + break; } + + return ret; +} + + +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) +/***************************************************************************//** + * @brief + * Get clock prescaler. + * + * @param[in] clock + * Clock point to get the prescaler for. Notice that not all clock points + * have a prescaler. Please refer to CMU overview in reference manual. + * + * @return + * The prescaler value of the current clock point. 0 is returned + * if @p clock specifies a clock point without a prescaler. + ******************************************************************************/ +uint32_t CMU_ClockPrescGet(CMU_Clock_TypeDef clock) +{ + uint32_t prescReg; + uint32_t ret; + + /* Get prescaler register id. */ + prescReg = (clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK; + + switch (prescReg) + { + case CMU_HFPRESC_REG: + ret = ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK) + >> _CMU_HFPRESC_PRESC_SHIFT); + break; + + case CMU_HFEXPPRESC_REG: + ret = ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK) + >> _CMU_HFEXPPRESC_PRESC_SHIFT); + break; + + case CMU_HFCLKLEPRESC_REG: + ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK) + >> _CMU_HFPRESC_HFCLKLEPRESC_SHIFT); + break; + + case CMU_HFPERPRESC_REG: + ret = ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK) + >> _CMU_HFPERPRESC_PRESC_SHIFT); + break; + +#if defined( _CMU_HFRADIOPRESC_PRESC_MASK ) + case CMU_HFRADIOPRESC_REG: + ret = ((CMU->HFRADIOPRESC & _CMU_HFRADIOPRESC_PRESC_MASK) + >> _CMU_HFRADIOPRESC_PRESC_SHIFT); + break; +#endif + + case CMU_HFCOREPRESC_REG: + ret = ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK) + >> _CMU_HFCOREPRESC_PRESC_SHIFT); + break; + + case CMU_LFAPRESC0_REG: + switch (clock) + { +#if defined( _CMU_LFAPRESC0_LETIMER0_MASK ) + case cmuClock_LETIMER0: + ret = (((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) + >> _CMU_LFAPRESC0_LETIMER0_SHIFT)); + /* Convert the exponent to prescaler value. */ + ret = CMU_Log2ToDiv(ret) - 1U; + break; +#endif + + default: + EFM_ASSERT(0); + ret = 0U; + break; + } + break; + + case CMU_LFBPRESC0_REG: + switch (clock) + { +#if defined( _CMU_LFBPRESC0_LEUART0_MASK ) + case cmuClock_LEUART0: + ret = (((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) + >> _CMU_LFBPRESC0_LEUART0_SHIFT)); + /* Convert the exponent to prescaler value. */ + ret = CMU_Log2ToDiv(ret) - 1U; + break; +#endif + +#if defined( _CMU_LFBPRESC0_LEUART1_MASK ) + case cmuClock_LEUART1: + ret = (((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) + >> _CMU_LFBPRESC0_LEUART1_SHIFT)); + /* Convert the exponent to prescaler value. */ + ret = CMU_Log2ToDiv(ret) - 1U; + break; +#endif + + default: + EFM_ASSERT(0); + ret = 0U; + break; + } + break; + + case CMU_LFEPRESC0_REG: + switch (clock) + { +#if defined( RTCC_PRESENT ) + case cmuClock_RTCC: + /* No need to compute with LFEPRESC0_RTCC - DIV1 is the only */ + /* allowed value. Convert the exponent to prescaler value. */ + ret = _CMU_LFEPRESC0_RTCC_DIV1; + break; + + default: + EFM_ASSERT(0); + ret = 0U; + break; +#endif + } + break; + + default: + EFM_ASSERT(0); + ret = 0U; + break; + } + return ret; } - - -/**************************************************************************//** +#endif + + +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) +/***************************************************************************//** + * @brief + * Set clock prescaler. + * + * @note + * If setting a LF clock prescaler, synchronization into the low frequency + * domain is required. If the same register is modified before a previous + * update has completed, this function will stall until the previous + * synchronization has completed. Please refer to CMU_FreezeEnable() for + * a suggestion on how to reduce stalling time in some use cases. + * + * @param[in] clock + * Clock point to set prescaler for. Notice that not all clock points + * have a prescaler, please refer to CMU overview in the reference manual. + * + * @param[in] presc + * The clock prescaler to use. + ******************************************************************************/ +void CMU_ClockPrescSet(CMU_Clock_TypeDef clock, CMU_ClkPresc_TypeDef presc) +{ + uint32_t freq; + uint32_t prescReg; + + /* Get divisor reg id */ + prescReg = (clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK; + + switch (prescReg) + { + case CMU_HFPRESC_REG: + EFM_ASSERT(presc < 32U); + + CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_PRESC_MASK) + | (presc << _CMU_HFPRESC_PRESC_SHIFT); + break; + + case CMU_HFEXPPRESC_REG: + EFM_ASSERT(presc < 32U); + + CMU->HFEXPPRESC = (CMU->HFEXPPRESC & ~_CMU_HFEXPPRESC_PRESC_MASK) + | (presc << _CMU_HFEXPPRESC_PRESC_SHIFT); + break; + + case CMU_HFCLKLEPRESC_REG: + EFM_ASSERT(presc < 2U); + + /* Specifies the clock divider for HFCLKLE. When running at frequencies + * higher than 32 MHz, this must be set to DIV4. */ + CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_HFCLKLEPRESC_MASK) + | (presc << _CMU_HFPRESC_HFCLKLEPRESC_SHIFT); + break; + + case CMU_HFPERPRESC_REG: + EFM_ASSERT(presc < 512U); + + CMU->HFPERPRESC = (CMU->HFPERPRESC & ~_CMU_HFPERPRESC_PRESC_MASK) + | (presc << _CMU_HFPERPRESC_PRESC_SHIFT); + break; + +#if defined( _CMU_HFRADIOPRESC_PRESC_MASK ) + case CMU_HFRADIOPRESC_REG: + EFM_ASSERT(presc < 512U); + + CMU->HFRADIOPRESC = (CMU->HFRADIOPRESC & ~_CMU_HFRADIOPRESC_PRESC_MASK) + | (presc << _CMU_HFRADIOPRESC_PRESC_SHIFT); + break; +#endif + + case CMU_HFCOREPRESC_REG: + EFM_ASSERT(presc < 512U); + + /* Configure worst case wait states for flash access before setting + * the prescaler. */ + flashWaitStateControl(CMU_MAX_FREQ_0WS + 1); + + CMU->HFCOREPRESC = (CMU->HFCOREPRESC & ~_CMU_HFCOREPRESC_PRESC_MASK) + | (presc << _CMU_HFCOREPRESC_PRESC_SHIFT); + + /* Update CMSIS core clock variable */ + /* (The function will update the global variable) */ + freq = SystemCoreClockGet(); + + /* Optimize flash access wait state setting for current core clk */ + flashWaitStateControl(freq); + break; + + case CMU_LFAPRESC0_REG: + switch (clock) + { +#if defined( RTC_PRESENT ) + case cmuClock_RTC: + EFM_ASSERT(presc <= 32768U); + + /* Convert prescaler value to DIV exponent scale. */ + presc = CMU_PrescToLog2(presc); + + /* LF register about to be modified require sync. Busy check. */ + syncReg(CMU_SYNCBUSY_LFAPRESC0); + + CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK) + | (presc << _CMU_LFAPRESC0_RTC_SHIFT); + break; +#endif + +#if defined( RTCC_PRESENT ) + case cmuClock_RTCC: +#if defined( _CMU_LFEPRESC0_RTCC_MASK ) + /* DIV1 is the only accepted value. */ + EFM_ASSERT(presc <= 0U); + + /* LF register about to be modified require sync. Busy check.. */ + syncReg(CMU_SYNCBUSY_LFEPRESC0); + + CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK) + | (presc << _CMU_LFEPRESC0_RTCC_SHIFT); +#else + EFM_ASSERT(presc <= 32768U); + + /* Convert prescaler value to DIV exponent scale. */ + presc = CMU_PrescToLog2(presc); + + /* LF register about to be modified require sync. Busy check. */ + syncReg(CMU_SYNCBUSY_LFAPRESC0); + + CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTCC_MASK) + | (presc << _CMU_LFAPRESC0_RTCC_SHIFT); +#endif + break; +#endif + +#if defined( _CMU_LFAPRESC0_LETIMER0_MASK ) + case cmuClock_LETIMER0: + EFM_ASSERT(presc <= 32768U); + + /* Convert prescaler value to DIV exponent scale. */ + presc = CMU_PrescToLog2(presc); + + /* LF register about to be modified require sync. Busy check. */ + syncReg(CMU_SYNCBUSY_LFAPRESC0); + + CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK) + | (presc << _CMU_LFAPRESC0_LETIMER0_SHIFT); + break; +#endif + + default: + EFM_ASSERT(0); + break; + } + break; + + case CMU_LFBPRESC0_REG: + switch (clock) + { +#if defined( _CMU_LFBPRESC0_LEUART0_MASK ) + case cmuClock_LEUART0: + EFM_ASSERT(presc <= 8U); + + /* Convert prescaler value to DIV exponent scale. */ + presc = CMU_PrescToLog2(presc); + + /* LF register about to be modified require sync. Busy check. */ + syncReg(CMU_SYNCBUSY_LFBPRESC0); + + CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK) + | (presc << _CMU_LFBPRESC0_LEUART0_SHIFT); + break; +#endif + +#if defined( _CMU_LFBPRESC0_LEUART1_MASK ) + case cmuClock_LEUART1: + EFM_ASSERT(presc <= 8U); + + /* Convert prescaler value to DIV exponent scale. */ + presc = CMU_PrescToLog2(presc); + + /* LF register about to be modified require sync. Busy check. */ + syncReg(CMU_SYNCBUSY_LFBPRESC0); + + CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK) + | (presc << _CMU_LFBPRESC0_LEUART1_SHIFT); + break; +#endif + + default: + EFM_ASSERT(0); + break; + } + break; + + case CMU_LFEPRESC0_REG: + switch (clock) + { +#if defined( _CMU_LFEPRESC0_RTCC_MASK ) + case cmuClock_RTCC: + EFM_ASSERT(presc <= 0U); + + /* LF register about to be modified require sync. Busy check. */ + syncReg(CMU_SYNCBUSY_LFEPRESC0); + + CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK) + | (presc << _CMU_LFEPRESC0_RTCC_SHIFT); + break; +#endif + + default: + EFM_ASSERT(0); + break; + } + break; + + default: + EFM_ASSERT(0); + break; + } +} +#endif + + +/***************************************************************************//** * @brief * Get currently selected reference clock used for a clock branch. * @@ -1278,7 +2032,11 @@ * Clock branch to fetch selected ref. clock for. One of: * @li #cmuClock_HF * @li #cmuClock_LFA - * @li #cmuClock_LFB + * @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO + * @li #cmuClock_LFC + * @endif @if _SILICON_LABS_32B_PLATFORM_2 + * @li #cmuClock_LFE + * @endif * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT * @li #cmuClock_USBC * @endif @@ -1286,216 +2044,326 @@ * @return * Reference clock used for clocking selected branch, #cmuSelect_Error if * invalid @p clock provided. - *****************************************************************************/ + ******************************************************************************/ CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock) { CMU_Select_TypeDef ret = cmuSelect_Disabled; - uint32_t selReg; - uint32_t statusClkSelMask; - - statusClkSelMask = - (CMU_STATUS_HFRCOSEL | - CMU_STATUS_HFXOSEL | - CMU_STATUS_LFRCOSEL | -#if defined( CMU_STATUS_USHFRCODIV2SEL ) - CMU_STATUS_USHFRCODIV2SEL | -#endif - CMU_STATUS_LFXOSEL); + uint32_t selReg; selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK; switch (selReg) { - case CMU_HFCLKSEL_REG: - switch (CMU->STATUS & statusClkSelMask) - { - case CMU_STATUS_LFXOSEL: - ret = cmuSelect_LFXO; - break; - - case CMU_STATUS_LFRCOSEL: - ret = cmuSelect_LFRCO; - break; - - case CMU_STATUS_HFXOSEL: - ret = cmuSelect_HFXO; - break; + case CMU_HFCLKSEL_REG: +#if defined( _CMU_HFCLKSEL_HF_MASK ) + switch (CMU->HFCLKSEL & _CMU_HFCLKSEL_HF_MASK) + { + case CMU_HFCLKSEL_HF_LFXO: + ret = cmuSelect_LFXO; + break; + + case CMU_HFCLKSEL_HF_LFRCO: + ret = cmuSelect_LFRCO; + break; + + case CMU_HFCLKSEL_HF_HFXO: + ret = cmuSelect_HFXO; + break; + + default: + ret = cmuSelect_HFRCO; + break; + } +#else + switch (CMU->STATUS + & (CMU_STATUS_HFRCOSEL + | CMU_STATUS_HFXOSEL + | CMU_STATUS_LFRCOSEL +#if defined( CMU_STATUS_USHFRCODIV2SEL ) + | CMU_STATUS_USHFRCODIV2SEL +#endif + | CMU_STATUS_LFXOSEL)) + { + case CMU_STATUS_LFXOSEL: + ret = cmuSelect_LFXO; + break; + + case CMU_STATUS_LFRCOSEL: + ret = cmuSelect_LFRCO; + break; + + case CMU_STATUS_HFXOSEL: + ret = cmuSelect_HFXO; + break; #if defined( CMU_STATUS_USHFRCODIV2SEL ) - case CMU_STATUS_USHFRCODIV2SEL: - ret = cmuSelect_USHFRCODIV2; + case CMU_STATUS_USHFRCODIV2SEL: + ret = cmuSelect_USHFRCODIV2; + break; +#endif + + default: + ret = cmuSelect_HFRCO; + break; + } +#endif + break; + + case CMU_LFACLKSEL_REG: +#if defined( _CMU_LFCLKSEL_MASK ) + switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK) + { + case CMU_LFCLKSEL_LFA_LFRCO: + ret = cmuSelect_LFRCO; + break; + + case CMU_LFCLKSEL_LFA_LFXO: + ret = cmuSelect_LFXO; + break; + +#if defined( CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2 ) + case CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2: + ret = cmuSelect_CORELEDIV2; + break; +#endif + + default: +#if defined( CMU_LFCLKSEL_LFAE ) + if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK) + { + ret = cmuSelect_ULFRCO; + break; + } +#else + ret = cmuSelect_Disabled; +#endif + break; + } +#endif /* _CMU_LFCLKSEL_MASK */ + +#if defined( _CMU_LFACLKSEL_MASK ) + switch (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK) + { + case CMU_LFACLKSEL_LFA_LFRCO: + ret = cmuSelect_LFRCO; + break; + + case CMU_LFACLKSEL_LFA_LFXO: + ret = cmuSelect_LFXO; + break; + + case CMU_LFACLKSEL_LFA_ULFRCO: + ret = cmuSelect_ULFRCO; + break; + +#if defined( _CMU_LFACLKSEL_LFA_HFCLKLE ) + case CMU_LFACLKSEL_LFA_HFCLKLE: + ret = cmuSelect_HFCLKLE; + break; +#endif + + default: + ret = cmuSelect_Disabled; + break; + } +#endif + break; + + case CMU_LFBCLKSEL_REG: +#if defined( _CMU_LFCLKSEL_MASK ) + switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK) + { + case CMU_LFCLKSEL_LFB_LFRCO: + ret = cmuSelect_LFRCO; + break; + + case CMU_LFCLKSEL_LFB_LFXO: + ret = cmuSelect_LFXO; + break; + +#if defined( CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2 ) + case CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2: + ret = cmuSelect_CORELEDIV2; + break; +#endif + +#if defined( CMU_LFCLKSEL_LFB_HFCLKLE ) + case CMU_LFCLKSEL_LFB_HFCLKLE: + ret = cmuSelect_HFCLKLE; + break; +#endif + + default: +#if defined( CMU_LFCLKSEL_LFBE ) + if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK) + { + ret = cmuSelect_ULFRCO; + break; + } +#else + ret = cmuSelect_Disabled; +#endif + break; + } +#endif /* _CMU_LFCLKSEL_MASK */ + +#if defined( _CMU_LFBCLKSEL_MASK ) + switch (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK) + { + case CMU_LFBCLKSEL_LFB_LFRCO: + ret = cmuSelect_LFRCO; + break; + + case CMU_LFBCLKSEL_LFB_LFXO: + ret = cmuSelect_LFXO; + break; + + case CMU_LFBCLKSEL_LFB_ULFRCO: + ret = cmuSelect_ULFRCO; + break; + + case CMU_LFBCLKSEL_LFB_HFCLKLE: + ret = cmuSelect_HFCLKLE; + break; + + default: + ret = cmuSelect_Disabled; + break; + } +#endif + break; + +#if defined( _CMU_LFCLKSEL_LFC_MASK ) + case CMU_LFCCLKSEL_REG: + switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK) + { + case CMU_LFCLKSEL_LFC_LFRCO: + ret = cmuSelect_LFRCO; + break; + + case CMU_LFCLKSEL_LFC_LFXO: + ret = cmuSelect_LFXO; + break; + + default: + ret = cmuSelect_Disabled; + break; + } + break; +#endif + +#if defined( _CMU_LFECLKSEL_LFE_MASK ) + case CMU_LFECLKSEL_REG: + switch (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK) + { + case CMU_LFECLKSEL_LFE_LFRCO: + ret = cmuSelect_LFRCO; + break; + + case CMU_LFECLKSEL_LFE_LFXO: + ret = cmuSelect_LFXO; + break; + + case CMU_LFECLKSEL_LFE_ULFRCO: + ret = cmuSelect_ULFRCO; + break; + +#if defined ( _CMU_LFECLKSEL_LFE_HFCLKLE ) + case CMU_LFECLKSEL_LFE_HFCLKLE: + ret = cmuSelect_HFCLKLE; + break; +#endif + + default: + ret = cmuSelect_Disabled; + break; + } + break; +#endif /* CMU_LFECLKSEL_REG */ + + case CMU_DBGCLKSEL_REG: +#if defined( _CMU_DBGCLKSEL_DBG_MASK ) + switch (CMU->DBGCLKSEL & _CMU_DBGCLKSEL_DBG_MASK) + { + case CMU_DBGCLKSEL_DBG_HFCLK: + ret = cmuSelect_HFCLK; + break; + + case CMU_DBGCLKSEL_DBG_AUXHFRCO: + ret = cmuSelect_AUXHFRCO; + break; + } +#else + ret = cmuSelect_AUXHFRCO; +#endif /* CMU_DBGCLKSEL_DBG */ + +#if defined( _CMU_CTRL_DBGCLK_MASK ) + switch(CMU->CTRL & _CMU_CTRL_DBGCLK_MASK) + { + case CMU_CTRL_DBGCLK_AUXHFRCO: + ret = cmuSelect_AUXHFRCO; + break; + + case CMU_CTRL_DBGCLK_HFCLK: + ret = cmuSelect_HFCLK; + break; + } +#else + ret = cmuSelect_AUXHFRCO; +#endif + break; + + +#if defined( USB_PRESENT ) + case CMU_USBCCLKSEL_REG: + switch (CMU->STATUS + & (CMU_STATUS_USBCLFXOSEL +#if defined(_CMU_STATUS_USBCHFCLKSEL_MASK) + | CMU_STATUS_USBCHFCLKSEL +#endif +#if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK) + | CMU_STATUS_USBCUSHFRCOSEL +#endif + | CMU_STATUS_USBCLFRCOSEL)) + { +#if defined(_CMU_STATUS_USBCHFCLKSEL_MASK) + case CMU_STATUS_USBCHFCLKSEL: + ret = cmuSelect_HFCLK; + break; +#endif + +#if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK) + case CMU_STATUS_USBCUSHFRCOSEL: + ret = cmuSelect_USHFRCO; + break; +#endif + + case CMU_STATUS_USBCLFXOSEL: + ret = cmuSelect_LFXO; + break; + + case CMU_STATUS_USBCLFRCOSEL: + ret = cmuSelect_LFRCO; + break; + + default: + ret = cmuSelect_Disabled; + break; + } break; #endif default: - ret = cmuSelect_HFRCO; - break; - } - break; - - case CMU_LFACLKSEL_REG: - switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK) - { - case CMU_LFCLKSEL_LFA_LFRCO: - ret = cmuSelect_LFRCO; - break; - - case CMU_LFCLKSEL_LFA_LFXO: - ret = cmuSelect_LFXO; - break; - - case CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2: - ret = cmuSelect_CORELEDIV2; - break; - - default: -#if defined( CMU_LFCLKSEL_LFAE ) - if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK) - { - ret = cmuSelect_ULFRCO; - break; - } -#else - ret = cmuSelect_Disabled; -#endif - break; - } - break; - - case CMU_LFBCLKSEL_REG: - switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK) - { - case CMU_LFCLKSEL_LFB_LFRCO: - ret = cmuSelect_LFRCO; - break; - - case CMU_LFCLKSEL_LFB_LFXO: - ret = cmuSelect_LFXO; - break; - - case CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2: - ret = cmuSelect_CORELEDIV2; - break; - - default: -#if defined( CMU_LFCLKSEL_LFBE ) - if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK) - { - ret = cmuSelect_ULFRCO; - break; - } -#else - ret = cmuSelect_Disabled; -#endif - break; - } - break; - -#if defined( _CMU_LFCLKSEL_LFC_MASK ) - case CMU_LFCCLKSEL_REG: - switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK) - { - case CMU_LFCLKSEL_LFC_LFRCO: - ret = cmuSelect_LFRCO; - break; - - case CMU_LFCLKSEL_LFC_LFXO: - ret = cmuSelect_LFXO; - break; - - default: - ret = cmuSelect_Disabled; + EFM_ASSERT(0); + ret = cmuSelect_Error; break; - } - break; -#endif - - case CMU_DBGCLKSEL_REG: - -#if defined( _CMU_DBGCLKSEL_DBG_MASK ) - switch (CMU->DBGCLKSEL & _CMU_DBGCLKSEL_DBG_MASK) - { - case CMU_DBGCLKSEL_DBG_HFCLK: - ret = cmuSelect_HFCLK; - break; - - case CMU_DBGCLKSEL_DBG_AUXHFRCO: - ret = cmuSelect_AUXHFRCO; - break; - } -#else - ret = cmuSelect_AUXHFRCO; -#endif /* CMU_DBGCLKSEL_DBG */ - -#if defined( _CMU_CTRL_DBGCLK_MASK ) - switch(CMU->CTRL & _CMU_CTRL_DBGCLK_MASK) - { - case CMU_CTRL_DBGCLK_AUXHFRCO: - ret = cmuSelect_AUXHFRCO; - break; - - case CMU_CTRL_DBGCLK_HFCLK: - ret = cmuSelect_HFCLK; - break; - } -#else - ret = cmuSelect_AUXHFRCO; -#endif - break; - - -#if defined(USB_PRESENT) - - case CMU_USBCCLKSEL_REG: - switch(CMU->STATUS & - (CMU_STATUS_USBCLFXOSEL | -#if defined(_CMU_STATUS_USBCHFCLKSEL_MASK) - CMU_STATUS_USBCHFCLKSEL | -#endif -#if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK) - CMU_STATUS_USBCUSHFRCOSEL | -#endif - CMU_STATUS_USBCLFRCOSEL)) - { - - case CMU_STATUS_USBCLFXOSEL: - ret = cmuSelect_LFXO; - break; - - case CMU_STATUS_USBCLFRCOSEL: - ret = cmuSelect_LFRCO; - break; - -#if defined(_CMU_STATUS_USBCHFCLKSEL_MASK) - case CMU_STATUS_USBCHFCLKSEL: - ret = cmuSelect_HFCLK; - break; -#endif - -#if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK) - case CMU_STATUS_USBCUSHFRCOSEL: - ret = cmuSelect_USHFRCO; - break; -#endif - - default: - ret = cmuSelect_Disabled; - break; - } - break; -#endif - - default: - EFM_ASSERT(0); - ret = cmuSelect_Error; - break; } return ret; } -/**************************************************************************//** +/***************************************************************************//** * @brief * Select reference clock/oscillator used for a clock branch. * @@ -1513,7 +2381,11 @@ * Clock branch to select reference clock for. One of: * @li #cmuClock_HF * @li #cmuClock_LFA - * @li #cmuClock_LFB + * @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO + * @li #cmuClock_LFC + * @endif @if _SILICON_LABS_32B_PLATFORM_2 + * @li #cmuClock_LFE + * @endif * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT * @li #cmuClock_USBC * @endif @@ -1530,308 +2402,425 @@ * @li #cmuSelect_HFCLK @ifnot DOXYDOC_EFM32_GECKO_FAMILY * @li #cmuSelect_ULFRCO * @endif - *****************************************************************************/ + ******************************************************************************/ void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref) { uint32_t select = cmuOsc_HFRCO; CMU_Osc_TypeDef osc = cmuOsc_HFRCO; uint32_t freq; - uint32_t selReg; -#if !defined(_EFM32_GECKO_FAMILY) + uint32_t tmp; + uint32_t selRegId; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + volatile uint32_t *selReg = NULL; +#endif +#if defined( CMU_LFCLKSEL_LFAE_ULFRCO ) uint32_t lfExtended = 0; #endif - uint32_t tmp; - - selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK; - - switch (selReg) + + selRegId = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK; + + switch (selRegId) { - case CMU_HFCLKSEL_REG: - switch (ref) - { - case cmuSelect_LFXO: - select = CMU_CMD_HFCLKSEL_LFXO; - osc = cmuOsc_LFXO; - break; - - case cmuSelect_LFRCO: - select = CMU_CMD_HFCLKSEL_LFRCO; - osc = cmuOsc_LFRCO; - break; - - case cmuSelect_HFXO: - select = CMU_CMD_HFCLKSEL_HFXO; - osc = cmuOsc_HFXO; + case CMU_HFCLKSEL_REG: + switch (ref) + { + case cmuSelect_LFXO: +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + select = CMU_HFCLKSEL_HF_LFXO; +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) + select = CMU_CMD_HFCLKSEL_LFXO; +#endif + osc = cmuOsc_LFXO; + break; + + case cmuSelect_LFRCO: +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + select = CMU_HFCLKSEL_HF_LFRCO; +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) + select = CMU_CMD_HFCLKSEL_LFRCO; +#endif + osc = cmuOsc_LFRCO; + break; + + case cmuSelect_HFXO: + osc = cmuOsc_HFXO; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + select = CMU_HFCLKSEL_HF_HFXO; + /* Adjust HFXO buffer current for high frequencies, */ + /* enable WSHFLE for frequencies above 32MHz. */ + if (SystemHFXOClockGet() > 32000000) + { + CMU->CTRL |= CMU_CTRL_WSHFLE; + } +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) + select = CMU_CMD_HFCLKSEL_HFXO; #if defined( CMU_CTRL_HFLE ) - /* Adjust HFXO buffer current for high frequencies, enable HFLE for */ - /* frequencies above CMU_MAX_FREQ_HFLE. */ - if(SystemHFXOClockGet() > CMU_MAX_FREQ_HFLE) - { - CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) | - CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ | - /* Must have HFLE enabled to access some LE peripherals >=32MHz */ - CMU_CTRL_HFLE; - - /* Set HFLE and DIV4 factor for peripheral clock if HFCORE clock for - LE is enabled. */ - if (CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE) - { - BITBAND_Peripheral(&(CMU->HFCORECLKDIV), - _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1); - } - } else { - /* This can happen if the user configures the EFM32_HFXO_FREQ to */ - /* use another oscillator frequency */ - CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) | - CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ; - } + /* Adjust HFXO buffer current for high frequencies, */ + /* enable HFLE for frequencies above CMU_MAX_FREQ_HFLE. */ + if(SystemHFXOClockGet() > CMU_MAX_FREQ_HFLE()) + { + CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) + | CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ + /* Must have HFLE enabled to access some LE peripherals >=32MHz */ + | CMU_CTRL_HFLE; + + /* Set HFLE and DIV4 factor for peripheral clock if HFCORE */ + /* clock for LE is enabled. */ + if (CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE) + { + BUS_RegBitWrite(&CMU->HFCORECLKDIV, + _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1); + } + } + else + { + /* This can happen if the user configures the EFM32_HFXO_FREQ to */ + /* use another oscillator frequency */ + CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) + | CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ; + } #endif - break; - - case cmuSelect_HFRCO: - select = CMU_CMD_HFCLKSEL_HFRCO; - osc = cmuOsc_HFRCO; - break; +#endif + break; + + case cmuSelect_HFRCO: +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + select = CMU_HFCLKSEL_HF_HFRCO; +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) + select = CMU_CMD_HFCLKSEL_HFRCO; +#endif + osc = cmuOsc_HFRCO; + break; #if defined( CMU_CMD_HFCLKSEL_USHFRCODIV2 ) - case cmuSelect_USHFRCODIV2: - select = CMU_CMD_HFCLKSEL_USHFRCODIV2; - osc = cmuOsc_USHFRCO; + case cmuSelect_USHFRCODIV2: + select = CMU_CMD_HFCLKSEL_USHFRCODIV2; + osc = cmuOsc_USHFRCO; + break; +#endif + +#if defined( CMU_LFCLKSEL_LFAE_ULFRCO ) || defined( CMU_LFACLKSEL_LFA_ULFRCO ) + case cmuSelect_ULFRCO: + /* ULFRCO cannot be used as HFCLK */ + EFM_ASSERT(0); + return; +#endif + + default: + EFM_ASSERT(0); + return; + } + + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(osc, true, true); + + /* Configure worst case wait states for flash access before selecting */ + flashWaitStateMax(); + + /* Switch to selected oscillator */ +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + CMU->HFCLKSEL = select; +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) + CMU->CMD = select; +#endif + + /* Keep EMU module informed */ + EMU_UpdateOscConfig(); + + /* Update CMSIS core clock variable */ + /* (The function will update the global variable) */ + freq = SystemCoreClockGet(); + + /* Optimize flash access wait state setting for currently selected core clk */ + flashWaitStateControl(freq); + break; + +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + case CMU_LFACLKSEL_REG: + selReg = (selReg == NULL) ? &CMU->LFACLKSEL : selReg; +#if !defined( _CMU_LFACLKSEL_LFA_HFCLKLE ) + /* HFCLKCLE can not be used as LFACLK */ + EFM_ASSERT(ref != cmuSelect_HFCLKLE); +#endif + case CMU_LFECLKSEL_REG: + selReg = (selReg == NULL) ? &CMU->LFECLKSEL : selReg; +#if !defined( _CMU_LFECLKSEL_LFE_HFCLKLE ) + /* HFCLKCLE can not be used as LFECLK */ + EFM_ASSERT(ref != cmuSelect_HFCLKLE); +#endif + case CMU_LFBCLKSEL_REG: + selReg = (selReg == NULL) ? &CMU->LFBCLKSEL : selReg; + switch (ref) + { + case cmuSelect_Disabled: + tmp = _CMU_LFACLKSEL_LFA_DISABLED; + break; + + case cmuSelect_LFXO: + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_LFXO, true, true); + tmp = _CMU_LFACLKSEL_LFA_LFXO; + break; + + case cmuSelect_LFRCO: + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); + tmp = _CMU_LFACLKSEL_LFA_LFRCO; + break; + + case cmuSelect_HFCLKLE: + /* Ensure HFCORE to LE clocking is enabled */ + BUS_RegBitWrite(&CMU->HFBUSCLKEN0, _CMU_HFBUSCLKEN0_LE_SHIFT, 1); + tmp = _CMU_LFBCLKSEL_LFB_HFCLKLE; + + /* If core frequency is > 32MHz enable WSHFLE */ + freq = SystemCoreClockGet(); + if (freq > 32000000U) + { + /* Enable CMU HFLE */ + BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_WSHFLE_SHIFT, 1); + + /* Enable DIV4 factor for peripheral clock */ + BUS_RegBitWrite(&CMU->HFPRESC, _CMU_HFPRESC_HFCLKLEPRESC_SHIFT, 1); + } + break; + + case cmuSelect_ULFRCO: + /* ULFRCO is always on, there is no need to enable it. */ + tmp = _CMU_LFACLKSEL_LFA_ULFRCO; + break; + + default: + EFM_ASSERT(0); + return; + } + *selReg = tmp; + break; + +#elif defined( _SILICON_LABS_32B_PLATFORM_1 ) + case CMU_LFACLKSEL_REG: + case CMU_LFBCLKSEL_REG: + switch (ref) + { + case cmuSelect_Disabled: + tmp = _CMU_LFCLKSEL_LFA_DISABLED; + break; + + case cmuSelect_LFXO: + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_LFXO, true, true); + tmp = _CMU_LFCLKSEL_LFA_LFXO; + break; + + case cmuSelect_LFRCO: + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); + tmp = _CMU_LFCLKSEL_LFA_LFRCO; + break; + + case cmuSelect_CORELEDIV2: + /* Ensure HFCORE to LE clocking is enabled */ + BUS_RegBitWrite(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_LE_SHIFT, 1); + tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2; +#if defined( CMU_CTRL_HFLE ) + /* If core frequency is higher than CMU_MAX_FREQ_HFLE on + Giant/Leopard/Wonder, enable HFLE and DIV4. */ + freq = SystemCoreClockGet(); + if(freq > CMU_MAX_FREQ_HFLE()) + { + /* Enable CMU HFLE */ + BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1); + + /* Enable DIV4 factor for peripheral clock */ + BUS_RegBitWrite(&CMU->HFCORECLKDIV, + _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1); + } +#endif + break; + +#if defined( CMU_LFCLKSEL_LFAE_ULFRCO ) + case cmuSelect_ULFRCO: + /* ULFRCO is always enabled */ + tmp = _CMU_LFCLKSEL_LFA_DISABLED; + lfExtended = 1; + break; +#endif + + default: + /* Illegal clock source for LFA/LFB selected */ + EFM_ASSERT(0); + return; + } + + /* Apply select */ + if (selRegId == CMU_LFACLKSEL_REG) + { +#if defined( _CMU_LFCLKSEL_LFAE_MASK ) + CMU->LFCLKSEL = (CMU->LFCLKSEL + & ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK)) + | (tmp << _CMU_LFCLKSEL_LFA_SHIFT) + | (lfExtended << _CMU_LFCLKSEL_LFAE_SHIFT); +#else + CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFA_MASK) + | (tmp << _CMU_LFCLKSEL_LFA_SHIFT); +#endif + } + else + { +#if defined( _CMU_LFCLKSEL_LFBE_MASK ) + CMU->LFCLKSEL = (CMU->LFCLKSEL + & ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK)) + | (tmp << _CMU_LFCLKSEL_LFB_SHIFT) + | (lfExtended << _CMU_LFCLKSEL_LFBE_SHIFT); +#else + CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFB_MASK) + | (tmp << _CMU_LFCLKSEL_LFB_SHIFT); +#endif + } + break; + +#if defined( _CMU_LFCLKSEL_LFC_MASK ) + case CMU_LFCCLKSEL_REG: + switch(ref) + { + case cmuSelect_Disabled: + tmp = _CMU_LFCLKSEL_LFA_DISABLED; + break; + + case cmuSelect_LFXO: + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_LFXO, true, true); + tmp = _CMU_LFCLKSEL_LFC_LFXO; + break; + + case cmuSelect_LFRCO: + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); + tmp = _CMU_LFCLKSEL_LFC_LFRCO; + break; + + default: + /* Illegal clock source for LFC selected */ + EFM_ASSERT(0); + return; + } + + /* Apply select */ + CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFC_MASK) + | (tmp << _CMU_LFCLKSEL_LFC_SHIFT); break; #endif - -#if !defined( _EFM32_GECKO_FAMILY ) - case cmuSelect_ULFRCO: - /* ULFRCO cannot be used as HFCLK */ - EFM_ASSERT(0); +#endif + +#if defined( CMU_DBGCLKSEL_DBG ) || defined( CMU_CTRL_DBGCLK ) + case CMU_DBGCLKSEL_REG: + switch(ref) + { +#if defined( CMU_DBGCLKSEL_DBG ) + case cmuSelect_AUXHFRCO: + /* Select AUXHFRCO as debug clock */ + CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_AUXHFRCO; + break; + + case cmuSelect_HFCLK: + /* Select divided HFCLK as debug clock */ + CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_HFCLK; + break; +#endif + +#if defined( CMU_CTRL_DBGCLK ) + case cmuSelect_AUXHFRCO: + /* Select AUXHFRCO as debug clock */ + CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK)) + | CMU_CTRL_DBGCLK_AUXHFRCO; + break; + + case cmuSelect_HFCLK: + /* Select divided HFCLK as debug clock */ + CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK)) + | CMU_CTRL_DBGCLK_HFCLK; + break; +#endif + + default: + /* Illegal clock source for debug selected */ + EFM_ASSERT(0); + return; + } + break; +#endif + +#if defined(USB_PRESENT) + case CMU_USBCCLKSEL_REG: + switch(ref) + { + case cmuSelect_LFXO: + /* Select LFXO as clock source for USB, can only be used in sleep mode */ + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_LFXO, true, true); + + /* Switch oscillator */ + CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO; + + /* Wait until clock is activated */ + while((CMU->STATUS & CMU_STATUS_USBCLFXOSEL)==0) + { + } + break; + + case cmuSelect_LFRCO: + /* Select LFRCO as clock source for USB, can only be used in sleep mode */ + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); + + /* Switch oscillator */ + CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO; + + /* Wait until clock is activated */ + while((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL)==0) + { + } + break; + +#if defined( CMU_STATUS_USBCHFCLKSEL ) + case cmuSelect_HFCLK: + /* Select undivided HFCLK as clock source for USB */ + /* Oscillator must already be enabled to avoid a core lockup */ + CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV; + /* Wait until clock is activated */ + while((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL)==0) + { + } + break; +#endif + +#if defined( CMU_CMD_USBCCLKSEL_USHFRCO ) + case cmuSelect_USHFRCO: + /* Select USHFRCO as clock source for USB */ + /* Ensure selected oscillator is enabled, waiting for it to stabilize */ + CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true); + + /* Switch oscillator */ + CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO; + + /* Wait until clock is activated */ + while((CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL)==0) + { + } + break; +#endif + + default: + /* Illegal clock source for USB */ + EFM_ASSERT(0); + return; + } break; #endif default: EFM_ASSERT(0); - return; - } - - /* Ensure selected oscillator is enabled, waiting for it to stabilize */ - CMU_OscillatorEnable(osc, true, true); - - /* Configure worst case wait states for flash access before selecting */ - CMU_FlashWaitStateMax(); - - /* Switch to selected oscillator */ - CMU->CMD = select; - - /* Keep EMU module informed */ - EMU_UpdateOscConfig(); - - /* Update CMSIS core clock variable */ - /* (The function will update the global variable) */ - freq = SystemCoreClockGet(); - - /* Optimize flash access wait state setting for currently selected core clk */ - CMU_FlashWaitStateControl(freq); - break; - - case CMU_LFACLKSEL_REG: - case CMU_LFBCLKSEL_REG: - - switch (ref) - { - case cmuSelect_Disabled: - tmp = _CMU_LFCLKSEL_LFA_DISABLED; break; - - case cmuSelect_LFXO: - /* Ensure selected oscillator is enabled, waiting for it to stabilize */ - CMU_OscillatorEnable(cmuOsc_LFXO, true, true); - tmp = _CMU_LFCLKSEL_LFA_LFXO; - break; - - case cmuSelect_LFRCO: - /* Ensure selected oscillator is enabled, waiting for it to stabilize */ - CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); - tmp = _CMU_LFCLKSEL_LFA_LFRCO; - break; - - case cmuSelect_CORELEDIV2: - /* Ensure HFCORE to LE clocking is enabled */ - BITBAND_Peripheral(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_LE_SHIFT, 1); - tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2; -#if defined( CMU_CTRL_HFLE ) - /* If core frequency is higher than CMU_MAX_FREQ_HFLE on - Giant/Leopard/Wonder, enable HFLE and DIV4. */ - freq = SystemCoreClockGet(); - if(freq > CMU_MAX_FREQ_HFLE) - { - /* Enable CMU HFLE */ - BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1); - - /* Enable DIV4 factor for peripheral clock */ - BITBAND_Peripheral(&(CMU->HFCORECLKDIV), - _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1); - } -#endif - break; - -#if !defined(_EFM32_GECKO_FAMILY) - case cmuSelect_ULFRCO: - /* ULFRCO is always enabled */ - tmp = _CMU_LFCLKSEL_LFA_DISABLED; - lfExtended = 1; - break; -#endif - - default: - /* Illegal clock source for LFA/LFB selected */ - EFM_ASSERT(0); - return; - } - - /* Apply select */ - if (selReg == CMU_LFACLKSEL_REG) - { -#if !defined( _EFM32_GECKO_FAMILY ) - CMU->LFCLKSEL = (CMU->LFCLKSEL & ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK) ) | - (tmp << _CMU_LFCLKSEL_LFA_SHIFT) | (lfExtended << _CMU_LFCLKSEL_LFAE_SHIFT); -#else - CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFA_MASK) | - (tmp << _CMU_LFCLKSEL_LFA_SHIFT); -#endif - } - else - { -#if !defined( _EFM32_GECKO_FAMILY ) - CMU->LFCLKSEL = (CMU->LFCLKSEL & ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK) ) | - (tmp << _CMU_LFCLKSEL_LFB_SHIFT) | (lfExtended << _CMU_LFCLKSEL_LFBE_SHIFT); -#else - CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFB_MASK) | - (tmp << _CMU_LFCLKSEL_LFB_SHIFT); -#endif - } - break; - -#if defined( _CMU_LFCLKSEL_LFC_MASK ) - case CMU_LFCCLKSEL_REG: - switch(ref) - { - case cmuSelect_Disabled: - tmp = _CMU_LFCLKSEL_LFA_DISABLED; - break; - - case cmuSelect_LFXO: - /* Ensure selected oscillator is enabled, waiting for it to stabilize */ - CMU_OscillatorEnable(cmuOsc_LFXO, true, true); - tmp = _CMU_LFCLKSEL_LFC_LFXO; - break; - - case cmuSelect_LFRCO: - /* Ensure selected oscillator is enabled, waiting for it to stabilize */ - CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); - tmp = _CMU_LFCLKSEL_LFC_LFRCO; - break; - - default: - /* Illegal clock source for LFC selected */ - EFM_ASSERT(0); - return; - } - - /* Apply select */ - CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFC_MASK) | - (tmp << _CMU_LFCLKSEL_LFC_SHIFT); - break; -#endif - -#if defined( CMU_CTRL_DBGCLK ) - case CMU_DBGCLKSEL_REG: - switch(ref) - { - case cmuSelect_AUXHFRCO: - /* Select AUXHFRCO as debug clock */ - CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))| CMU_CTRL_DBGCLK_AUXHFRCO; - break; - - case cmuSelect_HFCLK: - /* Select divided HFCLK as debug clock */ - CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))| CMU_CTRL_DBGCLK_HFCLK; - break; - - default: - /* Illegal clock source for debug selected */ - EFM_ASSERT(0); - return; - } - break; -#endif - -#if defined(USB_PRESENT) - case CMU_USBCCLKSEL_REG: - switch(ref) - { - case cmuSelect_LFXO: - /* Select LFXO as clock source for USB, can only be used in sleep mode */ - - /* Ensure selected oscillator is enabled, waiting for it to stabilize */ - CMU_OscillatorEnable(cmuOsc_LFXO, true, true); - - /* Switch oscillator */ - CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO; - - /* Wait until clock is activated */ - while((CMU->STATUS & CMU_STATUS_USBCLFXOSEL)==0); - break; - - case cmuSelect_LFRCO: - /* Select LFRCO as clock source for USB, can only be used in sleep mode */ - - /* Ensure selected oscillator is enabled, waiting for it to stabilize */ - CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); - - /* Switch oscillator */ - CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO; - - /* Wait until clock is activated */ - while((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL)==0); - break; - -#if defined( CMU_STATUS_USBCHFCLKSEL ) - case cmuSelect_HFCLK: - /* Select undivided HFCLK as clock source for USB */ - - /* Oscillator must already be enabled to avoid a core lockup */ - CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV; - /* Wait until clock is activated */ - while((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL)==0); - break; -#endif - -#if defined( CMU_CMD_USBCCLKSEL_USHFRCO ) - case cmuSelect_USHFRCO: - /* Select USHFRCO as clock source for USB */ - - /* Ensure selected oscillator is enabled, waiting for it to stabilize */ - CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true); - - /* Switch oscillator */ - CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO; - - /* Wait until clock is activated */ - while((CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL)==0); - break; -#endif - - default: - /* Illegal clock source for USB */ - EFM_ASSERT(0); - return; - } - /* Wait until clock has been activated */ - break; -#endif - - default: - EFM_ASSERT(0); - break; } } @@ -1877,7 +2866,8 @@ /* since modifying a register while it is in sync progress should be */ /* avoided. */ while (CMU->SYNCBUSY) - ; + { + } CMU->FREEZE = CMU_FREEZE_REGFREEZE; } @@ -1888,147 +2878,7 @@ } -#if defined( _CMU_AUXHFRCOCTRL_BAND_MASK ) -/***************************************************************************//** - * @brief - * Get AUXHFRCO band in use. - * - * @return - * AUXHFRCO band in use. - ******************************************************************************/ -CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void) -{ - return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK) >> - _CMU_AUXHFRCOCTRL_BAND_SHIFT); -} - -/***************************************************************************//** - * @brief - * Set AUIXHFRCO band and the tuning value based on the value in the - * calibration table made during production. - * - * @param[in] band - * AUXHFRCO band to activate. - ******************************************************************************/ -void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band) -{ - uint32_t tuning; - - /* Read tuning value from calibration table */ - switch (band) - { - case cmuAUXHFRCOBand_1MHz: - tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK) >> - _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT; - break; - - case cmuAUXHFRCOBand_7MHz: - tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK) >> - _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT; - break; - - case cmuAUXHFRCOBand_11MHz: - tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK) >> - _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT; - break; - - case cmuAUXHFRCOBand_14MHz: - tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK) >> - _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT; - break; - - case cmuAUXHFRCOBand_21MHz: - tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK) >> - _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT; - break; - -#if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ ) - case cmuAUXHFRCOBand_28MHz: - tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK) >> - _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT; - break; -#endif - - default: - EFM_ASSERT(0); - return; - } - - /* Set band/tuning */ - CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & - ~(_CMU_AUXHFRCOCTRL_BAND_MASK | _CMU_AUXHFRCOCTRL_TUNING_MASK)) | - (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT) | - (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT); - -} -#endif - - -#if defined( _CMU_USHFRCOCONF_BAND_MASK ) -/***************************************************************************//** - * @brief - * Get USHFRCO band in use. - * - * @return - * USHFRCO band in use. - ******************************************************************************/ -CMU_USHFRCOBand_TypeDef CMU_USHFRCOBandGet(void) -{ - return (CMU_USHFRCOBand_TypeDef)((CMU->USHFRCOCONF & _CMU_USHFRCOCONF_BAND_MASK) >> - _CMU_USHFRCOCONF_BAND_SHIFT); -} - -void CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band) -{ - uint32_t tuning; - uint32_t fineTuning; - CMU_Select_TypeDef osc; - - /* Cannot switch band if USHFRCO is already selected as HF clock. */ - osc = CMU_ClockSelectGet(cmuClock_HF); - EFM_ASSERT((CMU_USHFRCOBandGet() != band) && (osc != cmuSelect_USHFRCO)); - - /* Read tuning value from calibration table */ - switch (band) - { - case cmuUSHFRCOBand_24MHz: - tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_TUNING_MASK) >> - _DEVINFO_USHFRCOCAL0_BAND24_TUNING_SHIFT; - fineTuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_MASK) >> - _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_SHIFT; - break; - - case cmuUSHFRCOBand_48MHz: - tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_TUNING_MASK) >> - _DEVINFO_USHFRCOCAL0_BAND48_TUNING_SHIFT; - fineTuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_MASK) >> - _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_SHIFT; - /* Enable the clock divider before switching the band from 48 to 24MHz */ - BITBAND_Peripheral(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 0); - break; - - default: - EFM_ASSERT(0); - return; - } - - /* Set band and tuning */ - CMU->USHFRCOCONF = (CMU->USHFRCOCONF & ~_CMU_USHFRCOCONF_BAND_MASK) | - (band << _CMU_USHFRCOCONF_BAND_SHIFT); - CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~_CMU_USHFRCOCTRL_TUNING_MASK) | - (tuning << _CMU_USHFRCOCTRL_TUNING_SHIFT); - CMU->USHFRCOTUNE = (CMU->USHFRCOTUNE & ~_CMU_USHFRCOTUNE_FINETUNING_MASK) | - (fineTuning << _CMU_USHFRCOTUNE_FINETUNING_SHIFT); - - /* Disable the clock divider after switching the band from 48 to 24MHz */ - if (band == cmuUSHFRCOBand_24MHz) - { - BITBAND_Peripheral(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 1); - } -} -#endif - - +#if defined( _CMU_HFRCOCTRL_BAND_MASK ) /***************************************************************************//** * @brief * Get HFRCO band in use. @@ -2038,11 +2888,13 @@ ******************************************************************************/ CMU_HFRCOBand_TypeDef CMU_HFRCOBandGet(void) { - return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK) >> - _CMU_HFRCOCTRL_BAND_SHIFT); + return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK) + >> _CMU_HFRCOCTRL_BAND_SHIFT); } - - +#endif /* _CMU_HFRCOCTRL_BAND_MASK */ + + +#if defined( _CMU_HFRCOCTRL_BAND_MASK ) /***************************************************************************//** * @brief * Set HFRCO band and the tuning value based on the value in the calibration @@ -2060,41 +2912,41 @@ /* Read tuning value from calibration table */ switch (band) { - case cmuHFRCOBand_1MHz: - tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK) >> - _DEVINFO_HFRCOCAL0_BAND1_SHIFT; - break; - - case cmuHFRCOBand_7MHz: - tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK) >> - _DEVINFO_HFRCOCAL0_BAND7_SHIFT; - break; - - case cmuHFRCOBand_11MHz: - tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK) >> - _DEVINFO_HFRCOCAL0_BAND11_SHIFT; - break; - - case cmuHFRCOBand_14MHz: - tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK) >> - _DEVINFO_HFRCOCAL0_BAND14_SHIFT; - break; - - case cmuHFRCOBand_21MHz: - tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK) >> - _DEVINFO_HFRCOCAL1_BAND21_SHIFT; - break; + case cmuHFRCOBand_1MHz: + tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK) + >> _DEVINFO_HFRCOCAL0_BAND1_SHIFT; + break; + + case cmuHFRCOBand_7MHz: + tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK) + >> _DEVINFO_HFRCOCAL0_BAND7_SHIFT; + break; + + case cmuHFRCOBand_11MHz: + tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK) + >> _DEVINFO_HFRCOCAL0_BAND11_SHIFT; + break; + + case cmuHFRCOBand_14MHz: + tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK) + >> _DEVINFO_HFRCOCAL0_BAND14_SHIFT; + break; + + case cmuHFRCOBand_21MHz: + tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK) + >> _DEVINFO_HFRCOCAL1_BAND21_SHIFT; + break; #if defined( _CMU_HFRCOCTRL_BAND_28MHZ ) - case cmuHFRCOBand_28MHz: - tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK) >> - _DEVINFO_HFRCOCAL1_BAND28_SHIFT; - break; + case cmuHFRCOBand_28MHz: + tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK) + >> _DEVINFO_HFRCOCAL1_BAND28_SHIFT; + break; #endif - default: - EFM_ASSERT(0); - return; + default: + EFM_ASSERT(0); + return; } /* If HFRCO is used for core clock, we have to consider flash access WS. */ @@ -2102,14 +2954,14 @@ if (osc == cmuSelect_HFRCO) { /* Configure worst case wait states for flash access before setting divider */ - CMU_FlashWaitStateMax(); + flashWaitStateMax(); } /* Set band/tuning */ CMU->HFRCOCTRL = (CMU->HFRCOCTRL & - ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK)) | - (band << _CMU_HFRCOCTRL_BAND_SHIFT) | - (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT); + ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK)) + | (band << _CMU_HFRCOCTRL_BAND_SHIFT) + | (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT); /* If HFRCO is used for core clock, optimize flash WS */ if (osc == cmuSelect_HFRCO) @@ -2121,13 +2973,137 @@ freq = SystemCoreClockGet(); /* Optimize flash access wait state setting for current core clk */ - CMU_FlashWaitStateControl(freq); + flashWaitStateControl(freq); + } +} +#endif /* _CMU_HFRCOCTRL_BAND_MASK */ + + +#if defined( _CMU_HFRCOCTRL_FREQRANGE_MASK ) +/**************************************************************************//** + * @brief + * Get a pointer to the HFRCO frequency calibration word in DEVINFO + * + * @param[in] freq + * Frequency in Hz + * + * @return + * HFRCO calibration word for a given frequency + *****************************************************************************/ +static uint32_t CMU_HFRCODevinfoGet(CMU_HFRCOFreq_TypeDef freq) +{ + switch (freq) + { + /* 1, 2 and 4MHz share the same calibration word */ + case cmuHFRCOFreq_1M0Hz: + case cmuHFRCOFreq_2M0Hz: + case cmuHFRCOFreq_4M0Hz: + return DEVINFO->HFRCOCAL0; + + case cmuHFRCOFreq_7M0Hz: + return DEVINFO->HFRCOCAL3; + + case cmuHFRCOFreq_13M0Hz: + return DEVINFO->HFRCOCAL6; + + case cmuHFRCOFreq_16M0Hz: + return DEVINFO->HFRCOCAL7; + + case cmuHFRCOFreq_19M0Hz: + return DEVINFO->HFRCOCAL8; + + case cmuHFRCOFreq_26M0Hz: + return DEVINFO->HFRCOCAL10; + + case cmuHFRCOFreq_32M0Hz: + return DEVINFO->HFRCOCAL11; + + case cmuHFRCOFreq_38M0Hz: + return DEVINFO->HFRCOCAL12; + + default: /* cmuHFRCOFreq_UserDefined */ + return 0; } } /***************************************************************************//** * @brief + * Get HFRCO frequency enumeration in use + * + * @return + * HFRCO frequency enumeration in use + ******************************************************************************/ +CMU_HFRCOFreq_TypeDef CMU_HFRCOFreqGet(void) +{ + return (CMU_HFRCOFreq_TypeDef)SystemHfrcoFreq; +} + + +/***************************************************************************//** + * @brief + * Set HFRCO calibration for the selected target frequency + * + * @param[in] freq + * HFRCO frequency band to set + ******************************************************************************/ +void CMU_HFRCOFreqSet(CMU_HFRCOFreq_TypeDef freq) +{ + uint32_t freqCal; + + /* Get DEVINFO index, set CMSIS frequency SystemHfrcoFreq */ + freqCal = CMU_HFRCODevinfoGet(freq); + EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX)); + SystemHfrcoFreq = (uint32_t)freq; + + /* Set max wait-states while changing core clock */ + if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) + { + flashWaitStateMax(); + } + + /* Wait for any previous sync to complete, and then set calibration data + for the selected frequency. */ + while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT)); + + /* Check for valid calibration data */ + EFM_ASSERT(freqCal != UINT_MAX); + + /* Set divider in HFRCOCTRL for 1, 2 and 4MHz */ + switch(freq) + { + case cmuHFRCOFreq_1M0Hz: + freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK) + | CMU_HFRCOCTRL_CLKDIV_DIV4; + break; + + case cmuHFRCOFreq_2M0Hz: + freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK) + | CMU_HFRCOCTRL_CLKDIV_DIV2; + break; + + case cmuHFRCOFreq_4M0Hz: + freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK) + | CMU_HFRCOCTRL_CLKDIV_DIV1; + break; + + default: + break; + } + CMU->HFRCOCTRL = freqCal; + + /* Optimize flash access wait-state configuration for this frequency, */ + /* if HFRCO is reference for core clock. */ + if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO) + { + flashWaitStateControl((uint32_t)freq); + } +} +#endif /* _CMU_HFRCOCTRL_FREQRANGE_MASK */ + +#if defined( _CMU_HFRCOCTRL_SUDELAY_MASK ) +/***************************************************************************//** + * @brief * Get the HFRCO startup delay. * * @details @@ -2138,8 +3114,8 @@ ******************************************************************************/ uint32_t CMU_HFRCOStartupDelayGet(void) { - return((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK) >> - _CMU_HFRCOCTRL_SUDELAY_SHIFT); + return (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK) + >> _CMU_HFRCOCTRL_SUDELAY_SHIFT; } @@ -2157,10 +3133,156 @@ { EFM_ASSERT(delay <= 31); - delay &= (_CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT); - CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK)) | - (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT); + delay &= _CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT; + CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK)) + | (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT); +} +#endif + + +#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK ) +/***************************************************************************//** + * @brief + * Enable or disable HFXO autostart + * + * @param[in] enRACStartSel + * If true, HFXO is automatically started and selected upon RAC wakeup. + * If false, HFXO is not started or selected automatically upon RAC wakeup. + * + * @param[in] enEM0EM1Start + * If true, HFXO is automatically started upon entering EM0/EM1 entry from + * EM2/EM3. HFXO selection has to be handled by the user. + * If false, HFXO is not started automatically when entering EM0/EM1. + * + * @param[in] enEM0EM1StartSel + * If true, HFXO is automatically started and immediately selected upon + * entering EM0/EM1 entry from EM2/EM3. Note that this option stalls the use of + * HFSRCCLK until HFXO becomes ready. + * If false, HFXO is not started or selected automatically when entering + * EM0/EM1. + ******************************************************************************/ +void CMU_HFXOAutostartEnable(bool enRACStartSel, + bool enEM0EM1Start, + bool enEM0EM1StartSel) +{ + uint32_t hfxoCtrl; + hfxoCtrl = CMU->HFXOCTRL & ~(_CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK + | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK + | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK); + + hfxoCtrl |= (enRACStartSel ? CMU_HFXOCTRL_AUTOSTARTRDYSELRAC : 0) + | (enEM0EM1Start ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0) + | (enEM0EM1StartSel ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0); + + CMU->HFXOCTRL = hfxoCtrl; } +#endif /* _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK */ + + +#if defined( _CMU_HFXOCTRL_MASK ) +/**************************************************************************//** + * @brief + * Set HFXO control registers + * + * @note + * HFXO configuration should be obtained from a configuration tool, + * app note or xtal datasheet. This function disables the HFXO to ensure + * a valid state before update. + * + * @param[in] hfxoInit + * HFXO setup parameters + *****************************************************************************/ +void CMU_HFXOInit(CMU_HFXOInit_TypeDef *hfxoInit) +{ + uint32_t ishReg; + uint32_t ishMax; + + /* Do not disable HFXO if it is currently selected as HF/Core clock */ + EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_HFXO); + + /* HFXO must be disabled before reconfiguration */ + CMU_OscillatorEnable(cmuOsc_HFXO, false, false); + + /* Apply control settings */ + BUS_RegMaskedWrite(&CMU->HFXOCTRL, + _CMU_HFXOCTRL_LOWPOWER_MASK +#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK ) + | _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK +#endif + | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK + | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK, + (hfxoInit->lowPowerMode + ? CMU_HFXOCTRL_LOWPOWER : 0) +#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK ) + | (hfxoInit->autoStartSelOnRacWakeup + ? CMU_HFXOCTRL_AUTOSTARTRDYSELRAC : 0) +#endif + | (hfxoInit->autoStartEm01 + ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0) + | (hfxoInit->autoSelEm01 + ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0)); + + /* Set XTAL tuning parameters */ + + /* Set peak detection threshold in CMU_HFXOCTRL1_PEAKDETTHR[2:0] (hidden). */ + BUS_RegMaskedWrite((volatile uint32_t *)0x400E4028, 0x7, hfxoInit->thresholdPeakDetect); + + /* Set tuning for startup and steady state */ + BUS_RegMaskedWrite(&CMU->HFXOSTARTUPCTRL, + _CMU_HFXOSTARTUPCTRL_CTUNE_MASK + | _CMU_HFXOSTARTUPCTRL_REGISHWARM_MASK + | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK + | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCOREWARM_MASK, + (hfxoInit->ctuneStartup + << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT) + | (hfxoInit->regIshStartup + << _CMU_HFXOSTARTUPCTRL_REGISHWARM_SHIFT) + | (hfxoInit->xoCoreBiasTrimStartup + << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT) + | 0x4 /* Recommended tuning */ + << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCOREWARM_SHIFT); + + /* Adjust CMU_HFXOSTEADYSTATECTRL_REGISHUPPER according to regIshSteadyState. + Saturate at max value. Please see the reference manual page 433 and Section + 12.5.10 CMU_HFXOSTEADYSTATECTRL for more details. */ + ishReg = hfxoInit->regIshSteadyState + 3; + ishMax = _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK + >> _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT; + ishReg = ishReg > ishMax ? ishMax : ishReg; + ishReg <<= _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT; + + BUS_RegMaskedWrite(&CMU->HFXOSTEADYSTATECTRL, + _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK + | _CMU_HFXOSTEADYSTATECTRL_REGISH_MASK + | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK + | _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK, + (hfxoInit->ctuneSteadyState + << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT) + | (hfxoInit->regIshSteadyState + << _CMU_HFXOSTEADYSTATECTRL_REGISH_SHIFT) + | (hfxoInit->xoCoreBiasTrimSteadyState + << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT) + | ishReg); + + /* Set timeouts */ + BUS_RegMaskedWrite(&CMU->HFXOTIMEOUTCTRL, + _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_MASK + | _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_MASK + | _CMU_HFXOTIMEOUTCTRL_WARMSTEADYTIMEOUT_MASK + | _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_MASK + | _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_MASK, + (hfxoInit->timeoutShuntOptimization + << _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_SHIFT) + | (hfxoInit->timeoutPeakDetect + << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT) + | (hfxoInit->timeoutWarmSteady + << _CMU_HFXOTIMEOUTCTRL_WARMSTEADYTIMEOUT_SHIFT) + | (hfxoInit->timeoutSteady + << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT) + | (hfxoInit->timeoutStartup + << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT)); +} +#endif /***************************************************************************//** @@ -2172,8 +3294,8 @@ ******************************************************************************/ uint32_t CMU_LCDClkFDIVGet(void) { -#if defined(LCD_PRESENT) - return((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT); +#if defined( LCD_PRESENT ) + return (CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT; #else return 0; #endif /* defined(LCD_PRESENT) */ @@ -2195,7 +3317,7 @@ ******************************************************************************/ void CMU_LCDClkFDIVSet(uint32_t div) { -#if defined(LCD_PRESENT) +#if defined( LCD_PRESENT ) EFM_ASSERT(div <= cmuClkDiv_128); /* Do not allow modification if LCD clock enabled */ @@ -2213,6 +3335,38 @@ } +#if defined( _CMU_LFXOCTRL_MASK ) +/**************************************************************************//** + * @brief + * Set LFXO control registers + * + * @note + * LFXO configuration should be obtained from a configuration tool, + * app note or xtal datasheet. This function disables the LFXO to ensure + * a valid state before update. + * + * @param[in] lfxoInit + * LFXO setup parameters + *****************************************************************************/ +void CMU_LFXOInit(CMU_LFXOInit_TypeDef *lfxoInit) +{ + /* Do not disable LFXO if it is currently selected as HF/Core clock */ + EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_LFXO); + + /* LFXO must be disabled before reconfiguration */ + CMU_OscillatorEnable(cmuOsc_LFXO, false, false); + + BUS_RegMaskedWrite(&CMU->LFXOCTRL, + _CMU_LFXOCTRL_TUNING_MASK + | _CMU_LFXOCTRL_GAIN_MASK + | _CMU_LFXOCTRL_TIMEOUT_MASK, + (lfxoInit->ctune << _CMU_LFXOCTRL_TUNING_SHIFT) + | (lfxoInit->gain << _CMU_LFXOCTRL_GAIN_SHIFT) + | (lfxoInit->timeout << _CMU_LFXOCTRL_TIMEOUT_SHIFT)); +} +#endif + + /***************************************************************************//** * @brief * Enable/disable oscillator. @@ -2239,76 +3393,125 @@ ******************************************************************************/ void CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait) { - uint32_t status; + uint32_t rdyBitPos; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + uint32_t ensBitPos; +#endif uint32_t enBit; uint32_t disBit; switch (osc) { - case cmuOsc_HFRCO: - enBit = CMU_OSCENCMD_HFRCOEN; - disBit = CMU_OSCENCMD_HFRCODIS; - status = CMU_STATUS_HFRCORDY; - break; - - case cmuOsc_HFXO: - enBit = CMU_OSCENCMD_HFXOEN; - disBit = CMU_OSCENCMD_HFXODIS; - status = CMU_STATUS_HFXORDY; - break; - - case cmuOsc_AUXHFRCO: - enBit = CMU_OSCENCMD_AUXHFRCOEN; - disBit = CMU_OSCENCMD_AUXHFRCODIS; - status = CMU_STATUS_AUXHFRCORDY; - break; - - case cmuOsc_LFRCO: - enBit = CMU_OSCENCMD_LFRCOEN; - disBit = CMU_OSCENCMD_LFRCODIS; - status = CMU_STATUS_LFRCORDY; - break; - - case cmuOsc_LFXO: - enBit = CMU_OSCENCMD_LFXOEN; - disBit = CMU_OSCENCMD_LFXODIS; - status = CMU_STATUS_LFXORDY; - break; + case cmuOsc_HFRCO: + enBit = CMU_OSCENCMD_HFRCOEN; + disBit = CMU_OSCENCMD_HFRCODIS; + rdyBitPos = _CMU_STATUS_HFRCORDY_SHIFT; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + ensBitPos = _CMU_STATUS_HFRCOENS_SHIFT; +#endif + break; + + case cmuOsc_HFXO: + enBit = CMU_OSCENCMD_HFXOEN; + disBit = CMU_OSCENCMD_HFXODIS; + rdyBitPos = _CMU_STATUS_HFXORDY_SHIFT; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + ensBitPos = _CMU_STATUS_HFXOENS_SHIFT; +#endif + break; + + case cmuOsc_AUXHFRCO: + enBit = CMU_OSCENCMD_AUXHFRCOEN; + disBit = CMU_OSCENCMD_AUXHFRCODIS; + rdyBitPos = _CMU_STATUS_AUXHFRCORDY_SHIFT; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + ensBitPos = _CMU_STATUS_AUXHFRCOENS_SHIFT; +#endif + break; + + case cmuOsc_LFRCO: + enBit = CMU_OSCENCMD_LFRCOEN; + disBit = CMU_OSCENCMD_LFRCODIS; + rdyBitPos = _CMU_STATUS_LFRCORDY_SHIFT; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + ensBitPos = _CMU_STATUS_LFRCOENS_SHIFT; +#endif + break; + + case cmuOsc_LFXO: + enBit = CMU_OSCENCMD_LFXOEN; + disBit = CMU_OSCENCMD_LFXODIS; + rdyBitPos = _CMU_STATUS_LFXORDY_SHIFT; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + ensBitPos = _CMU_STATUS_LFXOENS_SHIFT; +#endif + break; #if defined( _CMU_STATUS_USHFRCOENS_MASK ) - case cmuOsc_USHFRCO: - enBit = CMU_OSCENCMD_USHFRCOEN; - disBit = CMU_OSCENCMD_USHFRCODIS; - status = CMU_STATUS_USHFRCORDY; - break; + case cmuOsc_USHFRCO: + enBit = CMU_OSCENCMD_USHFRCOEN; + disBit = CMU_OSCENCMD_USHFRCODIS; + rdyBitPos = _CMU_STATUS_USHFRCORDY_SHIFT; +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + ensBitPos = _CMU_STATUS_USHFRCOENS_SHIFT; +#endif + break; #endif -#if defined( _CMU_LFCLKSEL_LFAE_ULFRCO ) - case cmuOsc_ULFRCO: - /* ULFRCO is always enabled, and cannot be turned off */ - return; +#if defined( CMU_LFCLKSEL_LFAE_ULFRCO ) + case cmuOsc_ULFRCO: + /* ULFRCO is always enabled, and cannot be turned off */ + return; #endif - default: - /* Undefined clock source */ - EFM_ASSERT(0); - return; + default: + /* Undefined clock source */ + EFM_ASSERT(0); + return; } if (enable) { CMU->OSCENCMD = enBit; - /* Wait for clock to stabilize if requested */ +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + /* Always wait for ENS to go high */ + while (!BUS_RegBitRead(&CMU->STATUS, ensBitPos)) + { + } +#endif + + /* Wait for clock to become ready after enable */ if (wait) { - while (!(CMU->STATUS & status)) - ; + while (!BUS_RegBitRead(&CMU->STATUS, rdyBitPos)); +#if defined( _CMU_STATUS_HFXOSHUNTOPTRDY_MASK ) + /* Wait for shunt current optimization to complete */ + if ((osc == cmuOsc_HFXO) + && (BUS_RegMaskedRead(&CMU->HFXOCTRL, + _CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK) + == CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_AUTOCMD)) + { + while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_HFXOSHUNTOPTRDY_SHIFT)) + { + } + /* Assert on failed peak detection. Incorrect HFXO initialization parameters + caused startup to fail. Please review parameters. */ + EFM_ASSERT(BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_HFXOPEAKDETRDY_SHIFT)); + } +#endif } } else { CMU->OSCENCMD = disBit; + +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + /* Always wait for ENS to go low */ + while (BUS_RegBitRead(&CMU->STATUS, ensBitPos)) + { + } +#endif } /* Keep EMU module informed */ @@ -2335,28 +3538,28 @@ switch (osc) { - case cmuOsc_LFRCO: - ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK) >> - _CMU_LFRCOCTRL_TUNING_SHIFT; - break; - - case cmuOsc_HFRCO: - ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK) >> - _CMU_HFRCOCTRL_TUNING_SHIFT; - break; - - case cmuOsc_AUXHFRCO: - ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK) >> - _CMU_AUXHFRCOCTRL_TUNING_SHIFT; - break; - - default: - EFM_ASSERT(0); - ret = 0; - break; + case cmuOsc_LFRCO: + ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK) + >> _CMU_LFRCOCTRL_TUNING_SHIFT; + break; + + case cmuOsc_HFRCO: + ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK) + >> _CMU_HFRCOCTRL_TUNING_SHIFT; + break; + + case cmuOsc_AUXHFRCO: + ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK) + >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT; + break; + + default: + EFM_ASSERT(0); + ret = 0; + break; } - return(ret); + return ret; } @@ -2382,33 +3585,46 @@ { switch (osc) { - case cmuOsc_LFRCO: - EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT)); - - val &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT); - CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK)) | - (val << _CMU_LFRCOCTRL_TUNING_SHIFT); - break; - - case cmuOsc_HFRCO: - EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT)); - - val &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT); - CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK)) | - (val << _CMU_HFRCOCTRL_TUNING_SHIFT); - break; - - case cmuOsc_AUXHFRCO: - EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT)); - - val <<= _CMU_AUXHFRCOCTRL_TUNING_SHIFT; - val &= _CMU_AUXHFRCOCTRL_TUNING_MASK; - CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK)) | val; - break; - - default: - EFM_ASSERT(0); - break; + case cmuOsc_LFRCO: + EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK + >> _CMU_LFRCOCTRL_TUNING_SHIFT)); + val &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT); +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_LFRCOBSY_SHIFT)); +#endif + CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK)) + | (val << _CMU_LFRCOCTRL_TUNING_SHIFT); + break; + + case cmuOsc_HFRCO: + EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK + >> _CMU_HFRCOCTRL_TUNING_SHIFT)); + val &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT); +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT)) + { + } +#endif + CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK)) + | (val << _CMU_HFRCOCTRL_TUNING_SHIFT); + break; + + case cmuOsc_AUXHFRCO: + EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK + >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT)); + val &= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT); +#if defined( _SILICON_LABS_32B_PLATFORM_2 ) + while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT)) + { + } +#endif + CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK)) + | (val << _CMU_AUXHFRCOCTRL_TUNING_SHIFT); + break; + + default: + EFM_ASSERT(0); + break; } } @@ -2417,52 +3633,42 @@ * @brief * Determine if currently selected PCNTn clock used is external or LFBCLK. * - * @param[in] inst + * @param[in] instance * PCNT instance number to get currently selected clock source for. * * @return * @li true - selected clock is external clock. * @li false - selected clock is LFBCLK. *****************************************************************************/ -bool CMU_PCNTClockExternalGet(unsigned int inst) +bool CMU_PCNTClockExternalGet(unsigned int instance) { - bool ret; uint32_t setting; - switch (inst) + switch (instance) { -#if defined(_CMU_PCNTCTRL_PCNT0CLKEN_MASK) - case 0: - setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0; - break; - -#if defined(_CMU_PCNTCTRL_PCNT1CLKEN_MASK) - case 1: - setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0; - break; - -#if defined(_CMU_PCNTCTRL_PCNT2CLKEN_MASK) - case 2: - setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0; - break; +#if defined( _CMU_PCNTCTRL_PCNT0CLKEN_MASK ) + case 0: + setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0; + break; + +#if defined( _CMU_PCNTCTRL_PCNT1CLKEN_MASK ) + case 1: + setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0; + break; + +#if defined( _CMU_PCNTCTRL_PCNT2CLKEN_MASK ) + case 2: + setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0; + break; #endif #endif #endif - default: - setting = 0; - break; + default: + setting = 0; + break; } - - if (setting) - { - ret = true; - } - else - { - ret = false; - } - return ret; + return (setting ? true : false); } @@ -2470,33 +3676,111 @@ * @brief * Select PCNTn clock. * - * @param[in] inst + * @param[in] instance * PCNT instance number to set selected clock source for. * * @param[in] external * Set to true to select external clock, false to select LFBCLK. *****************************************************************************/ -void CMU_PCNTClockExternalSet(unsigned int inst, bool external) +void CMU_PCNTClockExternalSet(unsigned int instance, bool external) { -#if defined(PCNT_PRESENT) +#if defined( PCNT_PRESENT ) uint32_t setting = 0; - EFM_ASSERT(inst < PCNT_COUNT); + EFM_ASSERT(instance < PCNT_COUNT); if (external) { setting = 1; } - BITBAND_Peripheral(&(CMU->PCNTCTRL), (inst * 2) + 1, setting); + BUS_RegBitWrite(&(CMU->PCNTCTRL), (instance * 2) + 1, setting); #else - (void)inst; /* Unused parameter */ + (void)instance; /* Unused parameter */ (void)external; /* Unused parameter */ #endif } +#if defined( _CMU_USHFRCOCONF_BAND_MASK ) +/***************************************************************************//** + * @brief + * Get USHFRCO band in use. + * + * @return + * USHFRCO band in use. + ******************************************************************************/ +CMU_USHFRCOBand_TypeDef CMU_USHFRCOBandGet(void) +{ + return (CMU_USHFRCOBand_TypeDef)((CMU->USHFRCOCONF + & _CMU_USHFRCOCONF_BAND_MASK) + >> _CMU_USHFRCOCONF_BAND_SHIFT); +} +#endif + +#if defined( _CMU_USHFRCOCONF_BAND_MASK ) +/***************************************************************************//** + * @brief + * Set USHFRCO band to use. + * + * @param[in] band + * USHFRCO band to activate. + ******************************************************************************/ +void CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band) +{ + uint32_t tuning; + uint32_t fineTuning; + CMU_Select_TypeDef osc; + + /* Cannot switch band if USHFRCO is already selected as HF clock. */ + osc = CMU_ClockSelectGet(cmuClock_HF); + EFM_ASSERT((CMU_USHFRCOBandGet() != band) && (osc != cmuSelect_USHFRCO)); + + /* Read tuning value from calibration table */ + switch (band) + { + case cmuUSHFRCOBand_24MHz: + tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_TUNING_MASK) + >> _DEVINFO_USHFRCOCAL0_BAND24_TUNING_SHIFT; + fineTuning = (DEVINFO->USHFRCOCAL0 + & _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_MASK) + >> _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_SHIFT; + break; + + case cmuUSHFRCOBand_48MHz: + tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_TUNING_MASK) + >> _DEVINFO_USHFRCOCAL0_BAND48_TUNING_SHIFT; + fineTuning = (DEVINFO->USHFRCOCAL0 + & _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_MASK) + >> _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_SHIFT; + /* Enable the clock divider before switching the band from 24 to 48MHz */ + BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 0); + break; + + default: + EFM_ASSERT(0); + return; + } + + /* Set band and tuning */ + CMU->USHFRCOCONF = (CMU->USHFRCOCONF & ~_CMU_USHFRCOCONF_BAND_MASK) + | (band << _CMU_USHFRCOCONF_BAND_SHIFT); + CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~_CMU_USHFRCOCTRL_TUNING_MASK) + | (tuning << _CMU_USHFRCOCTRL_TUNING_SHIFT); + CMU->USHFRCOTUNE = (CMU->USHFRCOTUNE & ~_CMU_USHFRCOTUNE_FINETUNING_MASK) + | (fineTuning << _CMU_USHFRCOTUNE_FINETUNING_SHIFT); + + /* Disable the clock divider after switching the band from 48 to 24MHz */ + if (band == cmuUSHFRCOBand_24MHz) + { + BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 1); + } +} +#endif + + + /** @} (end addtogroup CMU) */ /** @} (end addtogroup EM_Library) */ #endif /* __EM_CMU_H */