avr: Integrate timer_try_set_next() into the irq handler
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
6d05dd07f5
commit
65be6d5146
|
@ -135,22 +135,23 @@ timer_periodic(void)
|
|||
#define TIMER_MIN_TRY_TICKS 60 // 40 ticks to exit irq; 20 ticks of progress
|
||||
#define TIMER_DEFER_REPEAT_TICKS 200
|
||||
|
||||
// Set the next timer wake time (in absolute clock ticks) or return 1
|
||||
// if the next timer is too close to schedule. Caller must disable
|
||||
// irqs.
|
||||
static uint8_t
|
||||
timer_try_set_next(unsigned int target)
|
||||
// Hardware timer IRQ handler - dispatch software timers
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
uint16_t next = target;
|
||||
uint16_t next;
|
||||
for (;;) {
|
||||
// Run the next software timer
|
||||
next = sched_timer_dispatch();
|
||||
|
||||
int16_t diff = next - timer_get();
|
||||
if (likely(diff < 0)) {
|
||||
// Another timer is pending - briefly allow irqs to fire
|
||||
irq_enable();
|
||||
if (unlikely(TIFR1 & (1<<OCF1B)))
|
||||
// Too many repeat timers - must exit irq handler
|
||||
goto force_pause;
|
||||
goto force_defer;
|
||||
irq_disable();
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (likely(diff > TIMER_MIN_TRY_TICKS))
|
||||
|
@ -158,17 +159,16 @@ timer_try_set_next(unsigned int target)
|
|||
goto done;
|
||||
|
||||
// Next timer in very near future - wait for it to be ready
|
||||
for (;;) {
|
||||
do {
|
||||
irq_enable();
|
||||
if (unlikely(TIFR1 & (1<<OCF1B)))
|
||||
break;
|
||||
goto force_defer;
|
||||
irq_disable();
|
||||
diff = next - timer_get();
|
||||
if (diff < 0)
|
||||
return 0;
|
||||
} while (diff >= 0);
|
||||
}
|
||||
|
||||
force_pause:
|
||||
force_defer:
|
||||
// Too many repeat timers - force a pause so tasks aren't starved
|
||||
irq_disable();
|
||||
uint16_t now = timer_get();
|
||||
|
@ -179,24 +179,11 @@ force_pause:
|
|||
|
||||
done:
|
||||
timer_set(next);
|
||||
return 1;
|
||||
return;
|
||||
fail:
|
||||
shutdown("Rescheduled timer in the past");
|
||||
}
|
||||
|
||||
// Harware OCR1A interrupt handler
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
for (;;) {
|
||||
uint16_t next_waketime = sched_timer_dispatch();
|
||||
|
||||
// Schedule next timer event (or run next timer if it's ready)
|
||||
uint8_t res = timer_try_set_next(next_waketime);
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Periodic background task that temporarily boosts priority of
|
||||
// timers. This helps prioritize timers when tasks are idling.
|
||||
static void
|
||||
|
|
Loading…
Reference in New Issue