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); }
int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg) { rtc_state.alarm_cb = cb; rtc_state.alarm_arg = arg; rtc_state.alarm_year = time->tm_year; /* disable interrupt so it doesn't accidentally trigger */ RTCC_IntDisable(RTCC_IEN_CC0); /* set compare registers */ RTCC_ChannelDateSet(0, RTCC_Channel_Month2BCD(time->tm_mon) | RTCC_Channel_Day2BCD(time->tm_mday)); RTCC_ChannelTimeSet(0, RTCC_Channel_Hour2BCD(time->tm_hour) | RTCC_Channel_Minute2BCD(time->tm_min) | RTCC_Channel_Second2BCD(time->tm_sec)); /* enable the interrupt */ RTCC_IntClear(RTCC_IFC_CC0); RTCC_IntEnable(RTCC_IEN_CC0); return 0; }