[Tinyos-beta-commits]
CVS: tinyos-1.x/beta/teps/txt tep112.txt, 1.2, 1.3
Phil Levis
scipio at users.sourceforge.net
Mon Sep 19 15:29:46 PDT 2005
Update of /cvsroot/tinyos/tinyos-1.x/beta/teps/txt
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11242
Modified Files:
tep112.txt
Log Message:
Rewrite of TEP 112 to follow the initial consensus of the WG.
Comments/criticisms greatly desired.
Index: tep112.txt
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/beta/teps/txt/tep112.txt,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** tep112.txt 13 Sep 2005 06:49:21 -0000 1.2
--- tep112.txt 19 Sep 2005 22:29:44 -0000 1.3
***************
*** 1,232 ****
! ============================
! Power Management
! ============================
!
! :TEP: 112
! :Group: Core Working Group
! :Type: Documentary
! :Status: Draft
! :TinyOS-Version: 2.x
! :Author: Martin Turon, Robert Szewczyk
!
! :Draft-Created: 03-Sep-2005
! :Draft-Version: $Revision$
! :Draft-Modified: $Date$
! :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 power management is done in TinyOS, the
! general design principles followed by components that affect power,
! and interfaces by which a developer can influence the power state.
!
!
! 1. Introduction
! ====================================================================
!
! This document defines the various power management techniques available
! in TinyOS. There are three disctint levels that are addressed, each with
! their own considerations:
!
! * Microcontroller (including subsystems such as timers and adc)
! * Platform (flash, radio, and other peripheral chips)
! * Application (including specific sensors)
!
! It is likely there will be applications with specific concerns that cannot
! conform to this specification, but following as closely to its spirit as
! possible will simplify generic applications.
!
!
! 2. Background
! ====================================================================
!
! The original TinyOS power management is as powerful as it is simple.
! The philosophy is that once the task queue is empty, the processor
! will automatically go to sleep. At the component level, a StdControl
! interface is used to start or stop the use of power as required.
!
! * MCU (automatic)
! * Component (manual)
!
! None of these concepts are to go away. Rather, this proposal adds
! extensions to each area to better handle some common cases:
!
! * MCU -- a notification hook for the platform HAL to quickly
! set pin states accordingly during MCU sleep/wake.
!
! * Component -- a set of services to power up a component and
! automatically "spin down" during periods of
! inactivity.
!
!
! 3. HPL Sleep Notification
! ====================================================================
!
! Historically, TinyOS uses a section of "adjustPower" code to calculate
! the desired sleep mode of the processor depending on the current
! conditions such as ADC and Timer state.
!
! command McuPwrMgrMcu.adjustPower {
! // chips/CPU determines exact sleep mode
! if (external timers running) {
! mode = IDLE;
! } else if (radio running) {
! mode = IDLE;
! } else if (adc running) {
! mode = ADC_NR;
! } else {
! mode = POWER_SAVE;
! }
! sleep_state = mode;
! }
!
! This code is to use a proper HAA interface into the MCU and not directly
! call registers by punching through the HPL abstraction layer. As such,
! it must be called by a wired in component. This must happen in the
! scheduler:
!
! [scheduler]
! while (1) {
! <do tasks>
!
! atomic {
! signal HalPwrMgr.sleep();
! __nesc_atomic_sleep();
! }
!
! // << Interrupt handler executes and returns >>
! // Pin state management not available in interrupt context!
!
! signal HalPwrMgr.wake();
! }
!
! The HalPwrMgr.sleep event is in a critical timing path for sleeping the
! processor. It is crucial that this code be extremely efficient. The
! first job of the sleep() code is to run adjustPower only if necessary.
! This can be determined by a dirty flag in the power management state that
! subsytems are required to responsibly set if they are started or stopped.
!
! async atomic event HalPwrMgr.sleep() {
! if (pwr_state.bits.dirty) {
!
! // set power down pin states
! call HalPwrMgrPlatform.adjustPower();
!
! // recalculate minimum MCU power down mode
! call HalPwrMgrMcu.adjustPower();
!
! }
! }
!
! It is the responsibility of the platform developer to set the power state
! dirty bits when in the subsystem Hpl code. Starting/stopping the ADC would
! set the dirty bit for example.
!
!
! 4. Platform Pin State Management
! ====================================================================
!
! When a node goes to sleep, it assumes that all GPIO pins are in the proper
! state. A platform may want to intercept a signal when the node is powering
! down to properly insure that pins it is responsible for are set correctly.
! This is especially true for a platform subsystem such as external flash or
! a thermistor that draws contiuous power when its Pwr pin is set high. Such
! devices may have nominal power consumtion relative to the MCU, have minimal
! latency requirements, and are convenient to have available while running.
! For devices with these properties, it makes sense to quickly powered them
! down with a GPIO pin when the MCU goes to sleep.
!
! In this way, a platform can specify reasonable defaults for pin-setting in
! its implementation of the HPLPwrMgr.sleep event. Restoration of these
! pin settings are done in the HPLPwrMgr.wake event, and account for whether
! the device has been started or stopped by the application:
!
! command HalPwrMgrPlatform.adjustPower {
! // chips/CPU determines exact sleep mode
! if (!flash_running) {
! call HalFlashPwrMgr.sleep();
! }
! if (!thermistor_sampling) {
! call HalThermistor.sleep();
! }
! }
!
! async atomic HalFlashPwrMgr.sleep() {
! // this must be fast, responsible code: just flip one pin!
! call HalFlashPwrPin.clr();
! }
!
! async HALFlashPwrMgr.wake() {
! if (flash_started) call HPLFlashPwrPin.set();
! }
!
! Note: for flash devices that use a bus command to set it into standby
! mode, this interface is not suggested. The HPLPwrMgr code path must be
! fast, is run in atomic context, and is reserved for simple pin management
! and sleep mode calculations.
!
!
! 5. Sensor Power Management
! ====================================================================
!
! Managing the power of individual devices in the system should be decoupled
! as much as possible from the MCU sleep. Modern processors can sleep and
! wake very quickly, and are on a different time scale from sensor devices
! which have warm up times and other latency requirements. This section
! attempts to address the concerns of simplifying sensor and device power
! management by specifying a set of general components that handle common
! application cases.
!
! An interesting example is to consider the following case: suppose you have a
! sensor that takes 2 seconds to warm up; its driver implements start, stop,
! and sampling methods correctly. The application samples the sensor
! periodically. Now, the power states of that sensor may look very different
! when you tell it to sample 10 times a second vs. 1 time per minute. How
! should this latency and sampling rate be embedded in the individual
! components? How should this be presented to the developer or network
! manager? This points to a set of basic power mgmt policy components
! that wrap the AcquireData interface with an internal timeout.
!
!
! 6. Application Services
! =====================================================================
!
! AutoPowerBasic
!
! An AutoPowerBasic component would provide the StdControl and AcquireData
! interfaces. If you stop the sensor, it will remain off. If you start it,
! it will only power on when you signal getData. The initial getData request
! will start up the sensor and internally manages warm up time latency.
! Subsequent getData requests reset the timeout. Finally, after a designated
! period of inactivity, the timeout timer fires and the sensor is put to sleep.
! The exact length of the timeout can be a generic component parameter and
! tuned by the sensor board driver developer to a reasonable default value.
!
! AutoPowerAdvanced
!
! Other wrapper components could provide a facility to preWarm() the sensor
! ahead of an actual getData request. An advanced interface would also
! allow an explicit ability to setTimeout() time. In addition, an advanced
! power management wrapper component may want to provide a getDataContinous
! style interface and power down immediately after the dataReady returns that
! a burst has ended.
!
!
! 7. Author's Address
! ====================================================================
!
! | Martin Turon
! | PO Box 8525
! | Berkeley, CA 94707
! |
! | phone - +1 408 965 3355
! | email - mturon at xbow.com
! |
--- 1,332 ----
! ============================
! Microcontroller Power Management
! ============================
!
! :TEP: 112
! :Group: Core Working Group
! :Type: Documentary
! :Status: Draft
! :TinyOS-Version: 2.x
! :Author: Robert Szewczyk, Philip Levis, Martin Turon, Lama Nachman, Philip Buonadonna, Vlado Handziski
!
! :Draft-Created: 19-Sep-2005
! :Draft-Version: $Revision$
! :Draft-Modified: $Date$
! :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 manages the lower power state of a
! microcontroller.
!
!
! 1. Introduction
! ====================================================================
!
! Microcontrollers often have several power states, with varying power
! draws, wakeup latencies, and peripheral support. The microcontroller
! should always be in the lowest possible power state that can satisfy
! application requirements. Determining this state accurately requires
! knowing a great deal about the power state of many subsystems and
! their peripherals. Additionally, state transitions are common. Every
! time a microcontroller handles an interrupt, it moves from a low power
! state to an active state, and whenever the TinyOS scheduler finds the
! task queue empty it returns the microcontroller to a low power state.
! TinyOS 2.x uses three mechanisms to decide what low power state it
! puts a microcontroller into: status and control registers, a dirty
! bit, and a power state override. This memo documents these mechanisms
! and how they work, as well as the basics of subsystem power
! management.
!
!
! 2. Background
! ====================================================================
!
! The TinyOS scheduler[_tep106] puts a processor into a sleep state when
! the task queue is empty. However, processors can have a spectrum of
! power states. For example, the MSP430 has one active mode (issuing
! instructions) and five low-power modes. The low power modes range from
! LPM0, which disables only the CPU and main system clock, to LPM4,
! which disables the CPU, all clocks, and the oscillator, expecting to
! be woken by an external interrupt source. The power draws of these low
! power modes can differ by a factor of 350 or more (75 uA for LPM0 at
! 3V, 0.2 uA for LPM4). Correctly choosing the right microcontroller low
! power state can greatly increase system lifetime.
!
! TinyOS 1.x platforms manage MCU power in several different ways, but
! there are commonalities in the approaches. The mica platforms, for
! example, have a component named HPLPowerManagement, which has a
! commands for enabling and disabling low power modes, as well as a
! command (adjustPower()) to tell it to compute the low power state
! based on the configuration of its various control and status
! registers, storing the result in the Atmega128's MCU control
! register. When TinyOS tells the microcontroller to go to sleep, it
! uses the control register to decide exactly which power state to go
! into. In contrast, MSP430 based platforms such as Telos and eyes
! compute the low power state every time the scheduler tells the system
! to go to sleep.
!
! Each of the two approaches has benefits and drawbacks. The 1.x mica
! approach is efficient, in that it only calculates the low power state
! when told to. However, this leaves the decision of when to calculate
! the low power state to other components, which is an easy way to
! introduce bugs. The lack of a well-defined hardware abstraction
! architecture in 1.x exacerbates this problem. In contrast, the MSP430
! approach is simpler, in that the system will always enter the right
! power state without any external prompting. However, it is
! correspondingly costly, introducing 40-60 cycles of overhead to every
! interrupt that wakes the system up, which can be a bottleneck on the rate
! at which the system can handle interrupts.
!
! Both of these approaches assume that TinyOS can determine the correct
! low power state by examining control and status registers. For
! example, the MSP430 defaults to low power mode 3 (LPM3) unless it
! detects that Timer A, the USARTs, or the ADC is active, in which case
! it uses low power mode 1 (LPM1). From the perspective of what
! peripherals and subsystems might wake the node up or must continue
! operating while the MCU sleeps, this is true. However, power modes
! introduce wakeup latency, a factor which could be of interest to
! higher-level components. While wakeup latency is not a significant
! issue on very low power microcontrollers, such as the Atmega128 and
! MSP430, more powerful processors, such as the Xscale family (the basis
! of platforms such as the imote2) can power states with wakeup
! latencies as large as 5ms. For some application domains, this latency
! could be a serious issue. Higher level components therefore need a way
! to give the TinyOS microcontroller power manager information on their
! requirements, which it considers when calculating the right low power
! state.
!
! 3. Microcontroller Power Management
! ====================================================================
!
! TinyOS 2.x uses three basic mechanisms to manage and control
! microcontroller power states: a dirty bit, a chip-specific low power
! state calculation function, and a power state override function. The
! dirty bit tells TinyOS when it needs to calculate a new low power
! state, the function performs the calculation, and the override allows
! higher level components to introduce additional requirements, if
! needed.
!
! These three mechanisms all operate in the TinyOS core scheduling loop,
! described in TEP 106: Schedulers and Tasks[_tep106]. This loop is
! called from the boot sequence, which is described in TEP 107: Boot
! Sequence[_tep107]. The command in question is
! ``Scheduler.runNextTask()``, when its sleep parameter is TRUE (i.e.,
! ``call Scheduler.runNextTask(TRUE)``).
!
! If this command is called when the task queue is empty, the TinyOS
! scheduler puts the microcontroller to sleep. It does so through
! the ``McuSleep`` interface:
!
! | ``interface McuSleep {``
! | ``async command void sleep();``
! | ``}``
!
! ``McuSleep.sleep()`` puts the microcontroller into a low power sleep
! state, to be woken by an interrupt. This command deprecates the
! ``__nesc_atomic_sleep()`` call of TinyOS 1.x. Note that, as the 1.x
! call suggests, putting the microcontroller to sleep MUST have certain
! atomicity properties. The command is called from within an atomic
! section, and MUST atomically re-enable interrupts and go to sleep. An
! issue arises if the system handles an interrupt after it re-enables
! interrupts but before it sleeps: the interrupt may post a task, but
! the task will not be run until the microcontroller wakes up from sleep.
!
! Microcontrollers generally have hardware mechanisms to support this
! requirement. For example, on the Atmega128, the ``sei`` instruction
! does not re-enable interrupts until two cycles after it is issued (so
! the sequence ``sei sleep`` runs atomically).
!
! A component named ``McuSleepC`` provides the McuSleep interface, and
! ``TinySchedulerC`` MUST automatically wire it to the scheduler
! implementation. McuSleepC is a chip- or platform-specific component,
! whose signature MUST include the following interfaces:
!
! | ``component McuSleepC {``
! | ``provides interface McuSleep;``
! | ``provides interface PowerState;``
! | ``uses interface PowerOverride;``
! | ``}``
! |
! | ``interface McuPowerState {``
! | ``async command void update();``
! | ``}``
! |
! | ``interface McuPowerOverride {``
! | ``async command mcu_power_t lowestState();``
! | ``}``
!
!
! McuSleepC MAY have additional interfaces.
!
! 3.1 The Dirty Bit
! ====================================================================
!
! Whenever a Hardware Presentation Layer (HPL, see TEP 2: Hardware
! Abstraction Architecture[_tep2]) component changes an aspect of
! hardware configuration that might change the possible low power state
! of the microcontroller, it MUST call McuPowerState.update(). This is
! the first power management mechanism, a *dirty bit*. If
! McuPowerState.update() is called, then McuSleepC MUST recompute the
! low power state before the next time it goes to sleep as a result of
! McuSleep.sleep() being called.
!
!
! 3.2 Low Power State Calculation
! ====================================================================
!
! McuSleepC is responsible for calculating the lowest power state that
! it can safely put the microcontroller into without disrupting the
! operation of TinyOS subsystems. McuSleepC SHOULD minimize how often it
! must perform this calculation: it is an inherently atomic calculation,
! and so if performed very often (e.g., on every interrupt) can
! introduce significant overhead and jitter.
!
! MCU power states MUST be represented as an enum in the standard chip
! implementation header file. This file MUST also define a type
! ``mcu_power_t`` and a combine function that given two power state
! values returns one that provides the union of their functionality.
!
! For example, consider a hypothetical microcontroller with three low
! power states, (LPM0, LPM1, LPM2) and two hardware resources such as
! clocks (HR0, HR1). In LPM0, both HR0 and HR1 are active. In LPM1, HR0
! is inactive but HR1 is active. In LPM2, both HR0 and HR1 are inactive.
! The following table describes the results of a proper combine function
! (essentially a MAX):
!
! +------+------+------+------+
! | | LPM0 | LPM1 | LPM2 |
! +------+------+------+------+
! | LPM0 | LPM0 | LPM0 | LPM0 |
! +------+------+------+------+
! | LPM1 | LPM0 | LPM1 | LPM1 |
! +------+------+------+------+
! | LPM2 | LPM0 | LPM1 | LPM2 |
! +------+------+------+------+
!
! In contrast, if in LPM2, HR0 is active but HR1 is inactive, the
! combine function would look like this:
!
! +------+------+------+------+
! | | LPM0 | LPM1 | LPM2 |
! +------+------+------+------+
! | LPM0 | LPM0 | LPM0 | LPM0 |
! +------+------+------+------+
! | LPM1 | LPM0 | LPM1 | LPM0 |
! +------+------+------+------+
! | LPM2 | LPM0 | LPM0 | LPM2 |
! +------+------+------+------+
!
! 3.3 Power State Override
! ====================================================================
!
! When McuSleepC computes the best low power state, it MUST call
! ``PowerOverride.lowestState().`` McuSleepC SHOULD have a default
! implementation of this command, which returns the lowest power state
! the MCU is capable of. The return value of this command is a
! ``mcu_power_t.`` McuSleepC MUST respect the requirements of the return
! of this call and combine it properly with the low power state it
! computes.
!
! The PowerOverride functionality exists in case higher-level components
! have some knowledge or requirements that cannot be captured in
! hardware status and configuration registers, such as a maximum
! tolerable wakeup latency. Because it can overrides all of the MCU
! power conservation mechanisms, it SHOULD be used sparingly, if at
! all. Because it is called in an atomic section during the core
! scheduling loop, implementations of PowerOverride.lowestState() SHOULD
! be an efficient function, and SHOULD NOT be longer than twenty or
! thirty cycles; implementations SHOULD be a simple return of a cached
! variable. Wiring arbitrarily to this command is an easy way to cause
! TinyOS to behave badly. The presence of a combine function for
! mcu_power_t means that this command can have fan-out calls.
!
! 4. Peripherals and Subsystems
! ====================================================================
!
! At the HIL level, TinyOS subsystems generally have a simple,
! imperative power management interface. Depending on the latencies
! involved, this interface is either ``StdControl`` or ``SplitControl``.
! These interfaces are imperative in that when any component calls
! ``StdControl.stop`` on another component, it causes the subsystem that
! component represents to enter an inactive, low-power state.
!
! From the perspective of MCU power management, this transition causes a
! change in status and control registers (e.g., a clock is
! disabled). Following the requirements in 3.1, the MCU power management
! subsystem will be notified of a significant change and act
! appropriately when the system next goes to sleep.
!
! These imperative appraoches are flexible and powerful, but are also
! very error prone, partially due to their deep semantics. For example,
! depending on the circumstances, an application calling StdControl.stop
! on a routing layer may or may not also want to turn off the underlying
! radio. StdControl and SplitControl provide a *mechanism* to control
! subsystem power states, but no real *policy* for arbitrating
! conflicting requirements from components built on top of them.
!
! Service distributions (described in TEP 110[_tep110]) are responsible
! for providing policies on top of these low-level mechanisms. OSKI, for
! example, the sample distribution described in TEP 110, uses an
! OR-policy: a subsystem is active if any of its clients want it active,
! and inactive iff all of its clients want it inactive. Other
! distributions can provide alternative power management policies in top
! of the basic HIL mechanisms.
!
! 5. Author's Address
! ====================================================================
!
! | Philip Levis
! | 358 Gates
! | Computer Science Laboratory
! | Stanford University
! | Stanford, CA 94305
! |
! | phone - +1 650 725 9046
! | email - pal at cs.stanford.edu
! |
! |
! | Martin Turon
! | PO Box 8525
! | Berkeley, CA 94707
! |
! | phone - +1 408 965 3355
! | email - mturon at xbow.com
! |
! |
! | Phil Buonadonna
! | Arched Rock Corp.
! | 2168 Shattuck Ave. 2nd Floor
! | Berkeley, CA 94704
! |
! | phone - +1 510 981 8714
! | email - pbuonadonna at archedrock.com
! |
! |
! | Vlado Handziski
! | Sekr FT5
! | Einsteinufer 25
! | 10587 Berlin
! | GERMANY
! |
! | email - handzisk at tkn.tu-berlin.de
! |
!
! 6. Citations
! ====================================================================
!
! .. [tep106] TEP 106: Schedulers and Tasks.
!
! .. [tep107] TEP 107: TinyOS 2.x Boot Sequence.
!
! .. [tep110] TEP 110: Service Distributions.
!
! .. [tep2] TEP 2: Hardware Abstraction Architecture.
More information about the Tinyos-beta-commits
mailing list