// this will set the default inactivity timeout using this event timer and our uid uint32_t e3x_channel_timeout(e3x_channel_t c, e3x_event_t ev, uint32_t timeout) { if(!c) return 0; // un-set any if(ev != c->ev) { // cancel and clearn any previous timer state c->timeout = 0; if(c->ev) e3x_event_set(c->ev,NULL,c->uid,0); c->ev = NULL; lob_free(c->timer); c->timer = NULL; } // no event manager, no timeouts if(!ev) return 0; // no timeout, just return how much time is left if(!timeout) return _time_left(c); // add/update new timeout c->tsince = util_sys_seconds(); // start timer now c->timeout = timeout; c->ev = ev; c->timer = lob_new(); lob_set_uint(c->timer,"c",c->id); lob_set(c->timer, "id", c->uid); lob_set(c->timer, "err", "timeout"); e3x_event_set(c->ev, c->timer, lob_get(c->timer, "id"), timeout*1000); // ms in the future return _time_left(c); }
/** * @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); }