]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/SilLabs_Code/emlib/em_emu.c
Add EFM32 Giant Gecko Starter Kit demo - still a work in progress as the low power...
[freertos] / FreeRTOS / Demo / CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio / Source / SilLabs_Code / emlib / em_emu.c
1 /***************************************************************************//**\r
2  * @file em_emu.c\r
3  * @brief Energy Management Unit (EMU) Peripheral API\r
4  * @version 4.0.0\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
8  *******************************************************************************\r
9  *\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
13  *\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
19  *\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
26  *\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
30  *\r
31  ******************************************************************************/\r
32 \r
33 \r
34 #include "em_emu.h"\r
35 #if defined( EMU_PRESENT ) && ( EMU_COUNT > 0 )\r
36 \r
37 #include "em_cmu.h"\r
38 #include "em_system.h"\r
39 #include "em_assert.h"\r
40 \r
41 /***************************************************************************//**\r
42  * @addtogroup EM_Library\r
43  * @{\r
44  ******************************************************************************/\r
45 \r
46 /***************************************************************************//**\r
47  * @addtogroup EMU\r
48  * @brief Energy Management Unit (EMU) Peripheral API\r
49  * @{\r
50  ******************************************************************************/\r
51 \r
52 /* Consistency check, since restoring assumes similar bitpositions in */\r
53 /* CMU OSCENCMD and STATUS regs */\r
54 #if (CMU_STATUS_AUXHFRCOENS != CMU_OSCENCMD_AUXHFRCOEN)\r
55 #error Conflict in AUXHFRCOENS and AUXHFRCOEN bitpositions\r
56 #endif\r
57 #if (CMU_STATUS_HFXOENS != CMU_OSCENCMD_HFXOEN)\r
58 #error Conflict in HFXOENS and HFXOEN bitpositions\r
59 #endif\r
60 #if (CMU_STATUS_LFRCOENS != CMU_OSCENCMD_LFRCOEN)\r
61 #error Conflict in LFRCOENS and LFRCOEN bitpositions\r
62 #endif\r
63 #if (CMU_STATUS_LFXOENS != CMU_OSCENCMD_LFXOEN)\r
64 #error Conflict in LFXOENS and LFXOEN bitpositions\r
65 #endif\r
66 \r
67 \r
68 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
69 /* Fix for errata EMU_E107 - non-WIC interrupt masks. */\r
70 #if defined(_EFM32_GECKO_FAMILY)\r
71   #define ERRATA_FIX_EMU_E107_EN\r
72   #define NON_WIC_INT_MASK_0    (~(0x0dfc0323U))\r
73   #define NON_WIC_INT_MASK_1    (~(0x0U))\r
74 #elif defined(_EFM32_TINY_FAMILY)\r
75   #define ERRATA_FIX_EMU_E107_EN\r
76   #define NON_WIC_INT_MASK_0    (~(0x001be323U))\r
77   #define NON_WIC_INT_MASK_1    (~(0x0U))\r
78 #elif defined(_EFM32_GIANT_FAMILY)\r
79   #define ERRATA_FIX_EMU_E107_EN\r
80   #define NON_WIC_INT_MASK_0    (~(0xff020e63U))\r
81   #define NON_WIC_INT_MASK_1    (~(0x00000046U))\r
82 #elif defined(_EFM32_WONDER_FAMILY)\r
83   #define ERRATA_FIX_EMU_E107_EN\r
84   #define NON_WIC_INT_MASK_0    (~(0xff020e63U))\r
85   #define NON_WIC_INT_MASK_1    (~(0x00000046U))\r
86 #else\r
87 /* Zero Gecko and future families are not affected by errata EMU_E107 */\r
88 #endif\r
89 \r
90 /* Fix for errata EMU_E108 - High Current Consumption on EM4 Entry. */\r
91 #if defined(_EFM32_HAPPY_FAMILY)\r
92 #define ERRATA_FIX_EMU_E108_EN\r
93 #endif\r
94 /** @endcond */\r
95 \r
96 /*******************************************************************************\r
97  **************************   LOCAL VARIABLES   ********************************\r
98  ******************************************************************************/\r
99 \r
100 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
101 /**\r
102  * CMU configured oscillator selection and oscillator enable status. When a\r
103  * user configures oscillators, this varaiable shall shadow the configuration.\r
104  * It is used by the EMU module in order to be able to restore the oscillator\r
105  * config after having been in certain energy modes (since HW may automatically\r
106  * alter config when going into an energy mode). It is the responsibility of\r
107  * the CMU module to keep it up-to-date (or a user if not using the CMU API\r
108  * for oscillator control).\r
109  */\r
110 static uint32_t cmuStatus;\r
111 /** @endcond */\r
112 \r
113 \r
114 /*******************************************************************************\r
115  **************************   LOCAL FUNCTIONS   ********************************\r
116  ******************************************************************************/\r
117 \r
118 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
119 \r
120 /***************************************************************************//**\r
121  * @brief\r
122  *   Restore oscillators and core clock after having been in EM2 or EM3.\r
123  ******************************************************************************/\r
124 static void EMU_Restore(void)\r
125 {\r
126   uint32_t oscEnCmd;\r
127   uint32_t cmuLocked;\r
128   uint32_t statusClkSelMask;\r
129 \r
130   /* Although we could use the CMU API for most of the below handling, we */\r
131   /* would like this function to be as efficient as possible. */\r
132 \r
133   /* CMU registers may be locked */\r
134   cmuLocked = CMU->LOCK & CMU_LOCK_LOCKKEY_LOCKED;\r
135   CMU_Unlock();\r
136 \r
137   /* AUXHFRCO are automatically disabled (except if using debugger). */\r
138   /* HFRCO, USHFRCO and HFXO are automatically disabled. */\r
139   /* LFRCO/LFXO may be disabled by SW in EM3. */\r
140   /* Restore according to status prior to entering energy mode. */\r
141   oscEnCmd = 0;\r
142   oscEnCmd |= ((cmuStatus & CMU_STATUS_HFRCOENS)    ? CMU_OSCENCMD_HFRCOEN : 0);\r
143   oscEnCmd |= ((cmuStatus & CMU_STATUS_AUXHFRCOENS) ? CMU_OSCENCMD_AUXHFRCOEN : 0);\r
144   oscEnCmd |= ((cmuStatus & CMU_STATUS_LFRCOENS)    ? CMU_OSCENCMD_LFRCOEN : 0);\r
145   oscEnCmd |= ((cmuStatus & CMU_STATUS_HFXOENS)     ? CMU_OSCENCMD_HFXOEN : 0);\r
146   oscEnCmd |= ((cmuStatus & CMU_STATUS_LFXOENS)     ? CMU_OSCENCMD_LFXOEN : 0);\r
147 #if defined( _CMU_STATUS_USHFRCOENS_MASK )\r
148   oscEnCmd |= ((cmuStatus & CMU_STATUS_USHFRCOENS)  ? CMU_OSCENCMD_USHFRCOEN : 0);\r
149 #endif\r
150   CMU->OSCENCMD = oscEnCmd;\r
151 \r
152   statusClkSelMask =\r
153     (CMU_STATUS_HFRCOSEL |\r
154      CMU_STATUS_HFXOSEL |\r
155      CMU_STATUS_LFRCOSEL |\r
156 #if defined( CMU_STATUS_USHFRCODIV2SEL )\r
157      CMU_STATUS_USHFRCODIV2SEL |\r
158 #endif\r
159      CMU_STATUS_LFXOSEL);\r
160 \r
161   /* Restore oscillator used for clocking core */\r
162   switch (cmuStatus & statusClkSelMask)\r
163   {\r
164   case CMU_STATUS_LFRCOSEL:\r
165     /* Wait for LFRCO to stabilize */\r
166     while (!(CMU->STATUS & CMU_STATUS_LFRCORDY))\r
167       ;\r
168     CMU->CMD = CMU_CMD_HFCLKSEL_LFRCO;\r
169     break;\r
170 \r
171   case CMU_STATUS_LFXOSEL:\r
172     /* Wait for LFXO to stabilize */\r
173     while (!(CMU->STATUS & CMU_STATUS_LFXORDY))\r
174       ;\r
175     CMU->CMD = CMU_CMD_HFCLKSEL_LFXO;\r
176     break;\r
177 \r
178   case CMU_STATUS_HFXOSEL:\r
179     /* Wait for HFXO to stabilize */\r
180     while (!(CMU->STATUS & CMU_STATUS_HFXORDY))\r
181       ;\r
182     CMU->CMD = CMU_CMD_HFCLKSEL_HFXO;\r
183     break;\r
184 \r
185 #if defined( CMU_STATUS_USHFRCODIV2SEL )\r
186   case CMU_STATUS_USHFRCODIV2SEL:\r
187     /* Wait for USHFRCO to stabilize */\r
188     while (!(CMU->STATUS & CMU_STATUS_USHFRCORDY))\r
189       ;\r
190     CMU->CMD = _CMU_CMD_HFCLKSEL_USHFRCODIV2;\r
191     break;\r
192 #endif\r
193 \r
194   default: /* CMU_STATUS_HFRCOSEL */\r
195     /* If core clock was HFRCO core clock, it is automatically restored to */\r
196     /* state prior to entering energy mode. No need for further action. */\r
197     break;\r
198   }\r
199 \r
200   /* If HFRCO was disabled before entering Energy Mode, turn it off again */\r
201   /* as it is automatically enabled by wake up */\r
202   if ( ! (cmuStatus & CMU_STATUS_HFRCOENS) )\r
203   {\r
204     CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS;\r
205   }\r
206 \r
207   /* Restore CMU register locking */\r
208   if (cmuLocked)\r
209   {\r
210     CMU_Lock();\r
211   }\r
212 }\r
213 \r
214 \r
215 /* Get enable conditions for errata EMU_E107 fix. */\r
216 #if defined(ERRATA_FIX_EMU_E107_EN)\r
217 static __INLINE bool getErrataFixEmuE107En(void)\r
218 {\r
219   /* SYSTEM_ChipRevisionGet could have been used here, but we would like a faster implementation in this case. */\r
220   uint16_t majorMinorRev;\r
221 \r
222   /* CHIP MAJOR bit [3:0] */\r
223   majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK) >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8);\r
224   /* CHIP MINOR bit [7:4] */\r
225   majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK) >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);\r
226   /* CHIP MINOR bit [3:0] */\r
227   majorMinorRev |=  ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK) >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);\r
228 \r
229 #if defined(_EFM32_GECKO_FAMILY)\r
230   return (majorMinorRev <= 0x0103);\r
231 #elif defined(_EFM32_TINY_FAMILY)\r
232   return (majorMinorRev <= 0x0102);\r
233 #elif defined(_EFM32_GIANT_FAMILY)\r
234   return (majorMinorRev <= 0x0103) || (majorMinorRev == 0x0204);\r
235 #elif defined(_EFM32_WONDER_FAMILY)\r
236   return (majorMinorRev == 0x0100);\r
237 #else\r
238   /* Zero Gecko and future families are not affected by errata EMU_E107 */\r
239   return false;\r
240 #endif\r
241 }\r
242 #endif\r
243 \r
244 /** @endcond */\r
245 \r
246 \r
247 /*******************************************************************************\r
248  **************************   GLOBAL FUNCTIONS   *******************************\r
249  ******************************************************************************/\r
250 \r
251 /***************************************************************************//**\r
252  * @brief\r
253  *   Enter energy mode 2 (EM2).\r
254  *\r
255  * @details\r
256  *   When entering EM2, the high frequency clocks are disabled, ie HFXO, HFRCO\r
257  *   and AUXHFRCO (for AUXHFRCO, see exception note below). When re-entering\r
258  *   EM0, HFRCO is re-enabled and the core will be clocked by the configured\r
259  *   HFRCO band. This ensures a quick wakeup from EM2.\r
260  *\r
261  *   However, prior to entering EM2, the core may have been using another\r
262  *   oscillator than HFRCO. The @p restore parameter gives the user the option\r
263  *   to restore all HF oscillators according to state prior to entering EM2,\r
264  *   as well as the clock used to clock the core. This restore procedure is\r
265  *   handled by SW. However, since handled by SW, it will not be restored\r
266  *   before completing the interrupt function(s) waking up the core!\r
267  *\r
268  * @note\r
269  *   If restoring core clock to use the HFXO oscillator, which has been\r
270  *   disabled during EM2 mode, this function will stall until the oscillator\r
271  *   has stabilized. Stalling time can be reduced by adding interrupt\r
272  *   support detecting stable oscillator, and an asynchronous switch to the\r
273  *   original oscillator. See CMU documentation. Such a feature is however\r
274  *   outside the scope of the implementation in this function.\r
275  * @par\r
276  *   If HFXO is re-enabled by this function, and NOT used to clock the core,\r
277  *   this function will not wait for HFXO to stabilize. This must be considered\r
278  *   by the application if trying to use features relying on that oscillator\r
279  *   upon return.\r
280  * @par\r
281  *   If a debugger is attached, the AUXHFRCO will not be disabled if enabled\r
282  *   upon entering EM2. It will thus remain enabled when returning to EM0\r
283  *   regardless of the @p restore parameter.\r
284  *\r
285  * @param[in] restore\r
286  *   @li true - restore oscillators and clocks, see function details.\r
287  *   @li false - do not restore oscillators and clocks, see function details.\r
288  * @par\r
289  *   The @p restore option should only be used if all clock control is done\r
290  *   via the CMU API.\r
291  ******************************************************************************/\r
292 void EMU_EnterEM2(bool restore)\r
293 {\r
294 #if defined(ERRATA_FIX_EMU_E107_EN)\r
295   bool errataFixEmuE107En;\r
296   uint32_t nonWicIntEn[2];\r
297 #endif\r
298 \r
299   /* Auto-update CMU status just in case before entering energy mode. */\r
300   /* This variable is normally kept up-to-date by the CMU API. */\r
301   cmuStatus = CMU->STATUS;\r
302 \r
303   /* Enter Cortex-M3 deep sleep mode */\r
304   SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;\r
305 \r
306   /* Fix for errata EMU_E107 - store non-WIC interrupt enable flags.\r
307      Disable the enabled non-WIC interrupts. */\r
308 #if defined(ERRATA_FIX_EMU_E107_EN)\r
309   errataFixEmuE107En = getErrataFixEmuE107En();\r
310   if (errataFixEmuE107En)\r
311   {\r
312     nonWicIntEn[0] = NVIC->ISER[0] & NON_WIC_INT_MASK_0;\r
313     NVIC->ICER[0] = nonWicIntEn[0];\r
314 #if (NON_WIC_INT_MASK_1 != (~(0x0U)))\r
315     nonWicIntEn[1] = NVIC->ISER[1] & NON_WIC_INT_MASK_1;\r
316     NVIC->ICER[1] = nonWicIntEn[1];\r
317 #endif\r
318   }\r
319 #endif\r
320 \r
321   __WFI();\r
322 \r
323   /* Fix for errata EMU_E107 - restore state of non-WIC interrupt enable flags. */\r
324 #if defined(ERRATA_FIX_EMU_E107_EN)\r
325   if (errataFixEmuE107En)\r
326   {\r
327     NVIC->ISER[0] = nonWicIntEn[0];\r
328 #if (NON_WIC_INT_MASK_1 != (~(0x0U)))\r
329     NVIC->ISER[1] = nonWicIntEn[1];\r
330 #endif\r
331   }\r
332 #endif\r
333 \r
334   /* Restore oscillators/clocks if specified */\r
335   if (restore)\r
336   {\r
337     EMU_Restore();\r
338   }\r
339   /* If not restoring, and original clock was not HFRCO, we have to */\r
340   /* update CMSIS core clock variable since core clock has changed */\r
341   /* to using HFRCO. */\r
342   else if (!(cmuStatus & CMU_STATUS_HFRCOSEL))\r
343   {\r
344     SystemCoreClockUpdate();\r
345   }\r
346 }\r
347 \r
348 \r
349 /***************************************************************************//**\r
350  * @brief\r
351  *   Enter energy mode 3 (EM3).\r
352  *\r
353  * @details\r
354  *   When entering EM3, the high frequency clocks are disabled by HW, ie HFXO,\r
355  *   HFRCO and AUXHFRCO (for AUXHFRCO, see exception note below). In addition,\r
356  *   the low frequency clocks, ie LFXO and LFRCO are disabled by SW. When\r
357  *   re-entering EM0, HFRCO is re-enabled and the core will be clocked by the\r
358  *   configured HFRCO band. This ensures a quick wakeup from EM3.\r
359  *\r
360  *   However, prior to entering EM3, the core may have been using another\r
361  *   oscillator than HFRCO. The @p restore parameter gives the user the option\r
362  *   to restore all HF/LF oscillators according to state prior to entering EM3,\r
363  *   as well as the clock used to clock the core. This restore procedure is\r
364  *   handled by SW. However, since handled by SW, it will not be restored\r
365  *   before completing the interrupt function(s) waking up the core!\r
366  *\r
367  * @note\r
368  *   If restoring core clock to use an oscillator other than HFRCO, this\r
369  *   function will stall until the oscillator has stabilized. Stalling time\r
370  *   can be reduced by adding interrupt support detecting stable oscillator,\r
371  *   and an asynchronous switch to the original oscillator. See CMU\r
372  *   documentation. Such a feature is however outside the scope of the\r
373  *   implementation in this function.\r
374  * @par\r
375  *   If HFXO/LFXO/LFRCO are re-enabled by this function, and NOT used to clock\r
376  *   the core, this function will not wait for those oscillators to stabilize.\r
377  *   This must be considered by the application if trying to use features\r
378  *   relying on those oscillators upon return.\r
379  * @par\r
380  *   If a debugger is attached, the AUXHFRCO will not be disabled if enabled\r
381  *   upon entering EM3. It will thus remain enabled when returning to EM0\r
382  *   regardless of the @p restore parameter.\r
383  *\r
384  * @param[in] restore\r
385  *   @li true - restore oscillators and clocks, see function details.\r
386  *   @li false - do not restore oscillators and clocks, see function details.\r
387  * @par\r
388  *   The @p restore option should only be used if all clock control is done\r
389  *   via the CMU API.\r
390  ******************************************************************************/\r
391 void EMU_EnterEM3(bool restore)\r
392 {\r
393   uint32_t cmuLocked;\r
394 \r
395 #if defined(ERRATA_FIX_EMU_E107_EN)\r
396   bool errataFixEmuE107En;\r
397   uint32_t nonWicIntEn[2];\r
398 #endif\r
399 \r
400   /* Auto-update CMU status just in case before entering energy mode. */\r
401   /* This variable is normally kept up-to-date by the CMU API. */\r
402   cmuStatus = CMU->STATUS;\r
403 \r
404   /* CMU registers may be locked */\r
405   cmuLocked = CMU->LOCK & CMU_LOCK_LOCKKEY_LOCKED;\r
406   CMU_Unlock();\r
407 \r
408   /* Disable LF oscillators */\r
409   CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS | CMU_OSCENCMD_LFRCODIS;\r
410 \r
411   /* Restore CMU register locking */\r
412   if (cmuLocked)\r
413   {\r
414     CMU_Lock();\r
415   }\r
416 \r
417   /* Enter Cortex-M3 deep sleep mode */\r
418   SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;\r
419 \r
420   /* Fix for errata EMU_E107 - store non-WIC interrupt enable flags.\r
421      Disable the enabled non-WIC interrupts. */\r
422 #if defined(ERRATA_FIX_EMU_E107_EN)\r
423   errataFixEmuE107En = getErrataFixEmuE107En();\r
424   if (errataFixEmuE107En)\r
425   {\r
426     nonWicIntEn[0] = NVIC->ISER[0] & NON_WIC_INT_MASK_0;\r
427     NVIC->ICER[0] = nonWicIntEn[0];\r
428 #if (NON_WIC_INT_MASK_1 != (~(0x0U)))\r
429     nonWicIntEn[1] = NVIC->ISER[1] & NON_WIC_INT_MASK_1;\r
430     NVIC->ICER[1] = nonWicIntEn[1];\r
431 #endif\r
432 \r
433   }\r
434 #endif\r
435 \r
436   __WFI();\r
437 \r
438   /* Fix for errata EMU_E107 - restore state of non-WIC interrupt enable flags. */\r
439 #if defined(ERRATA_FIX_EMU_E107_EN)\r
440   if (errataFixEmuE107En)\r
441   {\r
442     NVIC->ISER[0] = nonWicIntEn[0];\r
443 #if (NON_WIC_INT_MASK_1 != (~(0x0U)))\r
444     NVIC->ISER[1] = nonWicIntEn[1];\r
445 #endif\r
446   }\r
447 #endif\r
448 \r
449   /* Restore oscillators/clocks if specified */\r
450   if (restore)\r
451   {\r
452     EMU_Restore();\r
453   }\r
454   /* If not restoring, and original clock was not HFRCO, we have to */\r
455   /* update CMSIS core clock variable since core clock has changed */\r
456   /* to using HFRCO. */\r
457   else if (!(cmuStatus & CMU_STATUS_HFRCOSEL))\r
458   {\r
459     SystemCoreClockUpdate();\r
460   }\r
461 }\r
462 \r
463 \r
464 /***************************************************************************//**\r
465  * @brief\r
466  *   Enter energy mode 4 (EM4).\r
467  *\r
468  * @note\r
469  *   Only a power on reset or external reset pin can wake the device from EM4.\r
470  ******************************************************************************/\r
471 void EMU_EnterEM4(void)\r
472 {\r
473   int i;\r
474   uint32_t em4seq2;\r
475   uint32_t em4seq3;\r
476 \r
477   em4seq2 = (EMU->CTRL & ~_EMU_CTRL_EM4CTRL_MASK) | (2 << _EMU_CTRL_EM4CTRL_SHIFT);\r
478   em4seq3 = (EMU->CTRL & ~_EMU_CTRL_EM4CTRL_MASK) | (3 << _EMU_CTRL_EM4CTRL_SHIFT);\r
479 \r
480   /* Make sure register write lock is disabled */\r
481   EMU_Unlock();\r
482 \r
483 #if defined(ERRATA_FIX_EMU_E108_EN)\r
484   /* Fix for errata EMU_E108 - High Current Consumption on EM4 Entry. */\r
485   __disable_irq();\r
486   *(volatile uint32_t *)0x400C80E4 = 0;\r
487 #endif\r
488 \r
489   for (i = 0; i < 4; i++)\r
490   {\r
491     EMU->CTRL = em4seq2;\r
492     EMU->CTRL = em4seq3;\r
493   }\r
494   EMU->CTRL = em4seq2;\r
495 }\r
496 \r
497 \r
498 /***************************************************************************//**\r
499  * @brief\r
500  *   Power down memory block.\r
501  *\r
502  * @param[in] blocks\r
503  *   Specifies a logical OR of bits indicating memory blocks to power down.\r
504  *   Bit 0 selects block 1, bit 1 selects block 2, etc. Memory block 0 cannot\r
505  *   be disabled. Please refer to the EFM32 reference manual for available\r
506  *   memory blocks for a device.\r
507  *\r
508  * @note\r
509  *   Only a reset can make the specified memory block(s) available for use\r
510  *   after having been powered down. Function will be void for devices not\r
511  *   supporting this feature.\r
512  ******************************************************************************/\r
513 void EMU_MemPwrDown(uint32_t blocks)\r
514 {\r
515 #if defined(_EMU_MEMCTRL_RESETVALUE)\r
516   EFM_ASSERT(blocks <= _EMU_MEMCTRL_MASK);\r
517 \r
518   EMU->MEMCTRL = blocks;\r
519 #else\r
520   (void)blocks;\r
521 #endif\r
522 }\r
523 \r
524 \r
525 /***************************************************************************//**\r
526  * @brief\r
527  *   Update EMU module with CMU oscillator selection/enable status.\r
528  *\r
529  * @details\r
530  *   When entering EM2 and EM3, the HW may change the core clock oscillator\r
531  *   used, as well as disabling some oscillators. The user may optionally select\r
532  *   to restore the oscillators after waking up from EM2 and EM3 through the\r
533  *   SW API.\r
534  *\r
535  *   However, in order to support this in a safe way, the EMU module must\r
536  *   be kept up-to-date on the actual selected configuration. The CMU\r
537  *   module must keep the EMU module up-to-date.\r
538  *\r
539  *   This function is mainly intended for internal use by the CMU module,\r
540  *   but if the applications changes oscillator configurations without\r
541  *   using the CMU API, this function can be used to keep the EMU module\r
542  *   up-to-date.\r
543  ******************************************************************************/\r
544 void EMU_UpdateOscConfig(void)\r
545 {\r
546   /* Fetch current configuration */\r
547   cmuStatus = CMU->STATUS;\r
548 }\r
549 \r
550 \r
551 #if defined( _EMU_CTRL_EMVREG_MASK ) || defined( _EMU_CTRL_EM23VREG_MASK )\r
552 /***************************************************************************//**\r
553  * @brief\r
554  *   Update EMU module with Energy Mode 2 and 3 configuration\r
555  *\r
556  * @param[in] em23Init\r
557  *    Energy Mode 2 and 3 configuration structure\r
558  ******************************************************************************/\r
559 void EMU_EM23Init(EMU_EM23Init_TypeDef *em23Init)\r
560 {\r
561 #if defined( _EMU_CTRL_EMVREG_MASK )\r
562   EMU->CTRL = em23Init->em23Vreg ? (EMU->CTRL | EMU_CTRL_EMVREG) : (EMU->CTRL & ~EMU_CTRL_EMVREG);\r
563 #elif defined( _EMU_CTRL_EM23VREG_MASK )\r
564   EMU->CTRL = em23Init->em23Vreg ? (EMU->CTRL | EMU_CTRL_EM23VREG) : (EMU->CTRL & ~EMU_CTRL_EM23VREG);\r
565 #endif\r
566 }\r
567 #endif\r
568 \r
569 \r
570 #if defined( _EMU_EM4CONF_MASK )\r
571 /***************************************************************************//**\r
572  * @brief\r
573  *   Update EMU module with Energy Mode 4 configuration\r
574  *\r
575  * @param[in] em4Init\r
576  *    Energy Mode 4 configuration structure\r
577  ******************************************************************************/\r
578 void EMU_EM4Init(EMU_EM4Init_TypeDef *em4Init)\r
579 {\r
580   uint32_t em4conf = EMU->EM4CONF;\r
581 \r
582   /* Clear fields that will be reconfigured */\r
583   em4conf &= ~(\r
584     _EMU_EM4CONF_LOCKCONF_MASK |\r
585     _EMU_EM4CONF_OSC_MASK |\r
586     _EMU_EM4CONF_BURTCWU_MASK |\r
587     _EMU_EM4CONF_VREGEN_MASK);\r
588 \r
589   /* Configure new settings */\r
590   em4conf |= (\r
591     (em4Init->lockConfig << _EMU_EM4CONF_LOCKCONF_SHIFT) |\r
592     (em4Init->osc) |\r
593     (em4Init->buRtcWakeup << _EMU_EM4CONF_BURTCWU_SHIFT) |\r
594     (em4Init->vreg << _EMU_EM4CONF_VREGEN_SHIFT));\r
595 \r
596   /* Apply configuration. Note that lock can be set after this stage. */\r
597   EMU->EM4CONF = em4conf;\r
598 }\r
599 #endif\r
600 \r
601 \r
602 #if defined( BU_PRESENT )\r
603 \r
604 /***************************************************************************//**\r
605  * @brief\r
606  *   Configure Backup Power Domain settings\r
607  *\r
608  * @param[in] bupdInit\r
609  *   Backup power domain initialization structure\r
610  ******************************************************************************/\r
611 void EMU_BUPDInit(EMU_BUPDInit_TypeDef *bupdInit)\r
612 {\r
613   uint32_t reg;\r
614 \r
615   /* Set power connection configuration */\r
616   reg = EMU->PWRCONF & ~(\r
617     _EMU_PWRCONF_PWRRES_MASK|\r
618     _EMU_PWRCONF_VOUTSTRONG_MASK|\r
619     _EMU_PWRCONF_VOUTMED_MASK|\r
620     _EMU_PWRCONF_VOUTWEAK_MASK);\r
621 \r
622   reg |= (bupdInit->resistor|\r
623          (bupdInit->voutStrong << _EMU_PWRCONF_VOUTSTRONG_SHIFT)|\r
624          (bupdInit->voutMed    << _EMU_PWRCONF_VOUTMED_SHIFT)|\r
625          (bupdInit->voutWeak   << _EMU_PWRCONF_VOUTWEAK_SHIFT));\r
626 \r
627   EMU->PWRCONF = reg;\r
628 \r
629   /* Set backup domain inactive mode configuration */\r
630   reg = EMU->BUINACT & ~(_EMU_BUINACT_PWRCON_MASK);\r
631   reg |= (bupdInit->inactivePower);\r
632   EMU->BUINACT = reg;\r
633 \r
634   /* Set backup domain active mode configuration */\r
635   reg = EMU->BUACT & ~(_EMU_BUACT_PWRCON_MASK);\r
636   reg |= (bupdInit->activePower);\r
637   EMU->BUACT = reg;\r
638 \r
639   /* Set power control configuration */\r
640   reg = EMU->BUCTRL & ~(\r
641     _EMU_BUCTRL_PROBE_MASK|\r
642     _EMU_BUCTRL_BODCAL_MASK|\r
643     _EMU_BUCTRL_STATEN_MASK|\r
644     _EMU_BUCTRL_EN_MASK);\r
645 \r
646   /* Note use of ->enable to both enable BUPD, use BU_VIN pin input and\r
647      release reset */\r
648   reg |= (bupdInit->probe|\r
649          (bupdInit->bodCal          << _EMU_BUCTRL_BODCAL_SHIFT)|\r
650          (bupdInit->statusPinEnable << _EMU_BUCTRL_STATEN_SHIFT)|\r
651          (bupdInit->enable          << _EMU_BUCTRL_EN_SHIFT));\r
652 \r
653   /* Enable configuration */\r
654   EMU->BUCTRL = reg;\r
655 \r
656   /* If enable is true, enable BU_VIN input power pin, if not disable it  */\r
657   EMU_BUPinEnable(bupdInit->enable);\r
658 \r
659   /* If enable is true, release BU reset, if not keep reset asserted */\r
660   BITBAND_Peripheral(&(RMU->CTRL), _RMU_CTRL_BURSTEN_SHIFT, !bupdInit->enable);\r
661 }\r
662 \r
663 \r
664 /***************************************************************************//**\r
665  * @brief\r
666  *   Configure Backup Power Domain BOD Threshold value\r
667  * @note\r
668  *   These values are precalibrated\r
669  * @param[in] mode Active or Inactive mode\r
670  * @param[in] value\r
671  ******************************************************************************/\r
672 void EMU_BUThresholdSet(EMU_BODMode_TypeDef mode, uint32_t value)\r
673 {\r
674   EFM_ASSERT(value<=(_EMU_BUACT_BUEXTHRES_MASK>>_EMU_BUACT_BUEXTHRES_SHIFT));\r
675 \r
676   switch(mode)\r
677   {\r
678   case emuBODMode_Active:\r
679     EMU->BUACT = (EMU->BUACT & ~(_EMU_BUACT_BUEXTHRES_MASK))|(value<<_EMU_BUACT_BUEXTHRES_SHIFT);\r
680     break;\r
681   case emuBODMode_Inactive:\r
682     EMU->BUINACT = (EMU->BUINACT & ~(_EMU_BUINACT_BUENTHRES_MASK))|(value<<_EMU_BUINACT_BUENTHRES_SHIFT);\r
683     break;\r
684   }\r
685 }\r
686 \r
687 \r
688 /***************************************************************************//**\r
689  * @brief\r
690  *  Configure Backup Power Domain BOD Threshold Range\r
691  * @note\r
692  *  These values are precalibrated\r
693  * @param[in] mode Active or Inactive mode\r
694  * @param[in] value\r
695  ******************************************************************************/\r
696 void EMU_BUThresRangeSet(EMU_BODMode_TypeDef mode, uint32_t value)\r
697 {\r
698   EFM_ASSERT(value<=(_EMU_BUACT_BUEXRANGE_MASK>>_EMU_BUACT_BUEXRANGE_SHIFT));\r
699 \r
700   switch(mode)\r
701   {\r
702   case emuBODMode_Active:\r
703     EMU->BUACT = (EMU->BUACT & ~(_EMU_BUACT_BUEXRANGE_MASK))|(value<<_EMU_BUACT_BUEXRANGE_SHIFT);\r
704     break;\r
705   case emuBODMode_Inactive:\r
706     EMU->BUINACT = (EMU->BUINACT & ~(_EMU_BUINACT_BUENRANGE_MASK))|(value<<_EMU_BUINACT_BUENRANGE_SHIFT);\r
707     break;\r
708   }\r
709 }\r
710 \r
711 #endif\r
712 \r
713 \r
714 /** @} (end addtogroup EMU) */\r
715 /** @} (end addtogroup EM_Library) */\r
716 #endif /* __EM_EMU_H */\r