}
async command void Alarm.startAt( timer_size t0, timer_size dt ) {
- timer_size now;
- timer_size expires, guardedExpires;
-
- now = call HplAtm128Timer.get();
- dbg("Atm128AlarmC", " starting timer at %llu with dt %llu\n", (uint64_t)t0, (uint64_t) dt);
- /* We require dt >= mindt to avoid setting an interrupt which is in
- the past by the time we actually set it. mindt should always be
- at least 2, because you cannot set an interrupt one cycle in the
- future. It should be more than 2 if the timer's clock rate is
- very high (e.g., equal to the processor clock). */
- if (dt < mindt)
- dt = mindt;
-
- expires = t0 + dt;
-
- guardedExpires = expires - mindt;
-
- /* t0 is assumed to be in the past. If it's numerically greater than
- now, that just represents a time one wrap-around ago. This requires
- handling the t0 <= now and t0 > now cases separately.
-
- Note also that casting compared quantities to timer_size produces
- predictable comparisons (the C integer promotion rules would make it
- hard to write correct code for the possible timer_size size's) */
- /* Note: all HplAtm128Compare.set values have one subtracted, because
- the comparisons are continuous, but the actual interrupt is signalled
- at the next timer clock cycle. */
- if (t0 <= now)
- {
- /* if it's in the past or the near future, fire now (i.e., test
- guardedExpires <= now in wrap-around arithmetic). */
- if (guardedExpires >= t0 && // if it wraps, it's > now
- guardedExpires <= now)
- call HplAtm128Compare.set(call HplAtm128Timer.get() + mindt - 1);
- else
- call HplAtm128Compare.set(expires - 1);
- }
- else
+ /* We don't set an interrupt before "now" + mindt to avoid setting an
+ interrupt which is in the past by the time we actually set
+ it. mindt should always be at least 2, because you cannot set an
+ interrupt one cycle in the future. mindt should also be large enough
+ to cover the execution time of this function. */
+ atomic
{
- /* again, guardedExpires <= now in wrap-around arithmetic */
- if (guardedExpires >= t0 || // didn't wrap so < now
- guardedExpires <= now)
- call HplAtm128Compare.set(call HplAtm128Timer.get() + mindt - 1);
+ timer_size now, expires, minExpires, guardedExpires;
+
+ dbg("Atm128AlarmC", " starting timer at %llu with dt %llu\n", (uint64_t)t0, (uint64_t) dt);
+
+ if (dt < mindt) /* guardedExpires should not be less than t0 */
+ dt = mindt;
+ expires = t0 + dt;
+ guardedExpires = expires - mindt;
+ now = call HplAtm128Timer.get();
+ minExpires = now + mindt;
+
+ /* t0 is assumed to be in the past. If it's numerically greater
+ than now, that just represents a time one wrap-around
+ ago. This requires handling the t0 <= now and t0 > now cases
+ separately. */
+ if (t0 <= now)
+ {
+ /* if it's in the past or the near future, fire now (i.e., test
+ guardedExpires <= now in wrap-around arithmetic). */
+ if (guardedExpires >= t0 && // if it wraps, it's > now
+ guardedExpires <= now)
+ expires = minExpires;
+ }
else
- call HplAtm128Compare.set(expires - 1);
+ {
+ /* again, guardedExpires <= now in wrap-around arithmetic */
+ if (guardedExpires >= t0 || // didn't wrap so < now
+ guardedExpires <= now)
+ expires = minExpires;
+ }
+
+ /* Note: all HplAtm128Compare.set values have one subtracted,
+ because the comparisons are continuous, but the actual
+ interrupt is signalled at the next timer clock cycle. */
+ call HplAtm128Compare.set(expires - 1);
+ call HplAtm128Compare.reset();
+ call HplAtm128Compare.start();
}
- call HplAtm128Compare.reset();
- call HplAtm128Compare.start();
}
async event void HplAtm128Compare.fired() {
call HplAtm128Compare.stop();
dbg("Atm128AlarmC", " Compare fired, signal alarm above.\n");
+ __nesc_enable_interrupt();
signal Alarm.fired();
}