tick_t getTime() {
#if YOTTA_CFG_MINAR_TEST_CLOCK_OVERFLOW
    #warning "testing clock overflow"
    return lp_ticker_read() & Time_Mask;
#else
    return lp_ticker_read();
#endif
}
void sleepFromUntil(tick_t now, tick_t until){

#if YOTTA_CFG_MINAR_TEST_CLOCK_OVERFLOW
    /* only lower bits of the timer is passed to this function
     * in order to set the correct sleeping time in the underlying timer,
     * the full time (with the top bits) have to be reconstructed here.*/
    tick_t timer_top_bits = lp_ticker_read() & ~Time_Mask;
    now += timer_top_bits;
    until += timer_top_bits;

    if (until < now) {
        until += Time_Mask;
    }

    const tick_t real_now = timer_top_bits + getTime();

    uint32_t *buf = test::get_sleep_until_buf();
    uint32_t tail = test::get_sleep_until_buf_tail();
    buf[tail] = until;
    test::inc_sleep_until_buf_tail();
#else
    // use real-now for front-most end of do-not-sleep range check
    const tick_t real_now = getTime();
#endif

    if(timeIsInPeriod(now, until, real_now + Minimum_Sleep)){
        // in this case too soon to go to sleep, just return
        return;
    } else {
        const uint32_t next_int = lp_ticker_get_compare_match();

#if YOTTA_CFG_MINAR_STATS
        // update stats
        tick_t now = lp_ticker_read();
        total_active += now - last_wakeup;
        total_sleep += last_wakeup - last_gotosleep;
        last_gotosleep = now;
#endif

        if(timeIsInPeriod(now, until, next_int)){
            lp_ticker_sleep_until(now, until);
        } else {
            // existing compare match is sooner, go to sleep
            sleep();
        }

#if YOTTA_CFG_MINAR_STATS
        // update stats
        last_wakeup = lp_ticker_read();
#endif
    }
}
Ejemplo n.º 3
0
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
    uint32_t now = lp_ticker_read();
    wakeup_tick = timestamp;
    
    TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname));
    
    /**
     * FIXME: Scheduled alarm may go off incorrectly due to wrap around.
     * Conditions in which delta is negative:
     * 1. Wrap around
     * 2. Newly scheduled alarm is behind now
     */ 
    //int delta = (timestamp > now) ? (timestamp - now) : (uint32_t) ((uint64_t) timestamp + 0xFFFFFFFFu - now);
    int delta = (int) (timestamp - now);
    if (delta > 0) {
        cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC;
        lp_ticker_arm_cd();
    }
    else {
        cd_major_minor_clks = cd_minor_clks = 0;
        /**
         * This event was in the past. Set the interrupt as pending, but don't process it here.
         * This prevents a recurive loop under heavy load which can lead to a stack overflow.
         */  
        NVIC_SetPendingIRQ(timer3_modinit.irq_n);
    }
}
Ejemplo n.º 4
0
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
    uint32_t cur_time;
    uint32_t delta;

    cur_time = lp_ticker_read();
    delta = timestamp - cur_time;

    uint16_t interruptat=0;

    if(delta > OVERFLOW_16bit_VALUE) {
        lp_ticker_interrupt_counter= (delta/OVERFLOW_16bit_VALUE) -1;
        lp_ticker_interrupt_offset=delta%OVERFLOW_16bit_VALUE;
        interruptat=OVERFLOW_16bit_VALUE;
    } else {
        lp_ticker_interrupt_counter=0;
        lp_ticker_interrupt_offset=0;
        interruptat=delta;
    }

    NVIC_DisableIRQ(TICKER_COUNTER_IRQn2);

    tc_write_rc(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, (uint32_t)interruptat);

    NVIC_ClearPendingIRQ(TICKER_COUNTER_IRQn2);
    NVIC_SetPriority(TICKER_COUNTER_IRQn2, 0);
    NVIC_EnableIRQ(TICKER_COUNTER_IRQn2);
    tc_enable_interrupt(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, TC_IDR_CPCS );

    tc_start(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);
}
Ejemplo n.º 5
0
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
    uint32_t delta = timestamp - lp_ticker_read();
    wakeup_tick = timestamp;

    TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname));

    cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC;
    lp_ticker_arm_cd();
}
Ejemplo n.º 6
0
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
{
    (void)(obj);

    /* Return value defaults to error. */
    uint32_t result = NRF_ERROR_BUSY;

    /* Convert size to words. */
    uint32_t words = size / sizeof(uint32_t);

    if (NRF_HAL_SD_IS_ENABLED()) {

        /* Setup stop watch for timeout. */
        uint32_t start_us = lp_ticker_read();
        uint32_t now_us = start_us;

        /* Retry if flash is busy until timeout is reached. */
        while (((now_us - start_us) < (words * WORD_WRITE_TIMEOUT_US)) &&
               (result == NRF_ERROR_BUSY)) {

            result = sd_flash_write((uint32_t *) address, (const uint32_t *) data, words);

            /* Read timeout timer. */
            now_us = lp_ticker_read();            
        }

    } else {
        /* We will use *_words function to speed up flashing code. Word means 32bit -> 4B
         * or sizeof(uint32_t).
         */
        nrf_nvmc_write_words(address, (const uint32_t *) data, words);
        result = NRF_SUCCESS;
    }

    /* Convert Nordic error code to mbed HAL error code. */
    return (result == NRF_SUCCESS) ? 0 : -1;
}
Ejemplo n.º 7
0
void lp_ticker_init(void)
{
    if (lp_ticker_inited) {
        return;
    }
    lp_ticker_inited = 1;
    
    counter_major = 0;
    cd_major_minor_ms = 0;
    cd_minor_ms = 0;
    wakeup_tick = TMR_CMP_MAX * MS_PER_TMR2_CLK / MS_PER_TICK;

    // Reset module
    SYS_ResetModule(timer2_modinit.rsetidx);
    SYS_ResetModule(timer3_modinit.rsetidx);
    
    // Select IP clock source
    CLK_SetModuleClock(timer2_modinit.clkidx, timer2_modinit.clksrc, timer2_modinit.clkdiv);
    CLK_SetModuleClock(timer3_modinit.clkidx, timer3_modinit.clksrc, timer3_modinit.clkdiv);
    // Enable IP clock
    CLK_EnableModuleClock(timer2_modinit.clkidx);
    CLK_EnableModuleClock(timer3_modinit.clkidx);

    // Configure clock
    uint32_t clk_timer2 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer2_modinit.modname));
    uint32_t prescale_timer2 = clk_timer2 / TMR2_CLK_FREQ - 1;
    MBED_ASSERT((prescale_timer2 != (uint32_t) -1) && prescale_timer2 <= 127);
    uint32_t cmp_timer2 = MS_PER_TMR2_INT / MS_PER_TMR2_CLK;
    MBED_ASSERT(cmp_timer2 >= TMR_CMP_MIN && cmp_timer2 <= TMR_CMP_MAX);
    // Continuous mode
    ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CTL = TIMER_PERIODIC_MODE | prescale_timer2 | TIMER_CTL_CNTDATEN_Msk;
    ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CMP = cmp_timer2;
    
    // Set vector
    NVIC_SetVector(timer2_modinit.irq_n, (uint32_t) timer2_modinit.var);
    NVIC_SetVector(timer3_modinit.irq_n, (uint32_t) timer3_modinit.var);
    
    NVIC_EnableIRQ(timer2_modinit.irq_n);
    NVIC_EnableIRQ(timer3_modinit.irq_n);
    
    TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer2_modinit.modname));
    TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(timer2_modinit.modname));
    
    // Schedule wakeup to match semantics of lp_ticker_get_compare_match()
    lp_ticker_set_interrupt(lp_ticker_read(), wakeup_tick);
    
    // Start timer
    TIMER_Start((TIMER_T *) NU_MODBASE(timer2_modinit.modname));
}
Ejemplo n.º 8
0
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
{
    (void)(obj);

    /* Return value defaults to error. */
    uint32_t result = NRF_ERROR_BUSY;

    if (NRF_HAL_SD_IS_ENABLED()) {

        /* Convert address to page number. */
        uint32_t page_number = address / NRF_FICR->CODEPAGESIZE;

        /* Setup stop watch for timeout. */
        uint32_t start_us = lp_ticker_read();
        uint32_t now_us = start_us;

        /* Retry if flash is busy until timeout is reached. */
        while (((now_us - start_us) < PAGE_ERASE_TIMEOUT_US) &&
               (result == NRF_ERROR_BUSY)) {

            result = sd_flash_page_erase(page_number);

            /* Read timeout timer. */
            now_us = lp_ticker_read();            
        }

    } else {

        /* Raw API doesn't return error code, assume success. */
        nrf_nvmc_page_erase(address);
        result = NRF_SUCCESS;
    }

    /* Convert Nordic error code to mbed HAL error code. */
    return (result == NRF_SUCCESS) ? 0 : -1;
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
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);
    }
}