📄 tep115.txt
字号:
======================================================================
Power Management of Non-Virtualised Devices
======================================================================
:TEP: 115
:Group: Core Working Group
:Type: Documentary
:Status: Final
:TinyOS-Version: 2.x
:Author: Kevin Klues, Vlado Handziski, Jan-Hinrich Hauer, Phil Levis
.. 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
======================================================================
TinyOS platforms have limited energy. A unified power management
strategy for all devices and peripherals is not feasible, as
they vary significantly in warm-up times, power profiles, and
operation latencies. While some devices, such as
microcontrollers, can efficiently calculate their lowest possible
power state very quickly, others, such as sensors with warm-up
times, require external knowledge to do so.
In TinyOS 1.x, applications are responsible for all power management.
Low-level subsystems, such as an SPI bus, are explicitly powered on
and off by higher level abstractions. This approach of deep calls
to ``StdControl.start()`` and ``StdControl.stop()`` introduces strange behaviors
and can get in the way of power conservation. Turning off the radio
on the Telos platform, for example, turns off the SPI bus and therefore
prevents the flash driver from working. Additionally, the microcontroller
stays in a higher power state for the SPI bus even when it is
inactive.
TinyOS 2.x defines two classes of devices for power-management:
microcontrollers and peripherals. TEP 112 documents how TinyOS 2.x
manages the power state of a microcontroller [TEP112]_.
Unlike microcontrollers, which typically have several power states,
peripheral devices typically have two distinct states, *on* and *off*.
This TEP is dedicated to documenting how TinyOS 2.x controls the power
state of peripheral devices.
The term "peripheral device" refers to any hardware device which
arbitrates access with the mechanisms described in [TEP108]_ . These
devices are not virtualised in the sense that access to
them must be explicitly requested and released by their users.
2. Power Management Models
======================================================================
There are two different models to managing the power state of a
peripheral in TinyOS: *explicit power management* and *implicit
power management*.
The explicit 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 (except for delays in the hardware of course).
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 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.
Shared devices (as defined by [TEP108]_) can infer whether they
should be on or off based on the interfaces they provide to their
clients. For example, when a client requests the ADC, this implies
the ADC should be on; if there are no requests of the ADC, this implies
it should be off. Therefore shared devices do not need to provide a
power control interface. They can use an implicit power management policy.
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, TinyOS 2.x has ``StdControl`` and ``SplitControl``
interfaces in order to control the on and off
power states of explicitly managed peripherals. TinyOS 2.x also
introduces a third interface, ``AsyncStdControl``. A component
representing a hardware device that can be powered on and off MUST
provide one of these three interfaces.
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 interface's
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.
A general rule of thumb is that if waiting for powerup takes
more than one hundred microseconds, SplitControl is probably more
suitable.
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 that actually access
the device hardware 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 SHOULD 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, FAIL, EBUSY, or
EALREADY. SUCCESS indicates that the device has now started changing
its power state and will signal a corresponding completion event in
the future. EBUSY indicates that the device is in the midst of either starting
or stopping (e.g., it is starting when stop is called or stopping
when start is called) and will not issue an event. EALREADY indicates
that the device is already in that state; the call is erroneous and a
completion event will not be signaled. FAIL indicates that the
device's power state could not be changed. More explicitly:
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 that actually access
the device hardware 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 they MUST return FAIL.
Calls to either ``SplitControl.start()`` when the device is starting
or ``SplitControl.stop()`` while the device is stopping MUST return
SUCCESS, with the anticipation that a corresponding
``SplitControl.startDone()`` or ``SplitControl.stopDone()``
will be signaled in the future.
Calls to ``SplitControl.start()`` when the device is started
or ``SplitControl.stop()`` while the device is stopped MUST
return EALREADY, indicating that the device is already in that
state. The corresponding completion event (startDone for start
or stopDone for stop) MUST NOT be signaled.
Calls to ``SplitControl.start()`` when the device is stopping or
``SplitControl.stop()`` while the device is starting MUST return
EBUSY, indicating that the device is busy performing a differnet
operation. The correspodning completion event (startDone for start or
stopDone for stop) MUST NOT be signaled.
+----------------------+-----------+------------+----------+----------+
| Call | Device On | Device Off | Starting | Stopping |
+======================+===========+============+==========+==========+
| SplitControl.start() | EALREADY | SUCCESS | SUCCESS | EBUSY |
| | | FAIL | | |
+----------------------+-----------+------------+----------+----------+
| SplitControl.stop() | SUCCESS | EALREADY | EBUSY | 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
....
}
}
.. Note::
Other approaches were considered for the return values of
``SplitControl.start()`` and ``SplitControl.stop()``. One such
approach would have replaced EBUSY with SUCCESS when
``SplitControl.start()`` was called while in the process of stopping
and ``SplitControl.stop()`` was called while in the process of starting.
However, implementing such an approach adds unwanted complexity to
a device driver. It is unreasonable to expect the implementor of
each driver to implement this functionality.
Returning EBUSY is the most straightforward, unambiguous value
that can be returned in such a situation. By returning
EBUSY when a device is in a transitional state, the components
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -