[Tinyos Core WG] Meeting: 1/31
Kevin Klues
klueska at gmail.com
Tue Jan 30 23:53:48 PST 2007
Skipped content of type multipart/alternative-------------- 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.5 $
:Draft-Modified: $Date: 2006/12/12 18:22:54 $
: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 states 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 could 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. Different
devices contain a different number of supported power states and
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. This TEP is dedicated to describing the latter.
Details on the mechanisms used to perform microcontroller power management
can be found in [TEP112]_.
The term "peripheral device" refers to any hardware device for which the
mechanisms described in [TEP108]_ can be used to provide resource arbitration
on them. These devices are considered *non-virtualised* in the sense that
access to them must be explicitly requested and released by any higher level
components wishing to use them. 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*.
Various policies can be implemented on top of this class of
devices to decide exactly when a device 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 is being used.
Another policy can be used to automatically power up a device whenever
its use has been requested by some higher level component, and power it
down whenever all such components are finished using it. A complementary
policy might include the ability to defer its power down to some point
after it is no longer in use in order to cut down on any performance costs
associated with powering it back up again if long wake-up times are
an issue.
Providing such policies to automatically control the power state of a peripheral
device allows it to become virtualised in a sense. Higher level components
connecting to it only need to signify when they require its use and when they don't.
The time at which it is actually powered on or off is left up to the power
management policy in use.
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 is external to that device.
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 device itself. Devices following this model are never
explicitly powered up or down by some external client, but rather
*require* some 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 the physical device which adheres
to the *explicit power management* model.
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.
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 information provided by the Resource interface
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.
2.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
....
}
}
2.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.startDone()`` MUST signal one of
``SplitControl.startDone(SUCCESS)`` or ``SplitControl.startDone(FAIL)``.
Successful calls to ``SplitControl.stopDone()`` MUST signal one of
``SplitControl.stopDone(SUCCESS)`` or ``SplitControl.stopDone(FAIL)``.
Upon signalling either a ``SplitControl.startDone(SUCCESS)`` or a
``SplitControl.stopDone(FAIL)`` event, a device MUST be completely
powered on, and operation requests through calls to commands of other
interfaces implemented by the device SHOULD succeed.
Upon signalling either a ``SplitControl.stopDone(SUCCESS)`` or a
``SplitControl.startDone(FAIL)`` event, 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 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 top operattion 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
....
}
}
2.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.
3. Power Management Policies
======================================================================
While the *explicit power management* model provides the basic means
for controlling the power state of the device, it is void of any
policy about when, or how the power of the device should be
managed. 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 being 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.
3.1. Implicit Power Management for Shared Resources
----------------------------------------------------------------------------
Through the use of the arbiter components described in [TEP108]_, devices
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 a simple default power-management policy that
powers the resource off when no potential users are waiting for access
to the resource. Conversely, the resource is powered on whenever a
client requests its use.
The realization of a specific power-control policy for shared reources
does not need to be resource specific. 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 automated.
The *Power Manager* component implementing one of these polices acts as
the *default owner* of the shared resource and interacts with the resource
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.
Once it owns the resource, 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 ResourceController;
}
}
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 users
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.
3.2. Default Power Managers: PowerManagerC and DeferredPowerManagerC
====================================================================
TinyOS 2.x currently has two default power management policies
that it provides. These policies are impleneted 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.
Each of the available components are listed below, with a reference to
how they can be wired into and used by the implementation of a shared
resource.
Immediate Power Management:
- StdControlPowerManagerC
- SplitControlPowerManagerC
- AsyncStdControlPowerManagerC
Deferred Power Management:
- StdControlDeferredPowerManagerC
- SplitControlDeferredPowerManagerC
- AsyncStdControlDeferredPowerManagerC
::
/|\ /|\
| |
Data Interface Resource
| |
-----------------------------------------------------------------------
| Shared Resource |
-----------------------------------------------------------------------
/|\ /|\
| |
Data Interface Resource
| |
| ---------------------- |
| | Power Manager | |
| ---------------------- |
| /|\ /|\ |
| | | |
| StdControl ResourceDefaultOwner |
| | | |
--------------------------------- --------------------------------
| Dedicated Resource | | Arbiter |
--------------------------------- --------------------------------
6. 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.
More information about the Tinyos-2.0wg
mailing list