emlib/src/em_emu.c
void EMU_EnterEM3(bool restore)
{
  uint32_t cmuLocked;

#if defined(ERRATA_FIX_EMU_E107_EN)
  bool errataFixEmuE107En;
  uint32_t nonWicIntEn[2];
#endif

  /* Only save EMU and CMU state if restored on wake-up. */
  if (restore) {
    emState(emState_Save);
  }

#if defined(_EMU_CTRL_EM23VSCALE_MASK)
  vScaleDownEM23Setup();
#endif

  /* CMU registers may be locked */
  cmuLocked = CMU->LOCK & CMU_LOCK_LOCKKEY_LOCKED;
  CMU_Unlock();

  /* Disable LF oscillators */
  CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS | CMU_OSCENCMD_LFRCODIS;

  /* Restore CMU register locking */
  if (cmuLocked) {
    CMU_Lock();
  }

  /* Enter Cortex deep sleep mode */
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

  /* Fix for errata EMU_E107 - store non-WIC interrupt enable flags.
     Disable the enabled non-WIC interrupts. */
#if defined(ERRATA_FIX_EMU_E107_EN)
  errataFixEmuE107En = getErrataFixEmuE107En();
  if (errataFixEmuE107En) {
    nonWicIntEn[0] = NVIC->ISER[0] & NON_WIC_INT_MASK_0;
    NVIC->ICER[0] = nonWicIntEn[0];
#if (NON_WIC_INT_MASK_1 != (~(0x0U)))
    nonWicIntEn[1] = NVIC->ISER[1] & NON_WIC_INT_MASK_1;
    NVIC->ICER[1] = nonWicIntEn[1];
#endif
  }
#endif

#if defined(ERRATA_FIX_DCDC_FETCNT_SET_EN)
  dcdcFetCntSet(true);
#endif
#if defined(ERRATA_FIX_DCDC_LNHS_BLOCK_EN)
  dcdcHsFixLnBlock();
#endif

  __WFI();

#if defined(ERRATA_FIX_DCDC_FETCNT_SET_EN)
  dcdcFetCntSet(false);
#endif

  /* Fix for errata EMU_E107 - restore state of non-WIC interrupt enable flags. */
#if defined(ERRATA_FIX_EMU_E107_EN)
  if (errataFixEmuE107En) {
    NVIC->ISER[0] = nonWicIntEn[0];
#if (NON_WIC_INT_MASK_1 != (~(0x0U)))
    NVIC->ISER[1] = nonWicIntEn[1];
#endif
  }
#endif

  /* Restore oscillators/clocks and voltage scaling if supported. */
  if (restore) {
    emState(emState_Restore);
  } else {
    /* If not restoring, and original clock was not HFRCO, we have to */
    /* update CMSIS core clock variable since HF clock has changed */
    /* to HFRCO. */
    SystemCoreClockUpdate();
  }
}
/***************************************************************************/
/**
 * @brief
 *   Enter energy mode 3 (EM3).
 *
 * @details
 *   When entering EM3, the high frequency clocks are disabled by HW, ie HFXO,
 *   HFRCO and AUXHFRCO (for AUXHFRCO, see exception note below). In addition,
 *   the low frequency clocks, ie LFXO and LFRCO are disabled by SW. When
 *   re-entering EM0, HFRCO is re-enabled and the core will be clocked by the
 *   configured HFRCO band. This ensures a quick wakeup from EM3.
 *
 *   However, prior to entering EM3, the core may have been using another
 *   oscillator than HFRCO. The @p restore parameter gives the user the option
 *   to restore all HF/LF oscillators according to state prior to entering EM3,
 *   as well as the clock used to clock the core. This restore procedure is
 *   handled by SW. However, since handled by SW, it will not be restored
 *   before completing the interrupt function(s) waking up the core!
 *
 * @note
 *   If restoring core clock to use an oscillator other than HFRCO, this
 *   function will stall until the oscillator has stabilized. Stalling time
 *   can be reduced by adding interrupt support detecting stable oscillator,
 *   and an asynchronous switch to the original oscillator. See CMU
 *   documentation. Such a feature is however outside the scope of the
 *   implementation in this function.
 * @par
 *   If HFXO/LFXO/LFRCO are re-enabled by this function, and NOT used to clock
 *   the core, this function will not wait for those oscillators to stabilize.
 *   This must be considered by the application if trying to use features
 *   relying on those oscillators upon return.
 * @par
 *   If a debugger is attached, the AUXHFRCO will not be disabled if enabled
 *   upon entering EM3. It will thus remain enabled when returning to EM0
 *   regardless of the @p restore parameter.
 * @par
 *   If voltage scaling is supported, the restore parameter is true and the EM0
 *   voltage scaling level is set higher than the EM3 level, then the EM0 level is
 *   also restored.
 *
 * @param[in] restore
 *   @li true - save and restore oscillators, clocks and voltage scaling, see
 *   function details.
 *   @li false - do not save and restore oscillators and clocks, see function
 *   details.
 * @par
 *   The @p restore option should only be used if all clock control is done
 *   via the CMU API.
 ******************************************************************************/
@brief
Enter energy mode 3 (EM3).

@details
When entering EM3, the high frequency clocks are disabled by HW, ie HFXO,
HFRCO and AUXHFRCO (for AUXHFRCO, see exception note below). In addition,
the low frequency clocks, ie LFXO and LFRCO are disabled by SW. When
re-entering EM0, HFRCO is re-enabled and the core will be clocked by the
configured HFRCO band. This ensures a quick wakeup from EM3.

However, prior to entering EM3, the core may have been using another
oscillator than HFRCO. The @p restore parameter gives the user the option
to restore all HF/LF oscillators according to state prior to entering EM3,
as well as the clock used to clock the core. This restore procedure is
handled by SW. However, since handled by SW, it will not be restored
before completing the interrupt function(s) waking up the core!

@note
If restoring core clock to use an oscillator other than HFRCO, this
function will stall until the oscillator has stabilized. Stalling time
can be reduced by adding interrupt support detecting stable oscillator,
and an asynchronous switch to the original oscillator. See CMU
documentation. Such a feature is however outside the scope of the
implementation in this function.
@par
If HFXO/LFXO/LFRCO are re-enabled by this function, and NOT used to clock
the core, this function will not wait for those oscillators to stabilize.
This must be considered by the application if trying to use features
relying on those oscillators upon return.
@par
If a debugger is attached, the AUXHFRCO will not be disabled if enabled
upon entering EM3. It will thus remain enabled when returning to EM0
regardless of the @p restore parameter.
@par
If voltage scaling is supported, the restore parameter is true and the EM0
voltage scaling level is set higher than the EM3 level, then the EM0 level is
also restored.

@param[in] restore
@li true - save and restore oscillators, clocks and voltage scaling, see
function details.
@li false - do not save and restore oscillators and clocks, see function
details.
@par
The @p restore option should only be used if all clock control is done
via the CMU API.
@brief Enter energy mode 3 ( EM3 ) . @details When entering EM3 the high frequency clocks are disabled by HW ie HFXO HFRCO and AUXHFRCO ( for AUXHFRCO see exception note below ) . In addition the low frequency clocks ie LFXO and LFRCO are disabled by SW . When re - entering EM0 HFRCO is re - enabled and the core will be clocked by the configured HFRCO band . This ensures a quick wakeup from EM3 . However prior to entering EM3 the core may have been using another oscillator than HFRCO . The @p restore parameter gives the user the option to restore all HF / LF oscillators according to state prior to entering EM3 as well as the clock used to clock the core . This restore procedure is handled by SW . However since handled by SW it will not be restored before completing the interrupt function ( s ) waking up the core! @note If restoring core clock to use an oscillator other than HFRCO this function will stall until the oscillator has stabilized . Stalling time can be reduced by adding interrupt support detecting stable oscillator and an asynchronous switch to the original oscillator . See CMU documentation . Such a feature is however outside the scope of the implementation in this function . @par If HFXO / LFXO / LFRCO are re - enabled by this function and NOT used to clock the core this function will not wait for those oscillators to stabilize . This must be considered by the application if trying to use features relying on those oscillators upon return . @par If a debugger is attached the AUXHFRCO will not be disabled if enabled upon entering EM3 . It will thus remain enabled when returning to EM0 regardless of the @p restore parameter . @par If voltage scaling is supported the restore parameter is true and the EM0 voltage scaling level is set higher than the EM3 level then the EM0 level is also restored . @param [ in ] restore @li true - save and restore oscillators clocks and voltage scaling see function details . @li false - do not save and restore oscillators and clocks see function details . @par The @p restore option should only be used if all clock control is done via the CMU API .
void EMU_EnterEM3(bool restore)
{
  uint32_t cmuLocked;
#if defined(ERRATA_FIX_EMU_E107_EN)
  bool errataFixEmuE107En;
  uint32_t nonWicIntEn[2];
#endif
  if (restore) {
    emState(emState_Save);
  }
#if defined(_EMU_CTRL_EM23VSCALE_MASK)
  vScaleDownEM23Setup();
#endif
  cmuLocked = CMU->LOCK & CMU_LOCK_LOCKKEY_LOCKED;
  CMU_Unlock();
  CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS | CMU_OSCENCMD_LFRCODIS;
  if (cmuLocked) {
    CMU_Lock();
  }
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
#if defined(ERRATA_FIX_EMU_E107_EN)
  errataFixEmuE107En = getErrataFixEmuE107En();
  if (errataFixEmuE107En) {
    nonWicIntEn[0] = NVIC->ISER[0] & NON_WIC_INT_MASK_0;
    NVIC->ICER[0] = nonWicIntEn[0];
#if (NON_WIC_INT_MASK_1 != (~(0x0U)))
    nonWicIntEn[1] = NVIC->ISER[1] & NON_WIC_INT_MASK_1;
    NVIC->ICER[1] = nonWicIntEn[1];
#endif
  }
#endif
#if defined(ERRATA_FIX_DCDC_FETCNT_SET_EN)
  dcdcFetCntSet(true);
#endif
#if defined(ERRATA_FIX_DCDC_LNHS_BLOCK_EN)
  dcdcHsFixLnBlock();
#endif
  __WFI();
#if defined(ERRATA_FIX_DCDC_FETCNT_SET_EN)
  dcdcFetCntSet(false);
#endif
#if defined(ERRATA_FIX_EMU_E107_EN)
  if (errataFixEmuE107En) {
    NVIC->ISER[0] = nonWicIntEn[0];
#if (NON_WIC_INT_MASK_1 != (~(0x0U)))
    NVIC->ISER[1] = nonWicIntEn[1];
#endif
  }
#endif
  if (restore) {
    emState(emState_Restore);
  } else {
    SystemCoreClockUpdate();
  }
}
void EMU_EnterEM3 ( bool restore ) { uint32_t cmuLocked ; #if defined ( ERRATA_FIX_EMU_E107_EN ) bool errataFixEmuE107En ; uint32_t nonWicIntEn [ 2 ] ; #endif if ( restore ) { emState ( emState_Save ) ; } #if defined ( _EMU_CTRL_EM23VSCALE_MASK ) vScaleDownEM23Setup ( ) ; #endif cmuLocked = CMU -> LOCK & CMU_LOCK_LOCKKEY_LOCKED ; CMU_Unlock ( ) ; CMU -> OSCENCMD = CMU_OSCENCMD_LFXODIS | CMU_OSCENCMD_LFRCODIS ; if ( cmuLocked ) { CMU_Lock ( ) ; } SCB -> SCR |= SCB_SCR_SLEEPDEEP_Msk ; #if defined ( ERRATA_FIX_EMU_E107_EN ) errataFixEmuE107En = getErrataFixEmuE107En ( ) ; if ( errataFixEmuE107En ) { nonWicIntEn [ 0 ] = NVIC -> ISER [ 0 ] & NON_WIC_INT_MASK_0 ; NVIC -> ICER [ 0 ] = nonWicIntEn [ 0 ] ; #if ( NON_WIC_INT_MASK_1 != ( ~ ( 0x0U ) ) ) nonWicIntEn [ 1 ] = NVIC -> ISER [ 1 ] & NON_WIC_INT_MASK_1 ; NVIC -> ICER [ 1 ] = nonWicIntEn [ 1 ] ; #endif } #endif #if defined ( ERRATA_FIX_DCDC_FETCNT_SET_EN ) dcdcFetCntSet ( true ) ; #endif #if defined ( ERRATA_FIX_DCDC_LNHS_BLOCK_EN ) dcdcHsFixLnBlock ( ) ; #endif __WFI ( ) ; #if defined ( ERRATA_FIX_DCDC_FETCNT_SET_EN ) dcdcFetCntSet ( false ) ; #endif #if defined ( ERRATA_FIX_EMU_E107_EN ) if ( errataFixEmuE107En ) { NVIC -> ISER [ 0 ] = nonWicIntEn [ 0 ] ; #if ( NON_WIC_INT_MASK_1 != ( ~ ( 0x0U ) ) ) NVIC -> ISER [ 1 ] = nonWicIntEn [ 1 ] ; #endif } #endif if ( restore ) { emState ( emState_Restore ) ; } else { SystemCoreClockUpdate ( ) ; } }
@brief
   Enter energy mode 3 (EM3).
@brief Enter energy mode 3 ( EM3 ) .
/* Only save EMU and CMU state if restored on wake-up. */ /* CMU registers may be locked */ /* Disable LF oscillators */ /* Restore CMU register locking */ /* Enter Cortex deep sleep mode */ /* Fix for errata EMU_E107 - store non-WIC interrupt enable flags.
     Disable the enabled non-WIC interrupts. */ /* Fix for errata EMU_E107 - restore state of non-WIC interrupt enable flags. */ /* Restore oscillators/clocks and voltage scaling if supported. */ /* If not restoring, and original clock was not HFRCO, we have to */ /* update CMSIS core clock variable since HF clock has changed */ /* to HFRCO. */