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); }
timestamp_t lp_ticker_read() { if (! lp_ticker_inited) { lp_ticker_init(); } TIMER_T * timer2_base = (TIMER_T *) NU_MODBASE(timer2_modinit.modname); do { uint64_t major_minor_clks; uint32_t minor_clks; // NOTE: As TIMER_CNT = TIMER_CMP and counter_major has increased by one, TIMER_CNT doesn't change to 0 for one tick time. // NOTE: As TIMER_CNT = TIMER_CMP or TIMER_CNT = 0, counter_major (ISR) may not sync with TIMER_CNT. So skip and fetch stable one at the cost of 1 clock delay on this read. do { core_util_critical_section_enter(); // NOTE: Order of reading minor_us/carry here is significant. minor_clks = TIMER_GetCounter(timer2_base); uint32_t carry = (timer2_base->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0; // When TIMER_CNT approaches TIMER_CMP and will wrap soon, we may get carry but TIMER_CNT not wrapped. Handle carefully carry == 1 && TIMER_CNT is near TIMER_CMP. if (carry && minor_clks > (TMR2_CLK_PER_TMR2_INT / 2)) { major_minor_clks = (counter_major + 1) * TMR2_CLK_PER_TMR2_INT; } else { major_minor_clks = (counter_major + carry) * TMR2_CLK_PER_TMR2_INT + minor_clks; } core_util_critical_section_exit(); } while (minor_clks == 0 || minor_clks == TMR2_CLK_PER_TMR2_INT); // Add power-down compensation return ((uint64_t) major_minor_clks * US_PER_SEC / TMR2_CLK_PER_SEC / US_PER_TICK); } while (0); }
/** * Read the current counter * @return: The current timer's counter value in microseconds */ uint32_t lp_ticker_read(void) { uint32_t microseconds = 0; /* Verify if lp_ticker has not been Initialized */ if (lp_ticker_initialized == 0) lp_ticker_init(); /* Read Timer Value */ microseconds = DualTimer_Read_2(DUALTIMER0); return microseconds; }
uint32_t lp_ticker_read() { if (!lp_ticker_inited) { lp_ticker_init(); } uint32_t temp_pre = RTC_HAL_GetPrescaler(RTC_BASE); // RTC sec might be GT 4095, therfore use modulo the max allowance uint32_t temp_sec = RTC_HAL_GetSecsReg(RTC_BASE) % (1 << RTC_TIMER_BITS); while ((temp_pre != RTC_HAL_GetPrescaler(RTC_BASE)) || (temp_sec != (RTC_HAL_GetSecsReg(RTC_BASE) & RTC_TIMER_MASK))) { temp_pre = RTC_HAL_GetPrescaler(RTC_BASE); temp_sec = RTC_HAL_GetSecsReg(RTC_BASE) & RTC_TIMER_MASK; } return (temp_sec << 15 | temp_pre); }
timestamp_t lp_ticker_read() { lp_ticker_init(); uint64_t ticks_temp; uint64_t ticks = RTCC_CounterGet(); /* ticks = counter tick value * timestamp = value in microseconds * timestamp = ticks * 1.000.000 / RTC frequency */ ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT); return (timestamp_t) (ticks_temp & 0xFFFFFFFF); }
/** Read the current counter * * @return The current timer's counter value in microseconds */ uint32_t lp_ticker_read(void) { uint32_t sec, pre; if (!lp_ticker_inited) { lp_ticker_init(); } sec = RTC->TSR; /* 32b: Seconds */ pre = RTC->TPR; /* 16b: Increments every 32.768kHz clock cycle (30us) */ /* Final value: 11b (4095) for sec and 21b for usec (pre can reach 1,000,000us which is close to 1<<20) */ uint32_t ret = (((sec & MAX_SEC_MASK) * SEC_IN_USEC) + (((uint64_t)pre * SEC_IN_USEC) / OSC32K_CLK_HZ)); return ret; }
/** * Set interrupt for specified timestamp * timestamp: The time in microseconds to be set */ void lp_ticker_set_interrupt(timestamp_t timestamp) { int32_t delta = 0; /* Verify if lp_ticker has been not Initialized */ if (lp_ticker_initialized == 0) lp_ticker_init(); /* Calculate the delta */ delta = (int32_t)(timestamp - lp_ticker_read()); /* Check if the event was in the past */ if (delta <= 0) { /* This event was in the past */ DualTimer_SetInterrupt_1(DUALTIMER0, 0, DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT); return; } /* Enable interrupt on SingleTimer1 */ DualTimer_SetInterrupt_1(DUALTIMER0, delta, DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT); }
uint32_t lp_ticker_read() { if (! lp_ticker_inited) { lp_ticker_init(); } TIMER_T * timer2_base = (TIMER_T *) NU_MODBASE(timer2_modinit.modname); do { uint64_t major_minor_ms; uint32_t minor_ms; // NOTE: As TIMER_CNT = TIMER_CMP and counter_major has increased by one, TIMER_CNT doesn't change to 0 for one tick time. // NOTE: As TIMER_CNT = TIMER_CMP or TIMER_CNT = 0, counter_major (ISR) may not sync with TIMER_CNT. So skip and fetch stable one at the cost of 1 clock delay on this read. do { uint32_t _state = __get_PRIMASK(); __disable_irq(); // NOTE: Order of reading minor_us/carry here is significant. minor_ms = TIMER_GetCounter(timer2_base) * MS_PER_TMR2_CLK; uint32_t carry = (timer2_base->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0; // When TIMER_CNT approaches TIMER_CMP and will wrap soon, we may get carry but TIMER_CNT not wrapped. Hanlde carefully carry == 1 && TIMER_CNT is near TIMER_CMP. if (carry && minor_ms > (MS_PER_TMR2_INT / 2)) { major_minor_ms = (counter_major + 1) * MS_PER_TMR2_INT; } else { major_minor_ms = (counter_major + carry) * MS_PER_TMR2_INT + minor_ms; } __set_PRIMASK(_state); } while (minor_ms == 0 || minor_ms == MS_PER_TMR2_INT); // Add power-down compensation return (major_minor_ms / MS_PER_TICK); } while (0); }
/** Set interrupt for specified timestamp * * @param timestamp The time in microseconds to be set */ void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t now_us, delta_us, delta_ticks; if (!lp_ticker_inited) { lp_ticker_init(); } lptmr_schedule = 0; now_us = lp_ticker_read(); delta_us = timestamp > now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); /* Checking if LPTRM can handle this sleep */ delta_ticks = USEC_TO_COUNT(delta_us, CLOCK_GetFreq(kCLOCK_Er32kClk)); if (delta_ticks > MAX_LPTMR_SLEEP) { /* Using RTC if wait time is over 16b (2s @32kHz) */ uint32_t delta_sec; delta_us += COUNT_TO_USEC(RTC->TPR, CLOCK_GetFreq(kCLOCK_Er32kClk)); /* Accounting for started second */ delta_sec = delta_us / SEC_IN_USEC; delta_us -= delta_sec * SEC_IN_USEC; RTC->TAR = RTC->TSR + delta_sec - 1; RTC_EnableInterrupts(RTC, kRTC_AlarmInterruptEnable); /* Set aditional, subsecond, sleep time */ if (delta_us) { lptmr_schedule = USEC_TO_COUNT(delta_us, CLOCK_GetFreq(kCLOCK_Er32kClk)); } } else { /* Below RTC resolution using LPTMR */ LPTMR_SetTimerPeriod(LPTMR0, delta_ticks); LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); LPTMR_StartTimer(LPTMR0); } }
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); }
void init(){ lp_ticker_init(); }
uint32_t lp_ticker_read() { if (!lp_ticker_inited) lp_ticker_init(); return us_ticker_read(); }
uint32_t lp_ticker_read() { if (!lp_ticker_inited) { lp_ticker_init(); } return TIM2->CNT; }