1 /***************************************************************************//**
2 * @file
3 * @brief Clock management unit (CMU) Peripheral API
4 * @author Energy Micro AS
5 * @version 3.0.0
6 *******************************************************************************
7 * @section License
8 * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
9 *******************************************************************************
10 *
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions:
14 *
15 * 1. The origin of this software must not be misrepresented; you must not
16 * claim that you wrote the original software.
17 * 2. Altered source versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software.
19 * 3. This notice may not be removed or altered from any source distribution.
20 *
21 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
22 * obligation to support this Software. Energy Micro AS is providing the
23 * Software "AS IS", with no express or implied warranties of any kind,
24 * including, but not limited to, any implied warranties of merchantability
25 * or fitness for any particular purpose or warranties against infringement
26 * of any proprietary rights of a third party.
27 *
28 * Energy Micro AS will not be liable for any consequential, incidental, or
29 * special damages, or any other relief, or for any claim by any third party,
30 * arising from your use of this Software.
31 *
32 ******************************************************************************/
33 #include "em_part.h"
34 #include "em_cmu.h"
35 #include "em_assert.h"
36 #include "em_bitband.h"
37 #include "em_emu.h"
38
39 /***************************************************************************//**
40 * @addtogroup EM_Library
41 * @{
42 ******************************************************************************/
43
44 /***************************************************************************//**
45 * @addtogroup CMU
46 * @brief Clock management unit (CMU) Peripheral API
47 * @{
48 ******************************************************************************/
49
50 /*******************************************************************************
51 ****************************** DEFINES ************************************
52 ******************************************************************************/
53
54 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
55
56 /** Maximum allowed core frequency when using 0 wait states on flash access. */
57 #define CMU_MAX_FREQ_0WS 16000000
58 /** Maximum allowed core frequency when using 1 wait states on flash access */
59 #define CMU_MAX_FREQ_1WS 32000000
60 /** Maximum frequency before HFLE needs to be enabled on Giant Gecko */
61 #define CMU_MAX_FREQ_HFLE 32000000
62
63 /** Low frequency A group identifier */
64 #define CMU_LFA 0
65
66 /** Low frequency B group identifier */
67 #define CMU_LFB 1
68
69 /** @endcond */
70
71 /*******************************************************************************
72 ************************** LOCAL FUNCTIONS ********************************
73 ******************************************************************************/
74
75 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
76
77 /***************************************************************************//**
78 * @brief
79 * Configure flash access wait states to most conservative setting for
80 * this target. Retain SCBTP setting.
81 ******************************************************************************/
CMU_FlashWaitStateMax(void)82 static void CMU_FlashWaitStateMax(void)
83 {
84 uint32_t cfg;
85
86 cfg = MSC->READCTRL;
87
88 switch(cfg & _MSC_READCTRL_MODE_MASK)
89 {
90 case MSC_READCTRL_MODE_WS1:
91 case MSC_READCTRL_MODE_WS0:
92 #if defined(_EFM32_GIANT_FAMILY)
93 case MSC_READCTRL_MODE_WS2:
94 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS2;
95 #else
96 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS1;
97 #endif
98 break;
99 case MSC_READCTRL_MODE_WS1SCBTP:
100 case MSC_READCTRL_MODE_WS0SCBTP:
101 #if defined(_EFM32_GIANT_FAMILY)
102 case MSC_READCTRL_MODE_WS2SCBTP:
103 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS2SCBTP;
104 #else
105 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS1SCBTP;
106 #endif
107 break;
108 }
109 MSC->READCTRL = cfg;
110 }
111
112
113 /***************************************************************************//**
114 * @brief Convert dividend to prescaler logarithmic value. Only works for even
115 * numbers equal to 2^n
116 * @param[in] div Unscaled dividend,
117 * @return Base 2 logarithm of input, as used by fixed prescalers
118 ******************************************************************************/
CMU_DivToLog2(CMU_ClkDiv_TypeDef div)119 __STATIC_INLINE uint32_t CMU_DivToLog2(CMU_ClkDiv_TypeDef div)
120 {
121 uint32_t log2;
122
123 /* Prescalers take argument of 32768 or less */
124 EFM_ASSERT((div>0) && (div <= 32768));
125
126 /* Count leading zeroes and "reverse" result, Cortex-M3 intrinsic */
127 log2 = (31 - __CLZ(div));
128
129 return log2;
130 }
131
132
133 /***************************************************************************//**
134 * @brief Convert logarithm of 2 prescaler to division factor
135 * @param[in] log2
136 * @return Dividend
137 ******************************************************************************/
CMU_Log2ToDiv(uint32_t log2)138 __STATIC_INLINE uint32_t CMU_Log2ToDiv(uint32_t log2)
139 {
140 return 1<<log2;
141 }
142
143
144 /***************************************************************************//**
145 * @brief
146 * Configure flash access wait states in order to support given HFCORECLK
147 * frequency.
148 *
149 * @param[in] hfcoreclk
150 * HFCORECLK frequency that flash access wait states must be configured for.
151 ******************************************************************************/
CMU_FlashWaitStateControl(uint32_t hfcoreclk)152 static void CMU_FlashWaitStateControl(uint32_t hfcoreclk)
153 {
154 uint32_t cfg;
155
156 cfg = MSC->READCTRL;
157
158 #if defined(_EFM32_GIANT_FAMILY)
159 if (hfcoreclk > CMU_MAX_FREQ_1WS)
160 {
161 switch(cfg & _MSC_READCTRL_MODE_MASK)
162 {
163 case MSC_READCTRL_MODE_WS0SCBTP:
164 case MSC_READCTRL_MODE_WS1SCBTP:
165 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS2SCBTP;
166 break;
167 case MSC_READCTRL_MODE_WS0:
168 case MSC_READCTRL_MODE_WS1:
169 default:
170 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS2;
171 break;
172 }
173 }
174 #endif
175
176 if ((hfcoreclk > CMU_MAX_FREQ_0WS) && (hfcoreclk <= CMU_MAX_FREQ_1WS))
177 {
178 switch (cfg & _MSC_READCTRL_MODE_MASK)
179 {
180 #if defined(_EFM32_GIANT_FAMILY)
181 case MSC_READCTRL_MODE_WS2SCBTP:
182 #endif
183 case MSC_READCTRL_MODE_WS0SCBTP:
184 case MSC_READCTRL_MODE_WS1SCBTP:
185 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS1SCBTP;
186 break;
187
188 default:
189 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS1;
190 break;
191 }
192 }
193
194 if (hfcoreclk <= CMU_MAX_FREQ_0WS)
195 {
196 switch (cfg & _MSC_READCTRL_MODE_MASK)
197 {
198 #if defined(_EFM32_GIANT_FAMILY)
199 case MSC_READCTRL_MODE_WS2SCBTP:
200 #endif
201 case MSC_READCTRL_MODE_WS1SCBTP:
202 case MSC_READCTRL_MODE_WS0SCBTP:
203 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS0SCBTP;
204 break;
205
206 default:
207 cfg = (cfg & ~_MSC_READCTRL_MODE_MASK) | MSC_READCTRL_MODE_WS0;
208 break;
209 }
210 }
211
212 MSC->READCTRL = cfg;
213 }
214
215
216 #if defined(USB_PRESENT)
217 /***************************************************************************//**
218 * @brief
219 * Get the USBC frequency
220 *
221 * @return
222 * USBC frequency in Hz
223 ******************************************************************************/
CMU_USBCClkGet(void)224 static uint32_t CMU_USBCClkGet(void)
225 {
226 uint32_t ret;
227 CMU_Select_TypeDef clk;
228
229 /* Get selected clock source */
230 clk = CMU_ClockSelectGet(cmuClock_USBC);
231
232 switch(clk)
233 {
234 case cmuSelect_LFXO:
235 ret = SystemLFXOClockGet();
236 break;
237 case cmuSelect_LFRCO:
238 ret = SystemLFRCOClockGet();
239 break;
240 case cmuSelect_HFCLK:
241 ret = SystemHFClockGet();
242 break;
243 default:
244 /* Clock is not enabled */
245 ret = 0;
246 break;
247 }
248 return ret;
249 }
250 #endif
251
252
253 /***************************************************************************//**
254 * @brief
255 * Get the AUX clock frequency. Used by MSC flash programming and LESENSE,
256 * by default also as debug clock.
257 *
258 * @return
259 * AUX Frequency in Hz
260 ******************************************************************************/
CMU_AUXClkGet(void)261 static uint32_t CMU_AUXClkGet(void)
262 {
263 uint32_t ret;
264
265 #if defined (_EFM32_GECKO_FAMILY)
266 /* Gecko has a fixed 14Mhz AUXHFRCO clock */
267 ret = 14000000;
268 #else
269 switch(CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK)
270 {
271 case CMU_AUXHFRCOCTRL_BAND_1MHZ:
272 ret = 1000000;
273 break;
274 case CMU_AUXHFRCOCTRL_BAND_7MHZ:
275 ret = 7000000;
276 break;
277 case CMU_AUXHFRCOCTRL_BAND_11MHZ:
278 ret = 11000000;
279 break;
280 case CMU_AUXHFRCOCTRL_BAND_14MHZ:
281 ret = 14000000;
282 break;
283 case CMU_AUXHFRCOCTRL_BAND_21MHZ:
284 ret = 21000000;
285 break;
286 case CMU_AUXHFRCOCTRL_BAND_28MHZ:
287 ret = 28000000;
288 break;
289 default:
290 ret = 0;
291 break;
292 }
293 #endif
294 return ret;
295 }
296
297
298 /***************************************************************************//**
299 * @brief
300 * Get the Debug Trace clock frequency
301 *
302 * @return
303 * Debug Trace frequency in Hz
304 ******************************************************************************/
CMU_DBGClkGet(void)305 static uint32_t CMU_DBGClkGet(void)
306 {
307 uint32_t ret;
308 CMU_Select_TypeDef clk;
309
310 /* Get selected clock source */
311 clk = CMU_ClockSelectGet(cmuClock_DBG);
312
313 switch(clk)
314 {
315 case cmuSelect_HFCLK:
316 ret = SystemHFClockGet();
317 #if defined(_EFM32_GIANT_FAMILY)
318 /* Giant Gecko has an additional divider, not used by USBC */
319 ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>
320 _CMU_CTRL_HFCLKDIV_SHIFT));
321 #endif
322 break;
323
324 case cmuSelect_AUXHFRCO:
325 ret = CMU_AUXClkGet();
326 break;
327
328 default:
329 EFM_ASSERT(0);
330 ret = 0;
331 break;
332 }
333 return ret;
334 }
335
336
337 /***************************************************************************//**
338 * @brief
339 * Get the LFnCLK frequency based on current configuration.
340 *
341 * @param[in] lfClkBranch
342 * LF branch, 0 = LFA, 1 = LFB, ...
343 *
344 * @return
345 * The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is
346 * returned.
347 ******************************************************************************/
CMU_LFClkGet(unsigned int lfClkBranch)348 static uint32_t CMU_LFClkGet(unsigned int lfClkBranch)
349 {
350 uint32_t ret;
351
352 EFM_ASSERT(lfClkBranch == CMU_LFA || lfClkBranch == CMU_LFB);
353
354 switch ((CMU->LFCLKSEL >> (lfClkBranch * 2)) & 0x3)
355 {
356 case _CMU_LFCLKSEL_LFA_LFRCO:
357 ret = SystemLFRCOClockGet();
358 break;
359
360 case _CMU_LFCLKSEL_LFA_LFXO:
361 ret = SystemLFXOClockGet();
362 break;
363
364 case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
365 #if defined (_EFM32_GIANT_FAMILY)
366 /* Giant Gecko can use a /4 divider (and must if >32MHz) or HFLE is set */
367 if(((CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK) == CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4)||
368 (CMU->CTRL & CMU_CTRL_HFLE))
369 {
370 ret = SystemCoreClockGet() / 4;
371 }
372 else
373 {
374 ret = SystemCoreClockGet() / 2;
375 }
376 #else
377 ret = SystemCoreClockGet() / 2;
378 #endif
379 break;
380
381 case _CMU_LFCLKSEL_LFA_DISABLED:
382 #if defined (_EFM32_GIANT_FAMILY) || defined (_EFM32_TINY_FAMILY)
383 /* Check LF Extended bit setting for ULFRCO clock */
384 if(CMU->LFCLKSEL >> (_CMU_LFCLKSEL_LFAE_SHIFT + lfClkBranch * 4))
385 {
386 ret = SystemULFRCOClockGet();
387 }
388 else
389 {
390 ret = 0;
391 }
392 #else
393 ret = 0;
394 #endif
395 break;
396
397 default:
398 ret = 0;
399 break;
400 }
401
402 return ret;
403 }
404
405
406 /***************************************************************************//**
407 * @brief
408 * Wait for ongoing sync of register(s) to low frequency domain to complete.
409 *
410 * @param[in] mask
411 * Bitmask corresponding to SYNCBUSY register defined bits, indicating
412 * registers that must complete any ongoing synchronization.
413 ******************************************************************************/
CMU_Sync(uint32_t mask)414 __STATIC_INLINE void CMU_Sync(uint32_t mask)
415 {
416 /* Avoid deadlock if modifying the same register twice when freeze mode is */
417 /* activated. */
418 if (CMU->FREEZE & CMU_FREEZE_REGFREEZE)
419 return;
420
421 /* Wait for any pending previous write operation to have been completed */
422 /* in low frequency domain */
423 while (CMU->SYNCBUSY & mask)
424 ;
425 }
426
427
428 /** @endcond */
429
430 /*******************************************************************************
431 ************************** GLOBAL FUNCTIONS *******************************
432 ******************************************************************************/
433
434 /***************************************************************************//**
435 * @brief
436 * Calibrate clock.
437 *
438 * @details
439 * Run a calibration for HFCLK against a selectable reference clock. Please
440 * refer to the EFM32 reference manual, CMU chapter, for further details.
441 *
442 * @note
443 * This function will not return until calibration measurement is completed.
444 *
445 * @param[in] HFCycles
446 * The number of HFCLK cycles to run calibration. Increasing this number
447 * increases precision, but the calibration will take more time.
448 *
449 * @param[in] ref
450 * The reference clock used to compare HFCLK with.
451 *
452 * @return
453 * The number of ticks the reference clock after HFCycles ticks on the HF
454 * clock.
455 ******************************************************************************/
CMU_Calibrate(uint32_t HFCycles,CMU_Osc_TypeDef ref)456 uint32_t CMU_Calibrate(uint32_t HFCycles, CMU_Osc_TypeDef ref)
457 {
458 EFM_ASSERT(HFCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));
459
460 /* Set reference clock source */
461 switch (ref)
462 {
463 case cmuOsc_LFXO:
464 CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO;
465 break;
466
467 case cmuOsc_LFRCO:
468 CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO;
469 break;
470
471 case cmuOsc_HFXO:
472 CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO;
473 break;
474
475 case cmuOsc_HFRCO:
476 CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO;
477 break;
478
479 case cmuOsc_AUXHFRCO:
480 CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO;
481 break;
482
483 default:
484 EFM_ASSERT(0);
485 return 0;
486 }
487
488 /* Set top value */
489 CMU->CALCNT = HFCycles;
490
491 /* Start calibration */
492 CMU->CMD = CMU_CMD_CALSTART;
493
494 /* Wait until calibration completes */
495 while (CMU->STATUS & CMU_STATUS_CALBSY)
496 ;
497
498 return CMU->CALCNT;
499 }
500
501
502 #if defined (_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
503 /***************************************************************************//**
504 * @brief
505 * Configure clock calibration
506 *
507 * @details
508 * Configure a calibration for a selectable clock source against another
509 * selectable reference clock.
510 * Refer to the EFM32 reference manual, CMU chapter, for further details.
511 *
512 * @note
513 * After configuration, a call to CMU_CalibrateStart() is required, and
514 * the resulting calibration value can be read out with the
515 * CMU_CalibrateCountGet() function call.
516 *
517 * @param[in] downCycles
518 * The number of downSel clock cycles to run calibration. Increasing this
519 * number increases precision, but the calibration will take more time.
520 *
521 * @param[in] downSel
522 * The clock which will be counted down downCycles
523 *
524 * @param[in] upSel
525 * The reference clock, the number of cycles generated by this clock will
526 * be counted and added up, the result can be given with the
527 * CMU_CalibrateCountGet() function call.
528 ******************************************************************************/
CMU_CalibrateConfig(uint32_t downCycles,CMU_Osc_TypeDef downSel,CMU_Osc_TypeDef upSel)529 void CMU_CalibrateConfig(uint32_t downCycles, CMU_Osc_TypeDef downSel,
530 CMU_Osc_TypeDef upSel)
531 {
532 /* Keep untouched configuration settings */
533 uint32_t calCtrl = CMU->CALCTRL & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK);
534
535 /* 20 bits of precision to calibration count register */
536 EFM_ASSERT(downCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));
537
538 /* Set down counting clock source - down counter */
539 switch (downSel)
540 {
541 case cmuOsc_LFXO:
542 calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO;
543 break;
544
545 case cmuOsc_LFRCO:
546 calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO;
547 break;
548
549 case cmuOsc_HFXO:
550 calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO;
551 break;
552
553 case cmuOsc_HFRCO:
554 calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO;
555 break;
556
557 case cmuOsc_AUXHFRCO:
558 calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO;
559 break;
560
561 default:
562 EFM_ASSERT(0);
563 }
564
565 /* Set top value to be counted down by the downSel clock */
566 CMU->CALCNT = downCycles;
567
568 /* Set reference clock source - up counter */
569 switch (upSel)
570 {
571 case cmuOsc_LFXO:
572 calCtrl |= CMU_CALCTRL_UPSEL_LFXO;
573 break;
574
575 case cmuOsc_LFRCO:
576 calCtrl |= CMU_CALCTRL_UPSEL_LFRCO;
577 break;
578
579 case cmuOsc_HFXO:
580 calCtrl |= CMU_CALCTRL_UPSEL_HFXO;
581 break;
582
583 case cmuOsc_HFRCO:
584 calCtrl |= CMU_CALCTRL_UPSEL_HFRCO;
585 break;
586
587 case cmuOsc_AUXHFRCO:
588 calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO;
589 break;
590
591 default:
592 EFM_ASSERT(0);
593 }
594
595 CMU->CALCTRL = calCtrl;
596 }
597 #endif
598
599
600 /***************************************************************************//**
601 * @brief
602 * Get clock divisor/prescaler.
603 *
604 * @param[in] clock
605 * Clock point to get divisor/prescaler for. Notice that not all clock points
606 * have a divisor/prescaler. Please refer to CMU overview in reference manual.
607 *
608 * @return
609 * The current clock point divisor/prescaler. 1 is returned
610 * if @p clock specifies a clock point without a divisor/prescaler.
611 ******************************************************************************/
CMU_ClockDivGet(CMU_Clock_TypeDef clock)612 CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock)
613 {
614 uint32_t divReg;
615 CMU_ClkDiv_TypeDef ret;
616
617 /* Get divisor reg id */
618 divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;
619
620 switch (divReg)
621 {
622 #if defined(_EFM32_GIANT_FAMILY)
623 case CMU_HFCLKDIV_REG:
624 ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>
625 _CMU_CTRL_HFCLKDIV_SHIFT);
626 break;
627 #endif
628
629 case CMU_HFPERCLKDIV_REG:
630 ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV &
631 _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >>
632 _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);
633 ret = CMU_Log2ToDiv(ret);
634 break;
635
636 case CMU_HFCORECLKDIV_REG:
637 ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV &
638 _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >>
639 _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);
640 ret = CMU_Log2ToDiv(ret);
641 break;
642
643 case CMU_LFAPRESC0_REG:
644 switch (clock)
645 {
646 case cmuClock_RTC:
647 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) >>
648 _CMU_LFAPRESC0_RTC_SHIFT));
649 ret = CMU_Log2ToDiv(ret);
650 break;
651
652 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
653 case cmuClock_LETIMER0:
654 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) >>
655 _CMU_LFAPRESC0_LETIMER0_SHIFT));
656 ret = CMU_Log2ToDiv(ret);
657 break;
658 #endif
659
660 #if defined(_CMU_LFPRESC0_LCD_MASK)
661 case cmuClock_LCDpre:
662 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>
663 _CMU_LFAPRESC0_LCD_SHIFT) + cmuClkDiv_16);
664 ret = CMU_Log2ToDiv(ret);
665 break;
666 #endif
667
668 #if defined(_CMU_LFAPRESC0_LESENSE_MASK)
669 case cmuClock_LESENSE:
670 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) >>
671 _CMU_LFAPRESC0_LESENSE_SHIFT));
672 ret = CMU_Log2ToDiv(ret);
673 break;
674 #endif
675
676 default:
677 EFM_ASSERT(0);
678 ret = cmuClkDiv_1;
679 break;
680 }
681 break;
682
683 case CMU_LFBPRESC0_REG:
684 switch (clock)
685 {
686 #if defined(_CMU_LFPRESC0_LEUART0_MASK)
687 case cmuClock_LEUART0:
688 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) >>
689 _CMU_LFBPRESC0_LEUART0_SHIFT));
690 ret = CMU_Log2ToDiv(ret);
691 break;
692 #endif
693
694 #if defined(_CMU_LFPRESC0_LEUART1_MASK)
695 case cmuClock_LEUART1:
696 ret = (CMU_ClkDiv_TypeDef)(((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) >>
697 _CMU_LFBPRESC0_LEUART1_SHIFT));
698 ret = CMU_Log2ToDiv(ret);
699 break;
700 #endif
701
702 default:
703 EFM_ASSERT(0);
704 ret = cmuClkDiv_1;
705 break;
706 }
707 break;
708
709 default:
710 EFM_ASSERT(0);
711 ret = cmuClkDiv_1;
712 break;
713 }
714
715 return(ret);
716 }
717
718
719 /***************************************************************************//**
720 * @brief
721 * Set clock divisor/prescaler.
722 *
723 * @note
724 * If setting a LF clock prescaler, synchronization into the low frequency
725 * domain is required. If the same register is modified before a previous
726 * update has completed, this function will stall until the previous
727 * synchronization has completed. Please refer to CMU_FreezeEnable() for
728 * a suggestion on how to reduce stalling time in some use cases.
729 *
730 * @param[in] clock
731 * Clock point to set divisor/prescaler for. Notice that not all clock points
732 * have a divisor/prescaler, please refer to CMU overview in the reference
733 * manual.
734 *
735 * @param[in] div
736 * The clock divisor to use (<= cmuClkDiv_512).
737 ******************************************************************************/
CMU_ClockDivSet(CMU_Clock_TypeDef clock,CMU_ClkDiv_TypeDef div)738 void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)
739 {
740 uint32_t freq;
741 uint32_t divReg;
742
743 /* Get divisor reg id */
744 divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;
745
746 switch (divReg)
747 {
748 #if defined (_EFM32_GIANT_FAMILY)
749 case CMU_HFCLKDIV_REG:
750 EFM_ASSERT((div>=cmuClkDiv_1) && (div<=cmuClkDiv_8));
751
752 /* Configure worst case wait states for flash access before setting divisor */
753 CMU_FlashWaitStateMax();
754
755 /* Set divider */
756 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK) |
757 ((div-1) << _CMU_CTRL_HFCLKDIV_SHIFT);
758
759 /* Update CMSIS core clock variable */
760 /* (The function will update the global variable) */
761 freq = SystemCoreClockGet();
762
763 /* Optimize flash access wait state setting for current core clk */
764 CMU_FlashWaitStateControl(freq);
765 break;
766 #endif
767
768 case CMU_HFPERCLKDIV_REG:
769 EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512));
770 /* Convert to correct scale */
771 div = CMU_DivToLog2(div);
772 CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) |
773 (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);
774 break;
775
776 case CMU_HFCORECLKDIV_REG:
777 EFM_ASSERT(div <= cmuClkDiv_512);
778
779 /* Configure worst case wait states for flash access before setting divisor */
780 CMU_FlashWaitStateMax();
781
782 /* Convert to correct scale */
783 div = CMU_DivToLog2(div);
784
785 CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) |
786 (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);
787
788 /* Update CMSIS core clock variable */
789 /* (The function will update the global variable) */
790 freq = SystemCoreClockGet();
791
792 /* Optimize flash access wait state setting for current core clk */
793 CMU_FlashWaitStateControl(freq);
794 break;
795
796 case CMU_LFAPRESC0_REG:
797 switch (clock)
798 {
799 case cmuClock_RTC:
800 EFM_ASSERT(div <= cmuClkDiv_32768);
801
802 /* LF register about to be modified require sync. busy check */
803 CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);
804
805 /* Convert to correct scale */
806 div = CMU_DivToLog2(div);
807
808 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK) |
809 (div << _CMU_LFAPRESC0_RTC_SHIFT);
810 break;
811
812 #if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
813 case cmuClock_LETIMER0:
814 EFM_ASSERT(div <= cmuClkDiv_32768);
815
816 /* LF register about to be modified require sync. busy check */
817 CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);
818
819 /* Convert to correct scale */
820 div = CMU_DivToLog2(div);
821
822 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK) |
823 (div << _CMU_LFAPRESC0_LETIMER0_SHIFT);
824 break;
825 #endif
826
827 #if defined(LCD_PRESENT)
828 case cmuClock_LCDpre:
829 EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128));
830
831 /* LF register about to be modified require sync. busy check */
832 CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);
833
834 /* Convert to correct scale */
835 div = CMU_DivToLog2(div);
836
837 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK) |
838 ((div - cmuClkDiv_16) << _CMU_LFAPRESC0_LCD_SHIFT);
839 break;
840 #endif /* defined(LCD_PRESENT) */
841
842 #if defined(LESENSE_PRESENT)
843 case cmuClock_LESENSE:
844 EFM_ASSERT(div <= cmuClkDiv_8);
845
846 /* LF register about to be modified require sync. busy check */
847 CMU_Sync(CMU_SYNCBUSY_LFAPRESC0);
848
849 /* Convert to correct scale */
850 div = CMU_DivToLog2(div);
851
852 CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK) |
853 (div << _CMU_LFAPRESC0_LESENSE_SHIFT);
854 break;
855 #endif /* defined(LESENSE_PRESENT) */
856
857 default:
858 EFM_ASSERT(0);
859 break;
860 }
861 break;
862
863 case CMU_LFBPRESC0_REG:
864 switch (clock)
865 {
866 #if defined(_CMU_LFBPRESC0_LEUART0_MASK)
867 case cmuClock_LEUART0:
868 EFM_ASSERT(div <= cmuClkDiv_8);
869
870 /* LF register about to be modified require sync. busy check */
871 CMU_Sync(CMU_SYNCBUSY_LFBPRESC0);
872
873 /* Convert to correct scale */
874 div = CMU_DivToLog2(div);
875
876 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK) |
877 (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT);
878 break;
879 #endif
880
881 #if defined(_CMU_LFBPRESC0_LEUART1_MASK)
882 case cmuClock_LEUART1:
883 EFM_ASSERT(div <= cmuClkDiv_8);
884
885 /* LF register about to be modified require sync. busy check */
886 CMU_Sync(CMU_SYNCBUSY_LFBPRESC0);
887
888 /* Convert to correct scale */
889 div = CMU_DivToLog2(div);
890
891 CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK) |
892 (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT);
893 break;
894 #endif
895
896 default:
897 EFM_ASSERT(0);
898 break;
899 }
900 break;
901
902 default:
903 EFM_ASSERT(0);
904 break;
905 }
906 }
907
908
909 /***************************************************************************//**
910 * @brief
911 * Enable/disable a clock.
912 *
913 * @details
914 * In general, module clocking is disabled after a reset. If a module
915 * clock is disabled, the registers of that module are not accessible and
916 * reading from such registers may return undefined values. Writing to
917 * registers of clock disabled modules have no effect. One should normally
918 * avoid accessing module registers of a module with a disabled clock.
919 *
920 * @note
921 * If enabling/disabling a LF clock, synchronization into the low frequency
922 * domain is required. If the same register is modified before a previous
923 * update has completed, this function will stall until the previous
924 * synchronization has completed. Please refer to CMU_FreezeEnable() for
925 * a suggestion on how to reduce stalling time in some use cases.
926 *
927 * @param[in] clock
928 * The clock to enable/disable. Notice that not all defined clock
929 * points have separate enable/disable control, please refer to CMU overview
930 * in reference manual.
931 *
932 * @param[in] enable
933 * @li true - enable specified clock.
934 * @li false - disable specified clock.
935 ******************************************************************************/
CMU_ClockEnable(CMU_Clock_TypeDef clock,bool enable)936 void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
937 {
938 volatile uint32_t *reg;
939 uint32_t bit;
940 uint32_t sync = 0;
941
942 /* Identify enable register */
943 switch ((clock >> CMU_EN_REG_POS) & CMU_EN_REG_MASK)
944 {
945 case CMU_HFPERCLKDIV_EN_REG:
946 reg = &(CMU->HFPERCLKDIV);
947 break;
948
949 case CMU_HFPERCLKEN0_EN_REG:
950 reg = &(CMU->HFPERCLKEN0);
951 break;
952
953 case CMU_HFCORECLKEN0_EN_REG:
954 reg = &(CMU->HFCORECLKEN0);
955 break;
956
957 case CMU_LFACLKEN0_EN_REG:
958 reg = &(CMU->LFACLKEN0);
959 sync = CMU_SYNCBUSY_LFACLKEN0;
960 break;
961
962 case CMU_LFBCLKEN0_EN_REG:
963 reg = &(CMU->LFBCLKEN0);
964 sync = CMU_SYNCBUSY_LFBCLKEN0;
965 break;
966
967 case CMU_PCNT_EN_REG:
968 reg = &(CMU->PCNTCTRL);
969 break;
970
971 default: /* Cannot enable/disable clock point */
972 EFM_ASSERT(0);
973 return;
974 }
975
976 /* Get bit position used to enable/disable */
977 bit = (clock >> CMU_EN_BIT_POS) & CMU_EN_BIT_MASK;
978
979 /* LF synchronization required? */
980 if (sync)
981 {
982 CMU_Sync(sync);
983 }
984
985 /* Set/clear bit as requested */
986 BITBAND_Peripheral(reg, bit, (unsigned int)enable);
987 }
988
989
990 /***************************************************************************//**
991 * @brief
992 * Get clock frequency for a clock point.
993 *
994 * @param[in] clock
995 * Clock point to fetch frequency for.
996 *
997 * @return
998 * The current frequency in Hz.
999 ******************************************************************************/
CMU_ClockFreqGet(CMU_Clock_TypeDef clock)1000 uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
1001 {
1002 uint32_t ret;
1003
1004 switch(clock & (CMU_CLK_BRANCH_MASK << CMU_CLK_BRANCH_POS))
1005 {
1006 case (CMU_HF_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1007 {
1008 ret = SystemHFClockGet();
1009 #if defined(_EFM32_GIANT_FAMILY)
1010 /* Giant Gecko has an additional divider, not used by USBC */
1011 ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>
1012 _CMU_CTRL_HFCLKDIV_SHIFT));
1013 #endif
1014 } break;
1015
1016 #if defined(_CMU_HFPERCLKEN0_USART0_MASK) || \
1017 defined(_CMU_HFPERCLKEN0_USART1_MASK) || \
1018 defined(_CMU_HFPERCLKEN0_USART2_MASK) || \
1019 defined(_CMU_HFPERCLKEN0_UART0_MASK) || \
1020 defined(_CMU_HFPERCLKEN0_UART1_MASK) || \
1021 defined(_CMU_HFPERCLKEN0_TIMER0_MASK) || \
1022 defined(_CMU_HFPERCLKEN0_TIMER1_MASK) || \
1023 defined(_CMU_HFPERCLKEN0_TIMER2_MASK) || \
1024 defined(_CMU_HFPERCLKEN0_TIMER3_MASK) || \
1025 defined(_CMU_HFPERCLKEN0_ACMP0_MASK) || \
1026 defined(_CMU_HFPERCLKEN0_ACMP1_MASK) || \
1027 defined(_CMU_HFPERCLKEN0_DAC0_MASK) || \
1028 defined(_CMU_HFPERCLKEN0_ADC0_MASK) || \
1029 defined(_CMU_HFPERCLKEN0_I2C0_MASK) || \
1030 defined(_CMU_HFPERCLKEN0_I2C1_MASK) || \
1031 defined(PRS_PRESENT) || \
1032 defined(VCMP_PRESENT)|| \
1033 defined(GPIO_PRESENT)
1034 case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1035 {
1036 ret = SystemHFClockGet();
1037 #if defined (_EFM32_GIANT_FAMILY)
1038 /* Leopard/Giant Gecko has an additional divider */
1039 ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK) >>
1040 _CMU_CTRL_HFCLKDIV_SHIFT));
1041 #endif
1042 ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >>
1043 _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT;
1044 } break;
1045 #endif
1046
1047 #if defined(AES_PRESENT) || \
1048 defined(DMA_PRESENT) || \
1049 defined(EBI_PRESENT) || \
1050 defined(USB_PRESENT)
1051 case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1052 {
1053 ret = SystemCoreClockGet();
1054 } break;
1055 #endif
1056
1057 case (CMU_LFA_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1058 {
1059 ret = CMU_LFClkGet(CMU_LFA);
1060 } break;
1061 #if defined(_CMU_LFACLKEN0_RTC_MASK)
1062 case (CMU_RTC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1063 {
1064 ret = CMU_LFClkGet(CMU_LFA);
1065 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK) >>
1066 _CMU_LFAPRESC0_RTC_SHIFT;
1067 } break;
1068 #endif
1069 #if defined(_CMU_LFACLKEN0_LETIMER0_MASK)
1070 case (CMU_LETIMER_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1071 {
1072 ret = CMU_LFClkGet(CMU_LFA);
1073 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK) >>
1074 _CMU_LFAPRESC0_LETIMER0_SHIFT;
1075 } break;
1076 #endif
1077 #if defined(_CMU_LFACLKEN0_LCD_MASK)
1078 case (CMU_LCDPRE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1079 {
1080 ret = CMU_LFClkGet(CMU_LFA);
1081 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>
1082 _CMU_LFAPRESC0_LCD_SHIFT;
1083 } break;
1084
1085 case (CMU_LCD_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1086 {
1087 ret = CMU_LFClkGet(CMU_LFA);
1088 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK) >>
1089 _CMU_LFAPRESC0_LCD_SHIFT;
1090 ret /= (1 + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >>
1091 _CMU_LCDCTRL_FDIV_SHIFT));
1092 } break;
1093 #endif
1094 #if defined(_CMU_LFACLKEN0_LESENSE_MASK)
1095 case (CMU_LESENSE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1096 {
1097 ret = CMU_LFClkGet(CMU_LFA);
1098 ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK) >>
1099 _CMU_LFAPRESC0_LESENSE_SHIFT;
1100 } break;
1101 #endif
1102 case (CMU_LFB_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1103 {
1104 ret = CMU_LFClkGet(CMU_LFB);
1105 } break;
1106 #if defined(_CMU_LFBCLKEN0_LEUART0_MASK)
1107 case (CMU_LEUART0_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1108 {
1109 ret = CMU_LFClkGet(CMU_LFB);
1110 ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK) >>
1111 _CMU_LFBPRESC0_LEUART0_SHIFT;
1112 } break;
1113 #endif
1114 #if defined(_CMU_LFBCLKEN0_LEUART1_MASK)
1115 case (CMU_LEUART1_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1116 {
1117 ret = CMU_LFClkGet(CMU_LFB);
1118 ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK) >>
1119 _CMU_LFBPRESC0_LEUART1_SHIFT;
1120 } break;
1121 #endif
1122
1123 case (CMU_DBG_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1124 {
1125 ret = CMU_DBGClkGet();
1126 } break;
1127
1128 case (CMU_AUX_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1129 {
1130 ret = CMU_AUXClkGet();
1131 } break;
1132
1133 #if defined(USB_PRESENT)
1134 case (CMU_USBC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
1135 {
1136 ret = CMU_USBCClkGet();
1137 } break;
1138 #endif
1139 default:
1140 {
1141 EFM_ASSERT(0);
1142 ret = 0;
1143 } break;
1144 }
1145 return ret;
1146 }
1147
1148
1149 /**************************************************************************//**
1150 * @brief
1151 * Get currently selected reference clock used for a clock branch.
1152 *
1153 * @param[in] clock
1154 * Clock branch to fetch selected ref. clock for. One of:
1155 * @li #cmuClock_HF
1156 * @li #cmuClock_LFA
1157 * @li #cmuClock_LFB
1158 * @li #cmuClock_USBC
1159 * @li #cmuClock_DBG
1160 *
1161 * @return
1162 * Reference clock used for clocking selected branch, #cmuSelect_Error if
1163 * invalid @p clock provided.
1164 *****************************************************************************/
CMU_ClockSelectGet(CMU_Clock_TypeDef clock)1165 CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock)
1166 {
1167 CMU_Select_TypeDef ret = cmuSelect_Disabled;
1168 uint32_t selReg;
1169
1170 selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;
1171
1172 switch (selReg)
1173 {
1174 case CMU_HFCLKSEL_REG:
1175 switch (CMU->STATUS & (CMU_STATUS_HFRCOSEL | CMU_STATUS_HFXOSEL |
1176 CMU_STATUS_LFRCOSEL | CMU_STATUS_LFXOSEL))
1177 {
1178 case CMU_STATUS_LFXOSEL:
1179 ret = cmuSelect_LFXO;
1180 break;
1181
1182 case CMU_STATUS_LFRCOSEL:
1183 ret = cmuSelect_LFRCO;
1184 break;
1185
1186 case CMU_STATUS_HFXOSEL:
1187 ret = cmuSelect_HFXO;
1188 break;
1189
1190 default:
1191 ret = cmuSelect_HFRCO;
1192 break;
1193 }
1194 break;
1195
1196 case CMU_LFACLKSEL_REG:
1197 switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK)
1198 {
1199 case _CMU_LFCLKSEL_LFA_LFRCO:
1200 ret = cmuSelect_LFRCO;
1201 break;
1202
1203 case _CMU_LFCLKSEL_LFA_LFXO:
1204 ret = cmuSelect_LFXO;
1205 break;
1206
1207 case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
1208 ret = cmuSelect_CORELEDIV2;
1209 break;
1210
1211 default:
1212 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1213 if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK)
1214 {
1215 ret = cmuSelect_ULFRCO;
1216 break;
1217 }
1218 #else
1219 ret = cmuSelect_Disabled;
1220 #endif
1221 break;
1222 }
1223 break;
1224
1225 case CMU_LFBCLKSEL_REG:
1226 switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK)
1227 {
1228 case _CMU_LFCLKSEL_LFB_LFRCO:
1229 ret = cmuSelect_LFRCO;
1230 break;
1231
1232 case _CMU_LFCLKSEL_LFB_LFXO:
1233 ret = cmuSelect_LFXO;
1234 break;
1235
1236 case _CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2:
1237 ret = cmuSelect_CORELEDIV2;
1238 break;
1239
1240 default:
1241 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1242 if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK)
1243 {
1244 ret = cmuSelect_ULFRCO;
1245 break;
1246 }
1247 #else
1248 ret = cmuSelect_Disabled;
1249 #endif
1250 break;
1251 }
1252 break;
1253
1254 case CMU_DBGCLKSEL_REG:
1255 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1256 switch(CMU->CTRL & _CMU_CTRL_DBGCLK_MASK)
1257 {
1258 case CMU_CTRL_DBGCLK_AUXHFRCO:
1259 ret = cmuSelect_AUXHFRCO;
1260 break;
1261
1262 case CMU_CTRL_DBGCLK_HFCLK:
1263 ret = cmuSelect_HFCLK;
1264 break;
1265 }
1266 #endif
1267 #if defined(_EFM32_GECKO_FAMILY)
1268 ret = cmuSelect_AUXHFRCO;
1269 #endif
1270 break;
1271
1272
1273 #if defined(USB_PRESENT)
1274 case CMU_USBCCLKSEL_REG:
1275 switch(CMU->STATUS & (CMU_STATUS_USBCHFCLKSEL |
1276 CMU_STATUS_USBCLFXOSEL |
1277 CMU_STATUS_USBCLFRCOSEL))
1278 {
1279 case CMU_STATUS_USBCHFCLKSEL:
1280 ret = cmuSelect_HFCLK;
1281 break;
1282
1283 case CMU_STATUS_USBCLFXOSEL:
1284 ret = cmuSelect_LFXO;
1285 break;
1286
1287 case CMU_STATUS_USBCLFRCOSEL:
1288 ret = cmuSelect_LFRCO;
1289 break;
1290
1291 default:
1292 ret = cmuSelect_Disabled;
1293 break;
1294 }
1295 break;
1296 #endif
1297
1298 default:
1299 EFM_ASSERT(0);
1300 ret = cmuSelect_Error;
1301 break;
1302 }
1303
1304 return ret;
1305 }
1306
1307
1308 /**************************************************************************//**
1309 * @brief
1310 * Select reference clock/oscillator used for a clock branch.
1311 *
1312 * @details
1313 * Notice that if a selected reference is not enabled prior to selecting its
1314 * use, it will be enabled, and this function will wait for the selected
1315 * oscillator to be stable. It will however NOT be disabled if another
1316 * reference clock is selected later.
1317 *
1318 * This feature is particularly important if selecting a new reference
1319 * clock for the clock branch clocking the core, otherwise the system
1320 * may halt.
1321 *
1322 * @param[in] clock
1323 * Clock branch to select reference clock for. One of:
1324 * @li #cmuClock_HF
1325 * @li #cmuClock_LFA
1326 * @li #cmuClock_LFB
1327 * @li #cmuClock_USBC
1328 * @li #cmuClock_DBG
1329 *
1330 * @param[in] ref
1331 * Reference selected for clocking, please refer to reference manual for
1332 * for details on which reference is available for a specific clock branch.
1333 * @li #cmuSelect_HFRCO
1334 * @li #cmuSelect_LFRCO
1335 * @li #cmuSelect_HFXO
1336 * @li #cmuSelect_LFXO
1337 * @li #cmuSelect_CORELEDIV2
1338 * @li #cmuSelect_AUXHFRC
1339 * @li #cmuSelect_HFCLK
1340 * @li #cmuSelect_ULFRCO
1341 *****************************************************************************/
CMU_ClockSelectSet(CMU_Clock_TypeDef clock,CMU_Select_TypeDef ref)1342 void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
1343 {
1344 uint32_t select = cmuOsc_HFRCO;
1345 CMU_Osc_TypeDef osc = cmuOsc_HFRCO;
1346 uint32_t freq;
1347 uint32_t selReg;
1348 uint32_t lfShift;
1349 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1350 uint32_t lfExtendedShift;
1351 uint32_t lfExtended = 0;
1352 #endif
1353 uint32_t tmp;
1354
1355 selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;
1356
1357 switch (selReg)
1358 {
1359 case CMU_HFCLKSEL_REG:
1360 switch (ref)
1361 {
1362 case cmuSelect_LFXO:
1363 select = CMU_CMD_HFCLKSEL_LFXO;
1364 osc = cmuOsc_LFXO;
1365 break;
1366
1367 case cmuSelect_LFRCO:
1368 select = CMU_CMD_HFCLKSEL_LFRCO;
1369 osc = cmuOsc_LFRCO;
1370 break;
1371
1372 case cmuSelect_HFXO:
1373 select = CMU_CMD_HFCLKSEL_HFXO;
1374 osc = cmuOsc_HFXO;
1375 #if defined(_EFM32_GIANT_FAMILY)
1376 /* Adjust HFXO buffer current for high frequencies, enable HFLE for */
1377 /* frequencies above 32MHz */
1378 if(SystemHFXOClockGet() > CMU_MAX_FREQ_HFLE)
1379 {
1380 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) |
1381 CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ |
1382 /* Must have HFLE enabled to access some LE peripherals >=32MHz */
1383 CMU_CTRL_HFLE;
1384 } else {
1385 /* This can happen if the user configures the EFM32_HFXO_FREQ to */
1386 /* use another oscillator frequency */
1387 CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK) |
1388 CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ;
1389 }
1390 #endif
1391 break;
1392
1393 case cmuSelect_HFRCO:
1394 select = CMU_CMD_HFCLKSEL_HFRCO;
1395 osc = cmuOsc_HFRCO;
1396 break;
1397
1398 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1399 case cmuSelect_ULFRCO:
1400 /* ULFRCO cannot be used as HFCLK */
1401 EFM_ASSERT(0);
1402 break;
1403 #endif
1404
1405 default:
1406 EFM_ASSERT(0);
1407 return;
1408 }
1409
1410 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
1411 CMU_OscillatorEnable(osc, true, true);
1412
1413 /* Configure worst case wait states for flash access before selecting */
1414 CMU_FlashWaitStateMax();
1415
1416 /* Switch to selected oscillator */
1417 CMU->CMD = select;
1418
1419 /* Keep EMU module informed */
1420 EMU_UpdateOscConfig();
1421
1422 /* Update CMSIS core clock variable */
1423 /* (The function will update the global variable) */
1424 freq = SystemCoreClockGet();
1425
1426 /* Optimize flash access wait state setting for currently selected core clk */
1427 CMU_FlashWaitStateControl(freq);
1428 break;
1429
1430 case CMU_LFACLKSEL_REG:
1431 case CMU_LFBCLKSEL_REG:
1432 if (selReg == CMU_LFACLKSEL_REG)
1433 {
1434 lfShift = _CMU_LFCLKSEL_LFA_SHIFT;
1435 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1436 lfExtendedShift = _CMU_LFCLKSEL_LFAE_SHIFT;
1437 #endif
1438 }
1439 else
1440 {
1441 lfShift = _CMU_LFCLKSEL_LFB_SHIFT;
1442 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1443 lfExtendedShift = _CMU_LFCLKSEL_LFBE_SHIFT;
1444 #endif
1445 }
1446
1447 switch (ref)
1448 {
1449 case cmuSelect_Disabled:
1450 tmp = _CMU_LFCLKSEL_LFA_DISABLED;
1451 break;
1452
1453 case cmuSelect_LFXO:
1454 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
1455 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
1456 tmp = _CMU_LFCLKSEL_LFA_LFXO;
1457 break;
1458
1459 case cmuSelect_LFRCO:
1460 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
1461 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
1462 tmp = _CMU_LFCLKSEL_LFA_LFRCO;
1463 break;
1464
1465 case cmuSelect_CORELEDIV2:
1466 /* Ensure HFCORE to LE clocking is enabled */
1467 BITBAND_Peripheral(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_LE_SHIFT, 1);
1468 tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2;
1469 #if defined(_EFM32_GIANT_FAMILY)
1470 /* If core frequency is > 32MHz on Giant/Leopard, enable HFLE and DIV4 */
1471 freq = SystemCoreClockGet();
1472 if(freq > CMU_MAX_FREQ_HFLE)
1473 {
1474 /* Enable CMU HFLE */
1475 BITBAND_Peripheral(&(CMU->CTRL), _CMU_CTRL_HFLE_SHIFT, 1);
1476
1477 /* Enable DIV4 factor for peripheral clock */
1478 BITBAND_Peripheral(&(CMU->HFCORECLKDIV),
1479 _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
1480 }
1481 #endif
1482 break;
1483
1484 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1485 case cmuSelect_ULFRCO:
1486 /* ULFRCO is always enabled */
1487 tmp = _CMU_LFCLKSEL_LFA_DISABLED;
1488 lfExtended = 1;
1489 break;
1490 #endif
1491
1492 default:
1493 /* Illegal clock source for LFA/LFB selected */
1494 EFM_ASSERT(0);
1495 return;
1496 }
1497
1498 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1499 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~((_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK) << lfShift)) |
1500 (tmp << lfShift) | (lfExtended << lfExtendedShift);
1501 #else
1502 CMU->LFCLKSEL = (CMU->LFCLKSEL & ~(_CMU_LFCLKSEL_LFA_MASK << lfShift)) |
1503 (tmp << lfShift);
1504 #endif
1505 break;
1506
1507 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1508 case CMU_DBGCLKSEL_REG:
1509 switch(ref)
1510 {
1511 case cmuSelect_AUXHFRCO:
1512 /* Select AUXHFRCO as debug clock */
1513 CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))| CMU_CTRL_DBGCLK_AUXHFRCO;
1514 break;
1515
1516 case cmuSelect_HFCLK:
1517 /* Select divided HFCLK as debug clock */
1518 CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))| CMU_CTRL_DBGCLK_HFCLK;
1519 break;
1520
1521 default:
1522 /* Illegal clock source for debug selected */
1523 EFM_ASSERT(0);
1524 return;
1525 }
1526 break;
1527 #endif
1528
1529 #if defined(USB_PRESENT)
1530 case CMU_USBCCLKSEL_REG:
1531 switch(ref)
1532 {
1533
1534 case cmuSelect_HFCLK:
1535 /* Select undivided HFCLK as clock source for USB */
1536 /* Oscillator must already be enabled, if not the core had stopped */
1537 CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
1538 /* Wait until clock is activated */
1539 while((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL)==0);
1540 break;
1541
1542 case cmuSelect_LFXO:
1543 /* Select LFXO as clock source for USB, can only be used in sleep mode */
1544
1545 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
1546 CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
1547
1548 /* Switch oscillator */
1549 CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;
1550
1551 /* Wait until clock is activated */
1552 while((CMU->STATUS & CMU_STATUS_USBCLFXOSEL)==0);
1553 break;
1554
1555 case cmuSelect_LFRCO:
1556 /* Select LFRCO as clock source for USB, can only be used in sleep mode */
1557
1558 /* Ensure selected oscillator is enabled, waiting for it to stabilize */
1559 CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
1560
1561 /* Switch oscillator */
1562 CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;
1563
1564 /* Wait until clock is activated */
1565 while((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL)==0);
1566 break;
1567
1568 default:
1569 /* Illegal clock source for USB */
1570 EFM_ASSERT(0);
1571 return;
1572 }
1573 /* Wait until clock has been activated */
1574 break;
1575 #endif
1576
1577 default:
1578 EFM_ASSERT(0);
1579 break;
1580 }
1581 }
1582
1583
1584 /**************************************************************************//**
1585 * @brief
1586 * CMU low frequency register synchronization freeze control.
1587 *
1588 * @details
1589 * Some CMU registers requires synchronization into the low frequency (LF)
1590 * domain. The freeze feature allows for several such registers to be
1591 * modified before passing them to the LF domain simultaneously (which
1592 * takes place when the freeze mode is disabled).
1593 *
1594 * Another usage scenario of this feature, is when using an API (such
1595 * as the CMU API) for modifying several bit fields consecutively in the
1596 * same register. If freeze mode is enabled during this sequence, stalling
1597 * can be avoided.
1598 *
1599 * @note
1600 * When enabling freeze mode, this function will wait for all current
1601 * ongoing CMU synchronization to LF domain to complete (Normally
1602 * synchronization will not be in progress.) However for this reason, when
1603 * using freeze mode, modifications of registers requiring LF synchronization
1604 * should be done within one freeze enable/disable block to avoid unecessary
1605 * stalling.
1606 *
1607 * @param[in] enable
1608 * @li true - enable freeze, modified registers are not propagated to the
1609 * LF domain
1610 * @li false - disable freeze, modified registers are propagated to LF
1611 * domain
1612 *****************************************************************************/
CMU_FreezeEnable(bool enable)1613 void CMU_FreezeEnable(bool enable)
1614 {
1615 if (enable)
1616 {
1617 /* Wait for any ongoing LF synchronization to complete. This is just to */
1618 /* protect against the rare case when a user */
1619 /* - modifies a register requiring LF sync */
1620 /* - then enables freeze before LF sync completed */
1621 /* - then modifies the same register again */
1622 /* since modifying a register while it is in sync progress should be */
1623 /* avoided. */
1624 while (CMU->SYNCBUSY)
1625 ;
1626
1627 CMU->FREEZE = CMU_FREEZE_REGFREEZE;
1628 }
1629 else
1630 {
1631 CMU->FREEZE = 0;
1632 }
1633 }
1634
1635
1636 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
1637 /***************************************************************************//**
1638 * @brief
1639 * Get AUXHFRCO band in use.
1640 *
1641 * @return
1642 * AUXHFRCO band in use.
1643 ******************************************************************************/
CMU_AUXHFRCOBandGet(void)1644 CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void)
1645 {
1646 return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK) >>
1647 _CMU_AUXHFRCOCTRL_BAND_SHIFT);
1648 }
1649
1650 /***************************************************************************//**
1651 * @brief
1652 * Set AUIXHFRCO band and the tuning value based on the value in the
1653 * calibration table made during production.
1654 *
1655 * @param[in] band
1656 * AUXHFRCO band to activate.
1657 ******************************************************************************/
CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)1658 void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)
1659 {
1660 uint32_t tuning;
1661
1662 /* Read tuning value from calibration table */
1663 switch (band)
1664 {
1665 case cmuAUXHFRCOBand_1MHz:
1666 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK) >>
1667 _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT;
1668 break;
1669
1670 case cmuAUXHFRCOBand_7MHz:
1671 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK) >>
1672 _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT;
1673 break;
1674
1675 case cmuAUXHFRCOBand_11MHz:
1676 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK) >>
1677 _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT;
1678 break;
1679
1680 case cmuAUXHFRCOBand_14MHz:
1681 tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK) >>
1682 _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT;
1683 break;
1684
1685 case cmuAUXHFRCOBand_21MHz:
1686 tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK) >>
1687 _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT;
1688 break;
1689
1690 case cmuAUXHFRCOBand_28MHz:
1691 tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK) >>
1692 _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT;
1693 break;
1694
1695 default:
1696 EFM_ASSERT(0);
1697 return;
1698 }
1699
1700 /* Set band/tuning */
1701 CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL &
1702 ~(_CMU_AUXHFRCOCTRL_BAND_MASK | _CMU_AUXHFRCOCTRL_TUNING_MASK)) |
1703 (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT) |
1704 (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);
1705
1706 }
1707 #endif
1708
1709
1710 /***************************************************************************//**
1711 * @brief
1712 * Get HFRCO band in use.
1713 *
1714 * @return
1715 * HFRCO band in use.
1716 ******************************************************************************/
CMU_HFRCOBandGet(void)1717 CMU_HFRCOBand_TypeDef CMU_HFRCOBandGet(void)
1718 {
1719 return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK) >>
1720 _CMU_HFRCOCTRL_BAND_SHIFT);
1721 }
1722
1723
1724 /***************************************************************************//**
1725 * @brief
1726 * Set HFRCO band and the tuning value based on the value in the calibration
1727 * table made during production.
1728 *
1729 * @param[in] band
1730 * HFRCO band to activate.
1731 ******************************************************************************/
CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)1732 void CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)
1733 {
1734 uint32_t tuning;
1735 uint32_t freq;
1736 CMU_Select_TypeDef osc;
1737
1738 /* Read tuning value from calibration table */
1739 switch (band)
1740 {
1741 case cmuHFRCOBand_1MHz:
1742 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK) >>
1743 _DEVINFO_HFRCOCAL0_BAND1_SHIFT;
1744 break;
1745
1746 case cmuHFRCOBand_7MHz:
1747 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK) >>
1748 _DEVINFO_HFRCOCAL0_BAND7_SHIFT;
1749 break;
1750
1751 case cmuHFRCOBand_11MHz:
1752 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK) >>
1753 _DEVINFO_HFRCOCAL0_BAND11_SHIFT;
1754 break;
1755
1756 case cmuHFRCOBand_14MHz:
1757 tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK) >>
1758 _DEVINFO_HFRCOCAL0_BAND14_SHIFT;
1759 break;
1760
1761 case cmuHFRCOBand_21MHz:
1762 tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK) >>
1763 _DEVINFO_HFRCOCAL1_BAND21_SHIFT;
1764 break;
1765
1766 case cmuHFRCOBand_28MHz:
1767 tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK) >>
1768 _DEVINFO_HFRCOCAL1_BAND28_SHIFT;
1769 break;
1770
1771 default:
1772 EFM_ASSERT(0);
1773 return;
1774 }
1775
1776 /* If HFRCO is used for core clock, we have to consider flash access WS. */
1777 osc = CMU_ClockSelectGet(cmuClock_HF);
1778 if (osc == cmuSelect_HFRCO)
1779 {
1780 /* Configure worst case wait states for flash access before setting divider */
1781 CMU_FlashWaitStateMax();
1782 }
1783
1784 /* Set band/tuning */
1785 CMU->HFRCOCTRL = (CMU->HFRCOCTRL &
1786 ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK)) |
1787 (band << _CMU_HFRCOCTRL_BAND_SHIFT) |
1788 (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT);
1789
1790 /* If HFRCO is used for core clock, optimize flash WS */
1791 if (osc == cmuSelect_HFRCO)
1792 {
1793 /* Update CMSIS core clock variable and get current core clock */
1794 /* (The function will update the global variable) */
1795 /* NOTE! We need at least 21 cycles before setting zero wait state to flash */
1796 /* (i.e. WS0) when going from the 28MHz to 1MHz in the HFRCO band */
1797 freq = SystemCoreClockGet();
1798
1799 /* Optimize flash access wait state setting for current core clk */
1800 CMU_FlashWaitStateControl(freq);
1801 }
1802 }
1803
1804
1805 /***************************************************************************//**
1806 * @brief
1807 * Get the HFRCO startup delay.
1808 *
1809 * @details
1810 * Please refer to the reference manual for further details.
1811 *
1812 * @return
1813 * The startup delay in use.
1814 ******************************************************************************/
CMU_HFRCOStartupDelayGet(void)1815 uint32_t CMU_HFRCOStartupDelayGet(void)
1816 {
1817 return((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK) >>
1818 _CMU_HFRCOCTRL_SUDELAY_SHIFT);
1819 }
1820
1821
1822 /***************************************************************************//**
1823 * @brief
1824 * Set the HFRCO startup delay.
1825 *
1826 * @details
1827 * Please refer to the reference manual for further details.
1828 *
1829 * @param[in] delay
1830 * The startup delay to set (<= 31).
1831 ******************************************************************************/
CMU_HFRCOStartupDelaySet(uint32_t delay)1832 void CMU_HFRCOStartupDelaySet(uint32_t delay)
1833 {
1834 EFM_ASSERT(delay <= 31);
1835
1836 delay &= (_CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT);
1837 CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK)) |
1838 (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT);
1839 }
1840
1841
1842 /***************************************************************************//**
1843 * @brief
1844 * Get the LCD framerate divisor (FDIV) setting.
1845 *
1846 * @return
1847 * The LCD framerate divisor.
1848 ******************************************************************************/
CMU_LCDClkFDIVGet(void)1849 uint32_t CMU_LCDClkFDIVGet(void)
1850 {
1851 #if defined(LCD_PRESENT)
1852 return((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT);
1853 #else
1854 return 0;
1855 #endif /* defined(LCD_PRESENT) */
1856 }
1857
1858
1859 /***************************************************************************//**
1860 * @brief
1861 * Set the LCD framerate divisor (FDIV) setting.
1862 *
1863 * @note
1864 * The FDIV field (CMU LCDCTRL register) should only be modified while the
1865 * LCD module is clock disabled (CMU LFACLKEN0.LCD bit is 0). This function
1866 * will NOT modify FDIV if the LCD module clock is enabled. Please refer to
1867 * CMU_ClockEnable() for disabling/enabling LCD clock.
1868 *
1869 * @param[in] div
1870 * The FDIV setting to use.
1871 ******************************************************************************/
CMU_LCDClkFDIVSet(uint32_t div)1872 void CMU_LCDClkFDIVSet(uint32_t div)
1873 {
1874 #if defined(LCD_PRESENT)
1875 EFM_ASSERT(div <= cmuClkDiv_128);
1876
1877 /* Do not allow modification if LCD clock enabled */
1878 if (CMU->LFACLKEN0 & CMU_LFACLKEN0_LCD)
1879 {
1880 return;
1881 }
1882
1883 div <<= _CMU_LCDCTRL_FDIV_SHIFT;
1884 div &= _CMU_LCDCTRL_FDIV_MASK;
1885 CMU->LCDCTRL = (CMU->LCDCTRL & ~_CMU_LCDCTRL_FDIV_MASK) | div;
1886 #else
1887 (void)div; /* Unused parameter */
1888 #endif /* defined(LCD_PRESENT) */
1889 }
1890
1891
1892 /***************************************************************************//**
1893 * @brief
1894 * Enable/disable oscillator.
1895 *
1896 * @param[in] osc
1897 * The oscillator to enable/disable.
1898 *
1899 * @param[in] enable
1900 * @li true - enable specified oscillator.
1901 * @li false - disable specified oscillator.
1902 *
1903 * @param[in] wait
1904 * Only used if @p enable is true.
1905 * @li true - wait for oscillator start-up time to timeout before returning.
1906 * @li false - do not wait for oscillator start-up time to timeout before
1907 * returning.
1908 ******************************************************************************/
CMU_OscillatorEnable(CMU_Osc_TypeDef osc,bool enable,bool wait)1909 void CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait)
1910 {
1911 uint32_t status;
1912 uint32_t enBit;
1913 uint32_t disBit;
1914
1915 switch (osc)
1916 {
1917 case cmuOsc_HFRCO:
1918 enBit = CMU_OSCENCMD_HFRCOEN;
1919 disBit = CMU_OSCENCMD_HFRCODIS;
1920 status = CMU_STATUS_HFRCORDY;
1921 break;
1922
1923 case cmuOsc_HFXO:
1924 enBit = CMU_OSCENCMD_HFXOEN;
1925 disBit = CMU_OSCENCMD_HFXODIS;
1926 status = CMU_STATUS_HFXORDY;
1927 break;
1928
1929 case cmuOsc_AUXHFRCO:
1930 enBit = CMU_OSCENCMD_AUXHFRCOEN;
1931 disBit = CMU_OSCENCMD_AUXHFRCODIS;
1932 status = CMU_STATUS_AUXHFRCORDY;
1933 break;
1934
1935 case cmuOsc_LFRCO:
1936 enBit = CMU_OSCENCMD_LFRCOEN;
1937 disBit = CMU_OSCENCMD_LFRCODIS;
1938 status = CMU_STATUS_LFRCORDY;
1939 break;
1940
1941 case cmuOsc_LFXO:
1942 enBit = CMU_OSCENCMD_LFXOEN;
1943 disBit = CMU_OSCENCMD_LFXODIS;
1944 status = CMU_STATUS_LFXORDY;
1945 break;
1946
1947 #if defined _CMU_LFCLKSEL_LFAE_ULFRCO
1948 case cmuOsc_ULFRCO:
1949 /* ULFRCO is always enabled, and cannot be turned off */
1950 return;
1951 #endif
1952
1953 default:
1954 /* Undefined clock source */
1955 EFM_ASSERT(0);
1956 return;
1957 }
1958
1959 if (enable)
1960 {
1961 CMU->OSCENCMD = enBit;
1962
1963 /* Wait for clock to stabilize if requested */
1964 if (wait)
1965 {
1966 while (!(CMU->STATUS & status))
1967 ;
1968 }
1969 }
1970 else
1971 {
1972 CMU->OSCENCMD = disBit;
1973 }
1974
1975 /* Keep EMU module informed */
1976 EMU_UpdateOscConfig();
1977 }
1978
1979
1980 /***************************************************************************//**
1981 * @brief
1982 * Get oscillator frequency tuning setting.
1983 *
1984 * @param[in] osc
1985 * Oscillator to get tuning value for, one of:
1986 * @li #cmuOsc_LFRCO
1987 * @li #cmuOsc_HFRCO
1988 * @li #cmuOsc_AUXHFRCO
1989 *
1990 * @return
1991 * The oscillator frequency tuning setting in use.
1992 ******************************************************************************/
CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)1993 uint32_t CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)
1994 {
1995 uint32_t ret;
1996
1997 switch (osc)
1998 {
1999 case cmuOsc_LFRCO:
2000 ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK) >>
2001 _CMU_LFRCOCTRL_TUNING_SHIFT;
2002 break;
2003
2004 case cmuOsc_HFRCO:
2005 ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK) >>
2006 _CMU_HFRCOCTRL_TUNING_SHIFT;
2007 break;
2008
2009 case cmuOsc_AUXHFRCO:
2010 ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK) >>
2011 _CMU_AUXHFRCOCTRL_TUNING_SHIFT;
2012 break;
2013
2014 default:
2015 EFM_ASSERT(0);
2016 ret = 0;
2017 break;
2018 }
2019
2020 return(ret);
2021 }
2022
2023
2024 /***************************************************************************//**
2025 * @brief
2026 * Set the oscillator frequency tuning control.
2027 *
2028 * @note
2029 * Oscillator tuning is done during production, and the tuning value is
2030 * automatically loaded after a reset. Changing the tuning value from the
2031 * calibrated value is for more advanced use.
2032 *
2033 * @param[in] osc
2034 * Oscillator to set tuning value for, one of:
2035 * @li #cmuOsc_LFRCO
2036 * @li #cmuOsc_HFRCO
2037 * @li #cmuOsc_AUXHFRCO
2038 *
2039 * @param[in] val
2040 * The oscillator frequency tuning setting to use.
2041 ******************************************************************************/
CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc,uint32_t val)2042 void CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc, uint32_t val)
2043 {
2044 switch (osc)
2045 {
2046 case cmuOsc_LFRCO:
2047 EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT));
2048
2049 val &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT);
2050 CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK)) |
2051 (val << _CMU_LFRCOCTRL_TUNING_SHIFT);
2052 break;
2053
2054 case cmuOsc_HFRCO:
2055 EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT));
2056
2057 val &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT);
2058 CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK)) |
2059 (val << _CMU_HFRCOCTRL_TUNING_SHIFT);
2060 break;
2061
2062 case cmuOsc_AUXHFRCO:
2063 EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT));
2064
2065 val <<= _CMU_AUXHFRCOCTRL_TUNING_SHIFT;
2066 val &= _CMU_AUXHFRCOCTRL_TUNING_MASK;
2067 CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK)) | val;
2068 break;
2069
2070 default:
2071 EFM_ASSERT(0);
2072 break;
2073 }
2074 }
2075
2076
2077 /**************************************************************************//**
2078 * @brief
2079 * Determine if currently selected PCNTn clock used is external or LFBCLK.
2080 *
2081 * @param[in] inst
2082 * PCNT instance number to get currently selected clock source for.
2083 *
2084 * @return
2085 * @li true - selected clock is external clock.
2086 * @li false - selected clock is LFBCLK.
2087 *****************************************************************************/
CMU_PCNTClockExternalGet(unsigned int inst)2088 bool CMU_PCNTClockExternalGet(unsigned int inst)
2089 {
2090 bool ret;
2091 uint32_t setting;
2092
2093 switch (inst)
2094 {
2095 #if defined(_CMU_PCNTCTRL_PCNT0CLKEN_MASK)
2096 case 0:
2097 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0;
2098 break;
2099
2100 #if defined(_CMU_PCNTCTRL_PCNT1CLKEN_MASK)
2101 case 1:
2102 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0;
2103 break;
2104
2105 #if defined(_CMU_PCNTCTRL_PCNT2CLKEN_MASK)
2106 case 2:
2107 setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0;
2108 break;
2109 #endif
2110 #endif
2111 #endif
2112
2113 default:
2114 setting = 0;
2115 break;
2116 }
2117
2118 if (setting)
2119 {
2120 ret = true;
2121 }
2122 else
2123 {
2124 ret = false;
2125 }
2126 return ret;
2127 }
2128
2129
2130 /**************************************************************************//**
2131 * @brief
2132 * Select PCNTn clock.
2133 *
2134 * @param[in] inst
2135 * PCNT instance number to set selected clock source for.
2136 *
2137 * @param[in] external
2138 * Set to true to select external clock, false to select LFBCLK.
2139 *****************************************************************************/
CMU_PCNTClockExternalSet(unsigned int inst,bool external)2140 void CMU_PCNTClockExternalSet(unsigned int inst, bool external)
2141 {
2142 #if defined(PCNT_PRESENT)
2143 uint32_t setting = 0;
2144
2145 EFM_ASSERT(inst < PCNT_COUNT);
2146
2147 if (external)
2148 {
2149 setting = 1;
2150 }
2151
2152 BITBAND_Peripheral(&(CMU->PCNTCTRL), (inst * 2) + 1, setting);
2153
2154 #else
2155 (void)inst; /* Unused parameter */
2156 (void)external; /* Unused parameter */
2157 #endif
2158 }
2159
2160
2161 /** @} (end addtogroup CMU) */
2162 /** @} (end addtogroup EM_Library) */
2163