/**************************************************************************//** * @brief Energy Mode 3 demonstration, GPIO wake up - will restart application *****************************************************************************/ void Demo_EM3_GPIO(void) { /* Disable systick timer */ SysTick->CTRL = 0; /* Keep GPIO and EBI active, do not disable peripherals */ /* Disable LF peripherals */ CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; /* Enter Energy Mode 3 - wake up on GPIO interrupt */ /* Press AEM button again to read EFM, and then any PB/Joystick button */ EMU_EnterEM3(false); /* Setup SysTick Timer for 1 msec interrupts */ if (SysTick_Config(SystemCoreClockGet() / 1000)) while (1) ; /* Show LED pattern after wake up, to show we're alive */ while(1) { BSP_LedsSet(0xf00f); Delay(200); BSP_LedsSet(0x0ff0); Delay(200); } }
enum lpm_mode lpm_arch_set(enum lpm_mode target) { switch (target) { case LPM_ON: /* nothing to do */ break; case LPM_IDLE: /* wait for next event or interrupt */ EMU_EnterEM1(); break; case LPM_SLEEP: /* after exiting EM2, clocks are restored */ EMU_EnterEM2(true); break; case LPM_POWERDOWN: /* after exiting EM3, clocks are restored */ EMU_EnterEM3(true); break; case LPM_OFF: /* only a reset can wake up from EM4 */ EMU_EnterEM4(); break; /* do nothing here */ case LPM_UNKNOWN: default: break; } /* no matter which case was selected, instructions executed in EM0 only */ return LPM_ON; }
void hw_enter_lowpower_mode(uint8_t mode) { switch(mode) { case 0: { EMU_EnterEM1(); break; } case 1: { EMU_EnterEM2(true); break; } case 2: { EMU_EnterEM3(true); break; } case 4: { EMU_EnterEM4(); break; } default: { assert(0); } } }
/**************************************************************************//** * @brief Sleeps in EM3 until GPIO interrupt is triggered *****************************************************************************/ void EM3Sleep(void) { inEM3 = true; SegmentLCD_Disable(); EMU_EnterEM3(true); SegmentLCD_Init(false); inEM3 = false; }
/**************************************************************************//** * @brief Sleeps in EM3 until GPIO interrupt is triggered *****************************************************************************/ void EM3Sleep(void) { /* Tell AEM we're in EM3 */ BSP_EnergyModeSet(3); SegmentLCD_Disable(); EMU_EnterEM3(true); BSP_EnergyModeSet(0); SegmentLCD_Init(false); }
ERROR_CODE Statemachine::startApplication( STATUS_BLOCK *statusBlock ) { callingStatusBlock = currentStatusBlock; currentStatusBlock = statusBlock; if(!setupDone) return FSM_NotInitialized; // Run the FSM until the execution is stopped by the Application-Code. // The State-Function is called within the WHILE-STATEMENT !!!! while( ( *(stateDefinition)[statusBlock->nextState] )() ) { // Is the State-Function, which is selected for execution in the next step a valid one? if( currentStatusBlock->nextState < maxNumberOfStates ) { // Does the MCU have to enter a sleep-mode? if( currentStatusBlock->wantToSleep ) { // Which sleep-mode has to be entered? switch( currentStatusBlock->sleepMode ) { case 0: break; case 1: EMU_EnterEM1(); break; case 2: EMU_EnterEM2( currentStatusBlock->restoreClockSetting ); break; case 3: EMU_EnterEM3( currentStatusBlock->restoreClockSetting ); break; case 4: EMU_EnterEM4(); default: return EM_invalid; // Invalid sleep-mode!!! } } } else return StateID_Invalid; // Invalid State-Function number!!! } currentStatusBlock = callingStatusBlock; return FSM_finalized; // FSM-execution successfully finalized!!! }
/**************************************************************************//** * @brief Main function *****************************************************************************/ int main(void) { /* Initialize chip */ CHIP_Init(); setupSWO(); BSP_LedsInit(); /* Enable clock for GPIO module */ CMU_ClockEnable(cmuClock_GPIO, true); /* Configure interrupt for Push Button 0 */ GPIO_PinModeSet(PB0_PORT, PB0_PIN, gpioModeInput, 1); #if defined(_EFM32_GIANT_FAMILY) NVIC_EnableIRQ(GPIO_ODD_IRQn); #else NVIC_EnableIRQ(GPIO_EVEN_IRQn); #endif GPIO_IntConfig(PB0_PORT, PB0_PIN, false, true, true); /* By turning on retention in EM4, the state of the GPIO pins * can be retained in all energy modes */ GPIO->CTRL = GPIO_CTRL_EM4RET; /* Uncomment to drive LED in all energy modes */ /* BSP_LedSet(0);*/ while (1) { switch (STATE) { case EM0: break; case EM1: EMU_EnterEM1(); break; case EM2: EMU_EnterEM2(true); break; case EM3: EMU_EnterEM3(true); case EM4: EMU_EnterEM4(); break; } } }
/***************************************************************************** * Waits in EM3 until the bootloader pin is pulled low. This saves power * while waiting to install firmware. *****************************************************************************/ void enterLowPowerWait(void) { /* Enable interrupt on GPIO pin. Note that * if the pin is changed to an odd pin number * the interrupt handler must also be changed */ GPIO_IntConfig(BOOTLOADER_PIN, true, false, true); NVIC_EnableIRQ(GPIO_EVEN_IRQn); /* Wait in EM3 until the pin is pulled low */ while ( GPIO_PinInGet(BOOTLOADER_PIN) ) { EMU_EnterEM3(false); } /* Disable interrupts again */ GPIO_IntConfig(BOOTLOADER_PIN, false, false, false); NVIC_DisableIRQ(GPIO_EVEN_IRQn); }
/** * Sleep mode. * Enter the lowest possible sleep mode that is not blocked by ongoing activity. */ void sleep(void) { if (sleep_block_counter[0] > 0) { /* Blocked everything below EM0, so just return */ return; } else if (sleep_block_counter[1] > 0) { /* Blocked everything below EM1, enter EM1 */ EMU_EnterEM1(); } else if (sleep_block_counter[2] > 0) { /* Blocked everything below EM2, enter EM2 */ EMU_EnterEM2(true); } else { /* Blocked everything below EM3, enter EM3 */ EMU_EnterEM3(true); } /* Never enter EM4, as mbed has no way of configuring EM4 wakeup */ return; }
/***************************************************************************//** * @brief * Call the callbacks and enter the requested energy mode. * * @details * This function is not part of the API, therefore it shall not be called by * the user directly as it doesn not have any checks if the system is ready * for sleep! * * @note * The EM4 wakeup callback is not being called from this function because * waking up from EM4 causes a reset. * If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, SLEEP_Init() function * checks for the cause of the reset and calls the wakeup callback if the * reset was a wakeup from EM4. ******************************************************************************/ static void SLEEP_EnterEMx(SLEEP_EnergyMode_t eMode) { EFM_ASSERT((eMode > sleepEM0) && (eMode <= sleepEM4)); /* Call sleepCallback() before going to sleep. */ if (NULL != sleepCallback) { /* Call the callback before going to sleep. */ sleepCallback(eMode); } /* Enter the requested energy mode. */ switch (eMode) { case sleepEM1: { EMU_EnterEM1(); } break; case sleepEM2: { EMU_EnterEM2(true); } break; case sleepEM3: { EMU_EnterEM3(true); } break; case sleepEM4: { EMU_EnterEM4(); } break; default: { /* Don't do anything, stay in EM0. */ } break; } /* Call the callback after waking up from sleep. */ if (NULL != wakeUpCallback) { wakeUpCallback(eMode); } }
/**************************************************************************//** * @brief Enter a Energy Mode for a given number of seconds. * * @param[in] mode Energy Mode to enter (0..3). * @param[in] secs Time to stay in Energy Mode <mode>. *****************************************************************************/ static void EnterEMode( int mode, uint32_t secs ) { if ( secs ) { uint32_t startTime = seconds; if ( mode == 0 ) { int cnt = 0; while ((seconds - startTime) < secs) { if ( cnt == 0 ) printf( "\r - - EM0 - -" ); else if ( cnt == 1 ) printf( "\r \\ \\ EM0 / /" ); else if ( cnt == 2 ) printf( "\r | | EM0 | |" ); else if ( cnt == 3 ) printf( "\r / / EM0 \\ \\" ); cnt = (cnt + 1) % 4; if ( enterEM4 ) { printf( "\r EM0 " ); return; } } printf( "\r EM0 " ); } else { while ((seconds - startTime) < secs) { switch ( mode ) { case 1: EMU_EnterEM1(); break; case 2: EMU_EnterEM2( true ); break; case 3: EMU_EnterEM3( true ); break; } if ( enterEM4 ) { return; } } } } }
/**************************************************************************//** * @brief Energy Mode 3 demonstration, no active peripherals *****************************************************************************/ void Demo_EM3(void) { /* Disable systick timer */ SysTick->CTRL = 0; /* Disable DVK interrupts */ BSP_InterruptDisable(0xffff); NVIC_DisableIRQ(GPIO_EVEN_IRQn); NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn); /* Disable peripheral clocks */ CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; /* Enter Energy Mode 3 - never wake up */ EMU_EnterEM3(false); while(1) BSP_LedsSet(0xffff); }
/**************************************************************************//** * @brief Main function *****************************************************************************/ int main(void) { const int msDelay = 100; /* Chip errata */ CHIP_Init(); /* If first word of user data page is non-zero, enable eA Profiler trace */ BSP_TraceProfilerSetup(); /* Power down special RAM blocks to reduce current consumption with some nA. */ CMU_ClockEnable(cmuClock_CORELE, true); LESENSE->POWERDOWN = LESENSE_POWERDOWN_RAM; CMU_ClockEnable(cmuClock_CORELE, false); /* Configure push button interrupts */ gpioSetup(); /* Setup SysTick Timer for 1 msec interrupts */ if (SysTick_Config(SystemCoreClockGet() / 1000)) while (1) ; /* Initialize LCD controller */ SegmentLCD_Init(false); /* Run countdown for user to select energy mode */ msCountDown = 4000; /* milliseconds */ while (msCountDown > 0) { switch (eMode) { case 0: SegmentLCD_Write("EM0 32M"); break; case 1: SegmentLCD_Write("EM1 32M"); break; case 2: SegmentLCD_Write("EM2 32K"); break; case 3: SegmentLCD_Write("EM3"); break; case 4: SegmentLCD_Write("EM4"); break; case 5: SegmentLCD_Write("EM2+RTC"); break; case 6: SegmentLCD_Write("RTC+LCD"); break; case 7: SegmentLCD_Write("EM3+RTC"); break; case 8: SegmentLCD_Write("USER"); break; } SegmentLCD_Number(msCountDown); Delay(msDelay); msCountDown -= msDelay; } /* Disable components, reenable when needed */ SegmentLCD_Disable(); RTC_Enable(false); /* GPIO->ROUTE = 0x00000000; */ /* Go to energy mode and wait for reset */ switch (eMode) { case 0: /* Disable pin input */ GPIO_PinModeSet(gpioPortB, 10, gpioModeDisabled, 1); /* Disable systick timer */ SysTick->CTRL = 0; /* 32Mhz primes demo - running off HFXO */ CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); /* Disable HFRCO, LFRCO and all unwanted clocks */ CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS; CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS; CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; CMU->LFCLKSEL = 0x00000000; /* Supress Conditional Branch Target Prefetch */ MSC->READCTRL = MSC_READCTRL_MODE_WS1SCBTP; { #define PRIM_NUMS 64 uint32_t i, d, n; uint32_t primes[PRIM_NUMS]; /* Find prime numbers forever */ while (1) { primes[0] = 1; for (i = 1; i < PRIM_NUMS;) { for (n = primes[i - 1] + 1;; n++) { for (d = 2; d <= n; d++) { if (n == d) { primes[i] = n; goto nexti; } if (n % d == 0) break; } } nexti: i++; } } } case 1: /* Disable pin input */ GPIO_PinModeSet(gpioPortB, 10, gpioModeDisabled, 1); /* Disable systick timer */ SysTick->CTRL = 0; CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); /* Disable HFRCO, LFRCO and all unwanted clocks */ CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS; CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS; CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; CMU->LFCLKSEL = 0x00000000; EMU_EnterEM1(); break; case 2: /* Enable LFRCO */ CMU->OSCENCMD = CMU_OSCENCMD_LFRCOEN; /* Disable everything else */ CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS; CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; /* Disable LFB clock select */ CMU->LFCLKSEL = 0x00000000; EMU_EnterEM2(false); break; case 3: /* Disable all clocks */ CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS; CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS; CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; CMU->LFCLKSEL = 0x00000000; EMU_EnterEM3(false); break; case 4: /* Go straight down to EM4 */ EMU_EnterEM4(); break; case 5: /* EM2 + RTC - only briefly wake up to reconfigure every 2 seconds */ /* Disable LFB clock select */ CMU->LFCLKSEL &= ~(_CMU_LFCLKSEL_LFB_MASK); RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32); while (1) { RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(false); } case 6: /* EM2 + RTC + LCD (if battery slips below 3V vboost should be enabled) */ /* Disable LFB clock select */ CMU->LFCLKSEL &= ~(_CMU_LFCLKSEL_LFB_MASK); SegmentLCD_Init(false); RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32); while (1) { SegmentLCD_Write("Silicon"); /* Sleep in EM2 */ RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(false); SegmentLCD_Write(" Labs"); /* Sleep in EM2 */ RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(false); } case 7: /* EM3 + RTC - only briefly wake up to reconfigure every ~5 seconds */ while (1) { /* Disable LFB clock select */ CMU->LFCLKSEL &= ~(_CMU_LFCLKSEL_LFB_MASK); /* This RTCDRV_Setup will configure LFCLK A as ULFRCO */ RTCDRV_Setup(cmuSelect_ULFRCO, cmuClkDiv_1); RTCDRV_Trigger(5000, NULL); /* Sleep in EM3, wake up on RTC trigger */ EMU_EnterEM3(false); /* SegmentLCD_Init will configure LFCLK A as LFRCO */ SegmentLCD_Init(false); SegmentLCD_Write("ULFRCO"); Delay(1000); SegmentLCD_Disable(); } case 8: default: /* User defined */ break; } return 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 */ } }
/**************************************************************************//** * @brief Main function *****************************************************************************/ int main(void) { int msCountDown; const int msDelay = 100; char displayString[8]; LCD_AnimInit_TypeDef anim = { true, 0x00, lcdAnimShiftNone, 0x03, lcdAnimShiftLeft, lcdAnimLogicOr }; LCD_FrameCountInit_TypeDef fc = { true, 2, /* Update each 2nd frame */ lcdFCPrescDiv1, }; /* Chip errata */ CHIP_Init(); /* If first word of user data page is non-zero, enable eA Profiler trace */ BSP_TraceProfilerSetup(); /* Configure push button interrupts */ gpioSetup(); /* Setup SysTick Timer for 1 msec interrupts */ if (SysTick_Config(SystemCoreClockGet() / 1000)) while (1) ; /* Initialize LCD controller */ SegmentLCD_Init(false); /* Run countdown for user to select energy mode */ msCountDown = 4000; /* milliseconds */ while(msCountDown > 0) { if ( eMode >=3 && eMode<=4) { sprintf(displayString, "EM%d", eMode); SegmentLCD_Write(displayString); } switch( eMode ) { case 0: SegmentLCD_Write("EM0 32M"); break; case 1: SegmentLCD_Write("EM1 32M"); break; case 2: SegmentLCD_Write("EM2 32K"); break; case 5: SegmentLCD_Write("EM2+RTC"); break; case 6: SegmentLCD_Write("RTC+LCD"); break; } SegmentLCD_Number(msCountDown); Delay(msDelay); msCountDown -= msDelay; } /* Disable components, reenable when needed */ SegmentLCD_Disable(); RTC_Enable(false); /* Go to energy mode and wait for reset */ switch(eMode) { case 0: /* Disable pin input */ GPIO_PinModeSet(gpioPortB, 10, gpioModeDisabled, 1); /* Disable systick timer */ SysTick->CTRL = 0; /* 32Mhz primes demo - running off HFXO */ CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); /* Disable HFRCO, LFRCO and all unwanted clocks */ CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS; CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS; CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; CMU->LFCLKSEL = 0x00000000; /* Supress Conditional Branch Target Prefetch */ MSC->READCTRL = MSC_READCTRL_MODE_WS1SCBTP; { #define PRIM_NUMS 64 uint32_t i, d, n; uint32_t primes[PRIM_NUMS]; /* Find prime numbers forever */ while (1) { primes[0] = 1; for (i = 1; i < PRIM_NUMS;) { for (n = primes[i - 1] + 1; ;n++) { for (d = 2; d <= n; d++) { if (n == d) { primes[i] = n; goto nexti; } if (n%d == 0) break; } } nexti: i++; } } } case 1: /* Disable pin input */ GPIO_PinModeSet(gpioPortB, 10, gpioModeDisabled, 1); /* Disable systick timer */ SysTick->CTRL = 0; CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); /* Disable HFRCO, LFRCO and all unwanted clocks */ CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS; CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS; CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; CMU->LFCLKSEL = 0x00000000; EMU_EnterEM1(); break; case 2: /* Enable LFRCO */ CMU->OSCENCMD = CMU_OSCENCMD_LFRCOEN; /* Disable everything else */ CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS; CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; CMU->LFCLKSEL = 0x00000000; EMU_EnterEM2(false); break; case 3: /* Disable all clocks */ CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS; CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS; CMU->HFPERCLKEN0 = 0x00000000; CMU->HFCORECLKEN0 = 0x00000000; CMU->LFACLKEN0 = 0x00000000; CMU->LFBCLKEN0 = 0x00000000; EMU_EnterEM3(false); break; case 4: EMU_EnterEM4(); break; case 5: /* EM2 + RTC - only briefly wake up to reconfigure each second */ CMU->LFCLKSEL = CMU_LFCLKSEL_LFA_LFRCO; while(1) { RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(false); } case 6: default: /* EM2 + RTC + LCD (if battery slips below 3V vboost should be */ /* enabled) */ CMU->LFCLKSEL = CMU_LFCLKSEL_LFA_LFRCO; SegmentLCD_Init(false); /* Animate LCD */ LCD_FrameCountInit(&fc); LCD_AnimInit(&anim); while(1) { SegmentLCD_Write("Energy"); /* Sleep in EM2 */ RTCDRV_Trigger(2000,NULL); EMU_EnterEM2(false); SegmentLCD_Write("Micro"); /* Sleep in EM2 */ RTCDRV_Trigger(2000,NULL); EMU_EnterEM2(false); } } return 0; }
/**************************************************************************//** * @brief Main function *****************************************************************************/ int main(void) { WDOG_Init_TypeDef wInit = WDOG_INIT_DEFAULT; int i; /* Chip revision alignment and errata fixes */ CHIP_Init(); /* If first word of user data page is non-zero, enable eA Profiler trace */ BSP_TraceProfilerSetup(); /* Watchdog setup - Use defaults, excepts for these :*/ wInit.em2Run = true; wInit.em3Run = true; wInit.perSel = wdogPeriod_4k; /* 4k 1kHz periods should give ~4 seconds in EM3 */ /* Do the demo forever. */ /* EM0 - 1 sec HFXO */ CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); /* Setup SysTick Timer for 1 msec interrupts */ if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) { while (1) ; } Delay(1000); /* EM0 - 1 sec HFRCO */ CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO); /* Setup SysTick Timer for 1 msec interrupts */ if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) { while (1) ; } Delay(1000); /* Turn off systick */ SysTick_Disable(); /* EM1 - 1 sec */ RTCDRV_Trigger(1000, NULL); EMU_EnterEM1(); /* EM2 - 1 sec */ RTCDRV_Trigger(1000, NULL); EMU_EnterEM2(true); /* EM1 - 1 sec */ RTCDRV_Trigger(1000, NULL); EMU_EnterEM1(); /* EM2 - 1 sec */ RTCDRV_Trigger(1000, NULL); EMU_EnterEM2(true); /* Up and down from EM2 each 10 msec */ for (i=0; i < 10; i++) { RTCDRV_Trigger(10, NULL); EMU_EnterEM2(true); RTCDRV_Delay(10, false); } /* EM2 - 1 sec */ RTCDRV_Trigger(1000, NULL); EMU_EnterEM2(true); /* Up and down from EM2 each 2 msec */ for (i=0; i < 10; i++) { RTCDRV_Trigger(2, NULL); EMU_EnterEM2(true); } /* EM2 - 1 sec */ RTCDRV_Trigger(1000, NULL); EMU_EnterEM2(true); /* Up and down from EM2 each msec */ for (i=0; i < 10; i++) { RTCDRV_Trigger(1, NULL); EMU_EnterEM2(true); } /* EM2 - 1 sec */ RTCDRV_Trigger(1000, NULL); EMU_EnterEM2(true); /* Start watchdog */ WDOG_Init(&wInit); /* Enter EM3 - Watchdog will reset chip (and confuse debuggers) */ EMU_EnterEM3(true); /* We will never reach this point */ return 0; }
/**************************************************************************//** * @brief Sleeps in EM3 until GPIO interrupt is triggered *****************************************************************************/ void EM3Sleep(void) { inEM3 = true; EMU_EnterEM3(true); inEM3 = false; }