Пример #1
0
/***************************************************************************//**
 * @brief
 *   Initialize the Sleep module.
 *
 * @details
 *   Use this function to initialize the Sleep module, should be called
 *   only once! Pointers to sleep and wake-up callback functions shall be
 *   provided when calling this function.
 *   If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, this function checks
 *   for the cause of the reset that implicitly called it and calls the wakeup
 *   callback if the reset was a wakeup from EM4 (does not work on Gecko MCU).
 *
 * @param[in] pSleepCb
 *   Pointer to the callback function that is being called before the device is
 *   going to sleep.
 *
 * @param[in] pWakeUpCb
 *   Pointer to the callback function that is being called after wake up.
 ******************************************************************************/
void SLEEP_Init(SLEEP_CbFuncPtr_t pSleepCb, SLEEP_CbFuncPtr_t pWakeUpCb)
{
  /* Initialize callback functions. */
  sleepCallback  = pSleepCb;
  wakeUpCallback = pWakeUpCb;

  /* Reset sleep block counters. Note: not using for() saves code! */
  sleepBlockCnt[0U] = 0U;
  sleepBlockCnt[1U] = 0U;
  sleepBlockCnt[2U] = 0U;

#if (SLEEP_EM4_WAKEUP_CALLBACK_ENABLED == true) && defined(RMU_RSTCAUSE_EM4WURST)
  /* Check if the Init() happened after an EM4 reset. */
  if (RMU_ResetCauseGet() & RMU_RSTCAUSE_EM4WURST)
  {
    /* Clear the cause of the reset. */
    RMU_ResetCauseClear();
    /* Call wakeup callback with EM4 parameter. */
    if (NULL != wakeUpCallback)
    {
      wakeUpCallback(sleepEM4);
    }
  }
#endif
}
Пример #2
0
void main ()
{
  uint32_t lfa_Hz;
  uint16_t reset_cause;
  int sleep_mode = 0;
  uint32_t burtc_ctrl;

  CHIP_Init();
  reset_cause = RMU->RSTCAUSE;
  RMU_ResetCauseClear();
#if ! defined(_EFM32_ZERO_FAMILY)
  BSPACM_CORE_BITBAND_PERIPH(RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT) = 0;
#endif
  SystemCoreClockUpdate();
  vBSPACMledConfigure();

  setvbuf(stdout, NULL, _IONBF, 0);

  BSPACM_CORE_ENABLE_INTERRUPT();

  printf("\n" __DATE__ " " __TIME__ "\n");
  printf("System clock %lu Hz\n", SystemCoreClock);
  {
    int i = sizeof(xResetCause)/sizeof(*xResetCause);

    printf("Reset cause [%04x]:", reset_cause);
    while (0 <= --i) {
      const sResetCause * const rcp = xResetCause + i;
      if (rcp->value == (reset_cause & rcp->mask)) {
        printf(" %s", rcp->name);
      }
    }
    printf("\nRMU CTRL %lx\n", RMU->CTRL);
  }

  /* Enable low-energy support. */
  CMU_ClockEnable(cmuClock_CORELE, true);
  BURTC_Enable(true);

  if (MAGIC != retained_state->magic) {
    memset(retained_state, 0, sizeof(*retained_state));
    retained_state->magic = MAGIC;
    printf("Resetting retained state\n");
  }
  ++retained_state->boots;
  printf("Boot count %lu\n", retained_state->boots);

  printf("BURTC clock source: ");
#if (WITH_ULFRCO - 0)
  /* Use ULFRCO, which enables EM4 wakeup but is pretty inaccurate. */
  printf("ULFRCO\n");
  /* NB: DIV2 means 1 kHz instead of 2 kHz */
  burtc_ctrl = BURTC_CTRL_CLKSEL_ULFRCO | BURTC_CTRL_PRESC_DIV2;
  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO);
  lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA);
  {
    EMU_EM4Init_TypeDef cfg = {
      .lockConfig = 1,
      .osc = EMU_EM4CONF_OSC_ULFRCO,
      .buRtcWakeup = 1,
      .vreg = 1,
    };
    EMU_EM4Init(&cfg);
  }
#elif (WITH_LFRCO - 0)
  printf("LFRCO/32\n");
  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);
  burtc_ctrl = BURTC_CTRL_CLKSEL_LFRCO | BURTC_CTRL_PRESC_DIV32;
  lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA) / 32;
#else
  printf("LFXO/32\n");
  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO);
  burtc_ctrl = BURTC_CTRL_CLKSEL_LFXO | BURTC_CTRL_PRESC_DIV32;
  lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA) / 32;
#endif /* LFA source */
  printf("LFA clock at %lu Hz ; wake every %u seconds\n", lfa_Hz, WAKE_INTERVAL_S);

  /* Initialize BURTC. */
  if (! (RMU_RSTCAUSE_EM4WURST & reset_cause)) {
    printf("Initializing BURTC\n");
    BURTC->FREEZE = BURTC_FREEZE_REGFREEZE;
    BURTC->LPMODE = BURTC_LPMODE_LPMODE_DISABLE;
    BURTC->CTRL = burtc_ctrl /* CLKSEL + PRESC */
      | BURTC_CTRL_RSTEN
      | BURTC_CTRL_MODE_EM4EN
      ;
    BURTC->COMP0 = WAKE_INTERVAL_S * lfa_Hz;
    BURTC->IEN = BURTC_IF_COMP0;
    BURTC->CTRL &= ~BURTC_CTRL_RSTEN;
    BURTC->FREEZE = 0;
  } else {
    while (BURTC_SYNCBUSY_COMP0 & BURTC->SYNCBUSY) {
    }
    BURTC->COMP0 += WAKE_INTERVAL_S * lfa_Hz;
  }
  BURTC->IFC = BURTC_IFC_COMP0;
  NVIC_EnableIRQ(BURTC_IRQn);

  printf("BURTC CTRL %lx IEN %lx\n", BURTC->CTRL, BURTC->IEN);
  (void)iBSPACMperiphUARTflush(hBSPACMdefaultUART, eBSPACMperiphUARTfifoState_TX);
  while (1) {
    static const sBSPACMperiphUARTconfiguration cfg = { .speed_baud = 0 };
    printf("Sleeping in mode %u, %lu to %lu rtc_if %x or %lx\n", sleep_mode, BURTC->CNT, BURTC->COMP0, burtc_if, BURTC->IF);
    BSPACM_CORE_DISABLE_INTERRUPT();
    do {
      (void)iBSPACMperiphUARTflush(hBSPACMdefaultUART, eBSPACMperiphUARTfifoState_TX);
      hBSPACMperiphUARTconfigure(hBSPACMdefaultUART, 0);
      switch (sleep_mode) {
        case 0:
          while (! (BURTC_IF_COMP0 & BURTC->IF)) {
          }
          ++sleep_mode;
          break;
        case 1:
          EMU_EnterEM1();
          ++sleep_mode;
          break;
        case 2:
          EMU_EnterEM2(true);

          SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
          if (cmuSelect_ULFRCO == CMU_ClockSelectGet(cmuClock_LFA)) {
            ++sleep_mode;
          } else {
            sleep_mode = 0;
          }
          break;
        case 3:
          EMU_EnterEM3(true);
          SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
          if (cmuSelect_ULFRCO == CMU_ClockSelectGet(cmuClock_LFA)) {
            ++sleep_mode;
          } else {
            sleep_mode = 0;
          }
          break;
        case 4:
          EMU_EnterEM4();
          sleep_mode = 0;
          break;
      }
    } while (0);
    BSPACM_CORE_ENABLE_INTERRUPT();
    hBSPACMperiphUARTconfigure(hBSPACMdefaultUART, &cfg);
    while (BURTC_SYNCBUSY_COMP0 & BURTC->SYNCBUSY) {
    }
    BURTC->COMP0 += WAKE_INTERVAL_S * lfa_Hz;
    /* Giant Gecko
     *  Source    EM0    EM1    EM2     EM3    EM4
     * ULFRCO    2.5m   1.1m   622n    622n   450n
     */
  }

}
Пример #3
0
void halInternalClassifyReset(void)
{
  // Table used to convert from RESET_EVENT register bits to reset types
  static const uint16_t resetEventTable[] = {
  #ifdef _EZR_DEVICE
    RESET_POWERON_HV,                  // bit  0: PORST
    RESET_BROWNOUT_UNREGPOWER,         // bit  1: BODUNREGRST
    RESET_BROWNOUT_REGPOWER,           // bit  2: BODREGRST
    RESET_EXTERNAL_PIN,                // bit  3: EXTRST
    RESET_WATCHDOG_EXPIRED,            // bit  4: WDOGRST
    RESET_FATAL_LOCKUP,                // bit  5: LOCKUPRST
    RESET_SOFTWARE,                    // bit  6: SYSREQRST
    RESET_SOFTWARE_EM4,                // bit  7: EM4RST
    RESET_EXTERNAL_EM4PIN,             // bit  8: EM4WURST
    RESET_BROWNOUT_AVDD0,              // bit  9: BODAVDD0
    RESET_BROWNOUT_AVDD1,              // bit 10: BODAVDD1
    RESET_BROWNOUT_BACKUP_VDD_DREG,    // bit 11: BUBODVDDDREG
    RESET_BROWNOUT_BACKUP_BU_VIN,      // bit 12: BUBODBUVIN
    RESET_BROWNOUT_BACKUP_UNREGPOWER,  // bit 13: BUBODUNREG
    RESET_BROWNOUT_BACKUP_REGPOWER,    // bit 14: BUBODREG
    RESET_BROWNOUT_BACKUP_MODE,        // bit 15: BUMODERST
  #elif defined _EFR_DEVICE
    RESET_POWERON_HV,                  // bit  0: PORST
    RESET_UNKNOWN_UNKNOWN,             // bit  1: RESERVED
    RESET_BROWNOUT_AVDD,               // bit  2: AVDDBOD
    RESET_BROWNOUT_DVDD,               // bit  3: DVDDBOD
    RESET_BROWNOUT_DEC,                // bit  4: DECBOD
    RESET_UNKNOWN_UNKNOWN,             // bit  5: RESERVED
    RESET_UNKNOWN_UNKNOWN,             // bit  6: RESERVED
    RESET_UNKNOWN_UNKNOWN,             // bit  7: RESERVED
    RESET_EXTERNAL_PIN,                // bit  8: EXTRST
    RESET_FATAL_LOCKUP,                // bit  9: LOCKUPRST
    RESET_SOFTWARE,                    // bit 10: SYSREQRST
    RESET_WATCHDOG_EXPIRED,            // bit 11: WDOGRST
    RESET_UNKNOWN_UNKNOWN,             // bit 12: RESERVED
    RESET_UNKNOWN_UNKNOWN,             // bit 13: RESERVED
    RESET_UNKNOWN_UNKNOWN,             // bit 14: RESERVED
    RESET_UNKNOWN_UNKNOWN,             // bit 15: RESERVED
    RESET_SOFTWARE_EM4,                // bit 16: EM4RST
  #endif
  };
  
  uint32_t resetEvent = RMU_ResetCauseGet();
  RMU_ResetCauseClear();
  uint16_t cause = RESET_UNKNOWN;
  uint16_t i;

  for (i = 0; i < sizeof(resetEventTable)/sizeof(resetEventTable[0]); i++) {
    if (resetEvent & (1 << i)) {
      cause = resetEventTable[i];
      break;
    }
  }

  if (cause == RESET_SOFTWARE) {
    if((halResetInfo.crash.resetSignature == RESET_VALID_SIGNATURE) &&
       (RESET_BASE_TYPE(halResetInfo.crash.resetReason) < NUM_RESET_BASE_TYPES)) {
      // The extended reset cause is recovered from RAM
      // This can be trusted because the hardware reset event was software
      //  and additionally because the signature is valid
      savedResetCause = halResetInfo.crash.resetReason;
    } else {
      savedResetCause = RESET_SOFTWARE_UNKNOWN;
    }
    // mark the signature as invalid
    halResetInfo.crash.resetSignature = RESET_INVALID_SIGNATURE;
  } else if (    (cause == RESET_BOOTLOADER_DEEPSLEEP)
              && (halResetInfo.crash.resetSignature == RESET_VALID_SIGNATURE)
              && (halResetInfo.crash.resetReason == RESET_BOOTLOADER_DEEPSLEEP)) {
    // Save the crash info for bootloader deep sleep (even though it's not used
    // yet) and invalidate the resetSignature.
    halResetInfo.crash.resetSignature = RESET_INVALID_SIGNATURE;
    savedResetCause = halResetInfo.crash.resetReason;
  } else {
    savedResetCause = cause;
  }
  // If the last reset was due to an assert, save the assert info.
  if (savedResetCause == RESET_CRASH_ASSERT) {
    savedAssertInfo = halResetInfo.crash.data.assertInfo;
  }
}