1 /***************************************************************************//**
\r
3 * @brief Clock management unit (CMU) Peripheral API
\r
5 *******************************************************************************
\r
7 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
\r
8 *******************************************************************************
\r
10 * Permission is granted to anyone to use this software for any purpose,
\r
11 * including commercial applications, and to alter it and redistribute it
\r
12 * freely, subject to the following restrictions:
\r
14 * 1. The origin of this software must not be misrepresented; you must not
\r
15 * claim that you wrote the original software.
\r
16 * 2. Altered source versions must be plainly marked as such, and must not be
\r
17 * misrepresented as being the original software.
\r
18 * 3. This notice may not be removed or altered from any source distribution.
\r
20 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
\r
21 * obligation to support this Software. Silicon Labs is providing the
\r
22 * Software "AS IS", with no express or implied warranties of any kind,
\r
23 * including, but not limited to, any implied warranties of merchantability
\r
24 * or fitness for any particular purpose or warranties against infringement
\r
25 * of any proprietary rights of a third party.
\r
27 * Silicon Labs will not be liable for any consequential, incidental, or
\r
28 * special damages, or any other relief, or for any claim by any third party,
\r
29 * arising from your use of this Software.
\r
31 ******************************************************************************/
\r
35 #if defined( CMU_PRESENT )
\r
37 #include "em_assert.h"
\r
38 #include "em_bitband.h"
\r
41 /***************************************************************************//**
\r
42 * @addtogroup EM_Library
\r
44 ******************************************************************************/
\r
46 /***************************************************************************//**
\r
48 * @brief Clock management unit (CMU) Peripheral API
\r
50 ******************************************************************************/
\r
52 /*******************************************************************************
\r
53 ****************************** DEFINES ************************************
\r
54 ******************************************************************************/
\r
56 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
\r
58 /** Maximum allowed core frequency when using 0 wait states on flash access. */
\r
59 #define CMU_MAX_FREQ_0WS 16000000
\r
60 /** Maximum allowed core frequency when using 1 wait states on flash access */
\r
61 #define CMU_MAX_FREQ_1WS 32000000
\r
63 #if defined( CMU_CTRL_HFLE )
\r
64 /** Maximum frequency for HFLE needs to be enabled on Giant, Leopard and
\r
66 #if defined ( _EFM32_WONDER_FAMILY ) || \
\r
67 defined ( _EZR32_LEOPARD_FAMILY ) || \
\r
68 defined ( _EZR32_WONDER_FAMILY )
\r
69 #define CMU_MAX_FREQ_HFLE 24000000
\r
70 #elif defined ( _EFM32_GIANT_FAMILY )
\r
71 #define CMU_MAX_FREQ_HFLE (CMU_MaxFreqHfle())
\r
73 #error Invalid part/device.
\r
77 /** Low frequency A group identifier */
\r
80 /** Low frequency B group identifier */
\r
85 /*******************************************************************************
\r
86 ************************** LOCAL FUNCTIONS ********************************
\r
87 ******************************************************************************/
\r
89 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
\r
91 #if defined( CMU_CTRL_HFLE ) && \
\r
92 !defined ( _EFM32_WONDER_FAMILY ) && \
\r
93 !defined ( _EZR32_LEOPARD_FAMILY ) && \
\r
94 !defined ( _EZR32_WONDER_FAMILY )
\r
96 /***************************************************************************//**
\r
98 * Return max allowed frequency for low energy peripherals.
\r
99 ******************************************************************************/
\r
100 static uint32_t CMU_MaxFreqHfle(void)
\r
102 /* SYSTEM_GetFamily and SYSTEM_ChipRevisionGet could have been used here
\r
103 but we want to minimize dependencies in em_cmu.c. */
\r
104 uint16_t majorMinorRev;
\r
105 uint8_t deviceFamily = ((DEVINFO->PART & _DEVINFO_PART_DEVICE_FAMILY_MASK)
\r
106 >> _DEVINFO_PART_DEVICE_FAMILY_SHIFT);
\r
107 switch (deviceFamily)
\r
109 case _DEVINFO_PART_DEVICE_FAMILY_LG:
\r
110 /* CHIP MAJOR bit [3:0] */
\r
111 majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)
\r
112 >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8);
\r
113 /* CHIP MINOR bit [7:4] */
\r
114 majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)
\r
115 >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);
\r
116 /* CHIP MINOR bit [3:0] */
\r
117 majorMinorRev |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)
\r
118 >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);
\r
120 if (majorMinorRev >= 0x0204)
\r
124 case _DEVINFO_PART_DEVICE_FAMILY_GG:
\r
126 case _DEVINFO_PART_DEVICE_FAMILY_WG:
\r
129 /* Invalid device family. */
\r
137 /***************************************************************************//**
\r
139 * Configure flash access wait states in order to support given core clock
\r
142 * @param[in] hfcoreclk
\r
143 * Core clock frequency to configure flash wait-states for
\r
144 ******************************************************************************/
\r
145 static void CMU_FlashWaitStateControl(uint32_t hfcoreclk)
\r
149 #if defined( MSC_READCTRL_MODE_WS0SCBTP )
\r
153 /* Make sure the MSC is unlocked */
\r
154 mscLocked = MSC->LOCK;
\r
155 MSC->LOCK = MSC_UNLOCK_CODE;
\r
157 /* Get mode and SCBTP enable */
\r
158 mode = MSC->READCTRL & _MSC_READCTRL_MODE_MASK;
\r
159 #if defined( MSC_READCTRL_MODE_WS0SCBTP )
\r
162 case MSC_READCTRL_MODE_WS0:
\r
163 case MSC_READCTRL_MODE_WS1:
\r
164 #if defined( MSC_READCTRL_MODE_WS2 )
\r
165 case MSC_READCTRL_MODE_WS2:
\r
170 default: /* WSxSCBTP */
\r
177 /* Set mode based on the core clock frequency and SCBTP enable */
\r
178 #if defined( MSC_READCTRL_MODE_WS0SCBTP )
\r
182 #if defined( MSC_READCTRL_MODE_WS2 )
\r
183 else if (hfcoreclk > CMU_MAX_FREQ_1WS)
\r
185 mode = (scbtpEn ? MSC_READCTRL_MODE_WS2SCBTP : MSC_READCTRL_MODE_WS2);
\r
188 else if ((hfcoreclk <= CMU_MAX_FREQ_1WS) && (hfcoreclk > CMU_MAX_FREQ_0WS))
\r
190 mode = (scbtpEn ? MSC_READCTRL_MODE_WS1SCBTP : MSC_READCTRL_MODE_WS1);
\r
194 mode = (scbtpEn ? MSC_READCTRL_MODE_WS0SCBTP : MSC_READCTRL_MODE_WS0);
\r
197 #else /* If MODE and SCBTP is in separate register fields */
\r
202 #if defined( MSC_READCTRL_MODE_WS2 )
\r
203 else if (hfcoreclk > CMU_MAX_FREQ_1WS)
\r
205 mode = MSC_READCTRL_MODE_WS2;
\r
208 else if ((hfcoreclk <= CMU_MAX_FREQ_1WS) && (hfcoreclk > CMU_MAX_FREQ_0WS))
\r
210 mode = MSC_READCTRL_MODE_WS1;
\r
214 mode = MSC_READCTRL_MODE_WS0;
\r
218 /* BUS_RegMaskedWrite cannot be used here as it would temporarely set the
\r
219 mode field to WS0 */
\r
220 MSC->READCTRL = (MSC->READCTRL &~_MSC_READCTRL_MODE_MASK) | mode;
\r
229 /***************************************************************************//**
\r
231 * Configure flash access wait states to most conservative setting for
\r
232 * this target. Retain SCBTP setting.
\r
233 ******************************************************************************/
\r
234 static void CMU_FlashWaitStateMax(void)
\r
236 uint32_t maxCoreClock;
\r
237 #if defined (_EFM32_GECKO_FAMILY)
\r
238 maxCoreClock = 32000000;
\r
239 #elif defined (_EFM32_GIANT_FAMILY)
\r
240 maxCoreClock = 48000000;
\r
241 #elif defined (_EFM32_TINY_FAMILY)
\r
242 maxCoreClock = 32000000;
\r
243 #elif defined (_EFM32_LEOPARD_FAMILY)
\r
244 maxCoreClock = 48000000;
\r
245 #elif defined (_EFM32_WONDER_FAMILY)
\r
246 maxCoreClock = 48000000;
\r
247 #elif defined (_EFM32_ZERO_FAMILY)
\r
248 maxCoreClock = 24000000;
\r
249 #elif defined (_EFM32_HAPPY_FAMILY)
\r
250 maxCoreClock = 25000000;
\r
252 #error "Max core clock frequency is not defined for this family"
\r
255 /* Use SystemMaxCoreClockGet() when available in CMSIS */
\r
256 CMU_FlashWaitStateControl(maxCoreClock);
\r
260 /***************************************************************************//**
\r
261 * @brief Convert dividend to prescaler logarithmic value. Only works for even
\r
262 * numbers equal to 2^n
\r
263 * @param[in] div Unscaled dividend,
\r
264 * @return Base 2 logarithm of input, as used by fixed prescalers
\r
265 ******************************************************************************/
\r
266 __STATIC_INLINE uint32_t CMU_DivToLog2(CMU_ClkDiv_TypeDef div)
\r
270 /* Prescalers take argument of 32768 or less */
\r
271 EFM_ASSERT((div>0) && (div <= 32768));
\r
273 /* Count leading zeroes and "reverse" result, Cortex-M3 intrinsic */
\r
274 log2 = (31 - __CLZ(div));
\r
280 /***************************************************************************//**
\r
281 * @brief Convert logarithm of 2 prescaler to division factor
\r
284 ******************************************************************************/
\r
285 __STATIC_INLINE uint32_t CMU_Log2ToDiv(uint32_t log2)
\r
291 #if defined(USB_PRESENT)
\r
292 /***************************************************************************//**
\r
294 * Get the USBC frequency
\r
297 * USBC frequency in Hz
\r
298 ******************************************************************************/
\r
299 static uint32_t CMU_USBCClkGet(void)
\r
302 CMU_Select_TypeDef clk;
\r
304 /* Get selected clock source */
\r
305 clk = CMU_ClockSelectGet(cmuClock_USBC);
\r
309 case cmuSelect_LFXO:
\r
310 ret = SystemLFXOClockGet();
\r
312 case cmuSelect_LFRCO:
\r
313 ret = SystemLFRCOClockGet();
\r
315 case cmuSelect_HFCLK:
\r
316 ret = SystemHFClockGet();
\r
319 /* Clock is not enabled */
\r
328 /***************************************************************************//**
\r
330 * Get the AUX clock frequency. Used by MSC flash programming and LESENSE,
\r
331 * by default also as debug clock.
\r
334 * AUX Frequency in Hz
\r
335 ******************************************************************************/
\r
336 static uint32_t CMU_AUXClkGet(void)
\r
340 #if defined(_EFM32_GECKO_FAMILY)
\r
341 /* Gecko has a fixed 14Mhz AUXHFRCO clock */
\r
344 switch(CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK)
\r
346 case CMU_AUXHFRCOCTRL_BAND_1MHZ:
\r
349 case CMU_AUXHFRCOCTRL_BAND_7MHZ:
\r
352 case CMU_AUXHFRCOCTRL_BAND_11MHZ:
\r
355 case CMU_AUXHFRCOCTRL_BAND_14MHZ:
\r
358 case CMU_AUXHFRCOCTRL_BAND_21MHZ:
\r
361 #if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )
\r
362 case CMU_AUXHFRCOCTRL_BAND_28MHZ:
\r
375 /***************************************************************************//**
\r
377 * Get the Debug Trace clock frequency
\r
380 * Debug Trace frequency in Hz
\r
381 ******************************************************************************/
\r
382 static uint32_t CMU_DBGClkGet(void)
\r
385 CMU_Select_TypeDef clk;
\r
387 /* Get selected clock source */
\r
388 clk = CMU_ClockSelectGet(cmuClock_DBG);
\r
392 case cmuSelect_HFCLK:
\r
393 ret = SystemHFClockGet();
\r
394 #if defined( _CMU_CTRL_HFCLKDIV_MASK )
\r
395 /* Giant Gecko has an additional divider, not used by USBC */
\r
396 ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>
\r
397 _CMU_CTRL_HFCLKDIV_SHIFT));
\r
401 case cmuSelect_AUXHFRCO:
\r
402 ret = CMU_AUXClkGet();
\r
414 /***************************************************************************//**
\r
416 * Get the LFnCLK frequency based on current configuration.
\r
418 * @param[in] lfClkBranch
\r
419 * LF branch, 0 = LFA, 1 = LFB, ...
\r
422 * The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is
\r
424 ******************************************************************************/
\r
425 static uint32_t CMU_LFClkGet(unsigned int lfClkBranch)
\r
429 EFM_ASSERT(lfClkBranch == CMU_LFA || lfClkBranch == CMU_LFB);
\r
431 switch ((CMU->LFCLKSEL >> (lfClkBranch * 2)) & 0x3)
\r
433 case _CMU_LFCLKSEL_LFA_LFRCO:
\r
434 ret = SystemLFRCOClockGet();
\r
437 case _CMU_LFCLKSEL_LFA_LFXO:
\r
438 ret = SystemLFXOClockGet();
\r
441 case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
\r
442 #if defined( CMU_CTRL_HFLE )
\r
443 /* Giant Gecko can use a /4 divider (and must if >32MHz) or HFLE is set */
\r
444 if(((CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK) == CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4)||
\r
445 (CMU->CTRL & CMU_CTRL_HFLE))
\r
447 ret = SystemCoreClockGet() / 4;
\r
451 ret = SystemCoreClockGet() / 2;
\r
454 ret = SystemCoreClockGet() / 2;
\r
458 case _CMU_LFCLKSEL_LFA_DISABLED:
\r
459 #if defined( CMU_LFCLKSEL_LFAE )
\r
460 /* Check LF Extended bit setting for ULFRCO clock */
\r
461 if(CMU->LFCLKSEL >> (_CMU_LFCLKSEL_LFAE_SHIFT + lfClkBranch * 4))
\r
463 ret = SystemULFRCOClockGet();
\r
483 /***************************************************************************//**
\r
485 * Wait for ongoing sync of register(s) to low frequency domain to complete.
\r
488 * Bitmask corresponding to SYNCBUSY register defined bits, indicating
\r
489 * registers that must complete any ongoing synchronization.
\r
490 ******************************************************************************/
\r
491 __STATIC_INLINE void CMU_Sync(uint32_t mask)
\r
493 /* Avoid deadlock if modifying the same register twice when freeze mode is */
\r
495 if (CMU->FREEZE & CMU_FREEZE_REGFREEZE)
\r
498 /* Wait for any pending previous write operation to have been completed */
\r
499 /* in low frequency domain */
\r
500 while (CMU->SYNCBUSY & mask)
\r
507 /*******************************************************************************
\r
508 ************************** GLOBAL FUNCTIONS *******************************
\r
509 ******************************************************************************/
\r
511 /***************************************************************************//**
\r
516 * Run a calibration for HFCLK against a selectable reference clock. Please
\r
517 * refer to the EFM32 reference manual, CMU chapter, for further details.
\r
520 * This function will not return until calibration measurement is completed.
\r
522 * @param[in] HFCycles
\r
523 * The number of HFCLK cycles to run calibration. Increasing this number
\r
524 * increases precision, but the calibration will take more time.
\r
527 * The reference clock used to compare HFCLK with.
\r
530 * The number of ticks the reference clock after HFCycles ticks on the HF
\r
532 ******************************************************************************/
\r
533 uint32_t CMU_Calibrate(uint32_t HFCycles, CMU_Osc_TypeDef ref)
\r
535 EFM_ASSERT(HFCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));
\r
537 /* Set reference clock source */
\r
541 CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO;
\r
545 CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO;
\r
549 CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO;
\r
553 CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO;
\r
556 case cmuOsc_AUXHFRCO:
\r
557 CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO;
\r
565 /* Set top value */
\r
566 CMU->CALCNT = HFCycles;
\r
568 /* Start calibration */
\r
569 CMU->CMD = CMU_CMD_CALSTART;
\r
571 /* Wait until calibration completes */
\r
572 while (CMU->STATUS & CMU_STATUS_CALBSY)
\r
575 return CMU->CALCNT;
\r
579 #if defined( _CMU_CALCTRL_UPSEL_MASK ) && defined( _CMU_CALCTRL_DOWNSEL_MASK )
\r
580 /***************************************************************************//**
\r
582 * Configure clock calibration
\r
585 * Configure a calibration for a selectable clock source against another
\r
586 * selectable reference clock.
\r
587 * Refer to the EFM32 reference manual, CMU chapter, for further details.
\r
590 * After configuration, a call to CMU_CalibrateStart() is required, and
\r
591 * the resulting calibration value can be read out with the
\r
592 * CMU_CalibrateCountGet() function call.
\r
594 * @param[in] downCycles
\r
595 * The number of downSel clock cycles to run calibration. Increasing this
\r
596 * number increases precision, but the calibration will take more time.
\r
598 * @param[in] downSel
\r
599 * The clock which will be counted down downCycles
\r
602 * The reference clock, the number of cycles generated by this clock will
\r
603 * be counted and added up, the result can be given with the
\r
604 * CMU_CalibrateCountGet() function call.
\r
605 ******************************************************************************/
\r
606 void CMU_CalibrateConfig(uint32_t downCycles, CMU_Osc_TypeDef downSel,
\r
607 CMU_Osc_TypeDef upSel)
\r
609 /* Keep untouched configuration settings */
\r
610 uint32_t calCtrl = CMU->CALCTRL & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK);
\r
612 /* 20 bits of precision to calibration count register */
\r
613 EFM_ASSERT(downCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));
\r
615 /* Set down counting clock source - down counter */
\r
619 calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO;
\r
623 calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO;
\r
627 calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO;
\r
631 calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO;
\r
634 case cmuOsc_AUXHFRCO:
\r
635 calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO;
\r
643 /* Set top value to be counted down by the downSel clock */
\r
644 CMU->CALCNT = downCycles;
\r
646 /* Set reference clock source - up counter */
\r
650 calCtrl |= CMU_CALCTRL_UPSEL_LFXO;
\r
654 calCtrl |= CMU_CALCTRL_UPSEL_LFRCO;
\r
658 calCtrl |= CMU_CALCTRL_UPSEL_HFXO;
\r
662 calCtrl |= CMU_CALCTRL_UPSEL_HFRCO;
\r
665 case cmuOsc_AUXHFRCO:
\r
666 calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO;
\r
674 CMU->CALCTRL = calCtrl;
\r
679 /***************************************************************************//**
\r
681 * Get clock divisor/prescaler.
\r
684 * Clock point to get divisor/prescaler for. Notice that not all clock points
\r
685 * have a divisor/prescaler. Please refer to CMU overview in reference manual.
\r
688 * The current clock point divisor/prescaler. 1 is returned
\r
689 * if @p clock specifies a clock point without a divisor/prescaler.
\r
690 ******************************************************************************/
\r
691 CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock)
\r
694 CMU_ClkDiv_TypeDef ret;
\r
696 /* Get divisor reg id */
\r
697 divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;
\r
701 #if defined( _CMU_CTRL_HFCLKDIV_MASK )
\r
702 case CMU_HFCLKDIV_REG:
\r
703 ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>
\r
704 _CMU_CTRL_HFCLKDIV_SHIFT);
\r
708 case CMU_HFPERCLKDIV_REG:
\r
709 ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV &
\r
710 _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >>
\r
711 _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);
\r
712 ret = CMU_Log2ToDiv(ret);
\r
715 case CMU_HFCORECLKDIV_REG:
\r
716 ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV &
\r
717 _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >>
\r
718 _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);
\r
719 ret = CMU_Log2ToDiv(ret);
\r
722 case CMU_LFAPRESC0_REG:
\r
726 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) >>
\r
727 _CMU_LFAPRESC0_RTC_SHIFT));
\r
728 ret = CMU_Log2ToDiv(ret);
\r
731 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
\r
732 case cmuClock_LETIMER0:
\r
733 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) >>
\r
734 _CMU_LFAPRESC0_LETIMER0_SHIFT));
\r
735 ret = CMU_Log2ToDiv(ret);
\r
739 #if defined(_CMU_LFAPRESC0_LCD_MASK)
\r
740 case cmuClock_LCDpre:
\r
741 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>
\r
742 _CMU_LFAPRESC0_LCD_SHIFT) + CMU_DivToLog2(cmuClkDiv_16));
\r
743 ret = CMU_Log2ToDiv(ret);
\r
747 #if defined(_CMU_LFAPRESC0_LESENSE_MASK)
\r
748 case cmuClock_LESENSE:
\r
749 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) >>
\r
750 _CMU_LFAPRESC0_LESENSE_SHIFT));
\r
751 ret = CMU_Log2ToDiv(ret);
\r
762 case CMU_LFBPRESC0_REG:
\r
765 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)
\r
766 case cmuClock_LEUART0:
\r
767 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) >>
\r
768 _CMU_LFBPRESC0_LEUART0_SHIFT));
\r
769 ret = CMU_Log2ToDiv(ret);
\r
773 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)
\r
774 case cmuClock_LEUART1:
\r
775 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) >>
\r
776 _CMU_LFBPRESC0_LEUART1_SHIFT));
\r
777 ret = CMU_Log2ToDiv(ret);
\r
798 /***************************************************************************//**
\r
800 * Set clock divisor/prescaler.
\r
803 * If setting a LF clock prescaler, synchronization into the low frequency
\r
804 * domain is required. If the same register is modified before a previous
\r
805 * update has completed, this function will stall until the previous
\r
806 * synchronization has completed. Please refer to CMU_FreezeEnable() for
\r
807 * a suggestion on how to reduce stalling time in some use cases.
\r
810 * Clock point to set divisor/prescaler for. Notice that not all clock points
\r
811 * have a divisor/prescaler, please refer to CMU overview in the reference
\r
815 * The clock divisor to use (<= cmuClkDiv_512).
\r
816 ******************************************************************************/
\r
817 void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)
\r
822 /* Get divisor reg id */
\r
823 divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;
\r
827 #if defined( _CMU_CTRL_HFCLKDIV_MASK )
\r
828 case CMU_HFCLKDIV_REG:
\r
829 EFM_ASSERT((div>=cmuClkDiv_1) && (div<=cmuClkDiv_8));
\r
831 /* Configure worst case wait states for flash access before setting divisor */
\r
832 CMU_FlashWaitStateMax();
\r
835 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK) |
\r
836 ((div-1) << _CMU_CTRL_HFCLKDIV_SHIFT);
\r
838 /* Update CMSIS core clock variable */
\r
839 /* (The function will update the global variable) */
\r
840 freq = SystemCoreClockGet();
\r
842 /* Optimize flash access wait state setting for current core clk */
\r
843 CMU_FlashWaitStateControl(freq);
\r
847 case CMU_HFPERCLKDIV_REG:
\r
848 EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512));
\r
849 /* Convert to correct scale */
\r
850 div = CMU_DivToLog2(div);
\r
851 CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) |
\r
852 (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);
\r
855 case CMU_HFCORECLKDIV_REG:
\r
856 EFM_ASSERT(div <= cmuClkDiv_512);
\r
858 /* Configure worst case wait states for flash access before setting divisor */
\r
859 CMU_FlashWaitStateMax();
\r
861 #if defined( CMU_CTRL_HFLE )
\r
862 /* Clear HFLE and set DIV2 factor for peripheral clock
\r
863 when running at frequencies lower than or equal to CMU_MAX_FREQ_HFLE. */
\r
864 if ((CMU_ClockFreqGet(cmuClock_HF) / div) <= CMU_MAX_FREQ_HFLE)
\r
866 /* Clear CMU HFLE */
\r
867 BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 0);
\r
869 /* Set DIV2 factor for peripheral clock */
\r
870 BITBAND_Peripheral(&(CMU->HFCORECLKDIV),
\r
871 _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 0);
\r
876 BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1);
\r
878 /* Set DIV4 factor for peripheral clock */
\r
879 BITBAND_Peripheral(&(CMU->HFCORECLKDIV),
\r
880 _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
\r
884 /* Convert to correct scale */
\r
885 div = CMU_DivToLog2(div);
\r
887 CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) |
\r
888 (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);
\r
890 /* Update CMSIS core clock variable */
\r
891 /* (The function will update the global variable) */
\r
892 freq = SystemCoreClockGet();
\r
894 /* Optimize flash access wait state setting for current core clk */
\r
895 CMU_FlashWaitStateControl(freq);
\r
898 case CMU_LFAPRESC0_REG:
\r
902 EFM_ASSERT(div <= cmuClkDiv_32768);
\r
904 /* LF register about to be modified require sync. busy check */
\r
905 CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);
\r
907 /* Convert to correct scale */
\r
908 div = CMU_DivToLog2(div);
\r
910 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK) |
\r
911 (div << _CMU_LFAPRESC0_RTC_SHIFT);
\r
914 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
\r
915 case cmuClock_LETIMER0:
\r
916 EFM_ASSERT(div <= cmuClkDiv_32768);
\r
918 /* LF register about to be modified require sync. busy check */
\r
919 CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);
\r
921 /* Convert to correct scale */
\r
922 div = CMU_DivToLog2(div);
\r
924 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK) |
\r
925 (div << _CMU_LFAPRESC0_LETIMER0_SHIFT);
\r
929 #if defined(LCD_PRESENT)
\r
930 case cmuClock_LCDpre:
\r
931 EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128));
\r
933 /* LF register about to be modified require sync. busy check */
\r
934 CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);
\r
936 /* Convert to correct scale */
\r
937 div = CMU_DivToLog2(div);
\r
939 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK) |
\r
940 ((div - CMU_DivToLog2(cmuClkDiv_16)) << _CMU_LFAPRESC0_LCD_SHIFT);
\r
942 #endif /* defined(LCD_PRESENT) */
\r
944 #if defined(LESENSE_PRESENT)
\r
945 case cmuClock_LESENSE:
\r
946 EFM_ASSERT(div <= cmuClkDiv_8);
\r
948 /* LF register about to be modified require sync. busy check */
\r
949 CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);
\r
951 /* Convert to correct scale */
\r
952 div = CMU_DivToLog2(div);
\r
954 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK) |
\r
955 (div << _CMU_LFAPRESC0_LESENSE_SHIFT);
\r
957 #endif /* defined(LESENSE_PRESENT) */
\r
965 case CMU_LFBPRESC0_REG:
\r
968 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)
\r
969 case cmuClock_LEUART0:
\r
970 EFM_ASSERT(div <= cmuClkDiv_8);
\r
972 /* LF register about to be modified require sync. busy check */
\r
973 CMU_Sync(CMU_SYNCBUSY_LFBPRESC0);
\r
975 /* Convert to correct scale */
\r
976 div = CMU_DivToLog2(div);
\r
978 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK) |
\r
979 (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT);
\r
983 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)
\r
984 case cmuClock_LEUART1:
\r
985 EFM_ASSERT(div <= cmuClkDiv_8);
\r
987 /* LF register about to be modified require sync. busy check */
\r
988 CMU_Sync(CMU_SYNCBUSY_LFBPRESC0);
\r
990 /* Convert to correct scale */
\r
991 div = CMU_DivToLog2(div);
\r
993 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK) |
\r
994 (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT);
\r
1011 /***************************************************************************//**
\r
1013 * Enable/disable a clock.
\r
1016 * In general, module clocking is disabled after a reset. If a module
\r
1017 * clock is disabled, the registers of that module are not accessible and
\r
1018 * reading from such registers may return undefined values. Writing to
\r
1019 * registers of clock disabled modules have no effect. One should normally
\r
1020 * avoid accessing module registers of a module with a disabled clock.
\r
1023 * If enabling/disabling a LF clock, synchronization into the low frequency
\r
1024 * domain is required. If the same register is modified before a previous
\r
1025 * update has completed, this function will stall until the previous
\r
1026 * synchronization has completed. Please refer to CMU_FreezeEnable() for
\r
1027 * a suggestion on how to reduce stalling time in some use cases.
\r
1029 * @param[in] clock
\r
1030 * The clock to enable/disable. Notice that not all defined clock
\r
1031 * points have separate enable/disable control, please refer to CMU overview
\r
1032 * in reference manual.
\r
1034 * @param[in] enable
\r
1035 * @li true - enable specified clock.
\r
1036 * @li false - disable specified clock.
\r
1037 ******************************************************************************/
\r
1038 void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
\r
1040 volatile uint32_t *reg;
\r
1042 uint32_t sync = 0;
\r
1044 /* Identify enable register */
\r
1045 switch ((clock >> CMU_EN_REG_POS) & CMU_EN_REG_MASK)
\r
1047 case CMU_HFPERCLKDIV_EN_REG:
\r
1048 reg = &(CMU->HFPERCLKDIV);
\r
1051 case CMU_HFPERCLKEN0_EN_REG:
\r
1052 reg = &(CMU->HFPERCLKEN0);
\r
1055 case CMU_HFCORECLKEN0_EN_REG:
\r
1056 reg = &(CMU->HFCORECLKEN0);
\r
1058 #if defined( CMU_CTRL_HFLE )
\r
1059 /* Set HFLE and DIV4 factor for peripheral clock when
\r
1060 running at frequencies higher than or equal to CMU_MAX_FREQ_HFLE. */
\r
1061 if ( CMU_ClockFreqGet(cmuClock_CORE) > CMU_MAX_FREQ_HFLE )
\r
1063 /* Enable CMU HFLE */
\r
1064 BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1);
\r
1066 /* Set DIV4 factor for peripheral clock */
\r
1067 BITBAND_Peripheral(&(CMU->HFCORECLKDIV),
\r
1068 _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
\r
1073 case CMU_LFACLKEN0_EN_REG:
\r
1074 reg = &(CMU->LFACLKEN0);
\r
1075 sync = CMU_SYNCBUSY_LFACLKEN0;
\r
1078 case CMU_LFBCLKEN0_EN_REG:
\r
1079 reg = &(CMU->LFBCLKEN0);
\r
1080 sync = CMU_SYNCBUSY_LFBCLKEN0;
\r
1083 case CMU_PCNT_EN_REG:
\r
1084 reg = &(CMU->PCNTCTRL);
\r
1087 #if defined( _CMU_LFCCLKEN0_MASK )
\r
1088 case CMU_LFCCLKEN0_EN_REG:
\r
1089 reg = &(CMU->LFCCLKEN0);
\r
1090 sync = CMU_SYNCBUSY_LFCCLKEN0;
\r
1094 default: /* Cannot enable/disable clock point */
\r
1099 /* Get bit position used to enable/disable */
\r
1100 bit = (clock >> CMU_EN_BIT_POS) & CMU_EN_BIT_MASK;
\r
1102 /* LF synchronization required? */
\r
1108 /* Set/clear bit as requested */
\r
1109 BITBAND_Peripheral(reg, bit, (unsigned int)enable);
\r
1113 /***************************************************************************//**
\r
1115 * Get clock frequency for a clock point.
\r
1117 * @param[in] clock
\r
1118 * Clock point to fetch frequency for.
\r
1121 * The current frequency in Hz.
\r
1122 ******************************************************************************/
\r
1123 uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
\r
1127 switch(clock & (CMU_CLK_BRANCH_MASK << CMU_CLK_BRANCH_POS))
\r
1129 case (CMU_HF_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1131 ret = SystemHFClockGet();
\r
1132 #if defined( _CMU_CTRL_HFCLKDIV_MASK )
\r
1133 /* Giant Gecko has an additional divider, not used by USBC */
\r
1134 ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>
\r
1135 _CMU_CTRL_HFCLKDIV_SHIFT));
\r
1139 #if defined(_CMU_HFPERCLKEN0_USART0_MASK) || \
\r
1140 defined(_CMU_HFPERCLKEN0_USART1_MASK) || \
\r
1141 defined(_CMU_HFPERCLKEN0_USART2_MASK) || \
\r
1142 defined(_CMU_HFPERCLKEN0_UART0_MASK) || \
\r
1143 defined(_CMU_HFPERCLKEN0_UART1_MASK) || \
\r
1144 defined(_CMU_HFPERCLKEN0_TIMER0_MASK) || \
\r
1145 defined(_CMU_HFPERCLKEN0_TIMER1_MASK) || \
\r
1146 defined(_CMU_HFPERCLKEN0_TIMER2_MASK) || \
\r
1147 defined(_CMU_HFPERCLKEN0_TIMER3_MASK) || \
\r
1148 defined(_CMU_HFPERCLKEN0_ACMP0_MASK) || \
\r
1149 defined(_CMU_HFPERCLKEN0_ACMP1_MASK) || \
\r
1150 defined(_CMU_HFPERCLKEN0_DAC0_MASK) || \
\r
1151 defined(_CMU_HFPERCLKEN0_IDAC0_MASK) || \
\r
1152 defined(_CMU_HFPERCLKEN0_ADC0_MASK) || \
\r
1153 defined(_CMU_HFPERCLKEN0_I2C0_MASK) || \
\r
1154 defined(_CMU_HFPERCLKEN0_I2C1_MASK) || \
\r
1155 defined(PRS_PRESENT) || \
\r
1156 defined(VCMP_PRESENT)|| \
\r
1157 defined(GPIO_PRESENT)
\r
1158 case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1160 ret = SystemHFClockGet();
\r
1161 #if defined( _CMU_CTRL_HFCLKDIV_MASK )
\r
1162 /* Leopard/Giant Gecko has an additional divider */
\r
1163 ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>
\r
1164 _CMU_CTRL_HFCLKDIV_SHIFT));
\r
1166 ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >>
\r
1167 _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT;
\r
1171 #if defined(AES_PRESENT) || \
\r
1172 defined(DMA_PRESENT) || \
\r
1173 defined(EBI_PRESENT) || \
\r
1174 defined(USB_PRESENT)
\r
1175 case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1177 ret = SystemCoreClockGet();
\r
1181 case (CMU_LFA_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1183 ret = CMU_LFClkGet(CMU_LFA);
\r
1185 #if defined(_CMU_LFACLKEN0_RTC_MASK)
\r
1186 case (CMU_RTC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1188 ret = CMU_LFClkGet(CMU_LFA);
\r
1189 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) >>
\r
1190 _CMU_LFAPRESC0_RTC_SHIFT;
\r
1193 #if defined(_CMU_LFACLKEN0_LETIMER0_MASK)
\r
1194 case (CMU_LETIMER_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1196 ret = CMU_LFClkGet(CMU_LFA);
\r
1197 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) >>
\r
1198 _CMU_LFAPRESC0_LETIMER0_SHIFT;
\r
1201 #if defined(_CMU_LFACLKEN0_LCD_MASK)
\r
1202 case (CMU_LCDPRE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1204 ret = CMU_LFClkGet(CMU_LFA);
\r
1205 ret >>= ((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>
\r
1206 _CMU_LFAPRESC0_LCD_SHIFT) + CMU_DivToLog2(cmuClkDiv_16);
\r
1209 case (CMU_LCD_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1211 ret = CMU_LFClkGet(CMU_LFA);
\r
1212 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>
\r
1213 _CMU_LFAPRESC0_LCD_SHIFT;
\r
1214 ret /= (1 + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >>
\r
1215 _CMU_LCDCTRL_FDIV_SHIFT));
\r
1218 #if defined(_CMU_LFACLKEN0_LESENSE_MASK)
\r
1219 case (CMU_LESENSE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1221 ret = CMU_LFClkGet(CMU_LFA);
\r
1222 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) >>
\r
1223 _CMU_LFAPRESC0_LESENSE_SHIFT;
\r
1226 case (CMU_LFB_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1228 ret = CMU_LFClkGet(CMU_LFB);
\r
1230 #if defined(_CMU_LFBCLKEN0_LEUART0_MASK)
\r
1231 case (CMU_LEUART0_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1233 ret = CMU_LFClkGet(CMU_LFB);
\r
1234 ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) >>
\r
1235 _CMU_LFBPRESC0_LEUART0_SHIFT;
\r
1238 #if defined(_CMU_LFBCLKEN0_LEUART1_MASK)
\r
1239 case (CMU_LEUART1_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1241 ret = CMU_LFClkGet(CMU_LFB);
\r
1242 ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) >>
\r
1243 _CMU_LFBPRESC0_LEUART1_SHIFT;
\r
1247 case (CMU_DBG_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1249 ret = CMU_DBGClkGet();
\r
1252 case (CMU_AUX_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1254 ret = CMU_AUXClkGet();
\r
1257 #if defined(USB_PRESENT)
\r
1258 case (CMU_USBC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
\r
1260 ret = CMU_USBCClkGet();
\r
1273 /**************************************************************************//**
\r
1275 * Get currently selected reference clock used for a clock branch.
\r
1277 * @param[in] clock
\r
1278 * Clock branch to fetch selected ref. clock for. One of:
\r
1279 * @li #cmuClock_HF
\r
1280 * @li #cmuClock_LFA
\r
1281 * @li #cmuClock_LFB
\r
1282 * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT
\r
1283 * @li #cmuClock_USBC
\r
1287 * Reference clock used for clocking selected branch, #cmuSelect_Error if
\r
1288 * invalid @p clock provided.
\r
1289 *****************************************************************************/
\r
1290 CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock)
\r
1292 CMU_Select_TypeDef ret = cmuSelect_Disabled;
\r
1294 uint32_t statusClkSelMask;
\r
1296 statusClkSelMask =
\r
1297 (CMU_STATUS_HFRCOSEL |
\r
1298 CMU_STATUS_HFXOSEL |
\r
1299 CMU_STATUS_LFRCOSEL |
\r
1300 #if defined( CMU_STATUS_USHFRCODIV2SEL )
\r
1301 CMU_STATUS_USHFRCODIV2SEL |
\r
1303 CMU_STATUS_LFXOSEL);
\r
1305 selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;
\r
1309 case CMU_HFCLKSEL_REG:
\r
1310 switch (CMU->STATUS & statusClkSelMask)
\r
1312 case CMU_STATUS_LFXOSEL:
\r
1313 ret = cmuSelect_LFXO;
\r
1316 case CMU_STATUS_LFRCOSEL:
\r
1317 ret = cmuSelect_LFRCO;
\r
1320 case CMU_STATUS_HFXOSEL:
\r
1321 ret = cmuSelect_HFXO;
\r
1324 #if defined( CMU_STATUS_USHFRCODIV2SEL )
\r
1325 case CMU_STATUS_USHFRCODIV2SEL:
\r
1326 ret = cmuSelect_USHFRCODIV2;
\r
1331 ret = cmuSelect_HFRCO;
\r
1336 case CMU_LFACLKSEL_REG:
\r
1337 switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK)
\r
1339 case CMU_LFCLKSEL_LFA_LFRCO:
\r
1340 ret = cmuSelect_LFRCO;
\r
1343 case CMU_LFCLKSEL_LFA_LFXO:
\r
1344 ret = cmuSelect_LFXO;
\r
1347 case CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
\r
1348 ret = cmuSelect_CORELEDIV2;
\r
1352 #if defined( CMU_LFCLKSEL_LFAE )
\r
1353 if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK)
\r
1355 ret = cmuSelect_ULFRCO;
\r
1359 ret = cmuSelect_Disabled;
\r
1365 case CMU_LFBCLKSEL_REG:
\r
1366 switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK)
\r
1368 case CMU_LFCLKSEL_LFB_LFRCO:
\r
1369 ret = cmuSelect_LFRCO;
\r
1372 case CMU_LFCLKSEL_LFB_LFXO:
\r
1373 ret = cmuSelect_LFXO;
\r
1376 case CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2:
\r
1377 ret = cmuSelect_CORELEDIV2;
\r
1381 #if defined( CMU_LFCLKSEL_LFBE )
\r
1382 if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK)
\r
1384 ret = cmuSelect_ULFRCO;
\r
1388 ret = cmuSelect_Disabled;
\r
1394 #if defined( _CMU_LFCLKSEL_LFC_MASK )
\r
1395 case CMU_LFCCLKSEL_REG:
\r
1396 switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK)
\r
1398 case CMU_LFCLKSEL_LFC_LFRCO:
\r
1399 ret = cmuSelect_LFRCO;
\r
1402 case CMU_LFCLKSEL_LFC_LFXO:
\r
1403 ret = cmuSelect_LFXO;
\r
1407 ret = cmuSelect_Disabled;
\r
1413 case CMU_DBGCLKSEL_REG:
\r
1415 #if defined( _CMU_DBGCLKSEL_DBG_MASK )
\r
1416 switch (CMU->DBGCLKSEL & _CMU_DBGCLKSEL_DBG_MASK)
\r
1418 case CMU_DBGCLKSEL_DBG_HFCLK:
\r
1419 ret = cmuSelect_HFCLK;
\r
1422 case CMU_DBGCLKSEL_DBG_AUXHFRCO:
\r
1423 ret = cmuSelect_AUXHFRCO;
\r
1427 ret = cmuSelect_AUXHFRCO;
\r
1428 #endif /* CMU_DBGCLKSEL_DBG */
\r
1430 #if defined( _CMU_CTRL_DBGCLK_MASK )
\r
1431 switch(CMU->CTRL & _CMU_CTRL_DBGCLK_MASK)
\r
1433 case CMU_CTRL_DBGCLK_AUXHFRCO:
\r
1434 ret = cmuSelect_AUXHFRCO;
\r
1437 case CMU_CTRL_DBGCLK_HFCLK:
\r
1438 ret = cmuSelect_HFCLK;
\r
1442 ret = cmuSelect_AUXHFRCO;
\r
1447 #if defined(USB_PRESENT)
\r
1449 case CMU_USBCCLKSEL_REG:
\r
1450 switch(CMU->STATUS &
\r
1451 (CMU_STATUS_USBCLFXOSEL |
\r
1452 #if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)
\r
1453 CMU_STATUS_USBCHFCLKSEL |
\r
1455 #if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)
\r
1456 CMU_STATUS_USBCUSHFRCOSEL |
\r
1458 CMU_STATUS_USBCLFRCOSEL))
\r
1461 case CMU_STATUS_USBCLFXOSEL:
\r
1462 ret = cmuSelect_LFXO;
\r
1465 case CMU_STATUS_USBCLFRCOSEL:
\r
1466 ret = cmuSelect_LFRCO;
\r
1469 #if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)
\r
1470 case CMU_STATUS_USBCHFCLKSEL:
\r
1471 ret = cmuSelect_HFCLK;
\r
1475 #if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)
\r
1476 case CMU_STATUS_USBCUSHFRCOSEL:
\r
1477 ret = cmuSelect_USHFRCO;
\r
1482 ret = cmuSelect_Disabled;
\r
1490 ret = cmuSelect_Error;
\r
1498 /**************************************************************************//**
\r
1500 * Select reference clock/oscillator used for a clock branch.
\r
1503 * Notice that if a selected reference is not enabled prior to selecting its
\r
1504 * use, it will be enabled, and this function will wait for the selected
\r
1505 * oscillator to be stable. It will however NOT be disabled if another
\r
1506 * reference clock is selected later.
\r
1508 * This feature is particularly important if selecting a new reference
\r
1509 * clock for the clock branch clocking the core, otherwise the system
\r
1512 * @param[in] clock
\r
1513 * Clock branch to select reference clock for. One of:
\r
1514 * @li #cmuClock_HF
\r
1515 * @li #cmuClock_LFA
\r
1516 * @li #cmuClock_LFB
\r
1517 * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT
\r
1518 * @li #cmuClock_USBC
\r
1522 * Reference selected for clocking, please refer to reference manual for
\r
1523 * for details on which reference is available for a specific clock branch.
\r
1524 * @li #cmuSelect_HFRCO
\r
1525 * @li #cmuSelect_LFRCO
\r
1526 * @li #cmuSelect_HFXO
\r
1527 * @li #cmuSelect_LFXO
\r
1528 * @li #cmuSelect_CORELEDIV2
\r
1529 * @li #cmuSelect_AUXHFRCO
\r
1530 * @li #cmuSelect_HFCLK @ifnot DOXYDOC_EFM32_GECKO_FAMILY
\r
1531 * @li #cmuSelect_ULFRCO
\r
1533 *****************************************************************************/
\r
1534 void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
\r
1536 uint32_t select = cmuOsc_HFRCO;
\r
1537 CMU_Osc_TypeDef osc = cmuOsc_HFRCO;
\r
1540 #if !defined(_EFM32_GECKO_FAMILY)
\r
1541 uint32_t lfExtended = 0;
\r
1545 selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;
\r
1549 case CMU_HFCLKSEL_REG:
\r
1552 case cmuSelect_LFXO:
\r
1553 select = CMU_CMD_HFCLKSEL_LFXO;
\r
1554 osc = cmuOsc_LFXO;
\r
1557 case cmuSelect_LFRCO:
\r
1558 select = CMU_CMD_HFCLKSEL_LFRCO;
\r
1559 osc = cmuOsc_LFRCO;
\r
1562 case cmuSelect_HFXO:
\r
1563 select = CMU_CMD_HFCLKSEL_HFXO;
\r
1564 osc = cmuOsc_HFXO;
\r
1565 #if defined( CMU_CTRL_HFLE )
\r
1566 /* Adjust HFXO buffer current for high frequencies, enable HFLE for */
\r
1567 /* frequencies above CMU_MAX_FREQ_HFLE. */
\r
1568 if(SystemHFXOClockGet() > CMU_MAX_FREQ_HFLE)
\r
1570 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) |
\r
1571 CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ |
\r
1572 /* Must have HFLE enabled to access some LE peripherals >=32MHz */
\r
1575 /* Set HFLE and DIV4 factor for peripheral clock if HFCORE clock for
\r
1577 if (CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE)
\r
1579 BITBAND_Peripheral(&(CMU->HFCORECLKDIV),
\r
1580 _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
\r
1583 /* This can happen if the user configures the EFM32_HFXO_FREQ to */
\r
1584 /* use another oscillator frequency */
\r
1585 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) |
\r
1586 CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ;
\r
1591 case cmuSelect_HFRCO:
\r
1592 select = CMU_CMD_HFCLKSEL_HFRCO;
\r
1593 osc = cmuOsc_HFRCO;
\r
1596 #if defined( CMU_CMD_HFCLKSEL_USHFRCODIV2 )
\r
1597 case cmuSelect_USHFRCODIV2:
\r
1598 select = CMU_CMD_HFCLKSEL_USHFRCODIV2;
\r
1599 osc = cmuOsc_USHFRCO;
\r
1603 #if !defined( _EFM32_GECKO_FAMILY )
\r
1604 case cmuSelect_ULFRCO:
\r
1605 /* ULFRCO cannot be used as HFCLK */
\r
1615 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
\r
1616 CMU_OscillatorEnable(osc, true, true);
\r
1618 /* Configure worst case wait states for flash access before selecting */
\r
1619 CMU_FlashWaitStateMax();
\r
1621 /* Switch to selected oscillator */
\r
1622 CMU->CMD = select;
\r
1624 /* Keep EMU module informed */
\r
1625 EMU_UpdateOscConfig();
\r
1627 /* Update CMSIS core clock variable */
\r
1628 /* (The function will update the global variable) */
\r
1629 freq = SystemCoreClockGet();
\r
1631 /* Optimize flash access wait state setting for currently selected core clk */
\r
1632 CMU_FlashWaitStateControl(freq);
\r
1635 case CMU_LFACLKSEL_REG:
\r
1636 case CMU_LFBCLKSEL_REG:
\r
1640 case cmuSelect_Disabled:
\r
1641 tmp = _CMU_LFCLKSEL_LFA_DISABLED;
\r
1644 case cmuSelect_LFXO:
\r
1645 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
\r
1646 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
\r
1647 tmp = _CMU_LFCLKSEL_LFA_LFXO;
\r
1650 case cmuSelect_LFRCO:
\r
1651 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
\r
1652 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
\r
1653 tmp = _CMU_LFCLKSEL_LFA_LFRCO;
\r
1656 case cmuSelect_CORELEDIV2:
\r
1657 /* Ensure HFCORE to LE clocking is enabled */
\r
1658 BITBAND_Peripheral(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_LE_SHIFT, 1);
\r
1659 tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2;
\r
1660 #if defined( CMU_CTRL_HFLE )
\r
1661 /* If core frequency is higher than CMU_MAX_FREQ_HFLE on
\r
1662 Giant/Leopard/Wonder, enable HFLE and DIV4. */
\r
1663 freq = SystemCoreClockGet();
\r
1664 if(freq > CMU_MAX_FREQ_HFLE)
\r
1666 /* Enable CMU HFLE */
\r
1667 BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1);
\r
1669 /* Enable DIV4 factor for peripheral clock */
\r
1670 BITBAND_Peripheral(&(CMU->HFCORECLKDIV),
\r
1671 _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
\r
1676 #if !defined(_EFM32_GECKO_FAMILY)
\r
1677 case cmuSelect_ULFRCO:
\r
1678 /* ULFRCO is always enabled */
\r
1679 tmp = _CMU_LFCLKSEL_LFA_DISABLED;
\r
1685 /* Illegal clock source for LFA/LFB selected */
\r
1690 /* Apply select */
\r
1691 if (selReg == CMU_LFACLKSEL_REG)
\r
1693 #if !defined( _EFM32_GECKO_FAMILY )
\r
1694 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK) ) |
\r
1695 (tmp << _CMU_LFCLKSEL_LFA_SHIFT) | (lfExtended << _CMU_LFCLKSEL_LFAE_SHIFT);
\r
1697 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFA_MASK) |
\r
1698 (tmp << _CMU_LFCLKSEL_LFA_SHIFT);
\r
1703 #if !defined( _EFM32_GECKO_FAMILY )
\r
1704 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK) ) |
\r
1705 (tmp << _CMU_LFCLKSEL_LFB_SHIFT) | (lfExtended << _CMU_LFCLKSEL_LFBE_SHIFT);
\r
1707 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFB_MASK) |
\r
1708 (tmp << _CMU_LFCLKSEL_LFB_SHIFT);
\r
1713 #if defined( _CMU_LFCLKSEL_LFC_MASK )
\r
1714 case CMU_LFCCLKSEL_REG:
\r
1717 case cmuSelect_Disabled:
\r
1718 tmp = _CMU_LFCLKSEL_LFA_DISABLED;
\r
1721 case cmuSelect_LFXO:
\r
1722 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
\r
1723 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
\r
1724 tmp = _CMU_LFCLKSEL_LFC_LFXO;
\r
1727 case cmuSelect_LFRCO:
\r
1728 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
\r
1729 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
\r
1730 tmp = _CMU_LFCLKSEL_LFC_LFRCO;
\r
1734 /* Illegal clock source for LFC selected */
\r
1739 /* Apply select */
\r
1740 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFC_MASK) |
\r
1741 (tmp << _CMU_LFCLKSEL_LFC_SHIFT);
\r
1745 #if defined( CMU_CTRL_DBGCLK )
\r
1746 case CMU_DBGCLKSEL_REG:
\r
1749 case cmuSelect_AUXHFRCO:
\r
1750 /* Select AUXHFRCO as debug clock */
\r
1751 CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))| CMU_CTRL_DBGCLK_AUXHFRCO;
\r
1754 case cmuSelect_HFCLK:
\r
1755 /* Select divided HFCLK as debug clock */
\r
1756 CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))| CMU_CTRL_DBGCLK_HFCLK;
\r
1760 /* Illegal clock source for debug selected */
\r
1767 #if defined(USB_PRESENT)
\r
1768 case CMU_USBCCLKSEL_REG:
\r
1771 case cmuSelect_LFXO:
\r
1772 /* Select LFXO as clock source for USB, can only be used in sleep mode */
\r
1774 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
\r
1775 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
\r
1777 /* Switch oscillator */
\r
1778 CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;
\r
1780 /* Wait until clock is activated */
\r
1781 while((CMU->STATUS & CMU_STATUS_USBCLFXOSEL)==0);
\r
1784 case cmuSelect_LFRCO:
\r
1785 /* Select LFRCO as clock source for USB, can only be used in sleep mode */
\r
1787 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
\r
1788 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
\r
1790 /* Switch oscillator */
\r
1791 CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;
\r
1793 /* Wait until clock is activated */
\r
1794 while((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL)==0);
\r
1797 #if defined( CMU_STATUS_USBCHFCLKSEL )
\r
1798 case cmuSelect_HFCLK:
\r
1799 /* Select undivided HFCLK as clock source for USB */
\r
1801 /* Oscillator must already be enabled to avoid a core lockup */
\r
1802 CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
\r
1803 /* Wait until clock is activated */
\r
1804 while((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL)==0);
\r
1808 #if defined( CMU_CMD_USBCCLKSEL_USHFRCO )
\r
1809 case cmuSelect_USHFRCO:
\r
1810 /* Select USHFRCO as clock source for USB */
\r
1812 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
\r
1813 CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
\r
1815 /* Switch oscillator */
\r
1816 CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;
\r
1818 /* Wait until clock is activated */
\r
1819 while((CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL)==0);
\r
1824 /* Illegal clock source for USB */
\r
1828 /* Wait until clock has been activated */
\r
1839 /**************************************************************************//**
\r
1841 * CMU low frequency register synchronization freeze control.
\r
1844 * Some CMU registers requires synchronization into the low frequency (LF)
\r
1845 * domain. The freeze feature allows for several such registers to be
\r
1846 * modified before passing them to the LF domain simultaneously (which
\r
1847 * takes place when the freeze mode is disabled).
\r
1849 * Another usage scenario of this feature, is when using an API (such
\r
1850 * as the CMU API) for modifying several bit fields consecutively in the
\r
1851 * same register. If freeze mode is enabled during this sequence, stalling
\r
1855 * When enabling freeze mode, this function will wait for all current
\r
1856 * ongoing CMU synchronization to LF domain to complete (Normally
\r
1857 * synchronization will not be in progress.) However for this reason, when
\r
1858 * using freeze mode, modifications of registers requiring LF synchronization
\r
1859 * should be done within one freeze enable/disable block to avoid unecessary
\r
1862 * @param[in] enable
\r
1863 * @li true - enable freeze, modified registers are not propagated to the
\r
1865 * @li false - disable freeze, modified registers are propagated to LF
\r
1867 *****************************************************************************/
\r
1868 void CMU_FreezeEnable(bool enable)
\r
1872 /* Wait for any ongoing LF synchronization to complete. This is just to */
\r
1873 /* protect against the rare case when a user */
\r
1874 /* - modifies a register requiring LF sync */
\r
1875 /* - then enables freeze before LF sync completed */
\r
1876 /* - then modifies the same register again */
\r
1877 /* since modifying a register while it is in sync progress should be */
\r
1879 while (CMU->SYNCBUSY)
\r
1882 CMU->FREEZE = CMU_FREEZE_REGFREEZE;
\r
1891 #if defined( _CMU_AUXHFRCOCTRL_BAND_MASK )
\r
1892 /***************************************************************************//**
\r
1894 * Get AUXHFRCO band in use.
\r
1897 * AUXHFRCO band in use.
\r
1898 ******************************************************************************/
\r
1899 CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void)
\r
1901 return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK) >>
\r
1902 _CMU_AUXHFRCOCTRL_BAND_SHIFT);
\r
1905 /***************************************************************************//**
\r
1907 * Set AUIXHFRCO band and the tuning value based on the value in the
\r
1908 * calibration table made during production.
\r
1911 * AUXHFRCO band to activate.
\r
1912 ******************************************************************************/
\r
1913 void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)
\r
1917 /* Read tuning value from calibration table */
\r
1920 case cmuAUXHFRCOBand_1MHz:
\r
1921 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK) >>
\r
1922 _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT;
\r
1925 case cmuAUXHFRCOBand_7MHz:
\r
1926 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK) >>
\r
1927 _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT;
\r
1930 case cmuAUXHFRCOBand_11MHz:
\r
1931 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK) >>
\r
1932 _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT;
\r
1935 case cmuAUXHFRCOBand_14MHz:
\r
1936 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK) >>
\r
1937 _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT;
\r
1940 case cmuAUXHFRCOBand_21MHz:
\r
1941 tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK) >>
\r
1942 _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT;
\r
1945 #if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )
\r
1946 case cmuAUXHFRCOBand_28MHz:
\r
1947 tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK) >>
\r
1948 _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT;
\r
1957 /* Set band/tuning */
\r
1958 CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL &
\r
1959 ~(_CMU_AUXHFRCOCTRL_BAND_MASK | _CMU_AUXHFRCOCTRL_TUNING_MASK)) |
\r
1960 (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT) |
\r
1961 (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);
\r
1967 #if defined( _CMU_USHFRCOCONF_BAND_MASK )
\r
1968 /***************************************************************************//**
\r
1970 * Get USHFRCO band in use.
\r
1973 * USHFRCO band in use.
\r
1974 ******************************************************************************/
\r
1975 CMU_USHFRCOBand_TypeDef CMU_USHFRCOBandGet(void)
\r
1977 return (CMU_USHFRCOBand_TypeDef)((CMU->USHFRCOCONF & _CMU_USHFRCOCONF_BAND_MASK) >>
\r
1978 _CMU_USHFRCOCONF_BAND_SHIFT);
\r
1981 void CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band)
\r
1984 uint32_t fineTuning;
\r
1985 CMU_Select_TypeDef osc;
\r
1987 /* Cannot switch band if USHFRCO is already selected as HF clock. */
\r
1988 osc = CMU_ClockSelectGet(cmuClock_HF);
\r
1989 EFM_ASSERT((CMU_USHFRCOBandGet() != band) && (osc != cmuSelect_USHFRCO));
\r
1991 /* Read tuning value from calibration table */
\r
1994 case cmuUSHFRCOBand_24MHz:
\r
1995 tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_TUNING_MASK) >>
\r
1996 _DEVINFO_USHFRCOCAL0_BAND24_TUNING_SHIFT;
\r
1997 fineTuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_MASK) >>
\r
1998 _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_SHIFT;
\r
2001 case cmuUSHFRCOBand_48MHz:
\r
2002 tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_TUNING_MASK) >>
\r
2003 _DEVINFO_USHFRCOCAL0_BAND48_TUNING_SHIFT;
\r
2004 fineTuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_MASK) >>
\r
2005 _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_SHIFT;
\r
2006 /* Enable the clock divider before switching the band from 24 to 48MHz */
\r
2007 BITBAND_Peripheral(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 0);
\r
2015 /* Set band and tuning */
\r
2016 CMU->USHFRCOCONF = (CMU->USHFRCOCONF & ~_CMU_USHFRCOCONF_BAND_MASK) |
\r
2017 (band << _CMU_USHFRCOCONF_BAND_SHIFT);
\r
2018 CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~_CMU_USHFRCOCTRL_TUNING_MASK) |
\r
2019 (tuning << _CMU_USHFRCOCTRL_TUNING_SHIFT);
\r
2020 CMU->USHFRCOTUNE = (CMU->USHFRCOTUNE & ~_CMU_USHFRCOTUNE_FINETUNING_MASK) |
\r
2021 (fineTuning << _CMU_USHFRCOTUNE_FINETUNING_SHIFT);
\r
2023 /* Disable the clock divider after switching the band from 48 to 24MHz */
\r
2024 if (band == cmuUSHFRCOBand_24MHz)
\r
2026 BITBAND_Peripheral(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 1);
\r
2032 /***************************************************************************//**
\r
2034 * Get HFRCO band in use.
\r
2037 * HFRCO band in use.
\r
2038 ******************************************************************************/
\r
2039 CMU_HFRCOBand_TypeDef CMU_HFRCOBandGet(void)
\r
2041 return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK) >>
\r
2042 _CMU_HFRCOCTRL_BAND_SHIFT);
\r
2046 /***************************************************************************//**
\r
2048 * Set HFRCO band and the tuning value based on the value in the calibration
\r
2049 * table made during production.
\r
2052 * HFRCO band to activate.
\r
2053 ******************************************************************************/
\r
2054 void CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)
\r
2058 CMU_Select_TypeDef osc;
\r
2060 /* Read tuning value from calibration table */
\r
2063 case cmuHFRCOBand_1MHz:
\r
2064 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK) >>
\r
2065 _DEVINFO_HFRCOCAL0_BAND1_SHIFT;
\r
2068 case cmuHFRCOBand_7MHz:
\r
2069 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK) >>
\r
2070 _DEVINFO_HFRCOCAL0_BAND7_SHIFT;
\r
2073 case cmuHFRCOBand_11MHz:
\r
2074 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK) >>
\r
2075 _DEVINFO_HFRCOCAL0_BAND11_SHIFT;
\r
2078 case cmuHFRCOBand_14MHz:
\r
2079 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK) >>
\r
2080 _DEVINFO_HFRCOCAL0_BAND14_SHIFT;
\r
2083 case cmuHFRCOBand_21MHz:
\r
2084 tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK) >>
\r
2085 _DEVINFO_HFRCOCAL1_BAND21_SHIFT;
\r
2088 #if defined( _CMU_HFRCOCTRL_BAND_28MHZ )
\r
2089 case cmuHFRCOBand_28MHz:
\r
2090 tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK) >>
\r
2091 _DEVINFO_HFRCOCAL1_BAND28_SHIFT;
\r
2100 /* If HFRCO is used for core clock, we have to consider flash access WS. */
\r
2101 osc = CMU_ClockSelectGet(cmuClock_HF);
\r
2102 if (osc == cmuSelect_HFRCO)
\r
2104 /* Configure worst case wait states for flash access before setting divider */
\r
2105 CMU_FlashWaitStateMax();
\r
2108 /* Set band/tuning */
\r
2109 CMU->HFRCOCTRL = (CMU->HFRCOCTRL &
\r
2110 ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK)) |
\r
2111 (band << _CMU_HFRCOCTRL_BAND_SHIFT) |
\r
2112 (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT);
\r
2114 /* If HFRCO is used for core clock, optimize flash WS */
\r
2115 if (osc == cmuSelect_HFRCO)
\r
2117 /* Update CMSIS core clock variable and get current core clock */
\r
2118 /* (The function will update the global variable) */
\r
2119 /* NOTE! We need at least 21 cycles before setting zero wait state to flash */
\r
2120 /* (i.e. WS0) when going from the 28MHz to 1MHz in the HFRCO band */
\r
2121 freq = SystemCoreClockGet();
\r
2123 /* Optimize flash access wait state setting for current core clk */
\r
2124 CMU_FlashWaitStateControl(freq);
\r
2129 /***************************************************************************//**
\r
2131 * Get the HFRCO startup delay.
\r
2134 * Please refer to the reference manual for further details.
\r
2137 * The startup delay in use.
\r
2138 ******************************************************************************/
\r
2139 uint32_t CMU_HFRCOStartupDelayGet(void)
\r
2141 return((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK) >>
\r
2142 _CMU_HFRCOCTRL_SUDELAY_SHIFT);
\r
2146 /***************************************************************************//**
\r
2148 * Set the HFRCO startup delay.
\r
2151 * Please refer to the reference manual for further details.
\r
2153 * @param[in] delay
\r
2154 * The startup delay to set (<= 31).
\r
2155 ******************************************************************************/
\r
2156 void CMU_HFRCOStartupDelaySet(uint32_t delay)
\r
2158 EFM_ASSERT(delay <= 31);
\r
2160 delay &= (_CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT);
\r
2161 CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK)) |
\r
2162 (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT);
\r
2166 /***************************************************************************//**
\r
2168 * Get the LCD framerate divisor (FDIV) setting.
\r
2171 * The LCD framerate divisor.
\r
2172 ******************************************************************************/
\r
2173 uint32_t CMU_LCDClkFDIVGet(void)
\r
2175 #if defined(LCD_PRESENT)
\r
2176 return((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT);
\r
2179 #endif /* defined(LCD_PRESENT) */
\r
2183 /***************************************************************************//**
\r
2185 * Set the LCD framerate divisor (FDIV) setting.
\r
2188 * The FDIV field (CMU LCDCTRL register) should only be modified while the
\r
2189 * LCD module is clock disabled (CMU LFACLKEN0.LCD bit is 0). This function
\r
2190 * will NOT modify FDIV if the LCD module clock is enabled. Please refer to
\r
2191 * CMU_ClockEnable() for disabling/enabling LCD clock.
\r
2194 * The FDIV setting to use.
\r
2195 ******************************************************************************/
\r
2196 void CMU_LCDClkFDIVSet(uint32_t div)
\r
2198 #if defined(LCD_PRESENT)
\r
2199 EFM_ASSERT(div <= cmuClkDiv_128);
\r
2201 /* Do not allow modification if LCD clock enabled */
\r
2202 if (CMU->LFACLKEN0 & CMU_LFACLKEN0_LCD)
\r
2207 div <<= _CMU_LCDCTRL_FDIV_SHIFT;
\r
2208 div &= _CMU_LCDCTRL_FDIV_MASK;
\r
2209 CMU->LCDCTRL = (CMU->LCDCTRL & ~_CMU_LCDCTRL_FDIV_MASK) | div;
\r
2211 (void)div; /* Unused parameter */
\r
2212 #endif /* defined(LCD_PRESENT) */
\r
2216 /***************************************************************************//**
\r
2218 * Enable/disable oscillator.
\r
2221 * WARNING: When this function is called to disable either cmuOsc_LFXO or
\r
2222 * cmuOsc_HFXO the LFXOMODE or HFXOMODE fields of the CMU_CTRL register
\r
2223 * are reset to the reset value. I.e. if external clock sources are selected
\r
2224 * in either LFXOMODE or HFXOMODE fields, the configuration will be cleared
\r
2225 * and needs to be reconfigured if needed later.
\r
2228 * The oscillator to enable/disable.
\r
2230 * @param[in] enable
\r
2231 * @li true - enable specified oscillator.
\r
2232 * @li false - disable specified oscillator.
\r
2235 * Only used if @p enable is true.
\r
2236 * @li true - wait for oscillator start-up time to timeout before returning.
\r
2237 * @li false - do not wait for oscillator start-up time to timeout before
\r
2239 ******************************************************************************/
\r
2240 void CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait)
\r
2248 case cmuOsc_HFRCO:
\r
2249 enBit = CMU_OSCENCMD_HFRCOEN;
\r
2250 disBit = CMU_OSCENCMD_HFRCODIS;
\r
2251 status = CMU_STATUS_HFRCORDY;
\r
2255 enBit = CMU_OSCENCMD_HFXOEN;
\r
2256 disBit = CMU_OSCENCMD_HFXODIS;
\r
2257 status = CMU_STATUS_HFXORDY;
\r
2260 case cmuOsc_AUXHFRCO:
\r
2261 enBit = CMU_OSCENCMD_AUXHFRCOEN;
\r
2262 disBit = CMU_OSCENCMD_AUXHFRCODIS;
\r
2263 status = CMU_STATUS_AUXHFRCORDY;
\r
2266 case cmuOsc_LFRCO:
\r
2267 enBit = CMU_OSCENCMD_LFRCOEN;
\r
2268 disBit = CMU_OSCENCMD_LFRCODIS;
\r
2269 status = CMU_STATUS_LFRCORDY;
\r
2273 enBit = CMU_OSCENCMD_LFXOEN;
\r
2274 disBit = CMU_OSCENCMD_LFXODIS;
\r
2275 status = CMU_STATUS_LFXORDY;
\r
2278 #if defined( _CMU_STATUS_USHFRCOENS_MASK )
\r
2279 case cmuOsc_USHFRCO:
\r
2280 enBit = CMU_OSCENCMD_USHFRCOEN;
\r
2281 disBit = CMU_OSCENCMD_USHFRCODIS;
\r
2282 status = CMU_STATUS_USHFRCORDY;
\r
2286 #if defined( _CMU_LFCLKSEL_LFAE_ULFRCO )
\r
2287 case cmuOsc_ULFRCO:
\r
2288 /* ULFRCO is always enabled, and cannot be turned off */
\r
2293 /* Undefined clock source */
\r
2300 CMU->OSCENCMD = enBit;
\r
2302 /* Wait for clock to stabilize if requested */
\r
2305 while (!(CMU->STATUS & status))
\r
2311 CMU->OSCENCMD = disBit;
\r
2314 /* Keep EMU module informed */
\r
2315 EMU_UpdateOscConfig();
\r
2319 /***************************************************************************//**
\r
2321 * Get oscillator frequency tuning setting.
\r
2324 * Oscillator to get tuning value for, one of:
\r
2325 * @li #cmuOsc_LFRCO
\r
2326 * @li #cmuOsc_HFRCO
\r
2327 * @li #cmuOsc_AUXHFRCO
\r
2330 * The oscillator frequency tuning setting in use.
\r
2331 ******************************************************************************/
\r
2332 uint32_t CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)
\r
2338 case cmuOsc_LFRCO:
\r
2339 ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK) >>
\r
2340 _CMU_LFRCOCTRL_TUNING_SHIFT;
\r
2343 case cmuOsc_HFRCO:
\r
2344 ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK) >>
\r
2345 _CMU_HFRCOCTRL_TUNING_SHIFT;
\r
2348 case cmuOsc_AUXHFRCO:
\r
2349 ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK) >>
\r
2350 _CMU_AUXHFRCOCTRL_TUNING_SHIFT;
\r
2363 /***************************************************************************//**
\r
2365 * Set the oscillator frequency tuning control.
\r
2368 * Oscillator tuning is done during production, and the tuning value is
\r
2369 * automatically loaded after a reset. Changing the tuning value from the
\r
2370 * calibrated value is for more advanced use.
\r
2373 * Oscillator to set tuning value for, one of:
\r
2374 * @li #cmuOsc_LFRCO
\r
2375 * @li #cmuOsc_HFRCO
\r
2376 * @li #cmuOsc_AUXHFRCO
\r
2379 * The oscillator frequency tuning setting to use.
\r
2380 ******************************************************************************/
\r
2381 void CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc, uint32_t val)
\r
2385 case cmuOsc_LFRCO:
\r
2386 EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT));
\r
2388 val &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT);
\r
2389 CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK)) |
\r
2390 (val << _CMU_LFRCOCTRL_TUNING_SHIFT);
\r
2393 case cmuOsc_HFRCO:
\r
2394 EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT));
\r
2396 val &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT);
\r
2397 CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK)) |
\r
2398 (val << _CMU_HFRCOCTRL_TUNING_SHIFT);
\r
2401 case cmuOsc_AUXHFRCO:
\r
2402 EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT));
\r
2404 val <<= _CMU_AUXHFRCOCTRL_TUNING_SHIFT;
\r
2405 val &= _CMU_AUXHFRCOCTRL_TUNING_MASK;
\r
2406 CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK)) | val;
\r
2416 /**************************************************************************//**
\r
2418 * Determine if currently selected PCNTn clock used is external or LFBCLK.
\r
2421 * PCNT instance number to get currently selected clock source for.
\r
2424 * @li true - selected clock is external clock.
\r
2425 * @li false - selected clock is LFBCLK.
\r
2426 *****************************************************************************/
\r
2427 bool CMU_PCNTClockExternalGet(unsigned int inst)
\r
2434 #if defined(_CMU_PCNTCTRL_PCNT0CLKEN_MASK)
\r
2436 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0;
\r
2439 #if defined(_CMU_PCNTCTRL_PCNT1CLKEN_MASK)
\r
2441 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0;
\r
2444 #if defined(_CMU_PCNTCTRL_PCNT2CLKEN_MASK)
\r
2446 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0;
\r
2469 /**************************************************************************//**
\r
2471 * Select PCNTn clock.
\r
2474 * PCNT instance number to set selected clock source for.
\r
2476 * @param[in] external
\r
2477 * Set to true to select external clock, false to select LFBCLK.
\r
2478 *****************************************************************************/
\r
2479 void CMU_PCNTClockExternalSet(unsigned int inst, bool external)
\r
2481 #if defined(PCNT_PRESENT)
\r
2482 uint32_t setting = 0;
\r
2484 EFM_ASSERT(inst < PCNT_COUNT);
\r
2491 BITBAND_Peripheral(&(CMU->PCNTCTRL), (inst * 2) + 1, setting);
\r
2494 (void)inst; /* Unused parameter */
\r
2495 (void)external; /* Unused parameter */
\r
2500 /** @} (end addtogroup CMU) */
\r
2501 /** @} (end addtogroup EM_Library) */
\r
2502 #endif /* __EM_CMU_H */
\r