EFM32 Giant Gecko Software Documentation  efm32gg-doc-4.2.1
sleep.c
Go to the documentation of this file.
1 /***************************************************************************/
33 /* Chip specific header file(s). */
34 #include "em_device.h"
35 #include "em_assert.h"
36 #include "em_int.h"
37 #include "em_rmu.h"
38 #include "em_emu.h"
39 
40 /* Module header file(s). */
41 #include "sleep.h"
42 
43 /* stdlib is needed for NULL definition */
44 #include <stdlib.h>
45 
46 /***************************************************************************/
51 /***************************************************************************/
65 /*******************************************************************************
66  ******************************* MACROS ************************************
67  ******************************************************************************/
68 
71 /* Number of low energy modes (EM1, EM2, EM3). Note: EM4 sleep/wakeup is handled
72  * differently therefore it is not part of the list! */
73 #define SLEEP_NUMOF_LOW_ENERGY_MODES 3U
74 
75 
76 
77 /*******************************************************************************
78  ****************************** TYPEDEFS ***********************************
79  ******************************************************************************/
80 
81 
82 /*******************************************************************************
83  ****************************** CONSTANTS **********************************
84  ******************************************************************************/
85 
86 
87 /*******************************************************************************
88  ******************************* STATICS ***********************************
89  ******************************************************************************/
90 
91 /* Callback functions to call before and after sleep. */
92 static SLEEP_CbFuncPtr_t sleepCallback = NULL;
93 static SLEEP_CbFuncPtr_t wakeUpCallback = NULL;
94 
95 /* Sleep block counter array representing the nested sleep blocks for the low
96  * energy modes (EM1/EM2/EM3). Array index 0 corresponds to EM1, 1 to EM2 and 2
97  * to EM3 accordingly.
98  *
99  * Note:
100  * - EM4 sleep/wakeup is handled differently therefore it is not part of the
101  * list!
102  * - Max. number of sleep block nesting is 255. */
103 static uint8_t sleepBlockCnt[SLEEP_NUMOF_LOW_ENERGY_MODES];
104 
105 /*******************************************************************************
106  ****************************** PROTOTYPES *********************************
107  ******************************************************************************/
108 
109 static void SLEEP_EnterEMx(SLEEP_EnergyMode_t eMode);
110 //static SLEEP_EnergyMode_t SLEEP_LowestEnergyModeGet(void);
111 
114 /*******************************************************************************
115  *************************** GLOBAL FUNCTIONS ******************************
116  ******************************************************************************/
117 
118 /***************************************************************************/
138 {
139  /* Initialize callback functions. */
140  sleepCallback = pSleepCb;
141  wakeUpCallback = pWakeUpCb;
142 
143  /* Reset sleep block counters. Note: not using for() saves code! */
144  sleepBlockCnt[0U] = 0U;
145  sleepBlockCnt[1U] = 0U;
146  sleepBlockCnt[2U] = 0U;
147 
148 #if (SLEEP_EM4_WAKEUP_CALLBACK_ENABLED == true) && defined(RMU_RSTCAUSE_EM4WURST)
149  /* Check if the Init() happened after an EM4 reset. */
151  {
152  /* Clear the cause of the reset. */
154  /* Call wakeup callback with EM4 parameter. */
155  if (NULL != wakeUpCallback)
156  {
157  wakeUpCallback(sleepEM4);
158  }
159  }
160 #endif
161 }
162 
163 
164 /***************************************************************************/
184 {
185  SLEEP_EnergyMode_t allowedEM;
186 
187  INT_Disable();
188 
189  allowedEM = SLEEP_LowestEnergyModeGet();
190 
191  if ((allowedEM >= sleepEM1) && (allowedEM <= sleepEM3))
192  {
193  SLEEP_EnterEMx(allowedEM);
194  }
195  else
196  {
197  allowedEM = sleepEM0;
198  }
199 
200  INT_Enable();
201 
202  return(allowedEM);
203 }
204 
205 
206 /***************************************************************************/
220 {
221 #if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)
222  /* Unblock the EM2/EM3/EM4 block in the EMU. */
223  EMU_EM2UnBlock();
224 #endif
225 
226  /* Request entering to EM4. */
227  SLEEP_EnterEMx(sleepEM4);
228 }
229 
230 /***************************************************************************/
256 {
257  EFM_ASSERT((eMode >= sleepEM1) && (eMode < sleepEM4));
258  EFM_ASSERT((sleepBlockCnt[(uint8_t) eMode - 1U]) < 255U);
259 
260  /* Increase the sleep block counter of the selected energy mode. */
261  sleepBlockCnt[(uint8_t) eMode - 1U]++;
262 
263 #if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)
264  /* Block EM2/EM3 sleep if the EM2 block begins. */
265  if (eMode == sleepEM2)
266  {
267  EMU_EM2Block();
268  }
269 #endif
270 }
271 
272 /***************************************************************************/
300 {
301  EFM_ASSERT((eMode >= sleepEM1) && (eMode < sleepEM4));
302 
303  /* Decrease the sleep block counter of the selected energy mode. */
304  if (sleepBlockCnt[(uint8_t) eMode - 1U] > 0U)
305  {
306  sleepBlockCnt[(uint8_t) eMode - 1U]--;
307  }
308 
309 #if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)
310  /* Check if the EM2/EM3 block should be unblocked in the EMU. */
311  if (0U == sleepBlockCnt[(uint8_t) sleepEM2 - 1U])
312  {
313  EMU_EM2UnBlock();
314  }
315 #endif
316 }
317 
318 /***************************************************************************/
334 {
335  SLEEP_EnergyMode_t tmpLowestEM = sleepEM0;
336 
337  /* Check which is the lowest energy mode that the system can be set to. */
338  if (0U == sleepBlockCnt[(uint8_t) sleepEM1 - 1U])
339  {
340  tmpLowestEM = sleepEM1;
341  if (0U == sleepBlockCnt[(uint8_t) sleepEM2 - 1U])
342  {
343  tmpLowestEM = sleepEM2;
344  if (0U == sleepBlockCnt[(uint8_t) sleepEM3 - 1U])
345  {
346  tmpLowestEM = sleepEM3;
347  }
348  }
349  }
350 
351  /* Compare with the default lowest energy mode setting. */
352  if (SLEEP_LOWEST_ENERGY_MODE_DEFAULT < tmpLowestEM)
353  {
354  tmpLowestEM = SLEEP_LOWEST_ENERGY_MODE_DEFAULT;
355  }
356 
357  return tmpLowestEM;
358 }
359 
362 /***************************************************************************/
378 static void SLEEP_EnterEMx(SLEEP_EnergyMode_t eMode)
379 {
380  EFM_ASSERT((eMode > sleepEM0) && (eMode <= sleepEM4));
381 
382  /* Call sleepCallback() before going to sleep. */
383  if (NULL != sleepCallback)
384  {
385  /* Call the callback before going to sleep. */
386  sleepCallback(eMode);
387  }
388 
389  /* Enter the requested energy mode. */
390  switch (eMode)
391  {
392  case sleepEM1:
393  {
394  EMU_EnterEM1();
395  } break;
396 
397  case sleepEM2:
398  {
399  EMU_EnterEM2(true);
400  } break;
401 
402  case sleepEM3:
403  {
404  EMU_EnterEM3(true);
405  } break;
406 
407  case sleepEM4:
408  {
409  EMU_EnterEM4();
410  } break;
411 
412  default:
413  {
414  /* Don't do anything, stay in EM0. */
415  } break;
416  }
417 
418  /* Call the callback after waking up from sleep. */
419  if (NULL != wakeUpCallback)
420  {
421  wakeUpCallback(eMode);
422  }
423 }
void SLEEP_SleepBlockEnd(SLEEP_EnergyMode_t eMode)
End sleep block in the requested energy mode.
Definition: sleep.c:299
uint32_t RMU_ResetCauseGet(void)
Get the cause of the last reset.
Definition: em_rmu.c:273
Emlib peripheral API "assert" implementation.
void EMU_EnterEM4(void)
Enter energy mode 4 (EM4).
Definition: em_emu.c:626
void EMU_EnterEM3(bool restore)
Enter energy mode 3 (EM3).
Definition: em_emu.c:529
__STATIC_INLINE uint32_t INT_Enable(void)
Enable interrupts.
Definition: em_int.h:94
void EMU_EnterEM2(bool restore)
Enter energy mode 2 (EM2).
Definition: em_emu.c:413
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
void SLEEP_SleepBlockBegin(SLEEP_EnergyMode_t eMode)
Begin sleep block in the requested energy mode.
Definition: sleep.c:255
#define SLEEP_LOWEST_ENERGY_MODE_DEFAULT
Definition: sleep.h:91
void SLEEP_Init(SLEEP_CbFuncPtr_t pSleepCb, SLEEP_CbFuncPtr_t pWakeUpCb)
Initialize the Sleep module.
Definition: sleep.c:137
Interrupt enable/disable unit API.
SLEEP_EnergyMode_t
Definition: sleep.h:99
__STATIC_INLINE void EMU_EnterEM1(void)
Enter energy mode 1 (EM1).
Definition: em_emu.h:448
__STATIC_INLINE void EMU_EM2UnBlock(void)
Unblock entering EM2 or higher number energy modes.
Definition: em_emu.h:703
SLEEP_EnergyMode_t SLEEP_Sleep(void)
Sets the system to sleep into the lowest possible energy mode.
Definition: sleep.c:183
#define RMU_RSTCAUSE_EM4WURST
Definition: efm32gg_rmu.h:110
Reset Management Unit (RMU) peripheral API.
Energy management unit (EMU) peripheral API.
__STATIC_INLINE uint32_t INT_Disable(void)
Disable interrupts.
Definition: em_int.h:71
void(* SLEEP_CbFuncPtr_t)(SLEEP_EnergyMode_t)
Definition: sleep.h:118
void SLEEP_ForceSleepInEM4(void)
Force the device to go to EM4 without doing any checks.
Definition: sleep.c:219
void RMU_ResetCauseClear(void)
Clear the reset cause register.
Definition: em_rmu.c:231
SLEEP_EnergyMode_t SLEEP_LowestEnergyModeGet(void)
Gets the lowest energy mode that the system is allowed to be set to.
Definition: sleep.c:333
__STATIC_INLINE void EMU_EM2Block(void)
Block entering EM2 or higher number energy modes.
Definition: em_emu.h:694
Energy Modes management driver.