void lp_ticker_set_interrupt(timestamp_t timestamp) { uint64_t timestamp_ticks; uint64_t current_ticks = RTC_CounterGet(); timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)); /* Initialize RTC */ lp_ticker_init(); /* calculate offset value */ timestamp_t offset = timestamp - current_time; if(offset > 0xEFFFFFFF) offset = 100; /* map offset to RTC value */ // ticks = offset * RTC frequency div 1000000 timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000; timestamp_ticks += current_ticks; /* RTC has 24 bit resolution */ timestamp_ticks &= 0xFFFFFF; /* check for RTC limitation */ if((timestamp_ticks - RTC_CounterGet()) >= 0x800000) timestamp_ticks = RTC_CounterGet() + 2; /* Set callback */ RTC_FreezeEnable(true); RTC_CompareSet(0, (uint32_t)timestamp_ticks); RTC_IntEnable(RTC_IF_COMP0); RTC_FreezeEnable(false); }
void rtcSetup(){ RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; /* Enabling clock to LE configuration register */ CMU_ClockEnable(cmuClock_CORELE, true); /* Selecting crystal oscillator to drive LF clock */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); /* 32 clock division to save energy */ CMU_ClockDivSet(cmuClock_RTC, cmuClkDiv_32768); /* Providing clock to RTC */ CMU_ClockEnable(cmuClock_RTC, true); /* Initialize RTC */ rtcInit.enable = false; /* Do not start RTC after initialization is complete. */ rtcInit.debugRun = false; /* Halt RTC when debugging. */ rtcInit.comp0Top = true; /* Wrap around on COMP0 match. */ RTC_Init(&rtcInit); /* Interrupt every minute */ RTC_CompareSet(0, ((RTC_FREQ / CLOCK_DIVISION) * 10 ) - 1 ); /* Enable interrupt */ NVIC_EnableIRQ(RTC_IRQn); RTC_IntEnable(RTC_IEN_COMP0); /* Start Counter */ RTC_Enable(true); }
/**************************************************************************//** * @brief RTC_IRQHandler * Interrupt Service Routine for RTC which is used as system tick counter in EM2 *****************************************************************************/ void RTC_IRQHandler(void) { /* If using preemption, also force a context switch. */ #if (configUSE_PREEMPTION == 1) port_NVIC_INT_CTRL_REG = port_NVIC_PENDSVSET_BIT; #endif /* (configUSE_PREEMPTION == 1) */ /* Set RTC interrupt to one system tick period*/ RTC_Enable(false); RTC_CompareSet(0, ulTimerReloadValueForOneTick); /* Restart the counter */ #if (configUSE_TICKLESS_IDLE == 1) /* Set flag that interrupt was made*/ intTickFlag = true; #endif /* (configUSE_TICKLESS_IDLE == 1) */ /* Critical section which protect incrementing the tick*/ ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); { xTaskIncrementTick(); } portCLEAR_INTERRUPT_MASK_FROM_ISR(0); /* Clear interrupt */ RTC_IntClear(_RTC_IFC_MASK); RTC_CounterReset(); }
/***************************************************************************//** * @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 Enables LFACLK and selects LFXO as clock source for RTC * Sets up the RTC to generate an interrupt every minute. *****************************************************************************/ void rtcSetup(void) { RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; /* Enable LE domain registers */ CMU_ClockEnable(cmuClock_CORELE, true); /* Enable LFXO as LFACLK in CMU. This will also start LFXO */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); /* Set a clock divisor of 32 to reduce power conumption. */ CMU_ClockDivSet(cmuClock_RTC, cmuClkDiv_32); /* Enable RTC clock */ CMU_ClockEnable(cmuClock_RTC, true); /* Initialize RTC */ rtcInit.enable = false; /* Do not start RTC after initialization is complete. */ rtcInit.debugRun = false; /* Halt RTC when debugging. */ rtcInit.comp0Top = true; /* Wrap around on COMP0 match. */ RTC_Init(&rtcInit); /* Interrupt every minute */ RTC_CompareSet(0, ((RTC_FREQ / 32) * 60 ) - 1 ); /* Enable interrupt */ NVIC_EnableIRQ(RTC_IRQn); RTC_IntEnable(RTC_IEN_COMP0); /* Start Counter */ RTC_Enable(true); }
/**************************************************************************//** * @brief Enables LFACLK and selects LFXO as clock source for RTC * Sets up the RTC to generate an interrupt every second. *****************************************************************************/ static void rtcSetup(unsigned int frequency) { RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; palClockSetup(cmuClock_LFA); /* Set the prescaler. */ CMU_ClockDivSet( cmuClock_RTC, cmuClkDiv_2 ); /* Enable RTC clock */ CMU_ClockEnable(cmuClock_RTC, true); /* Initialize RTC */ rtcInit.enable = false; /* Do not start RTC after initialization is complete. */ rtcInit.debugRun = false; /* Halt RTC when debugging. */ rtcInit.comp0Top = true; /* Wrap around on COMP0 match. */ RTC_Init(&rtcInit); /* Interrupt at given frequency. */ RTC_CompareSet(0, ((CMU_ClockFreqGet(cmuClock_RTC) / frequency) - 1) & _RTC_COMP0_MASK ); #ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY /* Enable interrupt */ NVIC_EnableIRQ(RTC_IRQn); RTC_IntEnable(RTC_IEN_COMP0); #endif RTC_CounterReset(); /* Start Counter */ RTC_Enable(true); }
// Stores the hours/mins for clock time, start time, or stop time void set_clock_time(int index, uint16_t hours, uint16_t minutes) { // Set the time clock if (index == 0) { // Midnight is time zero RTC_CounterReset(); // 3600 seconds per hour, 60 seconds per minute RTC->CNT = hours * 3600 + minutes * 60; } else if (index == 1) { // Add 1 second so that RTC interrupt source is clear, // and not to confuse with the clock minute updates time_keeper.timer_start_seconds = hours * 3600 + minutes * 60 + 1; // Set up the RTC to trigger a start event RTC_CompareSet(0, time_keeper.timer_start_seconds); // Save for next program event start_hours = hours; start_minutes = minutes; } else if (index == 2) { // Add 1 second so that RTC interrupt source is clear, // and not to confuse with the clock minute updates time_keeper.timer_stop_seconds = hours * 3600 + minutes * 60 + 1; // Save for next program event stop_hours = hours; stop_minutes = minutes; } }
void os_idle_demon(void) { RTC_Init_TypeDef init; unsigned int sleep; /* The idle demon is a system thread, running when no other thread is */ /* ready to run. */ /* Enable system clock for RTC */ /* LFXO setup */ /* Use 70% boost */ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOBOOST_MASK) | CMU_CTRL_LFXOBOOST_70PCENT; /* Ensure LE modules are accessible */ CMU_ClockEnable(cmuClock_CORELE, true); /* Enable osc as LFACLK in CMU (will also enable oscillator if not enabled) */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); /* Use a 32 division prescaler to reduce power consumption. */ CMU_ClockDivSet(cmuClock_RTC, cmuClkDiv_32); /* Enable clock to RTC module */ CMU_ClockEnable(cmuClock_RTC, true); init.enable = false; init.debugRun = false; init.comp0Top = false; /* Count to max value before wrapping */ RTC_Init(&init); /* Disable interrupt generation from RTC0 */ RTC_IntDisable(_RTC_IF_MASK); /* Enable interrupts */ NVIC_ClearPendingIRQ(RTC_IRQn); NVIC_EnableIRQ(RTC_IRQn); for (;;) { /* os_suspend stops scheduler and returns time to next event in OS_TICK units */ sleep = os_suspend(); if (sleep) { RTC_CompareSet(0, sleep - 1); RTC_IntClear(RTC_IFC_COMP0); RTC_IntEnable(RTC_IF_COMP0); RTC_CounterReset(); /* Enter EM2 low power mode - could be replaced with EM1 if required */ EMU_EnterEM2(true); /* get information how long we were in sleep */ sleep = RTC_CounterGet(); RTC_Enable(false); }; /* resume scheduler providing information how long MCU was sleeping */ os_resume(sleep); } }
/**************************************************************************//** * @brief vPortSetupTimerInterrupt * Override the default definition of vPortSetupTimerInterrupt() that is weakly * defined in the FreeRTOS Cortex-M3, which set source of system tick interrupt *****************************************************************************/ void vPortSetupTimerInterrupt(void) { /* Set our data about timer used as system ticks*/ ulTimerReloadValueForOneTick = SYSTICK_LOAD_VALUE ; #if (configUSE_TICKLESS_IDLE == 1) xMaximumPossibleSuppressedTicks = TIMER_CAPACITY / (SYSTICK_LOAD_VALUE); ulStoppedTimerCompensation = TIMER_COMPENSATION / (configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ); #endif /* (configUSE_TICKLESS_IDLE == 1) */ /* Configure RTC as system tick source */ /* Structure of RTC init */ RTC_Init_TypeDef init; #if (configCRYSTAL_IN_EM2 == 1) /* LFXO setup */ /* For cut D, use 70% boost */ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOBOOST_MASK) | CMU_CTRL_LFXOBOOST_70PCENT; #if defined( EMU_AUXCTRL_REDLFXOBOOST ) EMU->AUXCTRL = (EMU->AUXCTRL & ~_EMU_AUXCTRL_REDLFXOBOOST_MASK) | EMU_AUXCTRL_REDLFXOBOOST; #endif #else /* RC oscillator */ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); #endif /* Ensure LE modules are accessible */ CMU_ClockEnable(cmuClock_CORELE, true); #if (configCRYSTAL_IN_EM2 == 1) /* Enable osc as LFACLK in CMU (will also enable oscillator if not enabled) */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); #else /* Enable osc as LFACLK in CMU (will also enable oscillator if not enabled) */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO); #endif /* Set 2 times divider to reduce energy*/ CMU_ClockDivSet(cmuClock_RTC, cmuClkDiv_2); /* Enable clock to RTC module */ CMU_ClockEnable(cmuClock_RTC, true); init.enable = false; init.debugRun = false; init.comp0Top = false; /* Count to max value before wrapping */ /* Initialization of RTC */ RTC_Init(&init); /* Disable interrupt generation from RTC0 */ RTC_IntDisable(RTC_IFC_COMP0); /* Tick interrupt MUST execute at the lowest interrupt priority. */ NVIC_SetPriority(RTC_IRQn, 255); /* Enable interrupts */ NVIC_ClearPendingIRQ(RTC_IRQn); NVIC_EnableIRQ(RTC_IRQn); RTC_CompareSet(0, SYSTICK_LOAD_VALUE); RTC_IntClear(RTC_IFC_COMP0); RTC_IntEnable(RTC_IF_COMP0); RTC_Enable(true); //RTC_CounterReset(); }
void lp_ticker_set_interrupt(timestamp_t timestamp) { RTC_IntDisable(RTC_IF_COMP0); RTC_IntClear(RTC_IF_COMP0); RTC_FreezeEnable(true); RTC_CompareSet(0, (uint32_t) (timestamp & RTC_MAX_VALUE)); RTC_FreezeEnable(false); RTC_IntEnable(RTC_IF_COMP0); }
/**************************************************************************//** * @brief Initialize Real Time Counter *****************************************************************************/ void initRTC() { /* Starting LFXO and waiting until it is stable */ CMU_OscillatorEnable(cmuOsc_LFXO, true, true); /* Routing the LFXO clock to the RTC */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); CMU_ClockEnable(cmuClock_RTC, true); /* Enabling clock to the interface of the low energy modules */ CMU_ClockEnable(cmuClock_CORELE, true); const RTC_Init_TypeDef rtcInit = { .enable = true, .debugRun = false, .comp0Top = true, }; RTC_Init(&rtcInit); /* Set comapre value for compare register 0 */ RTC_CompareSet(0, RTC_COUNT_BETWEEN_WAKEUP); /* Enable interrupt for compare register 0 */ RTC_IntEnable(RTC_IFC_COMP0); /* Enabling Interrupt from RTC */ NVIC_EnableIRQ(RTC_IRQn); RTC_Enable(false); } /**************************************************************************//** * @brief Initialize General Purpuse Input/Output *****************************************************************************/ void initGPIO() { /* Enable clock for GPIO module */ CMU_ClockEnable(cmuClock_GPIO, true); /* Configure pin PB9/PD8 (Push Button 1) and PB10/PB11 (Push Button 2) as an input, * so that we can read their values. */ GPIO_PinModeSet(PB0_PORT, PB0_PIN, gpioModeInput, 1); GPIO_PinModeSet(PB1_PORT, PB1_PIN, gpioModeInput, 1); /* Enable GPIO_ODD and GPIO_EVEN interrupts in NVIC */ NVIC_EnableIRQ(GPIO_ODD_IRQn); NVIC_EnableIRQ(GPIO_EVEN_IRQn); /* Configure interrupts on falling edge for pins B9/D8 (Push Button 1), * B10/B11 (Push Button 2) and D3 */ GPIO_IntConfig(PB0_PORT, PB0_PIN, true, true, true); GPIO_IntConfig(PB1_PORT, PB1_PIN, true, true, true); }
/*---------------------------------------------------------------------------*/ void rtimer_arch_schedule(rtimer_clock_t t) { // Program Alarm RTC_IntClear(RTC_IF_COMP0); // Enable Alarm 0 preventing overflow !!! RTC_CompareSet(0, (t & 0xFFFFFF)); PRINTF("Now %u, comp0 = %u\r\n", rtimer_arch_now(), t); RTC_IntEnable(RTC_IF_COMP0); }
/**************************************************************************//** * @brief Enables LFACLK and selects LFXO as clock source for RTC * Sets up the RTC to generate an interrupt every second. *****************************************************************************/ static void rtcSetup(unsigned int frequency) { RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; /* Enable LE domain registers */ if ( !( CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE) ) { CMU_ClockEnable(cmuClock_CORELE, true); } #ifdef PAL_RTC_CLOCK_LFXO /* LFA with LFXO setup is relatively time consuming. Therefore, check if it already enabled before calling. */ if ( !(CMU->STATUS & CMU_STATUS_LFXOENS) ) { CMU_OscillatorEnable(cmuOsc_LFXO, true, true); } if ( cmuSelect_LFXO != CMU_ClockSelectGet(cmuClock_LFA) ) { CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); } #elif defined PAL_RTC_CLOCK_LFRCO /* Enable LFACLK in CMU (will also enable LFRCO oscillator if not enabled) */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO); #elif defined PAL_RTC_CLOCK_ULFRCO /* Enable LFACLK in CMU (will also enable ULFRCO oscillator if not enabled) */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO); #else #error No clock source for RTC defined. #endif /* Set the prescaler. */ CMU_ClockDivSet( cmuClock_RTC, cmuClkDiv_1 ); /* Enable RTC clock */ CMU_ClockEnable(cmuClock_RTC, true); /* Initialize RTC */ rtcInit.enable = false; /* Do not start RTC after initialization is complete. */ rtcInit.debugRun = false; /* Halt RTC when debugging. */ rtcInit.comp0Top = true; /* Wrap around on COMP0 match. */ RTC_Init(&rtcInit); /* Interrupt at given frequency. */ RTC_CompareSet(0, (CMU_ClockFreqGet(cmuClock_RTC) / frequency) - 1 ); /* Enable interrupt */ NVIC_EnableIRQ(RTC_IRQn); RTC_IntEnable(RTC_IEN_COMP0); /* Start Counter */ RTC_Enable(true); }
/****************************************************************************** * @brief Configure RTC * *****************************************************************************/ void rtcSetup(void) { RTC_Init_TypeDef rtcInit; /* Select LFXO as clock source for the RTC */ CMU_ClockSelectSet(cmuClock_LFA,cmuSelect_LFXO); CMU_ClockEnable(cmuClock_RTC, true); /* Set RTC pre-scaler */ CMU_ClockDivSet(cmuClock_RTC,cmuClkDiv_1); /* Enable clock to low energy modules */ CMU_ClockEnable(cmuClock_CORELE, true); /* RTC configuration struct */ rtcInit.debugRun = false; rtcInit.comp0Top = false; rtcInit.enable = false; /* Initialize RTC */ RTC_Init(&rtcInit); /* Set RTC compare value for first display update */ RTC_CompareSet(0, RTC_COUNTS_BETWEEN_DISPLAY ); /* Set RTC compare value for first temperature compensation */ RTC_CompareSet(1, RTC_COUNTS_BETWEEN_TC ); /* Enable COMP0 interrupt to trigger display update, */ /* COMP1 interrupt to trigger temperature compensation, and */ /* OF interrupt to keep track of counter overflows */ RTC_IntEnable(RTC_IEN_COMP0 | RTC_IEN_COMP1 | RTC_IEN_OF ); /* Enable RTC interrupts */ NVIC_ClearPendingIRQ(RTC_IRQn); NVIC_EnableIRQ(RTC_IRQn); /* Enable RTC */ RTC_Enable(true); }
/**************************************************************************//** * @brief Delay function, does not depend on interrupts. *****************************************************************************/ static void Delay( uint32_t msec ) { /* RTC frequency is LFXO divided by 32 (prescaler) */ #define RTC_FREQ (32768 / 32) RTC_IntDisable( RTC_IF_COMP0 ); RTC_IntClear( RTC_IF_COMP0 ); RTC_CompareSet( 0, (RTC_FREQ * msec ) / 1000 ); /* Calculate trigger value */ RTC_Enable( true ); while ( !( RTC_IntGet() & RTC_IF_COMP0 ) ); /* Wait for trigger */ RTC_Enable( false ); }
/***************************************************************************//** * @brief RTC Interrupt Handler * ******************************************************************************/ void RTC_IRQHandler(void) { /* Interrupt source: compare match 0 */ /* Increment compare value and update TFT display */ if ( RTC_IntGet() & RTC_IF_COMP0 ) { RTC_CompareSet(0,RTC->COMP0 + RTC_COUNTS_BETWEEN_DISPLAY); RTC_IntClear(RTC_IFC_COMP0); /* Set flag for display update */ doDisplayUpdate = true; } /* Interrupt source: compare match 1 */ /* Increment compare value and compensate for temperature drift */ if ( RTC_IntGet() & RTC_IF_COMP1 ) { RTC_CompareSet(1,RTC->COMP1 + RTC_COUNTS_BETWEEN_TC); RTC_IntClear(RTC_IFC_COMP1); /* Set flag for temperature compensation */ doTemperatureCompensation = true; } /* Interrupt source: counter overflow */ /* Increase overflow counter and update display */ if ( RTC_IntGet() & RTC_IF_OF ) { clockOverflow( ); RTC_IntClear(RTC_IFC_OF); /* Set flag for display update */ doDisplayUpdate = true; } }
error_t hw_timer_schedule(hwtimer_id_t timer_id, hwtimer_tick_t tick ) { if(timer_id >= HWTIMER_NUM) return ESIZE; if(!timer_inited) return EOFF; start_atomic(); RTC_IntDisable(RTC_IEN_COMP1); RTC_CompareSet( 1, tick ); RTC_IntClear(RTC_IEN_COMP1); RTC_IntEnable(RTC_IEN_COMP1); end_atomic(); }
void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg) { rtt_state.alarm_cb = cb; rtt_state.alarm_arg = arg; /* disable interrupt so it doesn't accidentally trigger */ RTC_IntDisable(RTC_IEN_COMP0); /* set compare register */ RTC_CompareSet(0, alarm & RTT_MAX_VALUE); /* enable the interrupt */ RTC_IntClear(RTC_IFC_COMP0); RTC_IntEnable(RTC_IEN_COMP0); }
/**************************************************************************//** * @brief PCNT0_IRQHandler * Interrupt Service Routine for PCNT0 Interrupt Line *****************************************************************************/ void PCNT0_IRQHandler(void) { PCNT_IntGet(PCNT0); PCNT_IntClear(PCNT0, PCNT_IEN_DIRCNG); /* Enable clock for LCD. */ CMU_ClockEnable(cmuClock_LCD, true); /* Wait until SYNCBUSY_CTRL flag is cleared. */ LCD_SyncBusyDelay(LCD_SYNCBUSY_CTRL); /* Enable LCD. */ LCD_Enable(true); /* Write PCNT counter number the LCD */ SegmentLCD_Write(PCNT_DIRCHANGE_STRING); /* Disable RTC first to reset counter */ RTC_Enable(false); /* Set compare value */ RTC_CompareSet(0, RTC_COMP_VALUE); /* Enable RTC */ RTC_Enable(true); }
/**************************************************************************//** * @brief Enables LFACLK and selects LFXO as clock source for RTC. * Sets up the RTC to count at 1024 Hz. * The counter should not be cleared on a compare match and keep running. * Interrupts should be cleared and enabled. * The counter should run. *****************************************************************************/ error_t hw_timer_init(hwtimer_id_t timer_id, uint8_t frequency, timer_callback_t compare_callback, timer_callback_t overflow_callback) { if(timer_id >= HWTIMER_NUM) return ESIZE; if(timer_inited) return EALREADY; if(frequency != HWTIMER_FREQ_1MS && frequency != HWTIMER_FREQ_32K) return EINVAL; start_atomic(); compare_f = compare_callback; overflow_f = overflow_callback; timer_inited = true; /* Configuring clocks in the Clock Management Unit (CMU) */ startLfxoForRtc(frequency); RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; rtcInit.enable = false; /* Don't enable RTC after init has run */ rtcInit.comp0Top = true; /* Clear counter on compare 0 match: cmp 0 is used to limit the value of the rtc to 0xffff */ rtcInit.debugRun = false; /* Counter shall not keep running during debug halt. */ /* Initialize the RTC */ RTC_Init(&rtcInit); //disable all rtc interrupts while we're still configuring RTC_IntDisable(RTC_IEN_OF | RTC_IEN_COMP0 | RTC_IEN_COMP1); RTC_IntClear(RTC_IFC_OF | RTC_IFC_COMP0 | RTC_IFC_COMP1); //Set maximum value for the RTC RTC_CompareSet( 0, 0x0000FFFF ); RTC_CounterReset(); RTC_IntEnable(RTC_IEN_COMP0); NVIC_EnableIRQ(RTC_IRQn); RTC_Enable(true); end_atomic(); return SUCCESS; }
void portInitClock(void) { #define LFO_FREQUENCY 32768 #if PORTCFG_RTC_LFXO != 0 /* Starting LFRCO and waiting until it is stable */ CMU_OscillatorEnable(cmuOsc_LFXO, true, true); /* Routing the LFRCO clock to the RTC */ CMU_ClockSelectSet(cmuClock_LFA,cmuSelect_LFXO); #else /* Starting LFRCO and waiting until it is stable */ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); /* Routing the LFRCO clock to the RTC */ CMU_ClockSelectSet(cmuClock_LFA,cmuSelect_LFRCO); #endif CMU_ClockEnable(cmuClock_RTC, true); /* Enabling clock to the interface of the low energy modules */ CMU_ClockEnable(cmuClock_CORELE, true); RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; rtcInit.enable = true; /* Enable RTC after init has run */ rtcInit.comp0Top = true; /* Clear counter on compare match */ rtcInit.debugRun = false; /* Counter shall keep running during debug halt. */ /* Setting the compare value of the RTC */ RTC_CompareSet(0, (LFO_FREQUENCY / HZ) - 1); /* Enabling Interrupt from RTC */ RTC_IntEnable(RTC_IFC_COMP0); NVIC_EnableIRQ(RTC_IRQn); NVIC_SetPriority(RTC_IRQn, PORT_SYSTICK_PRI); /* Initialize the RTC */ RTC_Init(&rtcInit); }
void rtcSetDelay(int menuItem){ int delay; switch (menuItem) { case 0: delay = 10; break; case 1: delay = 3600 * 12; break; case 2: delay = 3600 * 24; break; case 3: delay = 3600 * 48; break; } /* Interrupt every minute */ RTC_CompareSet(0, ((RTC_FREQ / CLOCK_DIVISION) * delay ) - 1 ); /* Start Counter */ RTC_Enable(true); }
/********************************************//** * \brief configure RTC to run from 32K external crystal * configure RTC divider to count seconds * \param * \param * \return * ***********************************************/ void initClock(void) { // set RTC to generate interrupts every second time and date will be maintained by software /* Starting LFXO and waiting until it is stable */ CMU_OscillatorEnable(cmuOsc_LFXO, true, true); /* Routing the LFXO clock to the RTC */ CMU_ClockSelectSet(cmuClock_LFA,cmuSelect_LFXO); CMU_ClockEnable(cmuClock_RTC, true); /* Enabling clock to the interface of the low energy modules */ CMU_ClockEnable(cmuClock_CORELE, true); /* Setting up RTC */ /* Prescaler of 15 = 1 s of resolution and overflow each 194 days */ CMU_ClockDivSet(cmuClock_RTC,cmuClkDiv_32768); RTC_CompareSet(0, RTC_COUNT_BETWEEN_WAKEUP); RTC_IntEnable(RTC_IFC_COMP0); /* Enabling Interrupt from RTC */ NVIC_EnableIRQ(RTC_IRQn); RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; RTC_Init(&rtcInit); }
/***************************************************************************//** * @brief RTC trigger enable * @param msec Enable trigger in msec * @param cb Callback invoked when @p msec elapsed ******************************************************************************/ void RTC_Trigger(uint32_t msec, void (*cb)(void)) { /* Auto init if not configured already */ if (!rtcInitialized) { /* Default to LFRCO as clock source */ RTC_Setup(cmuSelect_LFRCO); } /* 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 RTC Setup * Produce an interrupt every second *****************************************************************************/ void rtc_setup(void) { /* Starting LFXO and waiting until it is stable */ CMU_OscillatorEnable(cmuOsc_LFXO, true, true); /* Routing the LFXO clock to the RTC */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); CMU_ClockEnable(cmuClock_RTC, true); /* Enabling clock to the interface of the low energy modules */ CMU_ClockEnable(cmuClock_CORELE, true); const RTC_Init_TypeDef rtcInit = { .enable = true, .debugRun = false, .comp0Top = true, }; RTC_Init(&rtcInit); /* Produce interrupt every second */ RTC_CompareSet(0, 32768); /* Enable interrupt for compare register 0 */ RTC_IntEnable(RTC_IFC_COMP0); /* Enabling interrupt from RTC */ NVIC_EnableIRQ(RTC_IRQn); } /**************************************************************************//** * @brief Main function *****************************************************************************/ int main(void) { /* Initialize chip */ CHIP_Init(); /* Enable code view */ setupSWO(); /* Configure peripherals */ rtc_setup(); BSP_LedsInit(); while (1) { switch (STATE) { case EM0: break; case EM1: EMU_EnterEM1(); break; case EM2: EMU_EnterEM2(true); break; } } }
/**************************************************************************//** * @brief vPortSuppressTicksAndSleep * Override the default definition of vPortSuppressTicksAndSleep() that is weakly * defined in the FreeRTOS Cortex-M3 port layer layer *****************************************************************************/ void vPortSuppressTicksAndSleep(portTickType xExpectedIdleTime) { unsigned long ulReloadValue, ulCompleteTickPeriods; unsigned int ulRemainingCounter; portTickType xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ if (xExpectedIdleTime > xMaximumPossibleSuppressedTicks) { xExpectedIdleTime = xMaximumPossibleSuppressedTicks; } /* Calculate the reload value required to wait xExpectedIdleTime * tick periods. */ ulReloadValue = (ulTimerReloadValueForOneTick * (xExpectedIdleTime )); if (ulReloadValue > ulStoppedTimerCompensation) { ulReloadValue -= ulStoppedTimerCompensation; } /* Stop the System Tick momentarily. The time the System Tick is stopped for * is accounted for as best it can be, but using the tickless mode will * inevitably result in some tiny drift of the time maintained by the * kernel with respect to calendar time. */ /* Stop the RTC clock*/ RTC_Enable(false); /* Enter a critical section but don't use the taskENTER_CRITICAL() * method as that will mask interrupts that should exit sleep mode. */ INT_Disable(); /* The tick flag is set to false before sleeping. If it is true when sleep * mode is exited then sleep mode was probably exited because the tick was * suppressed for the entire xExpectedIdleTime period. */ intTickFlag = false; /* If a context switch is pending or a task is waiting for the scheduler * to be unsuspended then abandon the low power entry. */ if (eTaskConfirmSleepModeStatus() == eAbortSleep) { RTC_Enable(true); /* Re-enable interrupts - see comments above __disable_interrupt() * call above. */ INT_Enable(); } else { /* Set the new reload value. */ ulReloadValue -= RTC_CounterGet(); RTC_CompareSet(0, ulReloadValue); /* Restart the counter*/ RTC_CounterReset(); /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can * set its parameter to 0 to indicate that its implementation contains * its own wait for interrupt or wait for event instruction, and so wfi * should not be executed again. However, the original expected idle * time variable must remain unmodified, so a copy is taken. */ xModifiableIdleTime = xExpectedIdleTime; configPRE_SLEEP_PROCESSING(xModifiableIdleTime); if (xModifiableIdleTime > 0) { SLEEP_Sleep(); __DSB(); __ISB(); } configPOST_SLEEP_PROCESSING(xExpectedIdleTime); /* Stop SysTick. Again, the time the SysTick is stopped for is * accounted for as best it can be, but using the tickless mode will * inevitably result in some tiny drift of the time maintained by the * kernel with respect to calendar time. */ /* Store current counter value */ ulRemainingCounter = RTC_CounterGet(); /* Stop the RTC clock*/ RTC_Enable(false); /* Re-enable interrupts */ INT_Enable(); if (intTickFlag != false) { /* The tick interrupt has already executed, * Reset the alarm value with whatever remains of this tick period. */ RTC_CompareSet(0, TIMER_CAPACITY & (ulTimerReloadValueForOneTick - RTC_CounterGet())); /* The tick interrupt handler will already have pended the tick * processing in the kernel. As the pending tick will be * processed as soon as this function exits, the tick value * maintained by the tick is stepped forward by one less than the * time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; } else { /* Some other interrupt than system tick ended the sleep. * Calculate how many tick periods passed while the processor * was waiting */ ulCompleteTickPeriods = ulRemainingCounter / ulTimerReloadValueForOneTick; /* The reload value is set to whatever fraction of a single tick * period remains. */ if (ulCompleteTickPeriods == 0) { ulReloadValue = ulTimerReloadValueForOneTick - ulRemainingCounter; } else { ulReloadValue = ulRemainingCounter - (ulCompleteTickPeriods * ulTimerReloadValueForOneTick); } RTC_CompareSet(0, ulReloadValue); } /* Restart the RTCounter */ RTC_CounterReset(); /* The tick forward by the number of tick periods that * remained in a low power state. */ vTaskStepTick(ulCompleteTickPeriods); } }
/**************************************************************************//** * @brief Main function *****************************************************************************/ int main(void) { unsigned char pucMACArray[8]; uint32_t temp; /* Chip revision alignment and errata fixes */ CHIP_Init(); /* Ensure core frequency has been updated */ SystemCoreClockUpdate(); CMU_ClockEnable(cmuClock_ADC0, true); /* Setup SysTick Timer for 1 msec interrupts */ if (SysTick_Config(SystemCoreClock / 1000)) while (1) ; /* Setup ADC for sampling internal temperature sensor. */ setupSensor(); /* Spi init*/ spiInit(); #if LWIP_DHCP /* Initialze the lwIP library, using DHCP.*/ lwIPInit(pucMACArray, 0, 0, 0, IPADDR_USE_DHCP); #else /* Initialze the lwIP library, using Static IP.*/ lwIPInit(pucMACArray, IPADDR(192, 168, 79, 160), IPADDR(255, 255, 255, 0), \ IPADDR(192, 168, 79, 1), IPADDR_USE_STATIC); #endif /* Initialize a sample httpd server.*/ httpd_init(); /* Start one ADC sample */ ADC_Start(ADC0, adcStartSingle); /* Enable board control interrupts */ gpioSetup(); axspi_write_reg(~IMR_RXPKT, P0_IMR); /* Start LCD without boost */ SegmentLCD_Init(false); CMU_ClockEnable(cmuClock_RTC, true); /* RTC configuration structure */ RTC_Init_TypeDef rtcInit = { .enable = false, .debugRun = false, .comp0Top = true }; /* Initialize RTC */ RTC_Init(&rtcInit); /* Set COMP0 value which will be the top value as well */ RTC_CompareSet(RTC_COMP, RTC_COMP_VALUE); /* Clear all pending interrupts */ RTC_IntClear(0x7); /* Enable COMP0 interrupts */ RTC_IntEnable(0x2); /* Enable interrupts */ NVIC_ClearPendingIRQ(RTC_IRQn); NVIC_EnableIRQ(RTC_IRQn); RTC_Enable(true); while (1) { /* check temperature flag*/ if (read_temperature) { temp = ADC_DataSingleGet(ADC0); /* Show Celsius on numeric part of display */ temperature = (int)(convertToCelsius(temp)); /* Start a new conversion */ ADC_Start(ADC0, adcStartSingle); /* Reset temperature flag */ read_temperature = 0; } if (updateIpFlag) { switch (ip_field) { case 1: { SegmentLCD_Write(IP_ADDR_FIRST_TEXT); SegmentLCD_Number(IP_ADDR_FIRST_NUM(lwip_netif.ip_addr.addr)); ip_field++; } break; case 2: { SegmentLCD_Write(IP_ADDR_SECOND_TEXT); SegmentLCD_Number(IP_ADDR_SECOND_NUM(lwip_netif.ip_addr.addr)); ip_field++; } break; case 3: { SegmentLCD_Write(IP_ADDR_THIRD_TEXT); SegmentLCD_Number(IP_ADDR_THIRD_NUM(lwip_netif.ip_addr.addr)); ip_field++; } break; case 4: { SegmentLCD_Write(IP_ADDR_FOURTH_TEXT); SegmentLCD_Number(IP_ADDR_FOURTH_NUM(lwip_netif.ip_addr.addr)); ip_field = 1; } break; default: break; } updateIpFlag = false; } } }
/**************************************************************************//** * @brief Configure RTC *****************************************************************************/ void rtc_setup(void) { CMU_ClockEnable(cmuClock_RTC, true); /* Enabling clock to the interface of the low energy modules */ CMU_ClockEnable(cmuClock_CORELE, true); const RTC_Init_TypeDef rtcInit = { .enable = true, .debugRun = false, .comp0Top = true, }; RTC_Init(&rtcInit); /* Set overflow every 0.1 seconds */ RTC_CompareSet(0, 3276); } /**************************************************************************//** * @brief SWO Setup * Enables code view in energyAware Profiler *****************************************************************************/ void setupSWO(void) { uint32_t *dwt_ctrl = (uint32_t *) 0xE0001000; uint32_t *tpiu_prescaler = (uint32_t *) 0xE0040010; uint32_t *tpiu_protocol = (uint32_t *) 0xE00400F0; CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO; /* Enable Serial wire output pin */ GPIO->ROUTE |= GPIO_ROUTE_SWOPEN; #if defined(_EFM32_GIANT_FAMILY) /* Set location 0 */ GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC0; /* Enable output on pin - GPIO Port F, Pin 2 */ GPIO->P[5].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK); GPIO->P[5].MODEL |= GPIO_P_MODEL_MODE2_PUSHPULL; #else /* Set location 1 */ GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC1; /* Enable output on pin */ GPIO->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE15_MASK); GPIO->P[2].MODEH |= GPIO_P_MODEH_MODE15_PUSHPULL; #endif /* Enable debug clock AUXHFRCO */ CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN; while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY)); /* Enable trace in core debug */ CoreDebug->DHCSR |= 1; CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; /* Enable PC and IRQ sampling output */ *dwt_ctrl = 0x400113FF; /* Set TPIU prescaler to 16. */ *tpiu_prescaler = 0xf; /* Set protocol to NRZ */ *tpiu_protocol = 2; /* Unlock ITM and output data */ ITM->LAR = 0xC5ACCE55; ITM->TCR = 0x10009; }
const hwtimer_info_t* hw_timer_get_info(hwtimer_id_t timer_id) { if(timer_id >= HWTIMER_NUM) return NULL; static const hwtimer_info_t timer_info = { .min_delay_ticks = 0, }; return &timer_info; } hwtimer_tick_t hw_timer_getvalue(hwtimer_id_t timer_id) { if(timer_id >= HWTIMER_NUM || (!timer_inited)) return 0; else { uint32_t value =(uint16_t)(RTC->CNT & 0xFFFF); return value; } } error_t hw_timer_schedule(hwtimer_id_t timer_id, hwtimer_tick_t tick ) { if(timer_id >= HWTIMER_NUM) return ESIZE; if(!timer_inited) return EOFF; start_atomic(); RTC_IntDisable(RTC_IEN_COMP1); RTC_CompareSet( 1, tick ); RTC_IntClear(RTC_IEN_COMP1); RTC_IntEnable(RTC_IEN_COMP1); end_atomic(); } error_t hw_timer_cancel(hwtimer_id_t timer_id) { if(timer_id >= HWTIMER_NUM) return ESIZE; if(!timer_inited) return EOFF; start_atomic(); RTC_IntDisable(RTC_IEN_COMP1); RTC_IntClear(RTC_IEN_COMP1); end_atomic(); } error_t hw_timer_counter_reset(hwtimer_id_t timer_id) { if(timer_id >= HWTIMER_NUM) return ESIZE; if(!timer_inited) return EOFF; start_atomic(); RTC_IntDisable(RTC_IEN_COMP0 | RTC_IEN_COMP1); RTC_IntClear(RTC_IEN_COMP0 | RTC_IEN_COMP1); RTC_CounterReset(); RTC_IntEnable(RTC_IEN_COMP0); end_atomic(); } bool hw_timer_is_overflow_pending(hwtimer_id_t timer_id) { if(timer_id >= HWTIMER_NUM) return false; start_atomic(); //COMP0 is used to limit thc RTC to 16 bits -> use this one to check bool is_pending = !!((RTC_IntGet() & RTC->IEN) & RTC_IFS_COMP0); end_atomic(); return is_pending; } bool hw_timer_is_interrupt_pending(hwtimer_id_t timer_id) { if(timer_id >= HWTIMER_NUM) return false; start_atomic(); bool is_pending = !!((RTC_IntGet() & RTC->IEN) & RTC_IFS_COMP1); end_atomic(); return is_pending; } INT_HANDLER(RTC_IRQHandler) { //retrieve flags. We 'OR' this with the enabled interrupts //since the COMP1 flag may be set if it wasn't used before (compare register == 0 -> ifs flag set regardless of whether interrupt is enabled) //by AND ing with the IEN we make sure we only consider the flags of the ENABLED interrupts uint32_t flags = (RTC_IntGet() & RTC->IEN); RTC_IntClear(RTC_IFC_OF | RTC_IFC_COMP0 | RTC_IFC_COMP1); //evaluate flags to see which one(s) fired: if((flags & RTC_IFS_COMP0) && (overflow_f != 0x0)) overflow_f(); if((flags & RTC_IFS_COMP1)) { RTC_IntDisable(RTC_IEN_COMP1); if(compare_f != 0x0) compare_f(); } }
/**************************************************************************//** * @brief Initialize Real Time Counter *****************************************************************************/ void initRTC() { /* Starting LFXO and waiting until it is stable */ CMU_OscillatorEnable(cmuOsc_LFXO, true, true); /* Routing the LFXO clock to the RTC */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); CMU_ClockEnable(cmuClock_RTC, true); /* Enabling clock to the interface of the low energy modules */ CMU_ClockEnable(cmuClock_CORELE, true); const RTC_Init_TypeDef rtcInit = { .enable = true, .debugRun = false, .comp0Top = true, }; RTC_Init(&rtcInit); /* Set comapre value for compare register 0 */ RTC_CompareSet(0, RTC_COUNT_BETWEEN_WAKEUP); /* Enable interrupt for compare register 0 */ RTC_IntEnable(RTC_IFC_COMP0); /* Enabling Interrupt from RTC */ NVIC_EnableIRQ(RTC_IRQn); } /**************************************************************************//** * @brief Initialize General Purpuse Input/Output *****************************************************************************/ void initGPIO() { /* Enable clock for GPIO module */ CMU_ClockEnable(cmuClock_GPIO, true); /* Configure pin PD8/PB9 (Push Button 0) and PB11/PB10 (Push Button 1) as an input, * so that we can read their values. */ GPIO_PinModeSet(PB0_PORT, PB0_PIN, gpioModeInput, 1); GPIO_PinModeSet(PB1_PORT, PB1_PIN, gpioModeInput, 1); /* Configure pin PD3 as an input. Unlike Push Button 0 and 1 this pin * does not have a pull down associated with it. We therefore need to set the * mode to InputPull, in order to set a default value of 1 with PinOutSet(). */ GPIO_PinModeSet(gpioPortD, 3, gpioModeInputPull, 1); GPIO_PinOutSet(gpioPortD, 3); /* Configure PC0 as a push pull for LED drive */ GPIO_PinModeSet(LED_PORT, LED_PIN, gpioModePushPull, 0); /* Enable GPIO_ODD and GPIO_EVEN interrupts in NVIC */ NVIC_EnableIRQ(GPIO_ODD_IRQn); NVIC_EnableIRQ(GPIO_EVEN_IRQn); NVIC_EnableIRQ(PendSV_IRQn); /* Set priorities - 0 is the highest, 7 is the lowest */ #if defined(_EFM32_GIANT_FAMILY) NVIC_SetPriority(GPIO_ODD_IRQn, 2); NVIC_SetPriority(GPIO_EVEN_IRQn, 1); #else NVIC_SetPriority(GPIO_EVEN_IRQn, 2); NVIC_SetPriority(GPIO_ODD_IRQn, 1); #endif NVIC_SetPriority(RTC_IRQn, 0); NVIC_SetPriority(PendSV_IRQn, 3); /* Configure interrupts on falling edge for pins D8/B9 (Push Button 0), * B11/B10 (Push Button 1) and D3 */ GPIO_IntConfig(PB0_PORT, PB0_PIN, false, true, true); GPIO_IntConfig(PB1_PORT, PB1_PIN, false, true, true); GPIO_IntConfig(gpioPortD, 3, false, true, true); }