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);
}
Example #2
0
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);
}
Example #3
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;
}
Example #4
0
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);
}
Example #6
0
/** 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;
}
Example #7
0
/**
 * 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);
}
Example #8
0
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);
}
Example #9
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();
}
Example #12
0
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;
}