/***************************************************************************//** * @brief RTC trigger enable * @param msec Enable trigger in msec * @param cb Callback invoked when @p msec elapsed ******************************************************************************/ void RTCDRV_Trigger(uint32_t msec, void (*cb)(void)) { /* Disable RTC - this will also reset the counter. */ RTC_Enable(false); /* Auto init if not configured already */ if (!rtcInitialized) { /* Default to LFRCO as clock source and prescale by 32. */ RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32); } /* Register callback */ rtcCb = cb; /* Clear interrupt source */ RTC_IntClear(RTC_IF_COMP0); /* Calculate trigger value in ticks based on 32768Hz clock */ RTC_CompareSet(0, (rtcFreq * msec) / 1000); /* Enable RTC */ RTC_Enable(true); /* Enable interrupt on COMP0 */ RTC_IntEnable(RTC_IF_COMP0); }
/**************************************************************************//** * @brief Main function. *****************************************************************************/ int main( void ) { int i; MPU_RegionInit_TypeDef flashInit = MPU_INIT_FLASH_DEFAULT; MPU_RegionInit_TypeDef sramInit = MPU_INIT_SRAM_DEFAULT; MPU_RegionInit_TypeDef peripheralInit = MPU_INIT_PERIPHERAL_DEFAULT; /* Chip alignment */ CHIP_Init(); /* If first word of user data page is non-zero, enable eA Profiler trace */ BSP_TraceProfilerSetup(); /* Enable LCD without voltage boost */ SegmentLCD_Init( false ); SegmentLCD_AllOff(); SegmentLCD_Symbol(LCD_SYMBOL_GECKO, 1); SegmentLCD_Symbol(LCD_SYMBOL_EFM32, 1); GpioInit(); RTCDRV_Setup( cmuSelect_LFXO, cmuClkDiv_32); ScrollText( " MPU DEMO PRESS Pb0 OR Pb1 " "TO GENERATE MPU EXCEPTIONS " ); MPU_Disable(); /* Flash memory */ MPU_ConfigureRegion( &flashInit ); /* SRAM */ MPU_ConfigureRegion( &sramInit ); /* SRAM, a 4k part with priviledged only access, this regions settings */ /* will override those of the previous region */ sramInit.regionNo = 2; sramInit.baseAddress = RAM_MEM_BASE + 0x2000; sramInit.size = mpuRegionSize4Kb; sramInit.accessPermission = mpuRegionApPRw; MPU_ConfigureRegion( &sramInit ); /* LCD, priviledged only access */ peripheralInit.regionNo = 3; peripheralInit.baseAddress = LCD_BASE; peripheralInit.size = mpuRegionSize128b; peripheralInit.accessPermission = mpuRegionApPRw; MPU_ConfigureRegion( &peripheralInit ); MPU_Enable( MPU_CTRL_PRIVDEFENA ); /* Full access to default memory map */ /* in priviledged state */ i = 0; while ( 1 ) { SegmentLCD_Number( i ); /* Count on numeric diplay */ i = ( i + 1 ) % 101; RTCDRV_Delay( 150 , false); if ( PB0_PUSHED() ) { BullsEye( 1 ); /* Generate an access violation in internal SRAM */ __set_CONTROL( 1 ); /* Enter User (unpriviledged) state */ *(volatile uint32_t *)(RAM_MEM_BASE + 0x2000) = 1; BullsEye( 0 ); } if ( PB1_PUSHED() ) { BullsEye( 1 ); /* Generate an access violation in LCD peripheral */ __set_CONTROL( 1 ); /* Enter User (unpriviledged) state */ BullsEye( 0 ); } } }
/**************************************************************************//** * @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; }
/**************************************************************************//** * @brief LCD Test Routine, shows various text and patterns *****************************************************************************/ void Test(void) { int i, numberOfIterations = 0; /* Initialize GPIO */ GPIO_IRQInit(); /* Initialize RTC */ RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32); /* Loop through funny pattern */ while (1) { SegmentLCD_AllOff(); #if VBOOST_SUPPORT checkVoltage(); #endif if (emMode != DEMO_MODE_NONE) { SegmentLCD_Symbol(LCD_SYMBOL_PAD0, 1); SegmentLCD_Symbol(LCD_SYMBOL_PAD1, 1); } else { for (i = 100; i > 0; i--) { SegmentLCD_Number(i); EM2Sleep(10); } SegmentLCD_NumberOff(); SegmentLCD_Symbol(LCD_SYMBOL_GECKO, 1); SegmentLCD_Symbol(LCD_SYMBOL_EFM32, 1); SegmentLCD_Write(" TINY "); EM2Sleep(500); SegmentLCD_Write(" Gecko "); EM2Sleep(1000); SegmentLCD_AllOn(); EM2Sleep(1000); SegmentLCD_AllOff(); } if (emMode != DEMO_MODE_NONE) { SegmentLCD_Symbol(LCD_SYMBOL_PAD0, 1); SegmentLCD_Symbol(LCD_SYMBOL_PAD1, 1); } else { SegmentLCD_Write("OOOOOOO"); EM2Sleep(62); SegmentLCD_Write("XXXXXXX"); EM2Sleep(62); SegmentLCD_Write("+++++++"); EM2Sleep(62); SegmentLCD_Write("@@@@@@@"); EM2Sleep(62); SegmentLCD_Write("ENERGY "); EM2Sleep(250); SegmentLCD_Write("@@ERGY "); EM2Sleep(62); SegmentLCD_Write(" @@RGY "); EM2Sleep(62); SegmentLCD_Write(" M@@GY "); EM2Sleep(62); SegmentLCD_Write(" MI@@Y "); EM2Sleep(62); SegmentLCD_Write(" MIC@@ "); EM2Sleep(62); SegmentLCD_Write(" MICR@@"); EM2Sleep(62); SegmentLCD_Write(" MICRO@"); EM2Sleep(62); SegmentLCD_Write(" MICRO "); EM2Sleep(250); SegmentLCD_Write("-EFM32-"); EM2Sleep(250); /* Various eye candy */ SegmentLCD_AllOff(); if (emMode != DEMO_MODE_NONE) { SegmentLCD_Symbol(LCD_SYMBOL_PAD0, 1); SegmentLCD_Symbol(LCD_SYMBOL_PAD1, 1); } for (i = 0; i < 8; i++) { SegmentLCD_Number(numberOfIterations + i); SegmentLCD_ARing(i, 1); EM2Sleep(20); } for (i = 0; i < 8; i++) { SegmentLCD_Number(numberOfIterations + i); SegmentLCD_ARing(i, 0); EM2Sleep(100); } for (i = 0; i < 5; i++) { SegmentLCD_Number(numberOfIterations + i); SegmentLCD_Battery(i); SegmentLCD_EnergyMode(i, 1); EM2Sleep(100); SegmentLCD_EnergyMode(i, 0); EM2Sleep(100); } SegmentLCD_Symbol(LCD_SYMBOL_ANT, 1); for (i = 0; i < 4; i++) { SegmentLCD_EnergyMode(i, 1); EM2Sleep(100); } SegmentLCD_Symbol(LCD_SYMBOL_ANT, 0); SegmentLCD_Battery(0); } /* Energy Modes */ SegmentLCD_NumberOff(); SegmentLCD_Symbol(LCD_SYMBOL_GECKO, 1); SegmentLCD_Symbol(LCD_SYMBOL_EFM32, 1); if ((emMode != DEMO_MODE_EM3) && (emMode != DEMO_MODE_EM4)) { ScrollText("Energy Mode demo, Press PB0 for EM3 or PB1 for EM4 "); } SegmentLCD_Write(" EM0 "); SegmentLCD_Number(0); SegmentLCD_EnergyMode(0, 1); SegmentLCD_EnergyMode(1, 1); SegmentLCD_EnergyMode(2, 1); SegmentLCD_EnergyMode(3, 1); SegmentLCD_EnergyMode(4, 1); RTCDRV_Delay(4000, false); SegmentLCD_Write(" EM1 "); SegmentLCD_Number(1111); SegmentLCD_EnergyMode(0, 0); EM1Sleep(4000); SegmentLCD_Write(" EM2 "); SegmentLCD_Number(2222); SegmentLCD_EnergyMode(1, 0); EM2Sleep(4000); /* Check if somebody has pressed one of the buttons */ if (emMode == DEMO_MODE_EM3) { ScrollText("Going down to EM3, press PB0 to wake up "); SegmentLCD_Write(" EM3 "); SegmentLCD_Number(3333); RTCDRV_Delay(1000, false); /* Wake up on GPIO interrupt */ EM3Sleep(); SegmentLCD_Number(0000); SegmentLCD_Write("--EM0--"); RTCDRV_Delay(500, false); SegmentLCD_Symbol(LCD_SYMBOL_PAD0, 0); SegmentLCD_Symbol(LCD_SYMBOL_PAD1, 0); emMode = DEMO_MODE_NONE; } /* Check if somebody's joystick down */ if (emMode == DEMO_MODE_EM4) { ScrollText("Going down to EM4, press reset to restart "); SegmentLCD_Write(" EM4 "); SegmentLCD_Number(4444); RTCDRV_Delay(1000, false); /* Wake up on reset */ EM4Sleep(); } SegmentLCD_EnergyMode(0, 0); SegmentLCD_EnergyMode(1, 0); SegmentLCD_EnergyMode(2, 0); SegmentLCD_EnergyMode(3, 0); SegmentLCD_EnergyMode(4, 0); /* Scrolltext */ ScrollText(stext); /* Blink and animation featurs */ BlinkTest(); numberOfIterations++; } }
/**************************************************************************//** * @brief Capsense demo loop *****************************************************************************/ void capSenseDemo(void) { int32_t slider; bool oldBoost = vboost; /* Setup RTC. */ RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32); /* Setup capSense callbacks. */ CAPLESENSE_setupCallbacks(&capSenseScanComplete, &capSenseChTrigger); /* Main loop */ while (1) { switch(demoState) { case DEMO_SLEEP_PREPARE: { /* Setup LESENSE in sleep mode. */ CAPLESENSE_setupLESENSE(true); /* Disable LCD to avoid excessive current consumption */ SegmentLCD_Disable(); /* Disable Vdd check. */ VDDCHECK_Disable(); /* Go to sleep state. */ demoState = DEMO_SLEEP; } break; case DEMO_SLEEP: { /* Go to sleep and wait until the measurement completes. */ CAPLESENSE_Sleep(); } break; case DEMO_SENSE_PREPARE: { /* Setup LESENSE in high-accuracy sense mode. */ CAPLESENSE_setupLESENSE(false); /* Start timeout counter. */ RTCDRV_Trigger(1000U, &capSenseTimerFired); /* Enable vboost */ SegmentLCD_Init(vboost); /* Go to sense state. */ demoState = DEMO_SENSE; } break; case DEMO_SENSE: { /* Go to sleep and wait until the measurement completes. */ CAPLESENSE_Sleep(); /* Get slider position. */ slider = CAPLESENSE_getSliderPosition(); if (-1 != slider) { /* Reset RTC */ RTC_Enable(false); RTC_Enable(true); } capSenseAringUpdate(slider); /* Check for change in input voltage. Enable vboost if necessary */ /* Initialize voltage comparator */ VDDCHECK_Init(); /* Check if voltage is below 3V, if so use voltage boost */ if (VDDCHECK_LowVoltage(2.9)) { vboost = true; if (oldBoost != vboost) { /* Enable vboost */ SegmentLCD_Init(vboost); /* Use antenna symbol to signify enabling of vboost */ SegmentLCD_Symbol(LCD_SYMBOL_ANT, vboost); } oldBoost = vboost; } else { vboost = false; } switch (demoMode) { case (DEMOMODE_SCROLLTEXT): capSenseScrollText(); break; case (DEMOMODE_BARS): capSenseBars(); break; case (DEMOMODE_VALUES): capSenseValues(); break; default: break; } } break; default: { ; } break; } } }