From 90fc469f877319e5a5f8743672ee3638b273f5c6 Mon Sep 17 00:00:00 2001 From: idgay Date: Thu, 29 Mar 2007 21:07:25 +0000 Subject: [PATCH] a nicer version, w/ cleaner HPL access in particular, HPL for timer0 now has less magic in it (this means that users of it have to be more aware of the asynchronous timer access rules, though) --- tos/chips/atm128/timer/Atm128AlarmAsyncC.nc | 2 +- tos/chips/atm128/timer/Atm128AlarmAsyncP.nc | 27 ++++------ tos/chips/atm128/timer/Atm128Timer.h | 2 +- .../atm128/timer/HplAtm128Timer0AsyncC.nc | 6 +-- .../atm128/timer/HplAtm128Timer0AsyncP.nc | 47 ++++++++++------- tos/chips/atm128/timer/HplAtm128TimerAsync.nc | 52 +++++++++++++++++++ 6 files changed, 96 insertions(+), 40 deletions(-) create mode 100644 tos/chips/atm128/timer/HplAtm128TimerAsync.nc diff --git a/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc b/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc index 6acee17c..46f1af11 100644 --- a/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc +++ b/tos/chips/atm128/timer/Atm128AlarmAsyncC.nc @@ -11,11 +11,11 @@ implementation HplAtm128Timer0AsyncC; Init = Atm128AlarmAsyncP; - Init = HplAtm128Timer0AsyncC; Alarm = Atm128AlarmAsyncP; Counter = Atm128AlarmAsyncP; Atm128AlarmAsyncP.Timer -> HplAtm128Timer0AsyncC; Atm128AlarmAsyncP.TimerCtrl -> HplAtm128Timer0AsyncC; Atm128AlarmAsyncP.Compare -> HplAtm128Timer0AsyncC; + Atm128AlarmAsyncP.TimerAsync -> HplAtm128Timer0AsyncC; } diff --git a/tos/chips/atm128/timer/Atm128AlarmAsyncP.nc b/tos/chips/atm128/timer/Atm128AlarmAsyncP.nc index 269c6552..a97c69e3 100644 --- a/tos/chips/atm128/timer/Atm128AlarmAsyncP.nc +++ b/tos/chips/atm128/timer/Atm128AlarmAsyncP.nc @@ -1,6 +1,6 @@ // $Id$ /* - * Copyright (c) 2005-2006 Intel Corporation + * Copyright (c) 2007 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE @@ -17,6 +17,8 @@ * So, instead, this version (inspired by the 1.x code and a remark from * Martin Turon) directly builds a 32-bit alarm and counter on top of timer 0 * and never lets timer 0 overflow. + * + * @author David Gay */ generic module Atm128AlarmAsyncP(typedef precision, int divider) { provides { @@ -28,6 +30,7 @@ generic module Atm128AlarmAsyncP(typedef precision, int divider) { interface HplAtm128Timer as Timer; interface HplAtm128TimerCtrl8 as TimerCtrl; interface HplAtm128Compare as Compare; + interface HplAtm128TimerAsync as TimerAsync; } } implementation @@ -53,12 +56,13 @@ implementation { Atm128TimerControl_t x; - call Compare.start(); + call TimerAsync.setTimer0Asynchronous(); x.flat = 0; x.bits.cs = divider; x.bits.wgm1 = 1; /* We use the clear-on-compare mode */ call TimerCtrl.setControl(x); - call Compare.set(MAXT); + call Compare.set(MAXT); /* setInterrupt needs a valid value here */ + call Compare.start(); setInterrupt(); } return SUCCESS; @@ -66,21 +70,18 @@ implementation /* Set compare register for timer 0 to n. But increment n by 1 if TCNT0 reaches this value before we can set the compare register. - Direct register access used because the HPL doesn't allow us to do this. */ void setOcr0(uint8_t n) { - while (ASSR & 1 << OCR0UB) + while (call TimerAsync.compareBusy()) ; - if (n == TCNT0) + if (n == call Timer.get()) n++; -#if 1 /* Support for overflow. Force interrupt at wrap around value. This does not cause a backwards-in-time value as we do this every time we set OCR0. */ if (base + n + 1 < base) n = -base - 1; -#endif - OCR0 = n; + call Compare.set(n); } void fire() { @@ -149,10 +150,8 @@ implementation /* Compare register fired. Update time knowledge */ base += call Compare.get() + 1; // interrupt is 1ms late setInterrupt(); -#if 1 if (!base) overflow(); -#endif } async command uint32_t Counter.get() { @@ -177,17 +176,12 @@ implementation } async command bool Counter.isOverflowPending() { -#if 0 - return FALSE; -#else atomic return (call TimerCtrl.getInterruptFlag()).bits.ocf0 && !(base + call Compare.get() + 1); -#endif } async command void Counter.clearOverflow() { -#if 1 atomic if (call Counter.isOverflowPending()) { @@ -195,7 +189,6 @@ implementation call Compare.reset(); setInterrupt(); } -#endif } async command void Alarm.start(uint32_t ndt) { diff --git a/tos/chips/atm128/timer/Atm128Timer.h b/tos/chips/atm128/timer/Atm128Timer.h index 9cf0c4e9..fe7b58dd 100644 --- a/tos/chips/atm128/timer/Atm128Timer.h +++ b/tos/chips/atm128/timer/Atm128Timer.h @@ -118,7 +118,7 @@ typedef union uint8_t as0 : 1; //!< Asynchronous Timer/Counter (off=CPU,on=32KHz osc) uint8_t rsvd : 4; //!< Reserved } bits; -} Atm128_ASSR_t; +} Atm128Assr_t; /* Timer/Counter Interrupt Mask Register */ typedef union diff --git a/tos/chips/atm128/timer/HplAtm128Timer0AsyncC.nc b/tos/chips/atm128/timer/HplAtm128Timer0AsyncC.nc index cd610a3c..0838d586 100644 --- a/tos/chips/atm128/timer/HplAtm128Timer0AsyncC.nc +++ b/tos/chips/atm128/timer/HplAtm128Timer0AsyncC.nc @@ -35,6 +35,7 @@ * wires it to McuSleepC for low-power calculations.. * * @author Philip Levis + * @author David Gay */ #include @@ -42,11 +43,11 @@ configuration HplAtm128Timer0AsyncC { provides { - interface Init @atleastonce(); // 8-bit Timers interface HplAtm128Timer as Timer; interface HplAtm128TimerCtrl8 as TimerCtrl; interface HplAtm128Compare as Compare; + interface HplAtm128TimerAsync as TimerAsync; } } implementation @@ -56,9 +57,8 @@ implementation McuSleepC.McuPowerOverride -> HplAtm128Timer0AsyncP; - Init = HplAtm128Timer0AsyncP; Timer = HplAtm128Timer0AsyncP; TimerCtrl = HplAtm128Timer0AsyncP; Compare = HplAtm128Timer0AsyncP; - + TimerAsync = HplAtm128Timer0AsyncP; } diff --git a/tos/chips/atm128/timer/HplAtm128Timer0AsyncP.nc b/tos/chips/atm128/timer/HplAtm128Timer0AsyncP.nc index 4d81a5e1..ce05c756 100644 --- a/tos/chips/atm128/timer/HplAtm128Timer0AsyncP.nc +++ b/tos/chips/atm128/timer/HplAtm128Timer0AsyncP.nc @@ -36,28 +36,21 @@ module HplAtm128Timer0AsyncP { provides { - interface Init @atleastonce(); // 8-bit Timers interface HplAtm128Timer as Timer; interface HplAtm128TimerCtrl8 as TimerCtrl; interface HplAtm128Compare as Compare; interface McuPowerOverride; + interface HplAtm128TimerAsync as TimerAsync; } } implementation { - command error_t Init.init() { - SET_BIT(ASSR, AS0); // set Timer/Counter0 to asynchronous mode - return SUCCESS; - } - //=== Read the current timer value. =================================== async command uint8_t Timer.get() { return TCNT0; } //=== Set/clear the current timer value. ============================== async command void Timer.set(uint8_t t) { - while (ASSR & 1 << TCN0UB) - ; TCNT0 = t; } @@ -81,8 +74,6 @@ implementation //=== Write the control registers. ==================================== async command void TimerCtrl.setControl( Atm128TimerControl_t x ) { - while (ASSR & 1 << TCR0UB) - ; TCCR0 = x.flat; } @@ -142,16 +133,11 @@ implementation //=== Write the compare registers. ==================================== async command void Compare.set(uint8_t t) { - atomic - { - while (ASSR & 1 << OCR0UB) - ; - OCR0 = t; - } + OCR0 = t; } //=== Timer interrupts signals ======================================== - void stabiliseTimer0() { + inline void stabiliseTimer0() { TCCR0 = TCCR0; while (ASSR & 1 << TCR0UB) ; @@ -174,7 +160,7 @@ implementation // need to wait for timer 0 updates propagate before sleeping // (we don't need to worry about reentering sleep mode too early, // as the wake ups from timer0 wait at least one TOSC1 cycle - // anyway - see the stabiliseTimer0 function in HplAtm128Timer0AsyncC) + // anyway - see the stabiliseTimer0 function) while (ASSR & (1 << TCN0UB | 1 << OCR0UB | 1 << TCR0UB)) ; diff = OCR0 - TCNT0; @@ -199,4 +185,29 @@ implementation stabiliseTimer0(); signal Timer.overflow(); } + + // Asynchronous status register support + async command Atm128Assr_t TimerAsync.getAssr() { + return *(Atm128Assr_t *)&ASSR; + } + + async command void TimerAsync.setAssr(Atm128Assr_t x) { + ASSR = x.flat; + } + + async command void TimerAsync.setTimer0Asynchronous() { + ASSR |= 1 << AS0; + } + + async command bool TimerAsync.controlBusy() { + return (ASSR & (1 << TCR0UB)) != 0; + } + + async command bool TimerAsync.compareBusy() { + return (ASSR & (1 << OCR0UB)) != 0; + } + + async command bool TimerAsync.countBusy() { + return (ASSR & (1 << TCN0UB)) != 0; + } } diff --git a/tos/chips/atm128/timer/HplAtm128TimerAsync.nc b/tos/chips/atm128/timer/HplAtm128TimerAsync.nc new file mode 100644 index 00000000..0965e98c --- /dev/null +++ b/tos/chips/atm128/timer/HplAtm128TimerAsync.nc @@ -0,0 +1,52 @@ +// $Id$ +/* + * Copyright (c) 2007 Intel Corporation + * All rights reserved. + * + * This file is distributed under the terms in the attached INTEL-LICENSE + * file. If you do not find these files, copies can be found by writing to + * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, + * 94704. Attention: Intel License Inquiry. + */ +/** + * + * @author David Gay + */ +interface HplAtm128TimerAsync +{ + /** + * Read timer0 asynchronous status register (ASSR) + * @return Current value of ASSR + */ + async command Atm128Assr_t getAssr(); + + /** + * Set timer0 asynchronous status register (ASSR) + * @param x New value for ASSR + */ + async command void setAssr(Atm128Assr_t x); + + /** + * Turn on timer 0 asynchronous mode + */ + async command void setTimer0Asynchronous(); + + /** + * Check if control register TCCR0 is busy (should not be updated if true) + * @return TRUE if TCCR0 is busy, FALSE otherwise (can be updated) + */ + async command bool controlBusy(); + + /** + * Check if compare register OCR0 is busy (should not be updated if true) + * @return TRUE if OCR0 is busy, FALSE otherwise (can be updated) + */ + async command bool compareBusy(); + + /** + * Check if current timer value (TCNT0) is busy (should not be updated if true) + * @return TRUE if TCNT0 is busy, FALSE otherwise (can be updated) + */ + async command bool countBusy(); + +} -- 2.39.2