[Tinyos Core WG] Meeting: 2/7
Gilman Tolle
gtolle at archrock.com
Wed Feb 7 10:36:37 PST 2007
Meeting notes are on the wiki.
http://tinyos.stanford.edu:8000/TinyOS_2.x_WG/02.07.2007
Gil
Philip Levis wrote:
> 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
>
>
>
> ------------------------------------------------------------------------
>
> =================================
> 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:
>
>
> ------------------------------------------------------------------------
>
> ======================================================================
> 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.
>
>
>
> ------------------------------------------------------------------------
>
>
> 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: 1.5
> Draft-Modified: 2006-12-12
> 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] <#tep112>.
>
> The term "peripheral device" specifically refers to any hardware device
> for which the mechanisms described in [TEP108] <#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] <#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] <#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] <#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 FAIL SUCCESS SUCCESS
> SplitControl.stop() SUCCESS FAIL SUCCESS SUCCESS SUCCESS
> operation depends FAIL EOFF EOFF FAIL EOFF SUCCESS FAIL EOFF
>
> 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]
> <#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] <#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 <mailto: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 <mailto: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 <mailto: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 <mailto:pal at cs.stanford.edu>
>
>
> 6. Citations
>
> [TEP102] <#id5> TEP 102: Timers.
>
> [TEP108] /(1 <#id2>, 2 <#id3>, 3 <#id4>, 4 <#id6>, 5 <#id7>)/ TEP 108:
> Resource Arbitration.
>
> [TEP112] <#id1> TEP 112: Microcontroller Power Management.
>
>
> ------------------------------------------------------------------------
>
>
> 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] <#haa2005> paper that is under IEEE
> copyright. This memo is in full compliance with [TEP1] <#tep1>.
>
>
> 1 Abstract <#id16>
>
> 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.
>
>
> 2 Table of Contents <#id17>
>
> Contents
>
> * 1 Abstract <#abstract>
> * 2 Table of Contents <#table-of-contents>
> * 3 Introduction <#introduction>
> * 4 Architecture <#architecture>
> o 4.1 Hardware Presentation Layer (HPL)
> <#hardware-presentation-layer-hpl>
> o 4.2 Hardware Adaptation Layer (HAL)
> <#hardware-adaptation-layer-hal>
> o 4.3 Hardware Interface Layer (HIL)
> <#hardware-interface-layer-hil>
> o 4.4 Selecting the level of abstraction
> <#selecting-the-level-of-abstraction>
> * 5 Reference <#reference>
> o 5.1 Processing unit <#processing-unit>
> o 5.2 Power management <#power-management>
> o 5.3 Clocks and timers <#clocks-and-timers>
> o 5.4 Analog-to-digital converters
> <#analog-to-digital-converters>
> o 5.5 Data busses <#data-busses>
> o 5.6 External storage <#external-storage>
> o 5.7 Radios <#radios>
> * 6 Conclusion <#conclusion>
> * 7 Author's Address <#author-s-address>
> * 8 Citations <#citations>
>
>
> 3 Introduction <#id18>
>
> 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.
>
>
> 4 Architecture <#id19>
>
> In the proposed architecture (Fig.1 <#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.
>
> +-----------------------------+
> | |
> | 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
>
>
> 4.1 Hardware Presentation Layer (HPL) <#id20>
>
> 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.
>
>
> 4.2 Hardware Adaptation Layer (HAL) <#id21>
>
> 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.
>
>
> 4.3 Hardware Interface Layer (HIL) <#id22>
>
> 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.
>
>
> 4.4 Selecting the level of abstraction <#id23>
>
> 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 <#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.
>
> 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.
>
>
> 5 Reference <#id24>
>
> The proposed HAA was applied for the first time during the
> implementation of the MSP430 platform
> <http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/tos/platform/msp430/>
> that abstracts the capabilities of the TI MSP430 microcontroller in
> TinyOS 1.1.7 <http://www.tinyos.net/scoop/section/Releases>. 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.
>
>
> 5.1 Processing unit <#id25>
>
> 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.
>
>
> 5.2 Power management <#id26>
>
> 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.
>
>
> 5.3 Clocks and timers <#id27>
>
> The application of the HAA for abstracting the clock and timer modules
> is documented in [TEP102] <#tep102>.
>
>
> 5.4 Analog-to-digital converters <#id28>
>
> The application of the HAA for abstracting the analog-to-digital
> converter modules is documented in [TEP101] <#tep101>.
>
>
> 5.5 Data busses <#id29>
>
> 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 comma