ptr_t slot_remove(ptr_t p, ptr_t c) { bool isFirst = p == MAX_TIMERS; bool isLast = c == slot[c].next; bool isOnly = isFirst && isLast; if (isOnly) { first = MAX_TIMERS; } else if (isFirst) { first = slot[c].next; } else if (isLast) { slot[p].next = p; } else { slot[p].next = slot[c].next; } if (isOnly) { timer_unset(); } else if (isFirst) { timer_set(slot[first].cmp); } slot[c].next = MAX_TIMERS; return isFirst ? first : slot[p].next; }
interrupt(TIMERA0_VECTOR) __attribute__((naked)) timer_isr_ccr0(void) { __enter_isr(); if (overflow_interrupt[0] == timer_round) { timer_unset(0); int_handler(0); } __exit_isr(); }
interrupt(TIMERA1_VECTOR) __attribute__((naked)) timer_isr(void) { __enter_isr(); short taiv_reg = TAIV; if (taiv_reg == 0x0A) { /* TAIV = 0x0A means overflow */ DEBUG("Overflow\n"); timer_round++; } else { short timer = taiv_reg >> 1; /* check which CCR has been hit and if the overflow counter for this timer has been reached (or exceeded); there is indeed a race condition where an hwtimer due to fire in the next round can be set after the timer's counter has overflowed but *before* timer_round incrementation has occured (when interrupts are disabled for any reason), thus effectively setting the timer one round in the past! */ int16_t round_delta = overflow_interrupt[timer] - timer_round; /* in order to correctly handle timer_round overflow, we must fire the timer when, for example, timer_round == 0 and overflow_interrupt[timer] == 65535; to that end, we compute the difference between the two on a 16-bit signed integer: any difference >= +32768 will thus overload to a negative number; we should then correctly fire "overdue" timers whenever the case */ if (round_delta <= 0) { timer_unset(timer); int_handler(timer); } } __exit_isr(); }
void timer_int() { slot_t c = slot[first]; slot[first].next = MAX_TIMERS; #ifndef NDEBUG timer_t now = timer_now(); if (in_range(timer_tracked_get(), c.cmp, now)) { DBG static timer_t timer_late_max; timer_late_max = MAX(timer_late_max, now - c.cmp); } #endif if (c.next == first) { first = MAX_TIMERS; timer_unset(); } else { timer_tracked = c.cmp; first = c.next; timer_set(slot[first].cmp); } sch_add(c.func); }
void hwtimer_arch_unset(short timer) { timer_unset(timer); }