[Tinyos Core WG] Meeting: 2/7
Philip Levis
pal at cs.stanford.edu
Mon Feb 5 16:19:02 PST 2007
I'm sending this mail out a bit early because there are 2 TEPs to
read, both of which are on significant topics.
Wednesday, February 7, 2007, 09:30 AM US Pacific Time
Bridge: 4
Passcode: 1149804
Numbers:
US: 1-916-356-2663 or 1-888-875-9370 (non-Intel)
UK: +44 1793 402663
Denmark: +45 4527 5090
Agenda:
Status
mica timers
CC2420 stack (low power, SACKs, cancellation)
6lowpan: I-Frame, T-Frame
TEP 115 (attached)
TEP 2 (attached)
Phil
-------------- next part --------------
=================================
Hardware Abstraction Architecture
=================================
:TEP: 2
:Group: Core Working Group
:Type: Best Current Practice
:Status: Draft
:TinyOS-Version: 2.0
:Author: Vlado Handziski, Joseph Polastre, Jan-Hinrich Hauer, Cory Sharp, Adam Wolisz and David Culler
:Draft-Created: 14-Sep-2004
:Draft-Version: $revision$
:Draft-Modified: $date$
:Draft-Discuss: TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu>
.. Note::
This document specifies a Best Current Practices for the TinyOS
Community, and requests discussion and suggestions for
improvements. The distribution of the memo is unlimited, provided
that the header information and this note are preserved. Parts of
this document are taken verbatim from the [HAA2005]_ paper that is
under IEEE copyright. This memo is in full compliance with [TEP1]_.
Abstract
========
This TEP documents the *Hardware Abstraction Architecture (HAA)* for TinyOS
2.0 that balances conflicting requirements of WSN applications and the
desire for increased portability and streamlined development of
applications. The three-layer design gradually adapts the capabilities
of the underlying hardware platforms to the selected
platform-independent hardware interface between the operating system
core and the application code. At the same time, it allows the
applications to utilize a platform's full capabilities -- exported at
the second layer, when the performance requirements outweigh the need
for cross-platform compatibility.
..
We demonstrate the practical value of the approach by presenting
how it can be applied to the most important hardware modules that
are found in a typical WSN platform. We support the claims using
concrete examples from existing hardware abstractions in TinyOS
and the implementation of the MSP430 platform that follows the
architecture proposed in this paper.
Table of Contents
=================
.. contents::
.. sectnum::
Introduction
============
The introduction of hardware abstraction in modern operating systems
has proved valuable for increasing portability and simplifying
application development by hiding the hardware intricacies from the
rest of the system. Although enabling portability, hardware
abstractions come into conflict with the performance and
energy-efficiency requirements of WSN applications.
We need a *Hardware Abstraction Architecture (HAA)* that can strike a
balance between the above conflicting goals. The component-based model
of TinyOS has the functionality required for resolving this
tension. The main challenge is to select an appropriate organization
of abstraction functionality in form of components to support
reusability while maintaining energy-efficiency through access to the
full hardware capabilities when it is needed.
Based on the experience in porting TinyOS to new platforms we believe
that an effective organization is possible when the strengths of the
component-based approach are combined with a flexible, three-tier
organization of the hardware abstraction architecture.
Architecture
============
In the proposed architecture (Fig.1_), the hardware abstraction
functionality is organized in three distinct layers of components.
Each layer has clearly defined responsibilities and is dependent on
interfaces provided by lower layers. The capabilities of the
underlying hardware are gradually adapted to the established
platform-independent interface between the operating system and the
applications. As we move from the hardware towards this top interface,
the components become less and less hardware dependent, giving the
developer more freedom in the design and the implementation of
reusable applications.
.. _Fig.1:
::
+-----------------------------+
| |
| Cross-platform applications |
| |
+--------------+--------------+
+-----------------+ | +-----------------+
|Platform-specific| | |Platform-specific|
| applications | | | applications |
+--------+--------+ Platform-independent | hardware interface +--------+--------+
| +-----------------+--------+--------+-----------------+ |
| | | | | |
| +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ |
| |.------+------.| |.------+------.| |.------+------.| |.------+------.| |
| || || || || || || || HIL 4 || |
| || HIL 1 || || HIL 2 || || HIL 3 || |`------+------'| |
| || || |`------+------'| |`------+------'| | | | |
| |`------+------'| | | | | | | | | +----+--+
+--+----+ | | |.------+------.| | | | | | | |
| | | | || || |.------+------.| |.------+--+---.|
|.---+--+------.| || || || || || ||
|| || || HAL 2 || || || || ||
|| || || || || HAL 3 || || HAL 4 ||
|| HAL 1 || |`------+------'| || || || ||
|| || | | | || || || ||
|| || | | | |`------+------'| |`------+------'|
|`------+------'| |.------+------.| | | | | | |
| | | || || |.------+------.| | | |
|.------+------.| || HPL 2 || || || |.------+------.|
|| HPL 1 || || || || HPL 3 || || HPL 4 ||
|`------+------'| |`------+------'| |`------+------'| |`------+------'|
+-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ HW/SW
| | | | boundary
************************************************************************************
+------+------+ +------+------+ +------+------+ +------+------+
|HW Platform 1| |HW Platform 2| |HW Platform 3| |HW Platform 4|
+-------------+ +-------------+ +-------------+ +-------------+
Fig.1: The proposed Hardware Abstraction Architecture
Hardware Presentation Layer (HPL)
---------------------------------
The components belonging to the *HPL* are positioned directly over
the HW/SW interface. As the name suggests, their major task is to
"present" the capabilities of the hardware using the native concepts
of the operating system. They access the hardware in the usual way,
either by memory or by port mapped I/O. In the reverse direction, the
hardware can request servicing by signaling an interrupt. Using these
communication channels internally, the *HPL* hides the hardware
intricacies and exports a more usable interface (simple function
calls) for the rest of the system.
The *HPL* components SHOULD be stateless and expose an interface
that is fully determined by the capabilities of the hardware module
that is abstracted. This tight coupling with the hardware leaves
little freedom in the design and the implementation of the components.
Even though each *HPL* component will be as unique as the underlying
hardware, all of them will have a similar general structure. For
optimal integration with the rest of the architecture, each *HPL*
component SHOULD have:
- commands for initialization, starting, and stopping of the
hardware module that are necessary for effective power management
policy
- "get" and "set" commands for the register(s) that control
the operation of the hardware
- separate commands with descriptive names for the most
frequently used flag-setting/testing operations
- commands for enabling and disabling of the interrupts generated by
the hardware module
- service routines for the interrupts that are generated by the
hardware module
The interrupt service routines in the *HPL* components perform only
the most time critical operations (like copying a single value,
clearing some flags, etc.), and delegate the rest of the processing to
the higher level components that possess extended knowledge about the
state of the system.
The above *HPL* structure eases manipulation of the hardware.
Instead of using cryptic macros and register names whose definitions
are hidden deep in the header files of compiler libraries, the
programmer can now access hardware through a familiar interface.
This *HPL* does not provide any substantial abstraction over the
hardware beyond automating frequently used command
sequences. Nonetheless, it hides the most hardware-dependent code and
opens the way for developing higher-level abstraction components.
These higher abstractions can be used with different *HPL*
hardware-modules of the same class. For example, many of the
microcontrollers used on the existing WSN platforms have two USART
modules for serial communication. They have the same functionality
but are accessed using slightly different register names and generate
different interrupt vectors. The *HPL* components can hide these
small differences behind a consistent interface, making the
higher-level abstractions resource independent. The programmer can
then switch between the different USART modules by simple rewiring
(*not* rewriting) the *HPL* components, without any changes to the
implementation code.
Hardware Adaptation Layer (HAL)
-------------------------------
The adaptation layer components represent the core of the
architecture. They use the raw interfaces provided by the *HPL*
components to build useful abstractions hiding the complexity
naturally associated with the use of hardware resources. In contrast
to the *HPL* components, they are allowed to maintain state that can
be used for performing arbitration and resource control.
Due to the efficiency requirements of WSN, abstractions at the *HAL*
level are tailored to the concrete device class and platform. Instead
of hiding the individual features of the hardware class behind generic
models, *HAL* interfaces expose specific features and provide the
"best" possible abstraction that streamlines application development
while maintaining effective use of resources.
For example, rather than using a single "file-like" abstraction for
all devices, we propose domain specific models like *Alarm*, *ADC
channel*, *EEPROM*. According to the model, *HAL* components SHOULD
provide access to these abstractions via rich, customized interfaces,
and not via standard narrow ones that hide all the functionality
behind few overloaded commands.
Hardware Interface Layer (HIL)
------------------------------
The final tier in the architecture is formed by the *HIL* components
that take the platform-specific abstractions provided by the *HAL* and
convert them to hardware-independent interfaces used by cross-platform
applications. These interfaces provide a platform independent
abstraction over the hardware that simplifies the development of the
application software by hiding the hardware differences. To be
successful, this API "contract" SHOULD reflect the *typical*
hardware services that are required in a WSN application.
The complexity of the *HIL* components mainly depends on how advanced
the capabilities of the abstracted hardware are with respect to the
platform-independent interface. When the capabilities of the hardware
exceed the current API contract, the *HIL* "downgrades" the
platform-specific abstractions provided by the *HAL* until they are
leveled-off with the chosen standard interface. Consequently, when the
underlying hardware is inferior, the *HIL* might have to resort to
software simulation of the missing hardware capabilities. As newer
and more capable platforms are introduced in the system, the pressure
to break the current API contract will increase. When the performance
requirements outweigh the benefits of the stable interface, a discrete
jump will be made that realigns the API with the abstractions provided
in the newer *HAL*. The evolution of the platform-independent interface
will force a reimplementation of the affected *HIL* components. For
newer platforms, the *HIL* will be much simpler because the API contract
and their *HAL* abstractions are tightly related. On the other extreme,
the cost of boosting up (in software) the capabilities of the old
platforms will rise.
Since we expect *HIL* interfaces to evolve as new platforms are
designed, we must determine when the overhead of software emulation of
hardware features can no longer be sustained. At this point, we
introduce *versioning* of *HIL* interfaces. By assigning a version
number to each iteration of an *HIL* interface, we can design
applications using a legacy interface to be compatible with previously
deployed devices. This is important for WSNs since they execute
long-running applications and may be deployed for years. An *HIL* MAY
also branch, providing multiple different *HIL* interfaces with
increasing levels of functionality.
Selecting the level of abstraction
----------------------------------
The platform-dependence of the *HAL* in the architecture leads to the
more general question about why we have opted for a three-layered
design. In other words, why we do not expose the platform-independent
hardware interface directly from the *HAL* components. The main reason
behind this decision is the increased *flexibility* that arises from
separating the platform-specific abstractions and the adaptation
wrappers that upgrade or downgrade them to the current
platform-independent interface. In this way, for maximum performance,
the platform specific applications can circumvent the *HIL* components
and directly tap to the *HAL* interfaces that provide access to the full
capabilities of the hardware module.
Selecting the "right" level--whether an application should use the *HIL*
or directly access the *HAL*--can sometimes cause one hardware asset to
be accessed using two levels of abstraction from different parts of
the application or the OS libraries.
Let us take an application similar to the standard OscilloscopeRF
application in TinyOS as an example. The application uses the ADC to
sample several values from a temperature sensor and sends them in the
form of a message over the radio. If the observed phenomenon does not
have a large signal bandwidth and the time between subsequent
conversions is long, for the sake of cross-platform compatibility, the
programmer might decide to use the standard ``ADCSingle``
interface. This interface is exported by the *HIL* sensor wrapper
(Fig.2_) using the services of the platform-specific *HAL*
component. When enough samples are collected in the message buffer,
the application passes the message to the networking stack. The MAC
protocol used for message exchange over the radio uses clear channel
assessment to determine when it is safe to send the message. This
usually requires taking several samples of the RSSI signal provided by
the radio hardware. Since this is a very time critical operation in
which the correlation between the consecutive samples has a
significant influence, the programmer of the MAC might directly use
the ``MSP430ADC12Multiple`` interface of the *HAL* component as it
provides much finer control over the conversion process.
.. _Fig.2:
::
StdControl
| ADCSingle
| | ADCMultiple
| | |
+------|----|----|------------------------------------------+
| | | | Temperature |
| v v v |
| +--------------------+ MSP430ADC12Single +------------+ |
| | TemperatureM |-------------------->|MSP430ADC12C| |
| | | MSP430ADC12Multiple | | |
| | |-------------------->| | |
| +--------------------+ +------------+ |
+-----------------------------------------------------------+
Fig.2: The ADC HIL sensor wrapper
As a result of this chain of decisions, we end up with a concurrent
use of the ADC hardware module using two different levels of
abstraction. To support this type of "vertical" flexibility we include
more complex arbitration and resource control functionality in the *HAL*
components so that a safe shared access to the *HPL* exported resources
can be guaranteed.
Reference
=========
The proposed HAA was applied for the first time during the
implementation of the `MSP430 platform`_ that abstracts the
capabilities of the TI MSP430 microcontroller in `TinyOS 1.1.7`_. The
implementation is currently being used by four hardware platforms
(TelosA, TelosB, eyesIFX and eyesIFXv2) and has quite successfully
satisfied the requirements of a large range of applications.
In the following we illustrate the properties of the proposed
architecture using real-world examples from the planned hardware
abstraction functionality in TinyOS 2.0.
Processing unit
---------------
In TinyOS most of the variability between the processing units is
hidden from the OS simply by using a nesC/C based programming language
with a common compiler suite (GCC). For example, the standard library
distributed with the compiler creates the necessary start-up code for
initializing the global variables, the stack pointer and the interrupt
vector table, shielding the OS from these MCU-specific tasks.
To unify things further, TinyOS provides mechanisms for declaring
reentrant and non-reentrant interrupt service routines and critical
code-sections. For the MCU's external pins, it provides macros that
permit setting and clearing the pin, as well as changing its direction
and function. For example, the TI~MSP430's ADC pins may be used as
either general I/O or as an analog input to the ADC hardware module.
Macros are also provided for timed spin loops at microsecond
resolution, independent of the microcontroller. These macros are
defined in each platform's ``hardware.h`` descriptor file. Finally,
the *HPL* components deal with the different ways of accessing
registers (memory-mapped or port-mapped I/O) using the definitions in
the standard library header files.
The three-layer architecture is not intended to abstract the features
of the different MCU cores. For the currently supported MCUs, the
combination of the compiler suite support with the thin abstraction in
the ``hardware.h`` files is sufficient. Nevertheless, if new cores
with radically different architectures need to be supported by TinyOS
in the future, this part of the hardware abstraction functionality
will have to be explicitly addressed.
Power management
----------------
On both the MSP430 and the Atmel, before entering a sleep mode, a
component checks if any hardware modules require that the MCU core is
active. Additionally, all services including *HPL* and *HAL*
components have a start and stop function. When a service is no
longer using a hardware module, it may call the stop function of the
*HPL* or *HAL* component. Doing so disables the module for power
savings, but also removes the MCU's dependence on that hardware module
to enter sleep mode. For example, the ADC module may be clocked from
a high speed oscillator. When a sample is not in progress, the ADC
module may be shut down and it will no longer use the high speed
oscillator. As a result, when the MCU is idle, it may enter low power
mode.
This rather efficient way of implementing the power management
functionality is made possible by the fact that most of the hardware
modules are on-chip, attached directly to the MCU system bus, and that
there is no hardware memory protection hindering the access to their
status registers. As TinyOS platforms add more external devices
connected via the peripheral buses, this task will get increasingly
complicated. Ultimately, keeping some state in the form of device
enumeration or reference counting mechanisms might be needed for
proper power management.
Clocks and timers
-----------------
The application of the HAA for abstracting the clock and timer
modules is documented in [TEP102]_.
Analog-to-digital converters
----------------------------
The application of the HAA for abstracting the analog-to-digital
converter modules is documented in [TEP101]_.
Data busses
-----------
The *HPL* functionality for the data busses includes two paths--one
for data and a second for control. The control path allows the clock
source, prescaler, and baud rate to be set. Interrupts may be enabled
or disabled and various hardware flags may be read, set, or cleared,
useful for polling or blocking implementations. Through the control
path, the entire module may be started or stopped for power control.
The data interface simply consists of sending and receiving a byte
through the hardware's data registers, as well as interrupt based
reporting of received data. Here is an example of the interfaces used
in the MSP430 platform::
interface HPLUSARTControl {
async command void enableUART();
async command void disableUART();
async command void enableUARTTx();
async command void disableUARTTx();
async command void enableUARTRx();
async command void disableUARTRx();
async command void enableSPI();
async command void disableSPI();
async command void setModeSPI();
async command void setModeUART_TX();
async command void setModeUART_RX();
async command void setModeUART();
async command void setClockSource(
uint8_t source);
async command void setClockRate(
uint16_t baudrate, uint8_t mctl);
async command result_t disableRxIntr();
async command result_t disableTxIntr();
async command result_t enableRxIntr();
async command result_t enableTxIntr();
async command result_t isTxIntrPending();
async command result_t isRxIntrPending();
async command result_t isTxEmpty();
async command result_t tx(uint8_t data);
async command uint8_t rx();
}
interface HPLUSARTFeedback {
async event result_t txDone();
async event result_t rxDone(uint8_t data);
}
Sometimes functionality for more than one bus protocol are supported
through a single hardware module. In these cases, wrappers for each
bus provide standard application interfaces for using the bus.
Sharing the bus amongst different hardware devices or protocols may be
done through a bus arbitration component. Bus arbitration allows
higher level services to attain exclusive use of the bus, complete its
operations, and then release the bus to the next service::
interface BusArbitration {
async command result_t getBus();
async command result_t releaseBus();
event result_t busFree();
}
External storage
----------------
The application of the HAA for abstracting the external storage
modules is documented in [TEP103]_.
Radios
------
The application of the HAA for abstracting the radio modules is
documented in [TEP104]_ and [TEP105]_.
Conclusion
==========
The referenced TEPs in the previous section show that the three-layer
design can be successfully used for exposing to the applications the
functionality of the main hardware modules. The proposed architecture
provides a set of core services that eliminate duplicated code and
provide a coherent view of the system across different architectures
and platforms. It supports the concurrent use of platform-independent
and the platform-dependent interfaces in the same application. In this
way, applications can localize their platform dependence to only the
places where performance matters, while using standard cross-platform
hardware interfaces for the remainder of the application.
Author's Address
================
| Vlado Handziski (handzisk at tkn.tu-berlin.de) [1]_
| Joseph Polastre (polastre at cs.berkeley.edu) [2]_
| Jan-Hinrich Hauer (hauer at tkn.tu-berlin.de) [1]_
| Cory Sharp (cssharp at eecs.berkeley.edu) [2]_
| Adam Wolisz (awo at ieee.org) [1]_
| David Culler (culler at eecs.berkeley.edu) [2]_
.. [1] Technische Universitaet Berlin
Telecommunication Networks Group
Sekr. FT 5, Einsteinufer 25
10587 Berlin, Germany
.. [2] University of California, Berkeley
Computer Science Department
Berkeley, CA 94720 USA
Citations
=========
.. [HAA2005] V. Handziski, J.Polastre, J.H.Hauer, C.Sharp,
A.Wolisz and D.Culler, "Flexible Hardware Abstraction for Wireless
Sensor Networks", in *Proceedings of the 2nd European Workshop on
Wireless Sensor Networks (EWSN 2005)*, Istanbul, Turkey, 2005.
.. _MSP430 platform: http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/tos/platform/msp430/
.. _TinyOS 1.1.7: http://www.tinyos.net/scoop/section/Releases
.. [TEP1] P. Levis, "TEP structure and key words"
.. [TEP101] J.H. Hauer, V. Handziski, J. Polastre, L. Nachman,
"Analog-to-digital Converter Abstraction"
.. [TEP102] C. Sharp, "Clock and Timers Abstraction"
.. [TEP103] D. Gay, J. Hui, "Non-volatile Storage Abstraction"
.. [TEP104] K. Klues, "Radio Hardware Abstraction"
.. [TEP105] J. Polastre, "Link Layer Primitives in TinyOS"
..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
End:
-------------- next part --------------
======================================================================
Power Management of Non-Virtualised Devices
======================================================================
:TEP: 115
:Group: Core Working Group
:Type: Documentary
:Status: Draft
:TinyOS-Version: 2.x
:Author: Kevin Klues, Vlado Handziski, Jan-Hinrich Hauer, Phil Levis
:Draft-Created: 11-Jan-2006
:Draft-Version: $Revision: 1.6 $
:Draft-Modified: $Date: 2007/02/01 17:44:49 $
: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 memo documents how TinyOS 2.x manages the power state of physical
(not virtualised) abstractions.
1. Introduction
======================================================================
The energy resources on a typical TinyOS platform are limited, so
every effort should be made to put all devices on a given platform
into their lowest possible power state as often as
possible. Depending on the device type, selecting the correct
power state could be as simple as switching between on and
off states, or involve selecting the optimum state from among
several. Choosing the best possible power state requires making
tradeoffs between various factors such as power consumption, fidelity,
performance, and wake-up latency.
Unfortunately, it is not feasible do design a unified one size-fits-all power
management strategy for use by all types of devices. Some devices
(particularly microcontollers) have direct access to internal registers that
allow them to efficiently calculate their lowest possible power state
very quickly. Other devices do not have this information readily available and
would have to calculate it on the fly if other mechanisms were not in place to
prevent this. Designing a general system wide power control algorithm to handle
all such devices would most likely be overly complex and in some cases even
suboptimal. TinyOS 2.x, therefore, takes the approach of defining two different
classes of devices for which different power-management strategies have been
optimized: microcontrollers and peripheral devices. As opposed to microcontrollers,
which normally contain a number of different valid power states, peripheral devices
tend to have only two distinct states they can be switched to (*on* and *off*). Even
in the rare case where a device of this type happens to contain multiple power
states, TinyOS has traditionally used just the two most useful power states and
designated them to mean either *on* or *off*. This TEP is dedicated to
describing power management for peripheral devices of this type. Details on the
mechanisms used to perform microcontroller power management can be found in [TEP112]_.
The term "peripheral device" specifically refers to any hardware device for which
the mechanisms described in [TEP108]_ can be used to provide resource arbitration
for them. These devices are considered *non-virtualised* in the sense that
access to them must be explicitly requested and released by higher level
components wishing to use them. Various policies can be implemented on top of
this class of devices to decide exactly when they should be powered on or off.
The simplest policy involves leaving it up to the programmer
to ensure that a device is switched on or off whenever it should be.
Other policies involve automatically powering a device up or down
by monitoring whether any clients are currently connected to it
or not. Depending on the type of power management policy desired,
different models should be followed when designing drivers for devices
of this class.
2. Power Management Models
======================================================================
In order to support both manual and automatic power management of
non-virtualised devices in TinyOS, two different power management models have
been defined: *explicit power management* and *implicit power management*.
The *explicit power management* model provides a means for a single
client to manually control the power state of a dedicated physical device
(as defined by [TEP108]_). Whenever this client tells the device to
power up or down it does so without delay. This model can be
particularly useful when the control information driving the selection
of the proper power state of a device relies on external logic contained in
higher level components. The following section discusses the ``StdControl``,
``SplitControl``, and ``AsyncStdControl`` interfaces used to perform power
management of this type.
The *implicit power management* model, on the other hand, provides a
means for allowing the power state of a device to be controlled from
within the driver for that device itself. Device drivers following
this model are never explicitly powered up or down by some external
client, but rather *require* some internal policy to be defined that
decides exactly when their power states should be changed. This policy
could exist natively on the hardware of the physical device itself, or
be implemented on top of some lower level abstraction of a physical
device adhering to the *explicit power management* model.
For shared devices (as defined by [TEP108]_), the information required to
determine if a device's clients require it to be powered on or not can
be inferred through the set of interfaces they provide.
Because of this fact, no StdControl-like interface needs to be provided
to any higher level components, and the *implicit power management* policy
in use can act accordingly whenever clients request or release the device.
Section 4.2 discusses this in more detail.::
/|\ /|\
| |
Data Interface Resource
| |
-----------------------------------------------------------------------
| Shared Device (implicitly power managed) |
-----------------------------------------------------------------------
/|\ /|\
| |
Data Interface Resource
| |
| ---------------------- |
| | Power Manager | |
| ---------------------- |
| /|\ /|\ |
| | | |
| StdControl ResourceDefaultOwner |
| | | |
--------------------------------- --------------------------------
| Dedicated Device | | Arbiter |
| (explicitly power managed) | | |
--------------------------------- --------------------------------
3. Explicit Power Management
======================================================================
Just as in TinyOS 1.x, ``StdControl`` and ``SplitControl`` interfaces have
been defined for TinyOS 2.x in order to control the on and off power
states of devices adhering to the *explicit power management* model.
A third interface called ``AsyncStdControl`` has also been introduced
for components in which it is critical to have the ability to power
them on or off while running in asynchronous context. One of these
three interfaces MUST be provided by components wrapping a hardware
device that supports switching between the devices on and off power
states. The selection of the right interface depends on the latencies
involved in changing between these two states as well as the nature of
the code (sync or async) executing any of the interfaces commands.
3.1 Power Management with ``StdControl``
----------------------------------------------------------------------
Whenever the powerup and powerdown times of a non-virtualised device
are negligible, they SHOULD provide the ``StdControl`` interface as
defined below::
interface StdControl {
command error_t start();
command error_t stop();
}
.. Note::
Powerup and powerdown times on the order of a few microseconds have
traditionally been considered negligible, and can be waited on using one of the
*BusyWait* interfaces described in [TEP102]_. Powerup and powerdown
times on the order of a few milliseconds, however, should not be
ignored, and MUST be hidden behind the use of the ``SplitControl`` interface
described later on in this section.
An external component MUST call ``StdControl.start()`` to power a
device on and ``StdControl.stop()`` to power a device off. Calls to
either command MUST return either SUCCESS or FAIL.
Upon the successful return of a call to ``StdControl.start()``, a
device MUST be completely powered on, allowing calls to commands of other
interfaces implemented by the device to succeed.
Upon the successful return of a call to ``StdControl.stop()``, a
device MUST be completely powered down, and any calls to commands
of other interfaces implemented by that device MUST return FAIL or EOFF.
If a device is not able to complete the ``StdControl.start()`` or
``StdControl.stop()`` request for any reason, it MUST return FAIL.
Based on these specifications, the following matrix has been created
to describe the valid return values for any call made through the
``StdControl`` interface in one of the devices valid power states:
+---------------------+-----------------+-----------------+
| Call | Device On | Device Off |
+=====================+=================+=================+
| StdControl.start() | SUCCESS | SUCCESS or FAIL |
+---------------------+-----------------+-----------------+
| StdControl.stop() | SUCCESS or FAIL | SUCCESS |
+---------------------+-----------------+-----------------+
| operation | depends | FAIL or EOFF |
+---------------------+-----------------+-----------------+
Devices providing this interface would do so as shown below::
configuration DeviceC {
provides {
interface Init;
interface StdControl; //For Power Management
....
}
}
3.2 Power Management with ``SplitControl``
----------------------------------------------------------------------
When a device's powerup and powerdown times are non-negligible, the
*``SplitControl``* interface MUST be used in place of the *``StdControl``*
interface. The definition of this interface can be seen below::
interface SplitControl {
command error_t start();
event void startDone(error_t error);
command error_t stop();
event void stopDone(error_t error);
}
An external component MUST call ``SplitControl.start()`` to power a
device on and ``SplitControl.stop()`` to power a device off. Calls to
either command return one of SUCCESS or FAIL.
Successful calls to ``SplitControl.start()`` MUST signal one of
``SplitControl.startDone(SUCCESS)`` or ``SplitControl.startDone(FAIL)``.
Successful calls to ``SplitControl.stop()`` MUST signal one of
``SplitControl.stopDone(SUCCESS)`` or ``SplitControl.stopDone(FAIL)``.
Upon signaling a ``SplitControl.startDone(SUCCESS)``, a device MUST
be completely powered on, and operation requests through calls to commands
of other interfaces implemented by the device MAY succeed.
Upon signalling a ``SplitControl.stopDone(SUCCESS)``, a device MUST be
completely powered down, and any subsequent calls to commands of other
interfaces implemented by the device MUST return EOFF or FAIL.
If a device is powered on and a successful call to ``SplitControl.stop()``
signals a ``SplitControl.stopDone(FAIL)``, the device MUST still be fully
powered on, and operation requests through calls to commands of other
interfaces implemented by the device MAY succeed.
If a device is powered down and a successful call to ``SplitControl.start()``
signals a ``SplitControl.startDone(FAIL)``, the device MUST still be fully
powered down, and operation requests through calls to commands of other
interfaces implemented by the device MUST return EOFF or FAIL.
If a device is not able to complete the ``SplitControl.start()`` or
``SplitControl.stop()`` requests for any reason, they MUST return
FAIL.
Calls to either ``StdControl.start()`` or ``StdControl.stop()`` while
a start or stop operation is pending MUST return SUCCESS, with the
anticipation that a corresponding ``StdControl.startDone()`` or
``StdControl.stopDone()`` will be signaled in the future.
+----------------------+-----------+------------+----------+----------+
| Call | Device On | Device Off | Starting | Stopping |
+======================+===========+============+==========+==========+
| SplitControl.start() | SUCCESS | SUCCESS | SUCCESS | SUCCESS |
| | | FAIL | | |
+----------------------+-----------+------------+----------+----------+
| SplitControl.stop() | SUCCESS | SUCCESS | SUCCESS | SUCCESS |
| | FAIL | | | |
+----------------------+-----------+------------+----------+----------+
| operation | depends | FAIL | FAIL | FAIL |
| | | EOFF | EOFF | EOFF |
| | | EOFF | SUCCESS | |
+----------------------+-----------+------------+----------+----------+
Devices providing this interface would do so as shown below::
configuration DeviceC {
provides {
interface Init;
interface SplitControl; \\ For Power Management
....
}
}
3.3 Power Management with ``AsyncStdControl``
----------------------------------------------------------------------
The commands and the events of the *``StdControl``* and the *``SplitControl``*
interfaces are synchronous and can not be called from within
asynchronous code (such as interrupt service routines, etc.). For the
cases when the power state of the device needs to be controlled from
within asynchronous code, the *``AsyncStdControl``* interface MUST be used
in place of the *``StdControl``* interface. The definition of this
interface can be seen below::
interface AsyncStdControl {
async command error_t start();
async command error_t stop();
}
All of the semantics that hold true for devices providing the
``StdControl`` interface also hold for this interface.
Devices providing this interface would do so as shown below::
configuration DeviceC {
provides {
interface Init;
interface AsyncStdControl; \\ For Power Management
....
}
}
.. Note::
The ``AsyncStdControl`` interface should be provided whenever it might be
necessary to allow a device to be powered on or off while running in
async context. If it is anticipated that a device *will* not (or more
likely *should* not) be powered on or off while in asynchronous context,
then the ``StdControl`` interface SHOULD be provided instead. Components
that wish to power the device on or off from within async context would
then be required to post a task before doing so. In practice,
``AsyncStdControl`` is provided by low-level hardware resources, while
``StdControl`` is provided by higher level services built on top of these
resources.
4. Implicit Power Management
======================================================================
While the *explicit power management* model provides the basic means
for controlling the power state of a device, it is void of any
policy about when, or how the power state of the device should be changed.
This does not represent a large problem for the simple case
of *dedicated* devices, but can become crucial for non-trivial cases
involving complex interdependencies between devices controlled by multiple
clients.
For example, if component *A* is a client of both component *B*
and component *C*, what happens with *B* and *C* if
``StdControl.stop()`` is called on component *A* ? Should components
*B* and *C* also be stopped? What about the reverse case where both
*B* and *C* are clients of the single shared component, *A*? If
devices *B* and *C* are shut off, should *A* be shut off as well?
How can one decide when it is appropriate to cascade such powerup
and powerdown requests?
The complex nature of the problem is evident from the number of
unexpected behaviors in TinyOS 1.x involving ``StdControl``. On several
platforms, one of the SPI buses is shared between the radio and the
flash device. On some of them, issuing ``StdControl.stop()`` on the
radio results in a series of cascaded calls that result in SPI bus
becoming disabled, rendering the communication with the flash impossible.
Of course, the right policy would involve tracking the clients of the
SPI bus and powering it off only once both the radio and the flash
devices were no longer using it. Conversely, the SPI bus should be
powered on whenever there is at least one active client.
The selection of the right power management policy to use is a complex
task that depends on the nature of the devices in use, their
interdependency, as well as on any specific application requirements.
For cases when some of these features are known a-priori or are
restricted in some sense, it is preferable that the system provide
architectural support for enforcing a meaningful *default* power-management
policy instead of passing that task on to the application programmer to be
solved on a case-by-case basis.
4.1. Power Management Policies
----------------------------------------------------------------------------
Just as generic arbiters are offered in TinyOS 2.x to provide the arbitration
functionality required by shared resources, generic power management policies are
also offered to allow the power management of non-virtualised devices to
be automatically control.
Through the use of the arbiter components described in [TEP108]_, device
drivers implemented as shared resources provide the type of restricted
resource interdependency where default power-management policies can be offered.
The shared resource class defined in Section 2.3 of [TEP108]_, provides a
well defined component interdependency, where a single resource is shared
among multiple clients. This relationship enables the definition of
default power-management policies that can be used to automatically power
the resource on and off.
The *Power Manager* component implementing one of these polices acts as
the *default owner* of the shared resource device and interacts with it
through the use of the ResourceDefaultOwner interface::
interface ResourceDefaultOwner {
async event void granted();
async command error_t release();
async command bool isOwner();
async event void requested();
async event void immediateRequested();
}
Acting as the default owner, the *Power Manager* waits for the
``ResourceDefaultOwner.granted()`` event to be signaled in order to
gain ownership over the resource device.
Once it owns the device, the *Power Manager* is free to execute its
power-management policy using the StdControl-like interface provided by the
underlying resource. Different power managers can implement different
policies. In the simplest case, this would involve an immediate power-down
via one of the ``stop()`` commands. When the power-state transition
involves non-negligible costs in terms of wake-up latency or power
consumption, the *PowerManager* might revert to a more intelligent
strategy that tries to reduce these effects. As pointed out in the
introduction, one such strategy might involve the use of a timer to defer
the power-down of the resource to some later point in time, giving any
resource clients a window of opportunity to put in requests before the
device is fully shut down.
Regardless of the power management policy in use, the *Power Manager*
remains owner of the resource as long as the resource is not requested
by one of its clients. Whenever a client puts in a request, the
*Power Manager* will receive a ``ResourceDefaultOwner.requested()`` event
(or ``immediateRequested()`` event) from the arbiter it is associated with.
Upon receiving this event, the *Power Manager* MUST power up the
resource through the StdControl-like interface provided by the lower level
abstraction of the physical device. The *Power Manager* SHOULD release the
ownership of the resource (using the ``ResourceDefaultOwner.release()``
command) but MUST wait until after the resource has been fully powered on
before doing so.
Modeling devices as shared resources and allowing them to be
controlled in the way described here, solves the problems outlined in
section 3 regarding how to keep track of when and how the
powerdown of nested resources should proceed. The *Power Manager*
component answers the question of how, and the combination of the power
management policy being used and the reception of the
``ResourceDefaultOwner.granted()`` and ``ResourceDefaultOwner.requested()``
events answers the question of when. As long as the resource at
the bottom of a large set of nested resource clients has been fully released,
the power mananger will be able to power down the resource appropriately.
Using the model described above, a resource that uses one of these policies
according to the *implicitly power management* model could be built as shown below::
module MyFlashP {
provides {
interface Init;
interface SplitControl;
interface Resource;
interface FlashCommands;
...
}
}
implementation {
...
}
generic module PowerManagerC(uint8_t POWERDOWN_DELAY) {
provides {
interface Init;
}
uses {
interface SplitControl;
interface ResourceDefaultOwner;
}
}
implementation {
...
}
#define MYFLASH_RESOURCE "MyFlash.resource"
#define MYFLASH_POWERDOWN_DELAY 1000
configuration MyFlashC {
provides {
interface Init;
interface Resource;
interface FlashCommands;
}
}
implementation {
components new PowerManagerC(MYFLASH_POWERDOWN_DELAY)
, FcfsArbiter(MYFLASH_RESOURCE)
, MyFlashP;
Init = MyFlashP;
Resource = FcfsArbiter;
FlashCommands = MyFlashP;
PowerManagerC.ResourceDefaultUser -> FcfsArbiter;
PowerManagerC.SplitControl -> MyFlashP;
}
This example implementation is built out of three components. The
first component (``MyFlashP``) follows the *explicit power management*
model for defining the interfaces to the physical flash device. The
second component (``PowerManagerC``) is the generic *Power Manager*
component that will be used to implement the specific power management
policy for this device. The third component (``MyFlashC``) is the
configuration file that wires together all of the components required
by the implementation of of the device as it adheres to the *implicit power
management* model. It includes the ``MyflashP`` and ``PowerManagerC``
components, as well as an arbiter component for managing shared clients
of the device. Notice how the *Power Manager* is wired to both the
``ResourceDefaultUser`` interface provided by the arbiter, and the
``SplitControl`` interface provided by the flash. All clients of this flash
device are directly connected to the resource interface provided by
the arbiter. As outlined above, the ``PowerManagerC`` component will use
the events signaled through the ``ResourceDefaultUser`` interface to determine
when to make calls to power the device up and power it down through
the ``SplitControl`` interface.
4.2. Example Power Managers: PowerManagerC and DeferredPowerManagerC
----------------------------------------------------------------------------
TinyOS 2.x currently has two default power management policies
that it provides. These policies are implemented by the various
components located under tinyos-2.x/lib/power. The first policy
is implemented using an *immediate* power control scheme, whereby
devices are powered on and off immediately after they have been
requested and released. The second policy is implemented using
a *deferred* power control scheme, whereby devices are powered
on immediately after being requested, but powered off after
some small delay from being released.
Each policy has three different implementations for use by each of
the ``StdControl``, ``SplitControl``, and ``AsyncStdControl``
interfaces.
For reference, each of the available components are listed below
Immediate Power Management:
- ``StdControlPowerManagerC``
- ``SplitControlPowerManagerC``
- ``AsyncStdControlPowerManagerC``
Deferred Power Management:
- ``StdControlDeferredPowerManagerC``
- ``SplitControlDeferredPowerManagerC``
- ``AsyncStdControlDeferredPowerManagerC``
5. Author's Address
====================================================================
| Kevin Klues
| 503 Bryan Hall
| Washington University
| St. Louis, MO 63130
|
| phone - +1-314-935-6355
| email - klueska at cs.wustl.edu
|
| Vlado Handziski
| Sekr FT5
| Einsteinufer 25
| 10587 Berlin
| GERMANY
|
| phone - +49 30 314 23831
| email - handzisk at tkn.tu-berlin.de
|
| Jan-Hinrich Hauer
| Sekr FT5
| Einsteinufer 25
| 10587 Berlin
| GERMANY
|
| phone - +49 30 314 23813
| email - hauer at tkn.tu-berlin.de
|
| Philip Levis
| 358 Gates Hall
| Stanford University
| Stanford, CA 94305-9030
|
| phone - +1 650 725 9046
| email - pal at cs.stanford.edu
6. Citations
====================================================================
.. [TEP102] TEP 102: Timers.
.. [TEP108] TEP 108: Resource Arbitration.
.. [TEP112] TEP 112: Microcontroller Power Management.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.millennium.berkeley.edu/pipermail/tinyos-2.0wg/attachments/20070205/1185f7b8/tep115-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.millennium.berkeley.edu/pipermail/tinyos-2.0wg/attachments/20070205/1185f7b8/tep2-0001.html
More information about the Tinyos-2.0wg
mailing list