]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
more reliable alarm system on async timer - avoid overflow, which seems to
authoridgay <idgay>
Mon, 26 Mar 2007 21:23:20 +0000 (21:23 +0000)
committeridgay <idgay>
Mon, 26 Mar 2007 21:23:20 +0000 (21:23 +0000)
cause problems
should have less interrupt overhead too

preliminary version - no wrap around support

tos/chips/atm128/timer/Atm128AlarmAsyncC.nc [new file with mode: 0644]
tos/chips/atm128/timer/Atm128AlarmAsyncP.nc [new file with mode: 0644]

diff --git a/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc b/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc
new file mode 100644 (file)
index 0000000..6acee17
--- /dev/null
@@ -0,0 +1,21 @@
+generic configuration Atm128AlarmAsyncC(typedef precision, int divider) {
+  provides {
+    interface Init @atleastonce();
+    interface Alarm<precision, uint32_t>;
+    interface Counter<precision, uint32_t>;
+  }
+}
+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 (file)
index 0000000..5aff0a8
--- /dev/null
@@ -0,0 +1,163 @@
+generic module Atm128AlarmAsyncP(typedef precision, int divider) {
+  provides {
+    interface Init;
+    interface Alarm<precision, uint32_t>;
+    interface Counter<precision, uint32_t>;
+  }
+  uses {
+    interface HplAtm128Timer<uint8_t> as Timer;
+    interface HplAtm128TimerCtrl8 as TimerCtrl;
+    interface HplAtm128Compare<uint8_t> 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() { }
+}