From: idgay Date: Mon, 26 Mar 2007 21:23:20 +0000 (+0000) Subject: more reliable alarm system on async timer - avoid overflow, which seems to X-Git-Tag: tinyos/2.0.1~120 X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=commitdiff_plain;h=4615cc283b6f1c61496187f07e1ff36ca1cdb77a;p=tinyos-2.x.git more reliable alarm system on async timer - avoid overflow, which seems to cause problems should have less interrupt overhead too preliminary version - no wrap around support --- diff --git a/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc b/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc new file mode 100644 index 00000000..6acee17c --- /dev/null +++ b/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc @@ -0,0 +1,21 @@ +generic configuration Atm128AlarmAsyncC(typedef precision, int divider) { + provides { + interface Init @atleastonce(); + interface Alarm; + interface Counter; + } +} +implementation +{ + components new Atm128AlarmAsyncP(precision, divider), + HplAtm128Timer0AsyncC; + + Init = Atm128AlarmAsyncP; + Init = HplAtm128Timer0AsyncC; + Alarm = Atm128AlarmAsyncP; + Counter = Atm128AlarmAsyncP; + + Atm128AlarmAsyncP.Timer -> HplAtm128Timer0AsyncC; + Atm128AlarmAsyncP.TimerCtrl -> HplAtm128Timer0AsyncC; + Atm128AlarmAsyncP.Compare -> HplAtm128Timer0AsyncC; +} diff --git a/tos/chips/atm128/timer/Atm128AlarmAsyncP.nc b/tos/chips/atm128/timer/Atm128AlarmAsyncP.nc new file mode 100644 index 00000000..5aff0a88 --- /dev/null +++ b/tos/chips/atm128/timer/Atm128AlarmAsyncP.nc @@ -0,0 +1,163 @@ +generic module Atm128AlarmAsyncP(typedef precision, int divider) { + provides { + interface Init; + interface Alarm; + interface Counter; + } + uses { + interface HplAtm128Timer as Timer; + interface HplAtm128TimerCtrl8 as TimerCtrl; + interface HplAtm128Compare as Compare; + } +} +implementation +{ + uint8_t set; + uint32_t t0, dt; + uint32_t base, lastNow; + + void oopsT0() { + } + + void oopsNow() { + } + + enum { + MINDT = 10, + MAXT = 230 + }; + + void setOcr0(uint8_t n) { + while (ASSR & 1 << OCR0UB) + ; + if (n == TCNT0) + n++; + OCR0 = n; + } + + void setInterrupt() { + bool fired = FALSE; + + atomic + { + uint8_t interrupt_in = 1 + call Compare.get() - call Timer.get(); + uint8_t newOcr0; + + if (interrupt_in < MINDT || (call TimerCtrl.getInterruptFlag()).bits.ocf0) + return; // wait for next interrupt + if (!set) + newOcr0 = MAXT; + else + { + uint32_t now = call Counter.get(); + if (now < t0) + { + oopsT0(); + t0 = now; + } + if (now - t0 >= dt) + { + set = FALSE; + fired = TRUE; + newOcr0 = MAXT; + } + else + { + uint32_t alarm_in = (t0 + dt) - base; + + if (alarm_in > MAXT) + newOcr0 = MAXT; + else if (alarm_in < MINDT) + newOcr0 = MINDT; + else + newOcr0 = alarm_in; + } + } + newOcr0--; // interrupt is 1ms late + setOcr0(newOcr0); + } + if (fired) + signal Alarm.fired(); + } + + async event void Compare.fired() { + base += call Compare.get() + 1; + setInterrupt(); + } + + command error_t Init.init() { + atomic + { + Atm128TimerControl_t x; + + call Compare.start(); + x.flat = 0; + x.bits.cs = divider; + x.bits.wgm1 = 1; + call TimerCtrl.setControl(x); + call Compare.set(MAXT); + setInterrupt(); + } + return SUCCESS; + } + + async command uint32_t Counter.get() { + uint32_t now; + + atomic + { + uint8_t now8 = call Timer.get(); + + if ((call TimerCtrl.getInterruptFlag()).bits.ocf0) + now = base + call Counter.get() + call Timer.get(); + else + now = base + now8; + + if (now < lastNow) + { + oopsNow(); + now = lastNow; + } + lastNow = now; + } + return now; + } + + async command bool Counter.isOverflowPending() { + return FALSE; + } + + async command void Counter.clearOverflow() { } + + async command void Alarm.start(uint32_t ndt) { + call Alarm.startAt(call Counter.get(), ndt); + } + + async command void Alarm.stop() { + atomic set = FALSE; + } + + async command bool Alarm.isRunning() { + atomic return set; + } + + async command void Alarm.startAt(uint32_t nt0, uint32_t ndt) { + atomic + { + set = TRUE; + t0 = nt0; + dt = ndt; + } + setInterrupt(); + } + + async command uint32_t Alarm.getNow() { + return call Counter.get(); + } + + async command uint32_t Alarm.getAlarm() { + atomic return t0 + dt; + } + + async event void Timer.overflow() { } +}