diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2017-08-06 19:21:16 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2017-08-08 00:27:28 -0400 |
commit | 78982ebb51b0895b3178a85edcb1543939dc13b4 (patch) | |
tree | a1961fb294104a81e37ff3af93e643fdd35e5f30 /src/avr/timer.c | |
parent | 6a63c27542fc7b432ed438ce1d62243b5aebc3da (diff) | |
download | kutter-78982ebb51b0895b3178a85edcb1543939dc13b4.tar.gz kutter-78982ebb51b0895b3178a85edcb1543939dc13b4.tar.xz kutter-78982ebb51b0895b3178a85edcb1543939dc13b4.zip |
avr: Implement internal avr specific timer to handle 16bit overflows
Don't rely on the generic scheduler code to always have a timer no
more than 1ms in the future. Instead, create an avr specific timer
that will be called every 0x8000 ticks. This simplifies the generic
code and it reduces the amount of code that needs to be run every
millisecond.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/avr/timer.c')
-rw-r--r-- | src/avr/timer.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/src/avr/timer.c b/src/avr/timer.c index a87ae206..1b281ec9 100644 --- a/src/avr/timer.c +++ b/src/avr/timer.c @@ -85,6 +85,15 @@ timer_kick(void) TIFR1 = 1<<OCF1A; } +static struct timer wrap_timer; + +void +timer_reset(void) +{ + sched_add_timer(&wrap_timer); +} +DECL_SHUTDOWN(timer_reset); + void timer_init(void) { @@ -96,6 +105,7 @@ timer_init(void) irqstatus_t flag = irq_save(); timer_kick(); timer_repeat_set(timer_get() + 50); + timer_reset(); TIFR1 = 1<<TOV1; // enable interrupt TIMSK1 = 1<<OCIE1A; @@ -115,25 +125,33 @@ uint32_t timer_read_time(void) { irqstatus_t flag = irq_save(); - union u32_u calc; - calc.val = timer_get(); + union u32_u calc = { .val = timer_get() }; calc.hi = timer_high; - if (TIFR1 & (1<<TOV1) && calc.lo < 0x8000) - calc.hi++; + if (unlikely(TIFR1 & (1<<TOV1))) { + irq_restore(flag); + if (calc.b1 < 0xff) + calc.hi++; + return calc.val; + } irq_restore(flag); return calc.val; } -// Called by main code once every millisecond. (IRQs disabled.) -void -timer_periodic(void) +// Timer that runs every ~2ms - allows 16bit comparison optimizations +static uint_fast8_t +timer_event(struct timer *t) { if (TIFR1 & (1<<TOV1)) { // Hardware timer has overflowed - update overflow counter TIFR1 = 1<<TOV1; timer_high++; } + wrap_timer.waketime += 0x8000; + return SF_RESCHEDULE; } +static struct timer wrap_timer = { + .func = timer_event, +}; #define TIMER_IDLE_REPEAT_TICKS 8000 #define TIMER_REPEAT_TICKS 3000 |