Example #1
0
int _xtimer_set_absolute(xtimer_t *timer, uint32_t target)
{
    uint32_t now = xtimer_now();
    int res = 0;

    DEBUG("timer_set_absolute(): now=%" PRIu32 " target=%" PRIu32 "\n", now, target);

    timer->next = NULL;
    if ((target >= now) && ((target - XTIMER_BACKOFF) < now)) {
        /* backoff */
        xtimer_spin_until(target + XTIMER_BACKOFF);
        _shoot(timer);
        return 0;
    }

    unsigned state = irq_disable();
    if (_is_set(timer)) {
        _remove(timer);
    }

    timer->target = target;
    timer->long_target = _long_cnt;
    if (target < now) {
        timer->long_target++;
    }

    if ( (timer->long_target > _long_cnt) || !_this_high_period(target) ) {
        DEBUG("xtimer_set_absolute(): the timer doesn't fit into the low-level timer's mask.\n");
        _add_timer_to_long_list(&long_list_head, timer);
    }
    else {
        if (_xtimer_lltimer_mask(now) >= target) {
            DEBUG("xtimer_set_absolute(): the timer will expire in the next timer period\n");
            _add_timer_to_list(&overflow_list_head, timer);
        }
        else {
            DEBUG("timer_set_absolute(): timer will expire in this timer period.\n");
            _add_timer_to_list(&timer_list_head, timer);

            if (timer_list_head == timer) {
                DEBUG("timer_set_absolute(): timer is new list head. updating lltimer.\n");
                _lltimer_set(target - XTIMER_OVERHEAD);
            }
        }
    }

    irq_restore(state);

    return res;
}
Example #2
0
void xtimer_set(xtimer_t *timer, uint32_t offset)
{
    DEBUG("timer_set(): offset=%" PRIu32 " now=%" PRIu32 " (%" PRIu32 ")\n", offset, xtimer_now(), _xtimer_now());
    if (!timer->callback) {
        DEBUG("timer_set(): timer has no callback.\n");
        return;
    }

    xtimer_remove(timer);
    uint32_t target = xtimer_now() + offset;

    if (offset < XTIMER_BACKOFF) {
        xtimer_spin(offset);
        _shoot(timer);
    }
    else {
        _xtimer_set_absolute(timer, target);
    }
}
Example #3
0
/**
 * @brief main xtimer callback function
 */
static void _timer_callback(void)
{
    uint32_t next_target;
    uint32_t reference;

    _in_handler = 1;

    DEBUG("_timer_callback() now=%" PRIu32 " (%" PRIu32 ")pleft=%" PRIu32 "\n", xtimer_now(),
            _mask(xtimer_now()), _mask(0xffffffff-xtimer_now()));

    if (!timer_list_head) {
        DEBUG("_timer_callback(): tick\n");
        /* there's no timer for this timer period,
         * so this was a timer overflow callback.
         *
         * In this case, we advance to the next timer period.
         */
        _next_period();

        reference = 0;

        /* make sure the timer counter also arrived
         * in the next timer period */
        while (_xtimer_now() == _mask(0xFFFFFFFF));
    }
    else {
        /* we ended up in _timer_callback and there is
         * a timer waiting.
         */
        /* set our period reference to that timer's target time. */
        reference = _mask(timer_list_head->target);
    }

overflow:
    /* check if next timers are close to expiring */
    while (timer_list_head && (_time_left(_mask(timer_list_head->target), reference) < XTIMER_ISR_BACKOFF)) {
        /* make sure we don't fire too early */
        while (_time_left(_mask(timer_list_head->target), reference));

        /* pick first timer in list */
        xtimer_t *timer = timer_list_head;

        /* advance list */
        timer_list_head = timer->next;

        /* make sure timer is recognized as being already fired */
        timer->target = 0;
        timer->long_target = 0;

        /* fire timer */
        _shoot(timer);
    }

    /* possibly executing all callbacks took enough
     * time to overflow.  In that case we advance to
     * next timer period and check again for expired
     * timers.*/
    if (reference > _xtimer_now()) {
        DEBUG("_timer_callback: overflowed while executing callbacks. %i\n", timer_list_head != 0);
        _next_period();
        reference = 0;
        goto overflow;
    }

    if (timer_list_head) {
        /* schedule callback on next timer target time */
        next_target = timer_list_head->target - XTIMER_OVERHEAD;
    }
    else {
        /* there's no timer planned for this timer period */
        /* schedule callback on next overflow */
        next_target = _mask(0xFFFFFFFF);
        uint32_t now = _xtimer_now();

        /* check for overflow again */
        if (now < reference) {
            _next_period();
            reference = 0;
            goto overflow;
        }
        else {
            /* check if the end of this period is very soon */
            if (_mask(now + XTIMER_ISR_BACKOFF) < now) {
                /* spin until next period, then advance */
                while (_xtimer_now() > now);
                _next_period();
                reference = 0;
                goto overflow;
            }
        }
    }

    _in_handler = 0;

    /* set low level timer */
    _lltimer_set(next_target);
}