void rtc_init(void) { /* enable clocks */ CMU_ClockEnable(cmuClock_CORELE, true); CMU_ClockEnable(cmuClock_RTCC, true); /* reset and initialize peripheral */ EFM32_CREATE_INIT(init, RTCC_Init_TypeDef, RTCC_INIT_DEFAULT, .conf.enable = false, .conf.presc = rtccCntPresc_32768, .conf.cntMode = rtccCntModeCalendar ); RTCC_Reset(); RTCC_Init(&init.conf); /* initialize alarm channel */ RTCC_CCChConf_TypeDef init_channel = RTCC_CH_INIT_COMPARE_DEFAULT; RTCC_ChannelInit(0, &init_channel); /* enable interrupt */ NVIC_ClearPendingIRQ(RTCC_IRQn); NVIC_EnableIRQ(RTCC_IRQn); /* enable peripheral */ RTCC_Enable(true); }
/**************************************************************************//** * @brief Enables LFECLK and selects clock source for RTCC * Sets up the RTCC to generate an interrupt every second. *****************************************************************************/ static void rtccSetup(unsigned int frequency) { RTCC_Init_TypeDef rtccInit = RTCC_INIT_DEFAULT; rtccInit.presc = rtccCntPresc_1; palClockSetup(cmuClock_LFE); /* Enable RTCC clock */ CMU_ClockEnable(cmuClock_RTCC, true); /* Initialize RTC */ rtccInit.enable = false; /* Do not start RTC after initialization is complete. */ rtccInit.debugRun = false; /* Halt RTC when debugging. */ rtccInit.cntWrapOnCCV1 = true; /* Wrap around on CCV1 match. */ RTCC_Init(&rtccInit); /* Interrupt at given frequency. */ RTCC_CCChConf_TypeDef ccchConf = RTCC_CH_INIT_COMPARE_DEFAULT; ccchConf.compMatchOutAction = rtccCompMatchOutActionToggle; RTCC_ChannelInit(1, &ccchConf); RTCC_ChannelCCVSet(1, (CMU_ClockFreqGet(cmuClock_RTCC) / frequency) - 1); #ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY /* Enable interrupt */ NVIC_EnableIRQ(RTCC_IRQn); RTCC_IntEnable(RTCC_IEN_CC1); #endif RTCC->CNT = _RTCC_CNT_RESETVALUE; /* Start Counter */ RTCC_Enable(true); }
void vPortSetupTimerInterrupt( void ) { /* Configure the RTCC to generate the RTOS tick interrupt. */ /* The maximum number of ticks that can be suppressed depends on the clock frequency. */ xMaximumPossibleSuppressedTicks = ULONG_MAX / ulReloadValueForOneTick; /* Ensure LE modules are accessible. */ CMU_ClockEnable( cmuClock_CORELE, true ); /* Use LFXO. */ CMU_ClockSelectSet( cmuClock_LFE, cmuSelect_LFXO ); /* Enable clock to the RTC module. */ CMU_ClockEnable( cmuClock_RTCC, true ); /* Use channel 1 to generate the RTOS tick interrupt. */ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValueForOneTick ); RTCC_Init( &xRTCInitStruct ); RTCC_ChannelInit( lpRTCC_CHANNEL, &xRTCCChannel1InitStruct ); RTCC_EM4WakeupEnable( true ); /* Disable RTCC interrupt. */ RTCC_IntDisable( _RTCC_IF_MASK ); RTCC_IntClear( _RTCC_IF_MASK ); RTCC->CNT = _RTCC_CNT_RESETVALUE; /* The tick interrupt must be set to the lowest priority possible. */ NVIC_SetPriority( RTCC_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY ); NVIC_ClearPendingIRQ( RTCC_IRQn ); NVIC_EnableIRQ( RTCC_IRQn ); RTCC_IntEnable( RTCC_IEN_CC1 ); RTCC_Enable( true ); #if( lpUSE_TEST_TIMER == 1 ) { void prvSetupTestTimer( void ); /* A second timer is used to test the path where the MCU is brought out of a low power state by a timer other than the tick timer. */ prvSetupTestTimer(); } #endif }
void lp_ticker_set_interrupt(timestamp_t timestamp) { uint64_t timestamp_ticks; uint64_t current_ticks = RTCC_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; // checking the rounding. If timeout is wanted between RTCC ticks, irq should be configured to // trigger in the latter RTCC-tick. Otherwise ticker-api fails to send timer event to its client if(((timestamp_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) < offset){ timestamp_ticks++; } timestamp_ticks += current_ticks; /* RTCC has 32 bit resolution */ timestamp_ticks &= 0xFFFFFFFF; /* check for RTCC limitation */ if((timestamp_ticks - RTCC_CounterGet()) >= 0x80000000) timestamp_ticks = RTCC_CounterGet() + 2; /* init channel */ RTCC_CCChConf_TypeDef ccchConf = RTCC_CH_INIT_COMPARE_DEFAULT; RTCC_ChannelInit(0,&ccchConf); /* Set callback */ RTCC_ChannelCCVSet(0, (uint32_t)timestamp_ticks); RTCC_IntEnable(RTCC_IF_CC0); }
/***************************************************************************//** * @brief * Initialize RTCDRV driver. * * @details * Will enable all necessary clocks. Initializes internal datastructures * and configures the underlying hardware timer. * * @return * @ref ECODE_EMDRV_RTCDRV_OK. ******************************************************************************/ Ecode_t RTCDRV_Init( void ) { if ( rtcdrvIsInitialized == true ) { return ECODE_EMDRV_RTCDRV_OK; } rtcdrvIsInitialized = true; // Ensure LE modules are clocked. CMU_ClockEnable( cmuClock_CORELE, true ); #if defined( CMU_LFECLKEN0_RTCC ) // Enable LFECLK in CMU (will also enable oscillator if not enabled). CMU_ClockSelectSet( cmuClock_LFE, RTCDRV_OSC ); #else // Enable LFACLK in CMU (will also enable oscillator if not enabled). CMU_ClockSelectSet( cmuClock_LFA, RTCDRV_OSC ); #endif #if defined( RTCDRV_USE_RTC ) // Set clock divider. CMU_ClockDivSet( cmuClock_RTC, RTC_DIVIDER ); // Enable RTC module clock. CMU_ClockEnable( cmuClock_RTC, true ); // Initialize RTC. RTC_Init( &initRTC ); #elif defined( RTCDRV_USE_RTCC ) // Set clock divider. initRTCC.presc = (RTCC_CntPresc_TypeDef)CMU_DivToLog2( RTC_DIVIDER ); // Enable RTCC module clock. CMU_ClockEnable( cmuClock_RTCC, true ); // Initialize RTCC. RTCC_Init( &initRTCC ); // Set up Compare channel. RTCC_ChannelInit( 1, &initRTCCCompareChannel ); #endif // Disable RTC/RTCC interrupt generation. RTC_INTDISABLE( RTC_ALL_INTS ); RTC_INTCLEAR( RTC_ALL_INTS ); RTC_COUNTERRESET(); // Clear and then enable RTC interrupts in NVIC. NVIC_CLEARPENDINGIRQ(); NVIC_ENABLEIRQ(); #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG ) // Enable overflow interrupt for wallclock. RTC_INTENABLE( RTC_OF_INT ); #endif // Reset RTCDRV internal data structures/variables. memset( timer, 0, sizeof( timer ) ); inTimerIRQ = false; rtcRunning = false; startTimerNestingLevel = 0; #if defined( EMODE_DYNAMIC ) sleepBlocked = false; #endif #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG ) wallClockOverflowCnt = 0; wallClockTimeBase = 0; #if defined( EMODE_NEVER_ALLOW_EM3EM4 ) // Always block EM3 and EM4 if wallclock is running. SLEEP_SleepBlockBegin( sleepEM3 ); #endif #endif return ECODE_EMDRV_RTCDRV_OK; }