[Tinyos-host-mote-wg] [Tinyos-2.0wg] TEP 102 overhauled
Cory Sharp
cory.sharp at gmail.com
Wed May 18 04:42:08 PDT 2005
I've overhauled TEP 102 Timers and committed it to CVS, attached here
for convenience. Major changes:
* The TEP now describes in detail for the timer subsystem: 1) all
interfaces, 2) all platform independent components, and best of all 3)
all required platform dependent components.
* No more XXX and XXXBase interface pairs. There is now one Timer
interface instead of four, it is sync and fixed 32-bit. There is now
one Alarm interface instead of two, it is async and parameterized by
width.
* Added the BusyWait interface and BusyWaitCounterC platform
independent component for busy waiting on a Counter.
* Added a LocalTime interface. It's similar to Counter but fixed at
32-bits and with no overflow mechanisms exposed.
* Removed the StopWatch interface. Code can still be easily timed
with a Counter or LocalTime. Let me know if we want StopWatch back
in.
* Renamed MultiplexTimerM to VirtualizeTimerC, because "multiplex" was
just wrong.
* Most all *M.nc components have been renamed to *C.nc, irregardless
if they are configurations or modules. This is the better naming
convention for abstracting away implementation files without causing
*C/*M file bloat.
There are more details for the folks implementing the timers for
platforms (Martin, Phil B). See the TEP for more details, let me know
if anything needs fixing.
Cory
-------------- next part --------------
============================
Timers
============================
:TEP: 102
:Group: Core Working Group
:Type: Documentary
:Status: Draft
:TinyOS-Version: 2.x
:Author: Cory Sharp
:Draft-Created: 22-Sep-2004
:Draft-Version: $Revision: 1.7 $
:Draft-Modified: $Date: 2005/05/18 11:16:28 $
:Draft-Discuss: TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu>
.. Note::
This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements. Distribution
of this memo is unlimited. This memo is in full compliance with
TEP 1.
Abstract
====================================================================
This TEP proposes a Timer design that supports common timing
requirements both in precision and width across common hardware
configurations. This TEP focuses on aligning the Timer abstraction
with the three-layer Hardware Abstraction Architecture (HAA).
Introduction
====================================================================
This TEP proposes all timer interfaces be parameterized by
precision. All precisions are in "binary" units with respect to one
second. Precision is expressed an empty type
* TMilli
* T32khz
* TMicro
This TEP proposes these timer interfaces:
* Alarm
* BusyWait
* Counter
* LocalTime
* Timer
The LocalTime and Timer interfaces are used primarily by user
applications and use a fixed width of 32-bits.
The Alarm, BusyWait, and Counter interfaces are used by the TinyOS
timer system and advanced user components. They are parameterized
by precision and size. The most common sizes are 16-bit and 32-bit.
Some platforms will likely use 8-bit for internal implementation,
and it is expected that some future platforms will use 64-bit.
A number of platform independent generic components are provided by
the TinyOS timer system:
* AlarmToTimerC
* BusyWaitCounterC
* CounterToLocalTimeC
* TransformAlarmC
* TransformCounterC
* VirtualizeTimerC
A number of platform dependent components MUST exist:
* Alarm32khzC
* AlarmMilliC
* BusyWait32khzC
* BusyWaitMicroC
* Counter32khzC
* CounterMilliC
* TimerMilliC
It is expected that a platform need only implement in code concise
Alarm and Counter components expressed in native precision and
native width. The platform independent components may use the native
Alarm's and Counter's to implement the platform dependent timer
components using only configurations.
Precision and Width
====================================================================
Two fundamental properties of timers are *precision* and *width*.
Examples of precision are millisecond, a cycle of a 32kHz clock, and
microseconds. All precisions are in "binary" units with respect to
one second. That is, one second contains 1024 binary milliseconds,
32768 32kHz ticks, or 1048576 microseconds. This TEP emphasizes
millisecond and 32kHz tick precisions while reasonably accommodating
other precisions.
Examples of widths are 8-bit, 16-bit, 32-bit, and 64-bit. The width
for timer interfaces and components SHOULD be 32-bits. That is, for
lack of a good reason, timer interfaces should expose a 32-bit
interface. In a number of circumstances there are good reasons not
to expose a 32-bit interface. This TEP emphasizes 32-bit widths
while reasonably accommodating other widths.
This TEP parameterizes all interfaces by precision and some
interfaces by width. This intentionally makes similar timer
interfaces with different precision or width mutually incompatible.
It also allows user code to clearly express and understand the
precision and width for a given timer interface.
Precision is expressed as an empty type -- TMilli, T32khz, and
TMicro -- written in the standard Timer.h header like this::
typedef struct { } TMilli;
typedef struct { } T32khz;
typedef struct { } TMicro;
Note that the precision names are expressed as either frequency or
period, whichever is convenient.
Interfaces
====================================================================
This TEP proposes these timer interfaces::
interface Alarm< precision_tag, size_type >
interface BusyWait< precision_tag, size_type >
interface Counter< precision_tag, size_type >
interface LocalTime< precision_tag >
interface Timer< precision_tag >
The LocalTime and Timer interfaces are used primarily by user
applications and use a fixed width of 32-bits. The Alarm, BusyWait,
and Counter interfaces are used by the TinyOS timer system and
advanced user components. by precision and size.
Alarm
--------------------------------------------------------------------
All commands and events of the Alarm interface are asynchronous (or
in "interrupt context"). The Alarm interface provides a set of
"basic" commands for common usage and provides a set of "extended"
commands for advanced use. ::
interface Alarm<precision_tag,size_type>
{
// basic interface
async command void startNow( size_type dt );
async command void stop();
async event void fired();
// extended interface
async command bool isRunning();
async command void start( size_type t0, size_type dt );
async command size_type getNow();
async command size_type getAlarm();
}
startNow(dt)
cancel any previously running alarm and set to fire in dt time units
from the time of invocation. The alarm will only fire once then
stop.
stop()
cancel any previously running alarm.
fired()
signals that the alarm has occurred.
isRunning()
return TRUE if the alarm has been started and has not been cancelled
or has not yet fired. FALSE is returned otherwise.
start(t0,dt)
cancel any previously running alarm and set to fire at time t1 =
t0+dt. This form allows a delay to be anchored to some time t0
taken before the invocation of start. This is also the form used
internally in the timer subsystem to allow the use of the full width
of an alarm while being able to detect if the alarm time for a short
alarm prematurely elapsed.
getNow()
return the current time in the precision and width of the alarm.
getAlarm()
return the time the currently running alarm will fire or the time
that the previously running alarm was set to fire.
BusyWait
--------------------------------------------------------------------
The BusyWait interface replaces the TOSH_uwait macro from TinyOS
1.x. ::
interface BusyWait<precision_tag,size_type>
{
async command void wait( size_type dt );
}
wait(dt)
block for no less than the specified amount of time.
Counter
--------------------------------------------------------------------
The Counter interface returns the current time and provides commands
and an event for managing overflow conditions. These overflow
commands and events are necessary for properly deriving larger width
Counters from smaller widths. ::
interface Counter<precision_tag,size_type>
{
async command size_type get();
async command bool isOverflowPending();
async command void clearOverflow();
async event void overflow();
}
get()
return the current time.
isOverflowPending()
return TRUE if an overflow interrupt will occur after the outermost
atomic block is exits. FALSE otherwise.
clearOverflow()
cancel the pending overflow interrupt.
overflow()
signals that an overflow in the current time. That is, the current
time has wrapped around from its maximum value to zero.
LocalTime
--------------------------------------------------------------------
The LocalTime interface exposes a 32-bit counter without overflow
utilities. This is primarily for application code that does not
care about overflow conditions. ::
interface LocalTime<precision_tag>
{
async command uint32_t get();
}
get()
return the current time.
Timer
--------------------------------------------------------------------
All commands and events of the Timer interface are synchronous (or
in "task context"). The Timer interface provides a set of "basic"
commands for common usage and provides a set of "extended" commands
for advanced use. The Timer interface allows for periodic events.
::
interface Timer<precision_tag>
{
// basic interface
command void startPeriodicNow( uint32_t dt );
command void startOneShotNow( uint32_t dt );
command void stop();
event void fired( uint32_t when, uint32_t numMissed );
// extended interface
command bool isRunning();
command bool isOneShot();
command void startPeriodic( uint32_t t0, uint32_t dt );
command void startOneShot( uint32_t t0, uint32_t dt );
command uint32_t getNow();
command uint32_t gett0();
command uint32_t getdt();
}
startPeriodicNow(dt)
cancel any previously running timer and set to fire in dt time units
from the time of invocation. The timer will fire periodically every
dt time units until stopped.
startOneShotNow(dt)
cancel any previously running timer and set to fire in dt time units
from the time of invocation. The timer will only fire once then
stop.
stop()
cancel any previously running timer.
fired(when,numMissed)
signals that the timer has occurred. The when parameter indicates
when the timer should have fired. Because the timers fire in
synchronous context, some time may have elapsed from "when" until
now. For periodic timers, numMissed indicates how many events were
outright missed and when indicates the time of the most recent
event. For one-shot timers, numMissed is always 0 and when is the
time of the event.
isRunning()
return TRUE if the timer has been started and has not been cancelled
and has not fired for the case of one-shot timers. One a periodic
timer is started, isRunning will return TRUE until it is cancelled.
isOneShot()
return TRUE if the timer is a one-shot timer. Return FALSE
otherwise if the timer is a periodic timer.
startPeriodic(t0,dt)
cancel any previously running timer and set to fire at time t1 =
t0+dt. The timer will fire periodically every dt time units until
stopped.
startOneShot(t0,dt)
cancel any previously running timer and set to fire at time t1 =
t0+dt. The timer will fire once then stop.
getNow()
return the current time in the precision and width of the timer.
gett0()
return the time anchor for the previously started timer or the time
of the previous event for periodic timers.
getdt()
return the delay or period for the previously started timer.
Platform independent components
====================================================================
A number of platform independent generic components are provided by
the TinyOS timer system:
* AlarmToTimerC
* BusyWaitCounterC
* CounterToLocalTimeC
* TransformAlarmC
* TransformCounterC
* VirtualizeTimerC
The platform independent components are used to help derive the
platform dependent components discussed in the next section.
AlarmToTimerC
--------------------------------------------------------------------
AlarmToTimerC converts a 32-bit Alarm to a Timer. ::
generic component AlarmToTimerC( typedef precision_tag )
{
provides interface Timer<precision_tag>;
uses interface Alarm<precision_tag,uint32_t>;
}
BusyWaitCounterC
--------------------------------------------------------------------
BusyWaitCounterC uses a Counter to block until a specified amount of
time elapses. ::
generic component BusyWaitC( typedef precision_tag,
typedef size_type @integer() )
{
provides interface BusyWait<precision_tag,size_type>;
uses interface Counter<precision_tag,size_type>;
}
CounterToLocalTimeC
--------------------------------------------------------------------
CounterToLocalTimeC converts from a 32-bit Counter to LocalTime. ::
generic component CounterToLocalTimeC( precision_tag )
{
provides interface LocalTime<precision_tag>;
uses interface Counter<precision_tag,uint32_t>;
}
TransformAlarmC
--------------------------------------------------------------------
TransformAlarmC decreases precision and/or widens an Alarm. An
already widened Counter component is used to help. ::
generic component TransformAlarmC(
typedef to_precision_tag,
typedef to_size_type @integer(),
typedef from_precision_tag,
typedef from_size_type @integer(),
uint8_t bit_shift_right )
{
provides interface Alarm<to_precision_tag,to_size_type> as Alarm;
uses interface Counter<to_precision_tag,to_size_type> as Counter;
uses interface Alarm<from_precision_tag,from_size_type> as AlarmFrom;
}
to_precision_tag and to_size_type describe the final precision and
final width for the provided Alarm. from_precision_tag and
from_size_type describe the precision and width for the source
AlarmFrom. bit_shift_right describes the bit-shift necessary to
convert from the used precision to the provided precision.
For instance to convert from an Alarm<T32khz,uint16_t> to an
Alarm<TMilli,uint32_t>, the following TransformAlarmC would be
created::
new TransformAlarmC( TMilli, uint32_t, T32khz, uint16_t, 5 )
TransformCounterC
--------------------------------------------------------------------
TransformCounterC decreases precision and/or widens a Counter. ::
generic component TransformCounterC(
typedef to_precision_tag,
typedef to_size_type @integer(),
typedef from_precision_tag,
typedef from_size_type @integer(),
uint8_t bit_shift_right,
typedef upper_count_type @integer() )
{
provides interface Counter<to_precision_tag,to_size_type> as Counter;
uses interface Counter<from_precision_tag,from_size_type> as CounterFrom;
}
to_precision_tag and to_size_type describe the final precision and
final width for the provided Counter. from_precision_tag and
from_size_type describe the precision and width for the source
AlarmFrom. bit_shift_right describes the bit-shift necessary to
convert from the used precision to the provided precision.
upper_count_type describes the numeric type used to store the
additional counter bits. upper_count_type MUST be a type with width
greater than or equal to the additional bits in to_size_type plus
bit_shift_right.
For instance to convert from a Counter<T32khz,uint16_t> to a
Counter<TMilli,uint32_t>, the following TransformCounterC would be
created::
new TransformCounterC( TMilli, uint32_t, T32khz, uint16_t, 5, uint32_t )
VirtualizeTimerC
--------------------------------------------------------------------
VirtualizeTimerC uses a single Timer to create up to 255 virtual
timers. ::
generic component VirtualizeTimerC( typedef precision_tag,
int max_timers )
{
provides interface Init;
provides interface Timer<precision_tag> as Timer[ uint8_t num ];
uses interface Timer<precision_tag> as TimerFrom;
}
Platform dependent components
====================================================================
A number of platform dependent components MUST exist:
* Alarm32khzC
* AlarmMilliC
* BusyWait32khzC
* BusyWaitMicroC
* Counter32khzC
* CounterMilliC
* TimerMilliC
Alarm32khzC
--------------------------------------------------------------------
Alarm32khzC MUST provide Init and Alarm<T32khz,uint32_t> as
Alarm32khz32. The configuration MAY provide additional
hardware-specific Alarm interfaces. Alarm32khzC is a generic
component. Each instantiation allocates a new, distinct Alarm.
Each instance of an Alarm32khzC MAY directly map to a hardware
timer. ::
generic configuration Alarm32khzC()
{
provides interface Init;
provides interface Alarm<T32khz,uint16_t> as Alarm32khz16;
provides interface Alarm<T32khz,uint32_t> as Alarm32khz32;
}
AlarmMilliC
--------------------------------------------------------------------
AlarmMilliC MUST provide Init and Alarm<TMilli,uint32_t> as
AlarmMilli32. The configuration MAY provide additional
hardware-specific Alarm interfaces. AlarmMilliC is a generic
component. Each instantiation allocates a new, distinct Alarm.
Each instance of an AlarmMilliC MAY directly map to a hardware
timer. ::
generic configuration AlarmMilliC()
{
provides interface Init;
provides interface Alarm<TMilli,uint32_t> as AlarmMilli32;
}
BusyWait32khzC
--------------------------------------------------------------------
BusyWait32khzC MUST provide BusyWait<T32khz,uint16_t> as
BusyWait32khz16. The configuration MAY provide additional
hardware-specific BusyWait interfaces. ::
configuration BusyWait32khzC
{
provides interface BusyWait<T32khz,uint16_t> as BusyWait32khz16;
}
BusyWaitMicroC
--------------------------------------------------------------------
BusyWaitMicroC MUST provide BusyWait<TMicro,uint16_t> as
BusyWaitMicro16. The configuration MAY provide additional
hardware-specific BusyWait interfaces. ::
configuration BusyWaitMicroC
{
provides interface BusyWait<TMicro,uint16_t> as BusyWaitMicro16;
}
Counter32khzC
--------------------------------------------------------------------
Counter32khz MUST provide Counter<T32khz,uint32_t> as Counter32khz32
and LocalTime<T32khz> as LocalTime32khz. The configuration MAY
provide additional hardware-specific Counter interfaces. ::
configuration Counter32khzC
{
provides interface Counter<T32khz,uint32_t> as Counter32khz32;
provides interface LocalTime<T32khz> as LocalTime32khz;
}
CounterMilliC
--------------------------------------------------------------------
CounterMilli MUST provide Counter<TMilli,uint32_t> as CounterMilli32
and LocalTime<TMilli> as LocalTimeMilli. The configuration MAY
provide additional hardware-specific Counter interfaces. ::
configuration CounterMilliC
{
provides interface Counter<TMilli,uint32_t> as CounterMilli32;
provides interface LocalTime<TMilli> as LocalTimeMilli;
}
TimerMilliC
--------------------------------------------------------------------
TimerMilliC MUST provide Init and Timer<TMilli> as
TimerMilli[uint8_t num]. TimerMilliC is used by OSKI to implement
the generic component TimerMilli that allocates a new, virtual timer
with each instantiation. ::
configuration TimerMilliC
{
provides interface Init;
provides interface Timer<TMilli> as TimerMilli[ uint8_t num ];
}
Hardware differences between the current platforms
====================================================================
a. Mica2 (ATmega128)
i. Two 8-bit timers, each with
* 10-bit prescaler
* One compare register
ii. Two 16-bit timers, each with
* Limited prescalers
* Three compare registers
b. Telos/EYES (MSP430)
i. Two 16-bit timers with
* One with three compare registers
* One with eight compare registers
* Each from distinct clock source
* Each with limited prescalers
c. Both platforms have a 32kHz clock and a high frequency clock
d. Platforms' timers are similar
Implementation
====================================================================
For platform independent headers, interfaces, and components, see
* tinyos-2.x/tos/lib/timer/
For platform dependent implementations, see specific chip
directories, such as
* tinyos-2.x/tos/chips/msp430/timer/
* tinyos-2.x/tos/chips/ATmega128/timer/
* tinyos-2.x/tos/chips/pxa27a/timer/
Hints
====================================================================
In implementing Alarm32khzC.nc and AlarmMilliC.nc for the MSP430 in
tinyos-2.x/tos/chips/msp430/timer/, see MSP430Timer32khzC.nc and
MSP430Timer32khzMapC.nc for an example of how a set of similar
hardware resources can be exposed through a parameterized interface
for compile-time allocation. See how Alarm32khzC.nc and
AlarmMilliC.nc call new MSP430Timer32khzC() to allocate a new,
arbitrary hardware timer. Using this methodology, specific
platforms can override MSP430Timer32khzMapC.nc to remove statically
allocated hardware timers from the set available for compile-time
allocation, such as the Telos platform in
tinyos-2.x/tos/platform/telosa.
Author's Address
====================================================================
| Cory Sharp
| 410 Soda Hall
| UC Berkeley
| Berkeley, CA 94720
|
| email - cssharp at eecs.berkeley.edu
-------------- next part --------------
_______________________________________________
Tinyos-2.0wg mailing list
Tinyos-2.0wg at Mail.Millennium.Berkeley.EDU
https://mail.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-2.0wg
More information about the Tinyos-host-mote-wg
mailing list