From: beutel Date: Tue, 14 Aug 2007 18:57:59 +0000 (+0000) Subject: fixed html validation error in docs X-Git-Tag: release_tinyos_2_1_0_0~821 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=843be811b125fd0bb60a470c2687dce7e8398471 fixed html validation error in docs --- diff --git a/doc/html/overview.html b/doc/html/overview.html index e69de29b..ea203ec1 100644 --- a/doc/html/overview.html +++ b/doc/html/overview.html @@ -0,0 +1,740 @@ + + + + + + +TinyOS 2.0 Overview + + + + + +
+

TinyOS 2.0 Overview

+ +++ + + + + + +
Author:Philip Levis
Date:Oct 30 2006
+
+

Note

+

This document gives a brief overview of TinyOS 2.0, highlighting how +and where it departs from 1.1 and 1.0. Further detail on these changes +is detailed in TEP (TinyOS Enhancement Proposal) documents.

+
+
+

1. Introduction

+

TinyOS 2.0 is a clean slate redesign and re-implementation of TinyOS. +Its development was motivated by our belief that many aspects of 1.x +strain to meet requirements and uses that were not foreseen +when it was designed and implemented. The structure and interfaces 1.x +defines have several fundamental limitations. While these limitations +can be worked around, this practice has led to tightly coupled +components, hard to find interactions, and a very steep learning curve +for a newcomer to sensor network programming.

+

TinyOS 2.0 is not backwards compatible with 1.x: code written for the +latter will not compile for the former. However, one important aspect +of 2.0's design is to minimize the difficulty of upgrading +code. Therefore, while porting a 1.x application to 2.0 will require +some work, it should not be very much.

+

This document provides a high-level overview of 2.0 and describes some +of the ways in which it departs from 1.x. It covers the basic TinyOS +abstractions, such as hardware abstractions, communication, timers, +the scheduler, booting and initialization. Further detail on each of +these can be found in TEPs (TinyOS Enhancement Proposals), which +document and describe these abstractions.

+
+
+

2. Platforms/Hardware Abstraction

+

Platforms exist in the tos/platforms subdirectory. In TinyOS 2.0, a +platform is a collection of chips and some glue code that connects +them together. For example, the mica2 platform is the CC1000 radio +chip and the ATmega128 microcontroller, while the micaZ platform is +the CC2420 radio and the ATmega128 microcontroller, and the Teloi +platforms are the CC2420 radio and the MSP430 microcontroller. Chip +code exists in tos/chips. A platform directory generally has a +.platform file, which has options to pass to the nesC compiler. For +example, the mica2 .platform file tells ncc to look in chips/cc1000 +and chips/atm128 directories, as well as to use avr-gcc to compile a +mote binary (Teloi platforms tell it to use msp430-gcc).

+

Hardware abstractions in TinyOS 2.0 generally follow a three-level +abstaction heirarchy, called the HAA (Hardware Abstraction +Architecture).

+

At the bottom of the HAA is the HPL (Hardware Presentation Layer). The +HPL is a thin software layer on top of the raw hardware, presenting +hardare such as IO pins or registers as nesC interfaces. The HPL +generally has no state besides the hardware itself (it has no +variables). HPL components usually have the prefix Hpl, followed by +the name of the chip. For example, the HPL components of the CC1000 +begin with HplCC1000.

+

The middle of the HAA is the HAL (Hardware Abstraction Layer). The HAL +builds on top of the HPL and provides higher-level abstractions that +are easier to use than the HPL but still provide the full +functionality of the underlying hardware. The HAL components usually have +a prefix of the chip name. For example, the HAL components of the CC1000 +begin with CC1000.

+

The top of the HAA is the HIL (Hardware Independent Layer). The HIL +builds on top of the HAL and provides abstractions that are hardware +independent. This generalization means that the HIL usually does not +provide all of the functionality that the HAL can. HIL components have +no naming prefix, as they represent abstractions that applications can +use and safely compile on multiple platforms. For example, the HIL +component of the CC1000 on the mica2 is ActiveMessageC, representing +a full active message communication layer.

+

The HAA is described in TEP 2: Hardware Abstraction Architecture[TEP2].

+

Currently (as of the 2.0 release in November 2006), TinyOS 2.0 supports +the following platforms:

+
+
    +
  • eyesIFXv2
  • +
  • intelmote2
  • +
  • mica2
  • +
  • mica2dot
  • +
  • micaZ
  • +
  • telosb
  • +
  • tinynode
  • +
  • btnode3
  • +
+
+

The btnode3 platform is not included in the RPM.

+
+
+

3. Scheduler

+

As with TinyOS 1.x, TinyOS 2.0 scheduler has a non-preemptive FIFO +policy. However, tasks in 2.0 operate slightly differently than in +1.x.

+

In TinyOS 1.x, there is a shared task queue for all tasks, and a +component can post a task multiple times. If the task queue is full, +the post operation fails. Experience with networking stacks showed +this to be problematic, as the task might signal completion of a +split-phase operation: if the post fails, the component above might +block forever, waiting for the completion event.

+

In TinyOS 2.x, every task has its own reserved slot in the task queue, +and a task can only be posted once. A post fails if and only if the +task has already been posted. If a component needs to post a task +multiple times, it can set an internal state variable so that when +the task executes, it reposts itself.

+

This slight change in semantics greatly simplifies a lot of component +code. Rather than test to see if a task is posted already before +posting it, a component can just post the task. Components do not have +to try to recover from failed posts and retry. The cost is one byte of +state per task. Even in large systems such as TinyDB, this cost is +under one hundred bytes (in TinyDB is is approximately 50).

+

Applications can also replace the scheduler, if they wish. This allows +programmers to try new scheduling policies, such as priority- or +deadline-based. It is important to maintain non-preemptiveness, +however, or the scheduler will break all nesC's static concurrency +analysis. Details on the new scheduler and how to extend it can be found +in TEP 106: Schedulers and Tasks[TEP106].

+
+
+

4. Booting/Initialization

+

TinyOS 2.0 has a different boot sequence than 1.x. The 1.x interface +StdControl has been split into two interfaces: Init and +StdControl. The latter only has two commands: start and stop. +In TinyOS 1.x, wiring components to the boot sequence would cause them +to be powered up and started at boot. That is no longer the case: the +boot sequence only initializes components. When it has completed +initializing the scheduler, hardware, and software, the boot sequence +signals the Boot.booted event. The top-level application component +handles this event and start services accordingly. Details on +the new boot sequence can be found in TEP 107: TinyOS 2.x Boot +Sequence[TEP107].

+
+
+

5. Virtualization

+

TinyOS 2.0 is written with nesC 1.2, which introduces the concept +of a 'generic' or instantiable component. Generic modules allow +TinyOS to have reusable data structures, such as bit vectors and +queues, which simplify development. More importantly, generic +configurations allow services to encapsulate complex wiring +relationships for clients that need them.

+

In practice, this means that many basic TinyOS services are now +virtualized. Rather than wire to a component with a parameterized +interface (e.g., GenericComm or TimerC in 1.x), a program instantiates +a service component that provides the needed interface. This +service component does all of the wiring underneath (e.g., in the +case of timers, to a unique) automatically, reducing wiring +mistakes and simplifying use of the abstraction.

+
+
+

6. Timers

+

TinyOS 2.0 provides a much richer set of timer interfaces than +1.x. Experience has shown that timers are one of the most critical +abstractions a mote OS can provide, and so 2.0 expands the fidelity +and form that timers take. Depending on the hardware resources of a +platform, a component can use 32KHz as well as millisecond granularity +timers, and the timer system may provide one or two high-precision +timers that fire asynchronously (they have the async +keyword). Components can query their timers for how much time +remainins before they fire, and can start timers in the future (e.g., +'start firing a timer at 1Hz starting 31ms from now'). TEP 102: +Timers[TEP102] defines what HIL components a platform must provide +in order to support standard TinyOS timers. Platforms are +required to provide millisecond granularity timers, and can provide +finer granularity timers (e.g., 32kHz) if needed.

+

Timers present a good example of virtualization in 2.0. In 1.x, +a program instantiates a timer by wiring to TimerC:

+
+components App, TimerC;
+App.Timer -> TimerC.Timer[unique("Timer")];
+
+

In 2.0, a program instantiates a timer:

+
+components App, new TimerMilliC();
+App.Timer -> TimerMilliC;
+
+
+
+

7. Communication

+

In TinyOS 2.0, the message buffer type is message_t, and it is a +buffer that is large enough to hold a packet from any of a node's +communication interfaces. The structure itself is completely opaque: +components cannot reference its fields. Instead, all buffer accesses +go through interfaces. For example, to get the destination address of +an AM packet named msg, a component calls AMPacket.destination(msg).

+

Send interfaces distinguish the addressing mode of communication +abstractions. For example, active message communication has the +AMSend interface, as sending a packet require an AM destination +address. In contrast, broadcasting and collection tree abstractions +have the address-free Send interface.

+

Active messages are the network HIL. A platform's ActiveMessageC +component defines which network interface is the standard +communication medium. For example, a mica2 defines the CC1000 active +message layer as ActiveMessageC, while the TMote defines the CC2420 +active message layer as ActiveMessageC.

+

There is no longer a TOS_UART_ADDRESS for active message +communication. Instead, a component should wire to +SerialActiveMessageC, which provides active message communication over +the serial port.

+

Active message communication is virtualized through four generic +components, which take the AM type as a parameter: AMSenderC, +AMReceiverC, AMSnooperC, and AMSnoopingReceiverC. AMSenderC is +virtualized in that the call to send() does not fail if some +other component is sending (as it does with GenericComm in 1.x). Instead, +it fails only if that particular AMSenderC already has a packet +outstanding or if the radio is not in a sending state. Underneath, +the active message system queues and sends these outstanding packets. +This is different than the QueuedSendC approach of 1.x, in which there +is an N-deep queue that is shared among all senders. With N AMSenderC +components, there is an N-deep queue where each sender has a single +reserved entry. This means that each AMSenderC receives +1/n of the available post-MAC transmission opportunities, where +n is the number of AMSenderC components with outstanding packets. +In the worst case, n is the number of components; even when every +protocol and component that sends packets is trying to send a packet, +each one will receive its fair share of transmission opportunities.

+

Further information on message_t can be found in TEP 111: +message_t[TEP111], while further information on AM can be +found in TEP 116: Packet Protocols[TEP116].

+

The current TinyOS release has a low-power stack for the CC1000 +radio (mica2 platform) and an experimental low-power stack for +the CC2420 radio (micaz, telosb, and intelmote2 platforms).

+
+
+

8. Sensors

+

In TinyOS 2.0, named sensor components comprise the HIL of a +platform's sensors. TEP 114 describes a set of HIL data acquisition +interfaces, such as Read, ReadStream, and Get, which sensors +provide according to their acquisition capabilities.

+

If a component needs +high-frequency or very accurate sampling, it must use the HAL, which +gives it the full power of the underlying platform (highly accurate +platform-independent sampling is not really feasible, due to the +particulars of individual platforms). Read assumes that the +request can tolerate some latencies (for example, it might schedule +competing requests using a FIFO policy).

+

Details on the ADC subsystem can be found in +TEP 101: Analog-to-Digital Converters[TEP101]; details on +the organization of sensor boards can be found in TEP 109: +Sensorboards[TEP109], and the details of the HIL sensor interfaces +can be found in TEP 114: Source and Sink Independent Drivers[TEP114].

+
+
+

9. Error Codes

+

The standard TinyOS 1.x return code is result_t, whose value is +either SUCCESS (a non-zero value) or FAIL (a zero value). While this +makes conditionals on calls very easy to write (e.g., if (call +A.b())), it does not allow the callee to distinguish causes of error +to the caller. In TinyOS 2.0, result_t is replaced by error_t, +whose values include SUCCESS, FAIL, EBUSY, and ECANCEL. Interface +commands and events define which error codes they may return and why.

+

From the perspective of porting code, this is the most significant +different in 2.0. Calls that were once:

+
+if (call X.y()) {
+  busy = TRUE;
+}
+
+

now have their meanings reversed. In 1.x, the busy statement will execute +if the call succeeds, while in 2.0 it will execute if the call fails. +This encourages a more portable, upgradable, and readable approach:

+
+if (call X.y() == SUCCESS) {
+  busy = TRUE;
+}
+
+
+
+

10. Arbitration

+

While basic abstractions, such as packet communication and timers, +can be virtualized, experiences with 1.x showed that some cannot +without either adding significant complexity or limiting the system. +The most pressing example of this is a shared bus on a microcontroller. +Many different systems -- sensors, storage, the radio -- might need +to use the bus at the same time, so some way of arbitrating access +is needed.

+

To support these kinds of abstractions, TinyOS 2.0 introduces +the Resource interface, which components use to request and +acquire shared resources, and arbiters, which provide a policy for +arbitrating access between multiple clients. For some abstractions, +the arbiter also provides a power management policy, as it can tell +when the system is no longer needed and can be safely turned off.

+

TEP 108: Resource Arbitration[TEP108] describes the Resource interface +and how arbiters work.

+
+
+

11. Power Management

+

Power management in 2.0 is divided into two parts: the power state +of the microcontroller and the power state of devices. The former, +discussed in TEP 112: Microcontroller Power Management[TEP112], +is computed in a chip-specific manner by examining which devices +and interrupt souces are active. The latter, discussed in +TEP 115: Power Management of Non-Virtualised Devices{TEP115], is handled +through resource abiters. Fully virtualized services have their +own, individual power management policies.

+

TinyOS 2.0 provides low-power stacks for the CC1000 (mica2) +and CC2420 (micaz, telosb, imote2) radios. Both use a low-power +listening apporach, where transmitters send long preambles or +repeatedly send packets and receivers wake up periodically to +sense the channel to hear if there is a packet being +transmitted. The low-power stack CC1000 is standard, while +the CC2420 stack is experimental. That is, the default CC1000 +stack (chips/cc1000) has low-power-listening, while the default +CC2420 stack (chips/cc2420) does not. To use the low-power CC2420 +stack, you must include chips/cc2420_lpl in your application Makefile.

+
+
+

12. Network Protocols

+

TinyOS 2.0 provides simple reference implementations of two of +the most basic protocols used in mote networks: dissemination +and collection. Dissemination reliably delivers small (fewer +than 20 byte) data items to every node in a network, while +collection builds a routing tree rooted at a sink node. Together, +these two protocols enable a wide range of data collection +applications. Collection has advanced significantly since the +most recent beta release; experimental tests in multiple +network conditions have seen very high (>98%) deliver rates +as long as the network is not saturated.

+
+
+

13. Conclusion

+

TinyOS 2.0 represents the next step of TinyOS development. Building on +user experiences over the past few years, it has taken the basic +TinyOS architecture and pushed it forward in several directions, +hopefully leading to simpler and easier application development. It is +still under active development: future prereleases will include +non-volatile storage, basic multihop protocols (collection routing, +dissemination), and further power management abstractions.

+
+
+

14. Acknowledgments

+

TinyOS 2.0 is the result of a lot of hard work from a lot of people, +including (but not limited to) David Gay, Philip Levis, Cory Sharp, +Vlado Handziski, Jan Hauer, Kevin Klues, Joe Polastre, Jonathan Hui, +Prabal Dutta, +Gilman Tolle, Martin Turon, Phil Buonodonna, Ben Greenstein, David Culler, +Kristin Wright, Ion Yannopoulos, Henri Dubois-Ferriere, Jan Beutel, +Robert Szewczyk, Rodrigo Fonseca, Kyle Jamieson, Omprakash Gnawali, +David Moss, and Kristin Wright.

+
+
+

15. Author's Address

+
+
Philip Levis
+
358 Gates
+
Computer Systems Laboratory
+
Stanford University
+
Stanford, CA 94305
+

+
phone - +1 650 725 9046
+

+ +
+
+
+

16. Citations

+ + + + + +
[TEP1]TEP 1: TEP Structure and Keywords. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep1.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP2]TEP 2: Hardware Abstraction Architecture. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep2.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP3]TEP 3: Coding Standard. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep3.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP101]TEP 101: Analog-to-Digital Converters. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep101.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP102]TEP 102: Timers. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep102.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP106]TEP 106: Schedulers and Tasks. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep106.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP107]TEP 107: Boot Sequence. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep107.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP108]TEP 108: message_t. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep108.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP109]TEP 109: Sensorboards. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep109.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP110]TEP 110: Service Distributions. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep110.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP111]TEP 111: message_t. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep111.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP112]TEP 112: Microcontroller Power Management. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep112.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP113]TEP 113: Serial Communication. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep113.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP114]TEP 114: SIDs: Source and Sink Independent Drivers. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep114.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP115]TEP 115: Power Management of Non-Virtualised Devices. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep115.html?pathrev=tinyos-2_0_devel-BRANCH
+ + + + + +
[TEP116]TEP 116: Packet Protocols. http://tinyos.cvs.sourceforge.net/checkout/tinyos/tinyos-2.x/doc/html/tep116.html?pathrev=tinyos-2_0_devel-BRANCH
+
+
+ + diff --git a/doc/html/porting.html b/doc/html/porting.html index dfc638f3..a7f668d8 100644 --- a/doc/html/porting.html +++ b/doc/html/porting.html @@ -3,7 +3,7 @@ - + Porting TinyOS 1.x Code to TinyOS 2.0 @@ -42,11 +42,6 @@ blockquote.epigraph { dd { margin-bottom: 0.5em } -/* Uncomment (& remove this text!) to get bold-faced definition list terms -dt { - font-weight: bold } -*/ - div.abstract { margin: 2em 5em } @@ -284,6 +279,7 @@ ul.auto-toc { +

Porting TinyOS 1.x Code to TinyOS 2.0

@@ -295,18 +291,17 @@ ul.auto-toc {
October 26 2006
-

Note

-

This document provides a few important points that describe +

This document provides a few important points that describe major steps required for porting TinyOS 1.x code to TinyOS 2.0. It is based on Tahir Azim's experience porting Beacon Vector Routing (BVR[1]) from TinyOS 1.x to T2. This document is not a complete porting guide, but the hope is that it will provide some help or guidance.

-
-

1. Porting Points

+
+

1. Porting Points

As these observations come from porting a network protocol, they are rather protocol-centric and do not consider other abstractions such as storage. We hope to add such points in the future.

@@ -322,7 +317,7 @@ if (call Packet...) {

In TinyOS 2.x, SUCCESS is equal to a zero error code, while other error codes are non-zero. So calls like this should be changed to make sure they test the result for equality with SUCCESS:

-if (call Packet... () == SUCCESS ) { 
+if (call Packet... () == SUCCESS ) {
       //SUCCESS!: do this...
   }
 
@@ -342,8 +337,8 @@ if (call Packet... () == SUCCESS ) {
-
-

2. Author's Address

+
+

2. Author's Address

Tahir Azim
358 Gates Hall
@@ -364,8 +359,8 @@ if (call Packet... () == SUCCESS ) {
-
-

3. Citations

+
+

3. Citations

diff --git a/doc/html/tep1.html b/doc/html/tep1.html index 8e9d2448..9b0d882c 100644 --- a/doc/html/tep1.html +++ b/doc/html/tep1.html @@ -3,7 +3,7 @@ - +TEP Structure and Keywords +

Analog-to-Digital Converters (ADCs)

@@ -302,7 +298,6 @@ ul.auto-toc {
Jan-Hinrich Hauer, Philip Levis, Vlado Handziski, David Gay
-

Note

This memo documents a part of TinyOS for the TinyOS Community, and @@ -310,15 +305,15 @@ requests discussion and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with [TEP1].

-
-

Abstract

+
+

Abstract

This TEP proposes a hardware abstraction for analog-to-digital converters (ADCs) in TinyOS 2.x, which is aligned to the three-layer Hardware Abstraction Architecture (HAA) specified in [TEP2]. It describes some design principles and documents the set of hardware-independent interfaces to an ADC.

-
-

1. Introduction

+
+

1. Introduction

Analog-to-digital converters (ADCs) are devices that convert analog input signals to discrete digital output signals, typically voltage to a binary number. The interested reader can refer to Appendix A for a brief overview of @@ -421,31 +416,31 @@ provides access to the hardware registers (see

  • the set of standard TinyOS interfaces for collecting ADC conversion results and for configuring an ADC (2. Interfaces)
  • -
  • guidelines on how an ADC's HAL should expose chip-specific +
  • guidelines on how an ADC's HAL should expose chip-specific interfaces (3. HAL guidelines)
  • what components an ADC's HIL MUST implement (4. HIL requirements)
  • -
  • guidelines on how the HIL should be implemented +
  • guidelines on how the HIL should be implemented (5. HIL guidelines)
  • a section pointing to current implementations (6. Implementation)
  • This TEP ends with appendices documenting, as an example, the ADC implementation for the TI MSP430 MCU.

    -
    -

    2. Interfaces

    +
    +

    2. Interfaces

    This TEP proposes the AdcConfigure interface for ADC hardware configuration and the Read, ReadStream and ReadNow interfaces to acquire conversion results. The Read and ReadStream interfaces are documented in [TEP114] and the ReadNow interface is documented in this TEP. A Read[Now|Stream] interface is always provided in conjunction with a AdcConfigure interface.

    -
    -

    Interface for configuring the ADC hardware

    +
    +

    Interface for configuring the ADC hardware

    The AdcConfigure interface is defined as follows:

    -interface AdcConfigure< config_type > 
    +interface AdcConfigure< config_type >
     {
    -  async command config_type getConfiguration(); 
    +  async command config_type getConfiguration();
     }
     

    This interface is used by the ADC stack to retrieve the hardware configuration @@ -468,8 +463,8 @@ The rationale is that the ADC HIL implementation does not have to store an ADC configuration per client - instead the ADC client can, for example, store its configuration in program memory.

    -
    -

    Interfaces for acquiring conversion results

    +
    +

    Interfaces for acquiring conversion results

    This TEP proposes to adopt the following two source-independent data collection interfaces from [TEP114] for the collection of ADC conversion results on the level of HIL:

    @@ -488,24 +483,24 @@ requirements). As the resolution of conversion results is chip-specific, th size_type parameter reflects an upper bound for the chip-specific resolution of the conversion results - the actual resolution may be smaller (e.g. uint16_t for a 12-bit ADC).

    -
    -

    Read

    +
    +

    Read

    The Read interface can be used to sample an ADC channel once and return a single conversion result as an uninterpreted value. The Read interface is documented in [TEP114].

    -
    -

    ReadStream

    +
    +

    ReadStream

    The ReadStream interface can be used to sample an ADC channel multiple times with a specified sampling period. The ReadStream interface is documented in [TEP114] .

    -
    -

    ReadNow

    +
    +

    ReadNow

    The ReadNow interface is intended for split-phase low-latency reading of small values:

    -interface ReadNow<val_t> 
    +interface ReadNow<val_t>
     {
       async command error_t read();
       async event void readDone( error_t result, val_t val );
    @@ -525,16 +520,16 @@ component.

    -
    -

    3. HAL guidelines

    +
    +

    3. HAL guidelines

    As explained in 1. Introduction the HAL exposes the full capabilities of the ADC hardware. Therefore only chip- and platform-dependent clients can wire to the HAL. Although the HAL is chip-specific, both, in terms of implementation and representation, its design should follow the guidelines described in this section to facilitate the mapping to the HIL representation. Appendix B shows the signature of the HAL for the MSP430.

    -
    -

    Resource reservation

    +
    +

    Resource reservation

    As the ADC hardware is a shared resource that is usually multiplexed between several clients some form of access arbitration is necessary. The HAL should therefore provide a parameterized Resource interface, instantiate a @@ -543,8 +538,8 @@ arbiter as described in Resource interface are the topic of [TEP108].

    -
    -

    Configuration and sampling

    +
    +

    Configuration and sampling

    As the ADC hardware is a shared resource the HAL should support hardware configuration and sampling per client (although per-port configuration is possible, it is not recommended, because it forces all clients to use the same @@ -566,8 +561,8 @@ configuration data is passed as a pointer, the HAL component MUST NOT reference it after the return of the respective command. Appendix B shows the HAL interfaces for the MSP430.

    -
    -

    HAL virtualization

    +
    +

    HAL virtualization

    In order to hide wiring complexities and/or export only a subset of all ADC functions generic ADC wrapper components may be provided on the level of HAL. Such components can also be used to ensure that a sampling interface is always @@ -575,14 +570,14 @@ provided with a Resource

    -
    -

    4. HIL requirements

    +
    +

    4. HIL requirements

    The following generic components MUST be provided on all platforms that have an ADC:

    -AdcReadClientC 
    -AdcReadNowClientC 
    -AdcReadStreamClientC 
    +AdcReadClientC
    +AdcReadNowClientC
    +AdcReadStreamClientC
     

    These components provide virtualized access to the HIL of an ADC. They are instantiated by an ADC client and provide/use the four interfaces described in @@ -592,8 +587,8 @@ TEP does not address the issue of how to deal with multiple ADCs on the same platform (the question of how to deal with multiple devices of the same class is a general one in TinyOS 2.x). Appendix C shows the AdcReadClientC for the MSP430.

    -
    -

    AdcReadClientC

    +
    +

    AdcReadClientC

     generic configuration AdcReadClientC() {
       provides {
    @@ -615,8 +610,8 @@ command.  Note that both, size_ty
     placeholders and will be instantiated by the respective HIL implementation (for
     an example, see the AdcReadClientC for the MSP430 in Appendix C).

    -
    -

    AdcReadNowClientC

    +
    +

    AdcReadNowClientC

     generic configuration AdcReadNowClientC() {
       provides {
    @@ -647,8 +642,8 @@ to dynamically "pull" the client's ADC settings when it translates the
     instantiated by the respective HIL implementation (for an example how this is
     done for the AdcReadClientC see Appendix C).

    -
    -

    AdcReadStreamClientC

    +
    +

    AdcReadStreamClientC

     generic configuration AdcReadStreamClientC() {
       provides {
    @@ -668,8 +663,8 @@ will be instantiated by the respective HIL implementation (for an example how
     this is done for the AdcReadClientC see Appendix C).

    -
    -

    5. HIL guidelines

    +
    +

    5. HIL guidelines

    The HIL implementation of an ADC stack has two main tasks: it translates a Read, ReadNow or ReadStream request to a chip-specific HAL sampling command and it abstracts from the Resource interface (the latter only for @@ -699,18 +694,18 @@ check ownership of the client through the ReadNow client.

    -
    -

    6. Implementation

    -
    -

    TestAdc application

    +
    +

    6. Implementation

    +
    +

    TestAdc application

    An ADC HIL test application can be found in tinyos-2.x/apps/tests/TestAdc. Note that this application instantiates generic DemoSensorC, DemoSensorStreamC and DemoSensorNowC components (see [TEP114]) and assumes that these components are actually wired to an ADC HIL. Please refer to tinyos-2.x/apps/tests/TestAdc/README.txt for more information.

    -
    -

    HAA on the MSP430 and Atmega 128

    +
    +

    HAA on the MSP430 and Atmega 128

    The implementation of the ADC12 stack on the MSP430 can be found in tinyos-2.x/tos/chips/msp430/adc12:

    @@ -730,7 +725,7 @@ HAL virtualization components are explained in
  • HplAtm128AdcC.nc is the HPL implementation
  • Atm128AdcP.nc is the HAL implementation
  • -
  • AdcP.nc, WireAdcP.nc and the library components for arbitrating +
  • AdcP.nc, WireAdcP.nc and the library components for arbitrating 'Read', 'ReadNow' and 'ReadStream', ArbitratedReadC and ArbitratedReadStreamC (in tinyos-2.x/tos/system), realize the HIL
  • @@ -740,8 +735,8 @@ the HIL
    -
    -

    Appendix A: Hardware differences between platforms

    +
    +

    Appendix A: Hardware differences between platforms

    The following table compares the characteristics of two microcontrollers commonly used in TinyOS platforms:

    @@ -751,9 +746,9 @@ commonly used in TinyOS platforms:

    - - - + + + @@ -870,8 +865,8 @@ sequence conversion
     Atmel Atmega 128TI MSP430 ADC12
     Atmel Atmega 128TI MSP430 ADC12
    -
    -

    Appendix B: a HAL representation: MSP430 ADC12

    +
    +

    Appendix B: a HAL representation: MSP430 ADC12

    This section shows the HAL signature for the ADC12 of the TI MSP430 MCU. It reflects the four MSP430 ADC12 conversion modes as it lets a client sample an ADC channel once ("Single-channel-single-conversion") or repeatedly @@ -882,41 +877,41 @@ interrupt after multiple samples and thus enable high-frequency sampling. The DMAExtension interface is used to reset the state machine when the DMA is responsible for data transfer (managed in an exterior component):

    -configuration Msp430Adc12P 
    -{ 
    +configuration Msp430Adc12P
    +{
       provides {
    -    interface Resource[uint8_t id]; 
    -    interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id]; 
    +    interface Resource[uint8_t id];
    +    interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
         interface AsyncStdControl as DMAExtension[uint8_t id];
       }
     }
     
    -interface Msp430Adc12SingleChannel 
    -{   
    +interface Msp430Adc12SingleChannel
    +{
       async command error_t configureSingle(const msp430adc12_channel_config_t *config);
       async command error_t configureSingleRepeat(const msp430adc12_channel_config_t *config, uint16_t jiffies);
       async command error_t configureMultiple( const msp430adc12_channel_config_t *config, uint16_t buffer[], uint16_t numSamples, uint16_t jiffies);
       async command error_t configureMultipleRepeat(const msp430adc12_channel_config_t *config, uint16_t buffer[], uint8_t numSamples, uint16_t jiffies);
       async command error_t getData();
       async event error_t singleDataReady(uint16_t data);
    -  async event uint16_t* multipleDataReady(uint16_t buffer[], uint16_t numSamples); 
    +  async event uint16_t* multipleDataReady(uint16_t buffer[], uint16_t numSamples);
     }
     
    -typedef struct 
    -{ 
    -  unsigned int inch: 4;            // input channel 
    -  unsigned int sref: 3;            // reference voltage 
    -  unsigned int ref2_5v: 1;         // reference voltage level 
    -  unsigned int adc12ssel: 2;       // clock source sample-hold-time 
    -  unsigned int adc12div: 3;        // clock divider sample-hold-time 
    +typedef struct
    +{
    +  unsigned int inch: 4;            // input channel
    +  unsigned int sref: 3;            // reference voltage
    +  unsigned int ref2_5v: 1;         // reference voltage level
    +  unsigned int adc12ssel: 2;       // clock source sample-hold-time
    +  unsigned int adc12div: 3;        // clock divider sample-hold-time
       unsigned int sht: 4;             // sample-hold-time
    -  unsigned int sampcon_ssel: 2;    // clock source sampcon signal 
    +  unsigned int sampcon_ssel: 2;    // clock source sampcon signal
       unsigned int sampcon_id: 2;      // clock divider sampcon signal
     } msp430adc12_channel_config_t;
     
    -
    -

    Appendix C: a HIL representation: MSP430 ADC12

    +
    +

    Appendix C: a HIL representation: MSP430 ADC12

    The signature of the AdcReadClientC component for the MSP430 ADC12 is as follows:

    diff --git a/doc/html/tep102.html b/doc/html/tep102.html
    index 006daf74..7d411fb8 100644
    --- a/doc/html/tep102.html
    +++ b/doc/html/tep102.html
    @@ -41,11 +41,6 @@ blockquote.epigraph {
     dd {
       margin-bottom: 0.5em }
     
    -/* Uncomment (& remove this text!) to get bold-faced definition list terms
    -dt {
    -  font-weight: bold }
    -*/
    -
     div.abstract {
       margin: 2em 5em }
     
    @@ -216,7 +211,11 @@ pre.line-block {
     pre.literal-block, pre.doctest-block {
       margin-left: 2em ;
       margin-right: 2em ;
    -  background-color: #eeeeee }
    +  background-color: #eeeeee;
    +  border-color: #000000;
    +  border-width: thin; 
    +  font-size: 14px
    +}
     
     span.classifier {
       font-family: sans-serif ;
    @@ -271,10 +270,7 @@ th.docinfo-name, th.field-name {
     h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
       font-size: 100% }
     
    -tt {
    -  font: Courier,monospaced;
    -  font-size: 12px;
    -  background-color: #eeeeee }
    +tt {}
     
     ul.auto-toc {
       list-style-type: none }
    @@ -302,9 +298,9 @@ ul.auto-toc {
     Cory Sharp, Martin Turon, David Gay
     Draft-Created:22-Sep-2004
     
    -Draft-Version:1.9
    +Draft-Version:1.10
     
    -Draft-Modified:2007-05-23
    +Draft-Modified:2007-06-11
     
     Draft-Discuss:TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu>
     
    diff --git a/doc/html/tep103.html b/doc/html/tep103.html
    index 82fc95b3..c9ab9f1c 100644
    --- a/doc/html/tep103.html
    +++ b/doc/html/tep103.html
    @@ -3,7 +3,7 @@
     
     
     
    -
    +
     Permanent Data Storage (Flash)
     
     
     
     
    +

    Permanent Data Storage (Flash)

    @@ -302,7 +298,6 @@ ul.auto-toc {
    David Gay, Jonathan Hui
    -

    Note

    This memo documents a part of TinyOS for the TinyOS Community, and @@ -310,14 +305,14 @@ requests discussion and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with TEP 1.

    -
    -

    Abstract

    +
    +

    Abstract

    This memo documents a set of hardware-independent interfaces to non-volatile storage for TinyOS 2.x. It describes some design principles for the HPL and HAL layers of various flash chips.

    -
    -

    1. Introduction

    +
    +

    1. Introduction

    Flash chips are a form of EEPROM (electrically-erasable, programmable read-only memory), distinguished by a fast erase capability. However, erases can only be done in large units (from 256B to 128kB depending on the @@ -338,17 +333,14 @@ significantly different tradeoffs than other flash chips:

    -X -NOR +X +NOR (ex: ST M25P40, Intel PXA27x) -AT45DB -
    -
    NAND
    -
    (ex: Samsung -K9K1G08R0B)
    -
    - +AT45DB +NAND +(ex: Samsung +K9K1G08R0B) @@ -444,8 +436,8 @@ reimplemented for these other chips, in part because it does not support some applications (e.g., network reprogramming) very well.
    -
    -

    2. Storage in TinyOS 2.x

    +
    +

    2. Storage in TinyOS 2.x

    One approach to hiding the differences between different flash chips is to provide a disk-like, block interface (with, e.g., 512B blocks). This is the approach taken by compact flash cards. However, in the context of TinyOS, @@ -503,8 +495,8 @@ this framework.

    flash chips (Section 3), then describes the flash volumes and storage abstractions in detail (Section 4).

    -
    -

    3. HPL/HAL/HIL Architecture

    +
    +

    3. HPL/HAL/HIL Architecture

    The flash chip architecture follows the three-layer Hardware Abstraction Architecture (HAA), with each chip providing a presentation layer (HPL, Section 3.1), adaptation layer (HAL, Section 3.2) and @@ -515,8 +507,8 @@ family with a similar interface, the HAA SHOULD support all family members by relying, e.g., on platform-provided configuration information.

    Appendix A shows example HPL and HAL specifications for the AT45DB and ST M25P chip families.

    -
    -

    3.1 Hardware Presentation Layer (HPL)

    +
    +

    3.1 Hardware Presentation Layer (HPL)

    The flash HPL has a chip-dependent, platform-independent interface. The implementation of this HPL is platform-dependent. The flash HPL SHOULD be stateless.

    @@ -528,8 +520,8 @@ directory. If the flash chip implementation supports a family of flash chips, this directory MAY also contain a file describing the particular flash chip found on the platform.

    -
    -

    3.2 Hardware Adaptation Layer (HAL)

    +
    +

    3.2 Hardware Adaptation Layer (HAL)

    The flash HAL has a chip-dependent, platform-independent interface and implementation. Flash families with a common HPL SHOULD have a common HAL. Flash HAL's SHOULD expose a Resource interface and automatically @@ -538,8 +530,8 @@ provide a way to access the volume information specified by the programmer (see Section 3). This allows users to build new flash abstractions that interact cleanly with the rest of the flash system.

    -
    -

    3.3 Hardware Interface Layer (HIL)

    +
    +

    3.3 Hardware Interface Layer (HIL)

    Each flash chip MUST support at least one of the storage abstractions described in Section 4. These abstractions SHOULD be presented in components named ChipAbstractionC, e.g., At45dbLogStorageC. @@ -553,13 +545,13 @@ SHOULD redirect uses of Abstracti chip, based on the requested volume.

    -
    -

    4. Non-Volatile Storage Abstractions

    +
    +

    4. Non-Volatile Storage Abstractions

    The HIL implementations are platform-independent, but chip (family) dependent. They implement the three storage abstractions and volume structure discussed in the introduction.

    -
    -

    4.1. Volumes

    +
    +

    4.1. Volumes

    The division of the flash chip into fixed-size volumes is specified by an XML file that is placed in the application's directory (where one types 'make'). The XML file specifies the allocation as follows:

    @@ -597,8 +589,8 @@ components new BlockStorageC(VOLUME_DELUGE0); compile-time error since the symbol will be undefined.

    A volume MUST NOT be used with more than one storage abstraction instance.

    -
    -

    4.2 Large objects

    +
    +

    4.2 Large objects

    The motivating example for large objects is the transmission or long-term storage of large pieces of data. For instance, programs in a network-reprogramming system, or large data-packets in a reliable @@ -647,8 +639,8 @@ integrity of the BlockStorage data, but such support can easily be built by using the computeCrc command and storing the result in a well-defined location, and checking this CRC when desired.

    -
    -

    4.3 Logging

    +
    +

    4.3 Logging

    Event and result logging is a common requirement in sensor networks. Such logging should be reliable (a mote crash should not lose data). It should also be easy to extract data from the log, @@ -735,8 +727,8 @@ a single record. However, the guarantee that only whole records are lost is sufficient to ensure that applications do not to have worry about incomplete or inconsistent log entries.

    -
    -

    4.4 Small objects:

    +
    +

    4.4 Small objects:

    Sensor network applications need to store configuration data, e.g., mote identity, radio frequency, sample rates, etc. Such data is not large, but losing it may lead to a mote misbehaving or losing contact with the @@ -783,13 +775,13 @@ in the small object. definitions.

    -
    -

    5. Implementations

    +
    +

    5. Implementations

    An AT45DB implementation can be found in tinyos-2.x/tos/chips/at45db.

    An ST M25P implementation can be found in tinyos-2.x/tos/chips/stm25p.

    -
    -

    6. Authors' Addresses

    +
    +

    6. Authors' Addresses

    David Gay
    2150 Shattuck Ave, Suite 1300
    @@ -809,8 +801,8 @@ definitions.

    -
    -

    7. Citations

    +
    +

    7. Citations

    @@ -825,10 +817,10 @@ motes. (version 1.0)."
    -
    -

    Appendix A. HAA for some existing flash chips

    -
    -

    A.1 AT45DB

    +
    +

    Appendix A. HAA for some existing flash chips

    +
    +

    A.1 AT45DB

    The Atmel AT45DB family HPL is:

     configuration HplAt45dbC {
    @@ -878,8 +870,8 @@ copy. It also includes flush and sync operations to manage the cache.

    The At45dbVolume interface has operations to report volume size and map volume-relative pages to absolute pages.

    -
    -

    A.2 ST M25P

    +
    +

    A.2 ST M25P

    The ST M25P family HPL is:

     configuration Stm25pSpiC {
    @@ -912,13 +904,13 @@ volume-relative addresses. Clients of the ST M25P HAL must implement the
     obtain the volume id of each of its clients.

    -
    -

    Appendix B. Storage interfaces

    +
    +

    Appendix B. Storage interfaces

    These interfaces are presented briefly here for reference; please refer to the TinyOS documentation for a full description of the commands, events and their parameters.

    -
    -

    B.1 BlockStorage interfaces

    +
    +

    B.1 BlockStorage interfaces

    The BlockStorage interfaces are:

     interface BlockRead {
    @@ -947,8 +939,8 @@ interface BlockWrite {
     }
     
    -
    -

    B.2 ConfigStorage interfaces

    +
    +

    B.2 ConfigStorage interfaces

    The ConfigStorage interfaces are:

     interface Mount {
    @@ -973,8 +965,8 @@ interface ConfigStorage {
     }
     
    -
    -

    B.3 LogStorage interfaces

    +
    +

    B.3 LogStorage interfaces

    The LogStorage interfaces are:

     interface LogRead {
    diff --git a/doc/html/tep105.html b/doc/html/tep105.html
    new file mode 100644
    index 00000000..afb17f9b
    --- /dev/null
    +++ b/doc/html/tep105.html
    @@ -0,0 +1,640 @@
    +
    +
    +
    +
    +
    +
    +Low Power Listening
    +
    +
    +
    +
    +
    +

    Low Power Listening

    + +++ + + + + + + + + + + + + + +
    TEP:105
    Group:Core Working Group
    Type:Documentary
    Status:Final
    TinyOS-Version:2.x
    Author:David Moss, Jonathan Hui, Kevin Klues
    +
    +

    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 TEP describes the structure and implementation of the TinyOS 2.x +link layer abstractions. The architecture is designed to allow each radio +type to implement its own low power strategy within the Hardware Adaptation +Layer (HAL), while maintaining a common application interface. The +history and strategies for low power listening are discussed, as well +as expected behavior and implementation recommendations.

    +
    +
    +

    1. Introduction

    +

    Asynchronous low power listening is a strategy used to duty cycle +the radio while ensuring reliable message delivery since TinyOS 1.x +[MICA2].

    +

    While a CC1000 or CC2420 radio is turned on and listening, it can +actively consume anywhere between 7.4 to 18.8 mA on top of the power +consumed by other components in the system [CC1000],[CC2420]_. +This can rapidly deplete batteries. In the interest of extending +battery lifetime, it is best to duty cycle the radio on and off to +prevent this idle waste of energy. In an asychronous low power +message delivery scheme, the duty cycling receiver node saves the +most energy by performing short, periodic receive checks. The power +consumption burden is then placed on the transmitter node, which +must modulate the radio channel long enough for the recipient?s +receive check to detect an incoming message. A synchronous low +power message delivery scheme takes this idea a step further by +allowing the transmitter to only transmit when it knows the +destination node is performing a receive check.

    +
    +
    +

    2. Background

    +
    +

    2.1 Early TinyOS 1.x CC1000 Low Power Listening Implementation

    +

    TinyOS 1.x introduced low power listening on the CC1000 radio, but +never introduced a similar scheme for the CC2420 radio in the baseline. +The CC1000 radio had the following low power listening commands, +provided directly by CC1000RadioIntM::

    +
    +command result_t SetListeningMode(uint8_t power);
    +command uint8_t GetListeningMode();
    +command result_t SetTransmitMode(uint8_t power);
    +command uint8_t GetTransmitMode();
    +
    +

    The uint8_t 'power' mode parameter was initially defined as follows::

    +
    +//Original CC1000 Low Power Listening Modes
    +Power Mode 0 = 100% duty cycle
    +Power Mode 1 = 35.5% duty cycle
    +Power Mode 2 = 11.5% duty cycle
    +Power Mode 3 = 7.53% duty cycle
    +Power Mode 4 = 5.61% duty cycle
    +Power Mode 5 = 2.22% duty cycle
    +Power Mode 6 = 1.00% duty cycle
    +
    +

    There were several issues with this interface and implementation. +First, setting up a low power network was cumbersome. The low power +listening commands had to be directly wired through CC1000RadioIntM, +and called while the radio was not performing any transactions. +Second, each node in a network was expected to have the same radio +power mode. Finally, the pre-programmed duty cycles were not linear +and offered a very limited selection of options.

    +

    In this low power listening implementation, the transmitter mote would +transmit a packet that consisted of an extremely long preamble. This +preamble was long enough to span a complete receive check period. On +the receiver?s end, the radio would turn on and read bits from the +radio. If a preamble sequence was detected in the incoming bits, the +receiver?s radio would remain on for the full duration of the +transmitter?s preamble and wait for the packet at the end.

    +

    This original low power listening scheme was rather inefficient on both +the transmit and receive end. On the receive end, turning on the radio +completely and reading in bits typically cost much more energy than +necessary. The transmitter's long preamble could end up costing both +nodes to have their radios on much longer than required, sending and +receiving useless preamble bits.

    +
    +
    +

    2.2 CC1000 Pulse Check Implementation

    +

    Joe Polastre and Jason Hill developed a better receive check +implementation in the CC1000 ?Pulse Check? radio stack for TinyOS 1.x, +while maintaining the same interface. This implementation took advantage +of a Clear Channel Assessment (CCA) to determine if a transmitter was +nearby.

    +

    In this implementation, the CC1000 radio did not have to be turned on +completely, so it consumed less maximum current than the previous +implementation. The radio on-time was also significantly reduced, only +turning on long enough for a single ADC conversion to occur. If energy +was detected on the channel after the first ADC conversion, subsequent +ADC conversions would verify this before committing to turning the +radio receiver on completely.

    +

    In this implementation the receiver's efficiency dramatically improved, +but the transmitter still sent a long, inefficient preamble. Energy +consumption used to transmit messages was still high, while throughput +was still low.

    +
    +
    +

    2.3 Possible Improvements

    +

    Low power listening is a struggle between minimizing energy efficiency +and maximizing throughput. In an asynchronous low power listening +scheme, several improvements can be made over earlier implementations. +One improvement that could have been made to earlier implementations is +to remove the long transmitted preamble and send many smaller messages +instead. For example, the transmitter could send the same message over +and over again for the duration of the receiver's receive check period. +The receiver could wake up and see that another node is transmitting, +receive a full message, and finally send back an acknowledgement for that +message. The transmitter would see the acknowledgement and stop +transmitting early, so both nodes can perform some high speed transaction +or go back to sleep. Useless preamble bits are minimized while useful +packet information is maximized. Incidentally, this is a good strategy +for CC2420 low power listening. This strategy certainly improves energy +efficiency and throughput, but further improvements may be possible by +employing a synchronous delivery method on top of this type of +asynchronous low power listening scheme.

    +

    Improvements can also be made to the original low power listening +interfaces. For example, instead of pre-programming power modes and +duty cycles, a low power listening interface should allow the developer +the flexibility to deploy a network of nodes with whatever duty cycle +percentage or sleep time desired for each individual node. Nodes with +different receive check periods should still have the ability to +reliably communicate with each other with little difficulty.

    +
    +
    + +
    +

    3.1 Low Power Listening Interface

    +

    The LowPowerListening interface MUST be provided for each radio by the +platform independent ActiveMessageC configuration.

    +

    In some implementations, low power listening may have an option to +compile into the radio stack for memory footprint reasons. If low +power listening is not compiled in with the stack, calls to +LowPowerListening MUST be handled by a dummy implementation.

    +

    The TEP proposes this LowPowerListening interface::

    +
    +interface LowPowerListening {
    +  command void setLocalSleepInterval(uint16_t sleepIntervalMs);
    +  command uint16_t getLocalSleepInterval();
    +  command void setLocalDutyCycle(uint16_t dutyCycle);
    +  command uint16_t getLocalDutyCycle();
    +  command void setRxSleepInterval(message_t *msg, uint16_t sleepIntervalMs);
    +  command uint16_t getRxSleepInterval(message_t *msg);
    +  command void setRxDutyCycle(message_t *msg, uint16_t dutyCycle);
    +  command uint16_t getRxDutyCycle(message_t *msg);
    +  command uint16_t dutyCycleToSleepInterval(uint16_t dutyCycle);
    +  command uint16_t sleepIntervalToDutyCycle(uint16_t sleepInterval);
    +}
    +
    +
    +
    setLocalSleepInterval(uint16_t sleepIntervalMs)
    +
      +
    • Sets the local node?s radio sleep interval, in milliseconds.
    • +
    +
    +
    getLocalSleepInterval()
    +
      +
    • Retrieves the local node?s sleep interval, in milliseconds. If duty cycle percentage was originally set, it is automatically converted to a sleep interval.
    • +
    +
    +
    setLocalDutyCycle(uint16_t dutyCycle)
    +
      +
    • Set the local node?s duty cycle percentage, in units of [percentage*100].
    • +
    +
    +
    getLocalDutyCycle()
    +
      +
    • Retrieves the local node?s duty cycle percentage. If sleep interval in milliseconds was originally set, it is automatically converted to a duty cycle percentage.
    • +
    +
    +
    setRxSleepInterval(message_t *msg, uint16_t sleepIntervalMs)
    +
      +
    • The given message will soon be sent to a low power receiver. The sleepIntervalMs is the sleep interval of that low power receiver, in milliseconds. When sent, the radio stack will automatically transmit the message so as to be detected by the low power receiver.
    • +
    +
    +
    getRxSleepInterval(message_t *msg)
    +
      +
    • Retrieves the message destination?s sleep interval. If a duty cycle was originally set for the outgoing message, it is automatically converted to a sleep interval.
    • +
    +
    +
    setRxDutyCycle(message_t *msg, uint16_t dutyCycle)
    +
      +
    • The given message will soon be sent to a low power receiver. The dutyCycle is the duty cycle percentage, in units of [percentage*100], of that low power receiver. When sent, the radio stack will automatically transmit the message so as to be detected by the low power receiver.
    • +
    +
    +
    getRxDutyCycle(message_t *msg)
    +
      +
    • Retrieves the message destination?s duty cycle percentage. If a sleep interval was originally set for the outgoing message, it is automatically converted to a duty cycle percentage.
    • +
    +
    +
    dutyCycleToSleepInterval(uint16_t dutyCycle)
    +
      +
    • Converts the given duty cycle percentage to a sleep interval in milliseconds.
    • +
    +
    +
    sleepIntervalToDutyCycle(uint16_t sleepInterval)
    +
      +
    • Converts the given sleep interval in milliseconds to a duty cycle percentage.
    • +
    +
    +
    +
    +

    3.2 Split Control Behaviour

    +

    Low power listening MUST be enabled and disabled through the radio?s +standard SplitControl interface, returning exactly one SplitControl +event upon completion. While the radio is duty cycling, it MUST NOT +alert the application layer each time the radio turns on and off to +perform a receive check or send a message.

    +
    +
    +

    3.3 Send Interface Behaviour

    +

    Attempts to send a message before SplitControl.start() has been called +SHOULD return EOFF, signifying the radio has not been enabled. When +SplitControl.start() has been called by the application layer, calls +to Send MUST turn the radio on automatically if the radio is currently +off due to duty cycling. If a message is already in the process of +being sent, multiple calls to Send should return FAIL.

    +

    The Send.sendDone(?) event SHOULD signal SUCCESS upon the successful +completion of the message delivery process, regardless if any mote +actually received the message.

    +
    +
    +

    3.4 Receive Interface Behaviour

    +

    Upon the successful reception of a message, the low power receive event +handler SHOULD drop duplicate messages sent to the broadcast address. +For example, the CC2420 implementation can perform this by checking +the message_t?s dsn value, where each dsn value is identical for every +message used in the delivery.

    +

    After the first successful message reception, the receiver?s radio +SHOULD stay on for a brief period of time to allow any further +transactions to occur at high speed. If no subsequent messages are +detected going inbound or outbound after some short delay, the radio +MUST continue duty cycling as configured.

    +
    +
    +
    +

    4. Low Power Listening message_t Metadata

    +

    To store the extra 16-bit receiver low power listening value, the radio +stack?s message_t footer MUST contain a parameter to store the message +destination?s receive check sleep interval in milliseconds or duty cycle +percentage. For example, the low power listening CC2420 message_t footer +stores the message's receive check interval in milliseconds, as shown +below [TEP111].:

    +
    +typedef nx_struct cc2420_metadata_t {
    +  nx_uint8_t tx_power;
    +  nx_uint8_t rssi;
    +  nx_uint8_t lqi;
    +  nx_bool crc;
    +  nx_bool ack;
    +  nx_uint16_t time;
    +  nx_uint16_t rxInterval;
    +} cc2420_metadata_t;
    +
    +
    +
    +

    5. Recommendations for HAL Implementation

    +

    In the interest of minimizing energy while maximizing throughput, it +is RECOMMENDED that any asynchronous low power listening implementation +use clear channel assessment methods to determine the presence of a +nearby transmitter. It is also RECOMMENDED that the transmitter send +duplicate messages continuously with minimum or no backoff period instead +of one long message. Removing backoffs on a continuous send delivery +scheme will allow the channel to be modulated sufficiently for a receiver +to quickly detect; furthermore, enabling acknowledgements on each +outgoing duplicate packet will allow the transmit period to be cut short +based on when the receiver actually receives the message.

    +

    Asynchronous low power listening requires some memory overhead, so +sometimes it is better to leave the added architecture out when it is +not required. When it is feasible to do so, it is RECOMMENDED that +the preprocessor variable LOW_POWER_LISTENING be defined when low +power listening functionality is to be compiled in with the radio stack, +and not defined when low power listening functionality shouldn?t exist.

    +

    It is RECOMMENDED that the radio on-time for actual receive checks be a +measured value to help approximate the duty cycle percentage.

    +
    +
    +

    6. Author's Address

    +
    +
    David Moss
    +
    Rincon Research Corporation
    +
    101 N. Wilmot, Suite 101
    +
    Tucson, AZ 85750
    +

    +
    phone - +1 520 519 3138
    + +

    +
    Jonathan Hui
    +
    657 Mission St. Ste. 600
    +
    Arched Rock Corporation
    +
    San Francisco, CA 94105-4120
    +

    +
    phone - +1 415 692 0828
    + +

    +
    Kevin Klues
    +
    503 Bryan Hall
    +
    Washington University
    +
    St. Louis, MO 63130
    +

    +
    phone - +1-314-935-6355
    + +
    +
    +
    +

    7. Citations

    + + + + + +
    [MICA2]"MICA2 Radio Stack for TinyOS." http://www.tinyos.net/tinyos-1.x/doc/mica2radio/CC1000.html
    + + + + + +
    [TEP111]TEP 111: message_t.
    + + + + + +
    [CC1000]TI/Chipcon CC1000 Datasheet. http://www.chipcon.com/files/CC1000_Data_Sheet_2_2.pdf
    + + + + + +
    [CC2420]TI/Chipcon CC2420 Datasheet. http://www.chipcon.com/files/CC2420_Data_Sheet_1_3.pdf
    +
    +
    + + diff --git a/doc/html/tep106.html b/doc/html/tep106.html index b7f83537..8f19af57 100644 --- a/doc/html/tep106.html +++ b/doc/html/tep106.html @@ -3,7 +3,7 @@ - + Schedulers and Tasks +

    Schedulers and Tasks

    @@ -302,7 +298,6 @@ ul.auto-toc {
    Philip Levis and Cory Sharp
    -

    Note

    This memo documents a part of TinyOS for the TinyOS Community, and @@ -310,13 +305,13 @@ requests discussion and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with TEP 1.

    -
    -

    Abstract

    +
    +

    Abstract

    This memo documents the structure and implementation of tasks and task schedulers in TinyOS 2.x.

    -
    -

    1. Introduction

    +
    +

    1. Introduction

    TinyOS has two basic computational abstractions: asynchronous events and tasks. Early versions of TinyOS provided a single type of task -- parameter free -- and only a FIFO scheduling policy. While changing @@ -328,8 +323,8 @@ available. TinyOS 2.0 takes both approaches, and this memo documents the structure of how it does so as well as a simple mechanism that greatly increases system dependability.

    -
    -

    2. Tasks and the Scheduler in TinyOS 1.x

    +
    +

    2. Tasks and the Scheduler in TinyOS 1.x

    Tasks in TinyOS are a form of deferred procedure call (DPC) [1], which enable a program to defer a computation or operation until a later time. TinyOS tasks run to completion and do not pre-empt one @@ -340,8 +335,8 @@ are atomic with respect to other tasks task declarations and post expressions:

     task void computeTask() {
    -  // Code here  
    -}  
    +  // Code here
    +}
     

    and:

    @@ -398,28 +393,28 @@ application component does not try to send another packet until it
     knows the one it is sending completes (so it can re-use the
     buffer). As the sendDone() event was lost, this does not occur,
     and the application stops sending network traffic.

    -

    The solution to this particular problem in TinyOS 1.x is to signal -sendDone() in the radio send complete interrupt if the post fails: -this violates the sync/async boundary, but the justification is that -a possible rare race condition is better than certain failure. +

    The solution to this particular problem in TinyOS 1.x is to signal +sendDone() in the radio send complete interrupt if the post fails: +this violates the sync/async boundary, but the justification is that +a possible rare race condition is better than certain failure. Another solution would be to use an interrupt source to periodically retry posting the task; while this does not break the sync/async -boundary, until the post succeeds the system cannot send packets. +boundary, until the post succeeds the system cannot send packets. The TinyOS 1.x model prevents it from doing any better.

    -
    -

    3. Tasks in TinyOS 2.x

    +
    +

    3. Tasks in TinyOS 2.x

    The semantics of tasks in TinyOS 2.x are different than those in 1.x. This change is based on experiences with the limitations and run time errors that the 1.x model introduces. In TinyOS 2.x, a basic post will -only fail if and only if the task has already been posted and has not -started execution. A task can always run, but can only have one +only fail if and only if the task has already been posted and has not +started execution. A task can always run, but can only have one outstanding post at any time.

    2.x achieves these semantics by allocating one byte of state per task (the assumption is that there will be fewer than 255 -tasks in the system). While a very large number of tasks could make +tasks in the system). While a very large number of tasks could make this overhead noticable, it is not significant in practice. -If a component needs to post a task several times, then the end of +If a component needs to post a task several times, then the end of the task logic can repost itself as need be.

    For example, one can do this:

    @@ -429,7 +424,7 @@ task void processTask() {
       // do work
       if (moreToProcess) {
         post processTask();
    -  } 
    +  }
     }
     

    These semantics prevent several problems, such as the inability to @@ -447,15 +442,15 @@ and an event, run. Th up to the interface. For example, a task interface that allows a task to take an integer parameter could look like this:

    -interface TaskParameter {  
    -  async error_t command postTask(uint16_t param);  
    -  event void runTask(uint16_t param);  
    -}  
    +interface TaskParameter {
    +  async error_t command postTask(uint16_t param);
    +  event void runTask(uint16_t param);
    +}
     

    Using this task interface, a component could post a task with a uint16_t parameter. When the scheduler runs the task, it will signal the runTask event with the passed parameter, which contains -the task's logic. Note, however, that this does not save any RAM: +the task's logic. Note, however, that this does not save any RAM: the scheduler must have RAM allocated for the parameter. Furthermore, as there can only be one copy of a task outstanding at any time, it is just as simple to store the variable in the component. E.g., @@ -475,7 +470,7 @@ uint16_t param; post parameterTask(); ... task void parameterTask() { - // use param + // use param }

    The principal difference between the simplest code for these @@ -490,8 +485,8 @@ if (post myTask() == SUCCESS) { }

    -
    -

    4. The Scheduler in TinyOS 2.x

    +
    +

    4. The Scheduler in TinyOS 2.x

    In TinyOS 2.x, the scheduler is a TinyOS component. Every scheduler MUST support nesC tasks. It MAY also support any number of additional task interfaces. The scheduler component is resonsible for @@ -507,29 +502,29 @@ function to obtain a unique identifier, which the scheduler uses to dispatch tasks.

    For example, the standard TinyOS scheduler has this signature:

    -module SchedulerBasicP {  
    -  provides interface Scheduler;  
    -  provides interface TaskBasic[uint8_t taskID];  
    -  uses interface McuSleep;  
    -}  
    +module SchedulerBasicP {
    +  provides interface Scheduler;
    +  provides interface TaskBasic[uint8_t taskID];
    +  uses interface McuSleep;
    +}
     

    A scheduler MUST provide a parameterized TaskBasic interface. If a call to TaskBasic.postTask() returns SUCCESS, the scheduler MUST run it -eventually, so that starvation is not a concern. The scheduler MUST +eventually, so that starvation is not a concern. The scheduler MUST return SUCCESS to a TaskBasic.postTask() operation unless it is not the first call to TaskBasic.postTask() since -that task's TaskBasic.runTask() event has been signaled. The +that task's TaskBasic.runTask() event has been signaled. The McuSleep interface is used for microcontroller power management; its workings are explained in TEP 112 [3].

    -

    A scheduler MUST provide the Scheduler interface. +

    A scheduler MUST provide the Scheduler interface. The Scheduler interface has commands for initialization and running tasks, and is used by TinyOS to execute tasks:

    -interface Scheduler {  
    -  command void init();  
    -  command bool runNextTask(bool sleep);  
    -  command void taskLoop();  
    -}  
    +interface Scheduler {
    +  command void init();
    +  command bool runNextTask(bool sleep);
    +  command void taskLoop();
    +}
     

    The init() command initializes the task queue and scheduler data structures. runNextTask() MUST run to completion whatever task the @@ -549,17 +544,17 @@ within the scheduler improves the efficiency of the task loop, in terms of the assembly generated by the TinyOS toolchain.

    This is the TaskBasic interface:

    -interface TaskBasic {  
    -  async command error_t postTask();  
    -  void event runTask();  
    -}  
    +interface TaskBasic {
    +  async command error_t postTask();
    +  void event runTask();
    +}
     

    When a component declares a task with the task keyword in nesC, it is implicitly declaring that it uses an instance of the TaskBasic interface: the task body is the runTask event. When a component uses the post keyword, it calls the postTask command. Each TaskBasic MUST be -wired to the scheduler with a unique identifier as its parameter. -The parameter MUST be obtained with the unique function in nesC, +wired to the scheduler with a unique identifier as its parameter. +The parameter MUST be obtained with the unique function in nesC, with a key of "TinySchedulerC.TaskBasic". The nesC compiler automatically does this wiring when the task and post keywords are used.

    @@ -572,8 +567,8 @@ components MUST NOT assume a FIFO policy. If two tasks must run in a particular temporal order, this order should be enforced by the earlier task posting the later task.

    -
    -

    5. Replacing the Scheduler

    +
    +

    5. Replacing the Scheduler

    The TinyOS scheduler is presented as a component named TinySchedulerC. The default TinyOS scheduler implementation is a module named SchedulerBasicP; the default scheduler component is a configuration @@ -586,41 +581,41 @@ scheduler implementations MUST provide a parameterize TaskBasic interface, as SchedulerBasicP does; this supports nesC post statements and task declarations and enables TinyOS core systems to operate properly. Generally, TinyOS core code needs to be able to run unchanged -with new scheduler implementations. All scheduler +with new scheduler implementations. All scheduler implementations MUST provide the Scheduler interface.

    For example, imagine a hypothetical scheduler that provides earliest deadline first tasks, which are provided through the TaskEdf interface:

    -interface TaskEdf {  
    -  async command error_t postTask(uint16_t deadlineMs);  
    -  event void runTask();  
    -}  
    +interface TaskEdf {
    +  async command error_t postTask(uint16_t deadlineMs);
    +  event void runTask();
    +}
     

    The scheduler implementation is named SchedulerEdfP, and provides both TaskBasic and TaskEdf interfaces:

    -module SchedulerEdfP {  
    -  provides interface Scheduler;  
    -  provides interface TaskBasic[uint8_t taskID];  
    -  provides interface TaskEdf[uint8_t taskID];  
    -}  
    +module SchedulerEdfP {
    +  provides interface Scheduler;
    +  provides interface TaskBasic[uint8_t taskID];
    +  provides interface TaskEdf[uint8_t taskID];
    +}
     

    An application that wants to use SchedulerEdfP instead of SchedulerBasicP includes a configuration named TinySchedulerC, which exports all of SchedulerEdfP's interfaces:

    -configuration TinySchedulerC {  
    -  provides interface Scheduler;  
    -  provides interface TaskBasic[uint8_t taskID];  
    -  provides interface TaskEdf[uint8_t taskID];  
    -}  
    -implementation {  
    -  components SchedulerEdfP;  
    -  Scheduler = SchedulerEdf;  
    -  TaskBasic = SchedulerEdfP;  
    -  TaskEDF   = SchedulerEdfP;  
    -}  
    +configuration TinySchedulerC {
    +  provides interface Scheduler;
    +  provides interface TaskBasic[uint8_t taskID];
    +  provides interface TaskEdf[uint8_t taskID];
    +}
    +implementation {
    +  components SchedulerEdfP;
    +  Scheduler = SchedulerEdf;
    +  TaskBasic = SchedulerEdfP;
    +  TaskEDF   = SchedulerEdfP;
    +}
     

    For a module to have an earliest deadline first task, it uses the TaskEdf interface. Its configuration SHOULD wire it to TinySchedulerC. @@ -634,14 +629,14 @@ is to #define it. For example, TaskEdf.nc might include:

    In this example, the module SomethingP requires two EDF tasks:

    -configuration SomethingC {  
    -  ...  
    -}  
    -implementation {  
    -  components SomethingP, TinySchedulerC;  
    -  SomethingP.SendTask -> TinySchedulerC.TaskEdf[unique(UQ_TASK_EDF)];  
    -  SomethingP.SenseTask -> TinySchedulerC.TaskEdf[unique(UQ_TASK_EDF)];  
    -}  
    +configuration SomethingC {
    +  ...
    +}
    +implementation {
    +  components SomethingP, TinySchedulerC;
    +  SomethingP.SendTask -> TinySchedulerC.TaskEdf[unique(UQ_TASK_EDF)];
    +  SomethingP.SenseTask -> TinySchedulerC.TaskEdf[unique(UQ_TASK_EDF)];
    +}
     

    The module SomethingP also has a basic task. The nesC compiler automatically transforms task keywords into BasicTask interfaces and @@ -651,55 +646,55 @@ interface. A component SHOULD use the keywords whenever possible, and it MUST NOT mix the two syntaxes for a given task. This is an example implementation of SomethingP that uses keywords for basic tasks:

    -module SomethingP {  
    -  uses interface TaskEdf as SendTask  
    -  uses interface TaskEdf as SenseTask  
    -}  
    -implementation {  
    -  // The TaskBasic, written with keywords  
    -  task void cleanupTask() { ... some logic ... }  
    -  event void SendTask.runTask() { ... some logic ... }  
    -  event void SenseTask.runTask() { ... some logic ... }  
    -
    -  void internal_function() {  
    -    call SenseTask.postTask(20);  
    -    call SendTask.postTask(100);  
    -    post cleanupTask();  
    -  }  
    -}  
    +module SomethingP {
    +  uses interface TaskEdf as SendTask
    +  uses interface TaskEdf as SenseTask
    +}
    +implementation {
    +  // The TaskBasic, written with keywords
    +  task void cleanupTask() { ... some logic ... }
    +  event void SendTask.runTask() { ... some logic ... }
    +  event void SenseTask.runTask() { ... some logic ... }
    +
    +  void internal_function() {
    +    call SenseTask.postTask(20);
    +    call SendTask.postTask(100);
    +    post cleanupTask();
    +  }
    +}
     

    The requirement that basic tasks not be subject to starvation requires that a scheduler supporting EDF tasks must ensure that basic tasks run eventually even if there is an unending stream of short deadline tasks to run. Quantifying "eventually" is difficult, -but a 1% share of the MCU cycles (or invocations) is a reasonable +but a 1% share of the MCU cycles (or invocations) is a reasonable approximation.

    If the scheduler provides two instances of the same task interface, -their unique keys are based on the name of the interface as the +their unique keys are based on the name of the interface as the scheduler presents it (the "as" keyword). For example, imagine a scheduler which provides two instances of TaskBasic: standard tasks and high-priority tasks. The scheduler usually selects a task for the high priority queue before the standard queue:

    -configuration TinySchedulerC {  
    -  provides interface Scheduler;  
    -  provides interface TaskBasic[uint8_t taskID];  
    -  provides interface TaskBasic[uint8_t taskID] as TaskHighPriority;  
    -}  
    +configuration TinySchedulerC {
    +  provides interface Scheduler;
    +  provides interface TaskBasic[uint8_t taskID];
    +  provides interface TaskBasic[uint8_t taskID] as TaskHighPriority;
    +}
     

    It cannot always select a high priority task because that could -starve basic tasks. A component that uses a high priority task would +starve basic tasks. A component that uses a high priority task would wire to TaskHighPriority with the key "TinySchedulerC.TaskHighPriority":

    -configuration SomethingElseC {}  
    -implementation {  
    -  components TinySchedulerC as Sched, SomethingElseP;  
    -  SomethingElseP.RetransmitTask -> Sched.TaskHighPriority[unique("TinySchedulerC.TaskHighPriority")];  
    -}  
    +configuration SomethingElseC {}
    +implementation {
    +  components TinySchedulerC as Sched, SomethingElseP;
    +  SomethingElseP.RetransmitTask -> Sched.TaskHighPriority[unique("TinySchedulerC.TaskHighPriority")];
    +}
     
    -
    -

    6. Implementation

    +
    +

    6. Implementation

    The following files in tinyos-2.x/tos/system contain the reference implementations of the scheduler:

    @@ -713,15 +708,15 @@ that wires SchedulerBasicP to McuSleepC http://csl.stanford.edu/~pal/tinyos/edf-sched.tgz.

    -
    -

    7. Author's Address

    +
    +

    7. Author's Address

    Philip Levis
    358 Gates Hall
    Stanford University
    Stanford, CA 94305

    -
    phone - +1 650 725 9046
    +
    phone - +1 650 725 9046

    Cory Sharp
    @@ -732,12 +727,12 @@ at the URL http://csl.stanford.ed
    -
    -

    8. Citations

    +
    +

    8. Citations

    - @@ -759,8 +754,8 @@ Programming Language Design and Implementation (PLDI).
    [1]Erik Cota-Robles and James P. Held. "A Comparison of Windows +
    [1]Erik Cota-Robles and James P. Held. "A Comparison of Windows Driver Model Latency Performance on Windows NT and Windows 98." In Proceedings of the Third Symposium on Operating System Design and Implementation (OSDI).
    -
    -

    Appendix A: Changing the Scheduler

    +
    +

    Appendix A: Changing the Scheduler

    The nesC compiler transforms the post and task keywords into nesC interfaces, wirings, and calls. By default, the statement:

    @@ -771,7 +766,7 @@ implementation {
       task x() {
         ...
         post x();
    -  } 
    +  }
     
     }
     
    diff --git a/doc/html/tep107.html b/doc/html/tep107.html index 77316a12..11e98437 100644 --- a/doc/html/tep107.html +++ b/doc/html/tep107.html @@ -3,7 +3,7 @@ - + TinyOS 2.x Boot Sequence +

    TinyOS 2.x Boot Sequence

    @@ -302,7 +298,6 @@ ul.auto-toc {
    Philip Levis
    -

    Note

    This memo documents a part of TinyOS for the TinyOS Community, and @@ -310,13 +305,13 @@ requests discussion and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with TEP 1.

    -
    -

    Abstract

    +
    +

    Abstract

    This memo documents the structure and implementation of the mote boot sequence in TinyOS 2.x.

    -
    -

    1. Introduction

    +
    +

    1. Introduction

    TinyOS has a set of calling conventions and semantics in its boot sequence. Earlier versions of TinyOS used an interface named "StdControl" to take care of system initialization and starting @@ -330,8 +325,8 @@ initialization, one for starting and stopping components, and one for notification that the mote has booted. This memo describes the TinyOS boot sequence and reasons for its semantics.

    -
    -

    2. TinyOS 1.x Boot Sequence

    +
    +

    2. TinyOS 1.x Boot Sequence

    The TinyOS 1.x boot sequence is uniform across most mote platforms (TOSSIM has a very different boot sequence, as it is a PC program). The module RealMain implements main(), and has the following @@ -351,11 +346,11 @@ int main() __attribute__ ((C, spontaneous)) { call hardwareInit(); call Pot.init(10); TOSH_sched_init(); - + call StdControl.init(); call StdControl.start(); __nesc_enable_interrupt(); - + while(1) { TOSH_run_task(); } @@ -386,8 +381,8 @@ start/stop model. In this case, some components can't operate properly until the radio starts, but main has no mechanism for waiting for the radio start completion event.

    -
    -

    3. TinyOS 2.x Boot Interfaces

    +
    +

    3. TinyOS 2.x Boot Interfaces

    The TinyOS 2.x boot sequence uses three interfaces:

      @@ -408,7 +403,7 @@ range of components need to be interleaved effectively, initialization is a sequential, synchronous operation: no component can be started until initialization is complete. If a particular component's initialization requires waiting for interrupts or other asynchronous -events, then it must explicitly wait for them (e.g., +events, then it must explicitly wait for them (e.g., with a spin loop), MUST NOT return until complete. Otherwise the system may start before initialization is complete.

      The Scheduler interface is for initializing and controlling task @@ -421,8 +416,8 @@ interface Boot { }

    -
    -

    4. TinyOS 2.x Boot Sequence

    +
    +

    4. TinyOS 2.x Boot Sequence

    The module RealMainP implements the standard TinyOS 2.x boot sequence. The configuration MainC wires some of RealMainP's interfaces to components that implement standard abstractions and exports the others @@ -457,8 +452,8 @@ implementation { default event void Boot.booted() { } } -

    -

    4.1 Initialization

    +
    +

    4.1 Initialization

    The first step in the boot sequence is initializing the system:

     atomic {
    @@ -475,11 +470,11 @@ places the system into an executable state. This function MUST NOT include
     operations besides those which are absolutely necessary for further code,
     such as scheduler initialization, to execute.
     Examples of platform_bootstrap() operations are configuring the memory
    -system and setting the processor mode. Generally, platform_bootstrap() 
    +system and setting the processor mode. Generally, platform_bootstrap()
     is an empty function. TinyOS's top-level include file, tos.h, includes
     a default implementation of this function which does nothing. If a platform
     needs to replace the default, it SHOULD put it in a platform's
    -platform.h file as a #define. The implementation of tos.h 
    +platform.h file as a #define. The implementation of tos.h
     supports this:

     /* This platform_bootstrap macro exists in accordance with TEP
    @@ -499,7 +494,7 @@ configuration MainC {
       uses interface Init as SoftwareInit;
     }
     implementation {
    -  components PlatformC, RealMainP, TinySchedulerC;  
    +  components PlatformC, RealMainP, TinySchedulerC;
     
       RealMainP.Scheduler -> TinySchedulerC;
       RealMainP.PlatformInit -> PlatformC;
    @@ -531,7 +526,7 @@ through PlatformC meet some or all of the following criteria:

  • The initialization is a prerequisite for common services in the system.
  • Three example operations that often belong in PlatformInit are I/O pin -configuration, clock calibration, and LED configuration. I/O pin +configuration, clock calibration, and LED configuration. I/O pin configuration meets the first two criteria. It should always be performed (regardless of what components the OS uses) for low-power reasons: incorrectly configured pins can draw current and prevent the MCU from @@ -540,13 +535,13 @@ all three criteria. LED configuration is a special case: while it nominally meets all three criteria, the most important one is the third: as LEDs are often needed during SoftwareInit initialization, they must be set up before it is invoked.

    -

    Note that not all code which meets some of these criteria is wired through -PlatformC. In particular, criterion 1 is typically necessary but not +

    Note that not all code which meets some of these criteria is wired through +PlatformC. In particular, criterion 1 is typically necessary but not sufficient to require PlatformC. For example, a timer system that configures overflow and capture settings or a UART stack that sets the baud rate and transmission options can often be wired to SoftwareInit. They are encapsulated abstractions which will not be invoked or -started until the boot event, and only need to be configured if the +started until the boot event, and only need to be configured if the system includes their functionality.

    Components whose initialization does not directly depend on hardware resources SHOULD wire to MainC.SoftwareInit. If a component requires a @@ -569,7 +564,7 @@ configuration TimerMilliP { implementation { components HilTimerMilliC, MainC; MainC.SoftwareInit -> HilTimerMilliC; - TimerMilli = HilTimerMilliC; + TimerMilli = HilTimerMilliC; }

    Rather than require an application to wire HilTimerMilliC to MainC, @@ -577,8 +572,8 @@ TimerMilliP does it automatically. When a component instantiates a TimerMilliC, that names TimerMilliP, which will automatically make sure that the timer system is initialized when TinyOS boots.

    -
    -

    4.2 Interrupts in Initialization

    +
    +

    4.2 Interrupts in Initialization

    Interrupts are not enabled until all calls to Init.init have returned. If a component's initialization needs to handle interrupts, it can do one of three things:

    @@ -605,7 +600,7 @@ flag) or to catch a brief edge transition. In these cases, a component can handle an interrupt in the boot sequence only if doing so will not cause any other component to handle an interrupt. As they have all been written assuming that interrupts are not enabled until after Init -completes, making one of them handle an interrupt could cause it to +completes, making one of them handle an interrupt could cause it to fail.

    Depending on what capabilities the hardware provides, there are several ways to meet these requirements. The simplest is to push these @@ -620,22 +615,22 @@ initialized unless it has initialized them, and MUST NOT call any functional interfaces on any components that might be shared or interact with shared resources. Components MAY call functions on other components that are completely internal to the subsystem. -For example, a networking layer can call queue operations to +For example, a networking layer can call queue operations to initialize its queue, but a link layer must not send commands over an SPI bus. An HAA component MAY make other calls to initialize hardware state. A component that is not part of an HAA SHOULD NOT call Init.init() on other components unless it needs to enforce a temporal ordering on initialization.

    -

    If a component A depends on another component, B, -which needs to be initialized, then A SHOULD wire B's Init directly +

    If a component A depends on another component, B, +which needs to be initialized, then A SHOULD wire B's Init directly to the boot sequence, unless there is a temporal ordering requirement to the initialization. The purpose of this convention is to simplify component initialization and the initialization sequence.

    -
    -

    5. Implementation

    +
    +

    5. Implementation

    The following files in tinyos-2.x/tos/system contain the reference implementations of the TinyOS boot sequence:

    @@ -646,8 +641,8 @@ PlatformC and TinySchedulerC
    -
    -

    6. Author's Address

    +
    +

    6. Author's Address

    Philip Levis
    467 Soda Hall
    @@ -659,8 +654,8 @@ PlatformC and TinySchedulerC email - pal@cs.berkeley.edu
    -
    -

    7. Citations

    +
    +

    7. Citations

    diff --git a/doc/html/tep108.html b/doc/html/tep108.html index e4c7083a..d8362636 100644 --- a/doc/html/tep108.html +++ b/doc/html/tep108.html @@ -3,13 +3,9 @@ - +Resource Arbitration - - - - - + +

    Resource Arbitration

    @@ -302,19 +294,14 @@ ul.auto-toc { - - - - - - - - - - + +
    Final
    TinyOS-Version:2.x
    Author:Kevin Klues
    Author:Philip Levis
    Author:David Gay
    Author:David Culler
    Author:Vlado Handziski
    Authors:Kevin Klues +
    Philip Levis +
    David Gay +
    David Culler +
    Vlado Handziski
    -

    Note

    This memo documents a part of TinyOS for the TinyOS Community, and @@ -322,14 +309,14 @@ requests discussion and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with TEP 1.

    -
    -

    Abstract

    +
    +

    Abstract

    This memo documents the general resource sharing mechanisms for TinyOS 2.x. These mechanisms are used to allow multiple software components to arbitrate access to shared abstractions.

    -
    -

    1. Introduction

    +
    +

    1. Introduction

    TinyOS 1.x has two mechanisms for managing shared resources: virtualization and completion events. A virtualized resource appears as an independent instance of an abstraction, such as the Timer @@ -341,19 +328,19 @@ programs need the control provided by a physical abstraction. For example, components in 1.x share a single communication stack, GenericComm. GenericComm can only handle one outgoing packet at a time. If a component tries to send a packet when GenericComm is -already busy, then the call returns FAIL. The component needs a way to +already busy, then the call returns FAIL. The component needs a way to tell when GenericComm is free so it can retry. TinyOS 1.x provides the mechanism of a global completion event which is signaled whenever a packet send completes. Interested components can handle this event and retry.

    -

    This approach to physical (rather than virtualized) abstractions +

    This approach to physical (rather than virtualized) abstractions has several drawbacks:

    • If you need to make several requests, you have to handle the -possibility of a request returning FAIL at any point. This complicates +possibility of a request returning FAIL at any point. This complicates implementations by adding internal states.
    • You have no control over the timing of a sequence of operations. One -example of when this can be a problem is timing-sensitive use of an +example of when this can be a problem is timing-sensitive use of an A/D converter. You need a way to pre-reserve the use of the ADC so that its operations can be run at the exact moment they are desired.
    • If a hardware resource supports reservation, you cannot express this @@ -364,7 +351,7 @@ but it is not clear how to use this in TinyOS 1.x's I2C abstraction.
    • monitoring an abstraction's availability for the purpose of retries, nor very clear documentation of which requests could happen simultaneously.
    -

    It should be clear that a single approach to resource sharing is not appropriate +

    It should be clear that a single approach to resource sharing is not appropriate for all circumstances. For instance, requiring explicit reservation of a resource allows programs to have better timing guarantees for access to an A/D converter. If a program does not need precise timing guarantees, however (e.g., @@ -374,10 +361,10 @@ nicely using virtualization. The following section introduces the concept of resource classes in order to address this issue. The sharing policy used by a particular resource abstraction is dictated by the resource class it belongs to.

    -
    -

    2. Resource Classes

    -

    TinyOS 2.x distinguishes between three kinds of abstractions: -dedicated, virtualized, and shared. Components offer resource +

    +

    2. Resource Classes

    +

    TinyOS 2.x distinguishes between three kinds of abstractions: +dedicated, virtualized, and shared. Components offer resource sharing mechanisms appropriate to their goals and level of abstraction.

    Note

    @@ -387,45 +374,45 @@ inevitably requires state. Depending on their expected use, HPL abstractions can either be dedicated or shared. For example, while hardware timers are rarely multiplexed between multiple components, buses almost always are. -This can be seen on the MSP430 microcontroller, where the compare and -counter registers are implemented as dedicated resources, and the USARTs +This can be seen on the MSP430 microcontroller, where the compare and +counter registers are implemented as dedicated resources, and the USARTs are shared ones.

    -
    -

    2.1 Dedicated

    +
    +

    2.1 Dedicated

    An abstraction is dedicated if it is a resource -which a subsystem needs exclusive access to at all times. -In this class of resources, no sharing policy is needed since only +which a subsystem needs exclusive access to at all times. +In this class of resources, no sharing policy is needed since only a single component ever requires use of the resource. Examples of dedicated abstractions include interrupts and counters.

    -

    Dedicated abstractions MAY be annotated with the nesC attribute +

    Dedicated abstractions MAY be annotated with the nesC attribute @atmostonce or @exactlyonce to provide compile-time checks that their usage assumptions are not violated.

    -

    Please refer to Appendix A for an example of how a dedicated -resource might be represented, including the use of +

    Please refer to Appendix A for an example of how a dedicated +resource might be represented, including the use of the nesC @exactlyonce attribute.

    -
    -

    2.2 Virtualized

    +
    +

    2.2 Virtualized

    Virtual abstractions hide multiple clients from each other -through software virtualization. Every client of a virtualized resource +through software virtualization. Every client of a virtualized resource interacts with it as if it were a dedicated resource, with all virtualized instances being multiplexed on top of a single underlying resource. Because the virtualization is done in software, there is no upper bound on the number of clients using the abstraction, barring memory or efficiency constraints. -As virtualization usually requires keeping state that scales with the number -of virtualized instances, virtualized resources often use the Service Instance +As virtualization usually requires keeping state that scales with the number +of virtualized instances, virtualized resources often use the Service Instance pattern [3], which is based on a parameterized interface.

    -

    Virtualization generally provides a very simple interface to its clients. -This simplicity comes at the cost of reduced efficiency and an inability to +

    Virtualization generally provides a very simple interface to its clients. +This simplicity comes at the cost of reduced efficiency and an inability to precisely control the underlying resource. For example, a virtualized -timer resource introduces CPU overhead from dispatching and maintaining -each individual virtual timer, as well as introducing jitter whenever two -timers happen to fire at the same time. Please refer to Appendix A for an +timer resource introduces CPU overhead from dispatching and maintaining +each individual virtual timer, as well as introducing jitter whenever two +timers happen to fire at the same time. Please refer to Appendix A for an example of how such a virtualized timer resource might be implemented.

    -
    -

    2.3 Shared

    +
    +

    2.3 Shared

    Dedicated abstractions are useful when a resource is always controlled by a single component. Virtualized abstractions are useful when clients are willing to pay a bit of overhead and sacrifice @@ -434,7 +421,7 @@ situations, however, when many clients need precise control of a resource. Clearly, they can't all have such control at the same time: some degree of multiplexing is needed.

    A motivating example of a shared resource is a bus. -The bus may have multiple peripherals on it, corresponding to +The bus may have multiple peripherals on it, corresponding to different subsystems. For example, on the Telos platform the flash chip (storage) and the radio (network) share a bus. The storage and network stacks need exclusive access to the bus when using it, @@ -442,38 +429,38 @@ but they also need to share it with the other subsystem. In this case, virtualization is problematic, as the radio stack needs to be able to perform a series of operations in quick succession without having to reacquire the bus in each case. Having the bus be a -shared resource allows the radio stack to send a series of operations -to the radio atomically, without having to buffer them all up +shared resource allows the radio stack to send a series of operations +to the radio atomically, without having to buffer them all up in memory beforehand (introducing memory pressure in the process).

    In TinyOS 2.x, a resource arbiter is responsible for multiplexing -between the different clients of a shared resource. It determines -which client has access to the resource at which time. While a client -holds a resource, it has complete and unfettered control. Arbiters assume -that clients are cooperative, only acquiring the resource when needed -and holding on to it no longer than necessary. Clients explicitly +between the different clients of a shared resource. It determines +which client has access to the resource at which time. While a client +holds a resource, it has complete and unfettered control. Arbiters assume +that clients are cooperative, only acquiring the resource when needed +and holding on to it no longer than necessary. Clients explicitly release resources: there is no way for an arbiter to forcibly reclaim it. -The following section is dedicated to describing the arbiter and its +The following section is dedicated to describing the arbiter and its interfaces.

    -
    -

    3. Resource Arbiters

    +
    +

    3. Resource Arbiters

    Every shared resource has an arbiter to manage which client can use the resource at any given time. Because an arbiter is a centralized place that knows whether the resource is in use, it can also provide information useful for a variety of other services, such as power management. An arbiter MUST provide a parameterized Resource interface as well as an instance of the ArbiterInfo interface. The Resource -interface is instantiated by different clients wanting to gain access to a -resource. The ArbiterInfo interface is used by components that wish to -retrieve global information about the status of a resource (i.e. if it is in -use, who is using it, etc.). An arbiter SHOULD also provide a parameterized -ResourceRequested interface and use a parameterized ResourceConfigure interface. -It MAY also provide an instance of the ResourceDefaultOwner interface or -any additional interfaces specific to the particular arbitration policy +interface is instantiated by different clients wanting to gain access to a +resource. The ArbiterInfo interface is used by components that wish to +retrieve global information about the status of a resource (i.e. if it is in +use, who is using it, etc.). An arbiter SHOULD also provide a parameterized +ResourceRequested interface and use a parameterized ResourceConfigure interface. +It MAY also provide an instance of the ResourceDefaultOwner interface or +any additional interfaces specific to the particular arbitration policy being implemented. Each of these interfaces is explained in greater detail below:

    -Resource     ArbiterInfo ResourceRequested     ResourceDefaultOwner 
    +Resource     ArbiterInfo ResourceRequested     ResourceDefaultOwner
        |                |         |                        |
        |                |         |                        |
        |               \|/       \|/                       |
    @@ -481,13 +468,13 @@ Resource     ArbiterInfo ResourceRequested     ResourceDefaultOwner
        |--------------|   Arbiter   |----------------------|
                      /---------------\
                              |
    -                         |      
    +                         |
                             \|/
                       ResourceConfigure
     
    -
    -

    3.1 Resource

    -

    Clients of an arbiter request access +

    +

    3.1 Resource

    +

    Clients of an arbiter request access to a shared resource using the Resource interface:

     interface Resource {
    @@ -498,41 +485,41 @@ interface Resource {
       async command bool isOwner();
     }
     
    -

    A client lets an arbiter know it needs access to a resource by +

    A client lets an arbiter know it needs access to a resource by making a call to request(). If the resource is free, -SUCCESS is returned, and a granted event is signaled -back to the client. If the resource is busy, SUCCESS will -still be returned, but the request will be queued -according to the queuing policy of the arbiter. Whenever a client is -done with the resource, it calls the release() command, and the next -client in the request queue is given access to the resource and -is signaled its granted() event. If a client ever makes multiple -requests before receiving a granted event, an EBUSY value is returned, -and the request is not queued. Using this policy, clients are not able to +SUCCESS is returned, and a granted event is signaled +back to the client. If the resource is busy, SUCCESS will +still be returned, but the request will be queued +according to the queuing policy of the arbiter. Whenever a client is +done with the resource, it calls the release() command, and the next +client in the request queue is given access to the resource and +is signaled its granted() event. If a client ever makes multiple +requests before receiving a granted event, an EBUSY value is returned, +and the request is not queued. Using this policy, clients are not able to monolopize the resource queue by making multiple requests, but they may still be -able to monopolize the use of the resource if they do not release it in a +able to monopolize the use of the resource if they do not release it in a timely manner.

    -

    Clients can also request the use of a resource through the -immediateRequest() command. A call to immediateRequest() can either -return SUCCESS or FAIL, with requests made through this command never being -queued. If a call to immediateRequest() returns SUCCESS, the client is granted -access to the resource immediately after the call has returned, and no granted -event is ever signaled. If it returns FAIL, the client is not granted access to -the resource and the request does not get queued. The client will have to try +

    Clients can also request the use of a resource through the +immediateRequest() command. A call to immediateRequest() can either +return SUCCESS or FAIL, with requests made through this command never being +queued. If a call to immediateRequest() returns SUCCESS, the client is granted +access to the resource immediately after the call has returned, and no granted +event is ever signaled. If it returns FAIL, the client is not granted access to +the resource and the request does not get queued. The client will have to try and gain access to the resource again later.

    -

    A client can use the isOwner command of the Resource interface to -check if it is the current owner of the resource. This command is mostly +

    A client can use the isOwner command of the Resource interface to +check if it is the current owner of the resource. This command is mostly used to perform runtime checks to make sure that clients not owning a resource are not able to use it. If a call to isOwner fails, then no call should be made to commands provided by that resource.

    -

    The diagram below shows how a simple shared resource can be -built from a dedicated resource by using just the Resource interface +

    The diagram below shows how a simple shared resource can be +built from a dedicated resource by using just the Resource interface provided by an arbiter.:

              /|\                    /|\
               |                      |
               | Data Interface       | Resource
    -          |                      |  
    +          |                      |
     --------------------------------------------
     |               Shared Resource            |
     --------------------------------------------
    @@ -547,7 +534,7 @@ provided by an arbiter.:

    An arbiter MUST provide exactly one parameterized Resource interface, where the parameter is a client ID, following the Service Instance pattern[3]_. An arbitrated component SomeNameP MUST -#define SOME_NAME_RESOURCE to a string which can be passed to unique() +#define SOME_NAME_RESOURCE to a string which can be passed to unique() to obtain a client id. This #define must be placed in a separate file because of the way nesC files are preprocessed: including the SomeNameP component isn't enough to ensure that macros #define'd in @@ -557,14 +544,14 @@ inside a generic configuration. Wrapping the component in this way ensures that each Resource client is given a unique client ID, with the added benefit of properly coupling multiple components that all need to refer to the same client ID.

    -

    Appendix B also provides a complete example of how an I2C resource might be -abstracted according to this pattern. For further examples see the various +

    Appendix B also provides a complete example of how an I2C resource might be +abstracted according to this pattern. For further examples see the various chip implementations in the tinyos-2.x source tree under tinyos-2.x/chips/

    -
    -

    3.2 ArbiterInfo

    +
    +

    3.2 ArbiterInfo

    Arbiters MUST provide an instance of the ArbiterInfo interface. -The ArbiterInfo interface allows a component to query the current +The ArbiterInfo interface allows a component to query the current status of an arbiter:

     interface ArbiterInfo {
    @@ -572,24 +559,24 @@ interface ArbiterInfo {
       async command uint8_t clientId();
     }
     
    -

    In contrast to the parameterized Resource interface provided by an arbiter, -only a single ArbiterInfo interface is provided. Its purpose is +

    In contrast to the parameterized Resource interface provided by an arbiter, +only a single ArbiterInfo interface is provided. Its purpose is to allow one to find out:

    • Whether the resource for which it is arbitrating use is currently in use or not
    • Which client is using it.
    -

    One can view ArbiterInfo as an interface for obtaining global information about -the use of a resource, while Resource can be viewed as an interface for obtaining +

    One can view ArbiterInfo as an interface for obtaining global information about +the use of a resource, while Resource can be viewed as an interface for obtaining local access to that resource.

    -

    The primary use of the ArbiterInfo interface is to allow a shared resource to reject -any calls made through its data interface by clients that do not currently have access to +

    The primary use of the ArbiterInfo interface is to allow a shared resource to reject +any calls made through its data interface by clients that do not currently have access to it. For an example of how this interface is used in this fashion refer to Appendix B.:

              /|\                        /|\
               |                          |
               | Data Interface           | Resource
    -          |                          |  
    +          |                          |
     -----------------------------------------------------------
     |                     Shared Resource                     |
     -----------------------------------------------------------
    @@ -602,9 +589,9 @@ it.  For an example of how this interface is used in this fashion refer to Appen
     ----------------------      -------------------------------
     
    -
    -

    3.3 ResourceRequested

    -

    Sometimes it is useful for a client to be able to hold onto a resource until +

    +

    3.3 ResourceRequested

    +

    Sometimes it is useful for a client to be able to hold onto a resource until someone else needs it and only at that time decide to release it. Using the ResourceRequested interface, this information is made available to the current owner of a resource:

    @@ -618,10 +605,10 @@ interface ResourceRequested { client makes a request for the resource through the request() command of its Resource interface. If a request is made through the immediateRequest() command, then the immediateRequested() event is signaled.

    -

    An arbiter SHOULD provide a parameterized ResourceRequested interface to its -clients, but is not required to. The client id of the parameterized -ResourceRequested interface should be coupled with the client id of the Resource -interface to ensure that all events are signaled to the proper clients. Please +

    An arbiter SHOULD provide a parameterized ResourceRequested interface to its +clients, but is not required to. The client id of the parameterized +ResourceRequested interface should be coupled with the client id of the Resource +interface to ensure that all events are signaled to the proper clients. Please refer to Appendix B for an example of how this interface might be used.:

              /|\                        /|\                   /|\
    @@ -640,16 +627,16 @@ refer to Appendix B for an example of how this interface might be used.:

    ---------------------- ----------------------------------------------------
    -
    -

    3.4 ResourceConfigure

    -

    The existence of the ResourceConfigure interface allows a resource to be +

    +

    3.4 ResourceConfigure

    +

    The existence of the ResourceConfigure interface allows a resource to be automatically configured just before a client is granted access to it. Components providing the ResourceConfigure interface use the interfaces provided by an underlying dedicated resource to configure it into one -of its desired modes of operation. A cleint then wires its shared resource -abstraction to the component implementing the desired configuration. The -configure command is called immediataely before the client is granted access -to the resource, and the unconfigure command is called just before fully +of its desired modes of operation. A cleint then wires its shared resource +abstraction to the component implementing the desired configuration. The +configure command is called immediataely before the client is granted access +to the resource, and the unconfigure command is called just before fully releasing it.:

     interface ResourceConfigure {
    @@ -661,45 +648,45 @@ interface ResourceConfigure {
       ResourceConfigure       ResourceConfigure      ResourceConfigure
              |                       |                     /|\
              |                       |                      |
    -        \|/                     \|/                     |                
    --------------------     -------------------    ------------------- 
    +        \|/                     \|/                     |
    +-------------------     -------------------    -------------------
     | Configuration 1 |     | Configuration 2 |    | Shared Resource |
     -------------------     -------------------    -------------------
              |                       |                     /|\
              |   Control Interface   |                      | ResourceConfigure
             \|/                     \|/                     |
    -      ------------------------------               -----------                 
    +      ------------------------------               -----------
           |     Dedicated Resource     |               | Arbiter |
           ------------------------------               -----------
     
    -

    The arbiter SHOULD use a parameterized ResourceConfigure interface, with +

    The arbiter SHOULD use a parameterized ResourceConfigure interface, with its client ID parameter coupled with the client id of its parameterized -Resource interface. If an arbiter uses the ResourceConfigure interface, -it MUST call ResourceConfigure.configure() on the granted client ID +Resource interface. If an arbiter uses the ResourceConfigure interface, +it MUST call ResourceConfigure.configure() on the granted client ID before it signals the Resource.granted() event. Similarly, after a valid -call to Resource.release(), it MUST call ResourceConfigure.unconfigure() +call to Resource.release(), it MUST call ResourceConfigure.unconfigure() on the releasing client ID. By calling ResourceConfigure.configure() just -before granting a client access to a resource and calling +before granting a client access to a resource and calling ResourceConfigure.unconfigure() just before fully releasing it, it is guaranteed -that a resource is always unconfigured before an attempt to configure it can be +that a resource is always unconfigured before an attempt to configure it can be made again.

    The commands included in this interface could have been made part of the standard -Resource interface (and changed into callback events), but at a higher cost than -keeping them separate. Introducing these new commands into the Resource interface -would have lead to a large number of clients all including redundant configuration -code, while using the call out approach to a separate component ensures that we +Resource interface (and changed into callback events), but at a higher cost than +keeping them separate. Introducing these new commands into the Resource interface +would have lead to a large number of clients all including redundant configuration +code, while using the call out approach to a separate component ensures that we only have a single instance of the code.

    -

    For an example of how configurations for the three different modes of the -Msp430 Usart component can take advantage of the ResourceConfigure -interface refer to Appendix B as well as section 4 on the use of +

    For an example of how configurations for the three different modes of the +Msp430 Usart component can take advantage of the ResourceConfigure +interface refer to Appendix B as well as section 4 on the use of cross-component reservation.

    -
    -

    3.5 ResourceDefaultOwner

    -

    The normal Resource interface is for use by clients that all share the resource -in an equal fashion. The ResourceDefaultOwner interface is for use by a single -client that needs to be given control of the resource whenever no one else is -using it. An arbiter MAY provide a single instance of the ResourceDefaultOwner +

    +

    3.5 ResourceDefaultOwner

    +

    The normal Resource interface is for use by clients that all share the resource +in an equal fashion. The ResourceDefaultOwner interface is for use by a single +client that needs to be given control of the resource whenever no one else is +using it. An arbiter MAY provide a single instance of the ResourceDefaultOwner interface. It MUST NOT provide more than one.:

     interface ResourceDefaultOwner {
    @@ -711,43 +698,43 @@ interface ResourceDefaultOwner {
     }
     

    The Arbiter MUST guarantee that the client of the ResourceDefaulrClient interface is -made the owner of the resource before the boot initialization sequence is -completed. When a normal resource client makes a request for the resource, the -ResourceDefaultOwner will receive either a requested() or an immediateRequested() -event depending on how the request was made. It must then decide if and when to -release it. Once released, all clients that have pending requests will be -granted access to the resource in the order determined by the queuing policy of -the arbiter in use. Once all pending requests have been granted (including -those that came in while other clients had access to the resource), the -ResourceDefaultOwner is automatically given control of the resource, receiving its -granted() event in the process. The ResourceDefaultOwner interface also contains -the same isOwner() command as the normal Resource interface, and the semantics +made the owner of the resource before the boot initialization sequence is +completed. When a normal resource client makes a request for the resource, the +ResourceDefaultOwner will receive either a requested() or an immediateRequested() +event depending on how the request was made. It must then decide if and when to +release it. Once released, all clients that have pending requests will be +granted access to the resource in the order determined by the queuing policy of +the arbiter in use. Once all pending requests have been granted (including +those that came in while other clients had access to the resource), the +ResourceDefaultOwner is automatically given control of the resource, receiving its +granted() event in the process. The ResourceDefaultOwner interface also contains +the same isOwner() command as the normal Resource interface, and the semantics of its use are exactly the same.

    -

    Although the ResourceDefaultOwner interface looks similar to a combination of the -normal Resource interface and the ResourceRequested interface, its intended use -is quite different. The ResourceDefaultOwner interface should only be used by -clients that wish to have access to a resource only when no other clients are -using it. They do not actively seek access to the resource, but rather use +

    Although the ResourceDefaultOwner interface looks similar to a combination of the +normal Resource interface and the ResourceRequested interface, its intended use +is quite different. The ResourceDefaultOwner interface should only be used by +clients that wish to have access to a resource only when no other clients are +using it. They do not actively seek access to the resource, but rather use it to perform operations when it would otherwise simply be idle.

    -

    The primary motivation behind the definition of the ResourceDefaultOwner +

    The primary motivation behind the definition of the ResourceDefaultOwner interface is to allow for an easy integration of power management -for a resource with its arbitration policy. Arbiters that want to allow -a resource to be controlled by a particular power management policy can -provide the ResourceDefaultOwner interface for use by a component that -implements that policy. The power management component will receive the +for a resource with its arbitration policy. Arbiters that want to allow +a resource to be controlled by a particular power management policy can +provide the ResourceDefaultOwner interface for use by a component that +implements that policy. The power management component will receive the granted() event whenever the resource has gone idle, and will proceed in -powering it down. When another client requests the resource, the power -manager will be notified through either the requested() or -immediateRequested() events as appropriate. It can then power up the resource -and release it once the power up has completed. Note that if power up is -a split-phase operation (takes a while), then calls by clients to -immediateRequest() when in the powered down state will return +powering it down. When another client requests the resource, the power +manager will be notified through either the requested() or +immediateRequested() events as appropriate. It can then power up the resource +and release it once the power up has completed. Note that if power up is +a split-phase operation (takes a while), then calls by clients to +immediateRequest() when in the powered down state will return FAIL. Please see the TEP on the Power Management of Non-Virtualized devices ([4]) for more details.

    -
    -

    4. Cross-Component Reservation

    +
    +

    4. Cross-Component Reservation

    In some cases, it is desirable to share the reservation of a single resource across multiple components. For example, on the TI MSP430, a single USART component can be used as an I2C bus, a UART, @@ -799,21 +786,21 @@ new Msp430Spi0C component is instantiated. This id is used as a parameter to the parameterized Resource interface provided by the Msp430Spi0P component. This is where the mapping of the two different ids begins. As well as providing a parameterized -Resource interface (Msp430Spi0P.Resource), the Msp430Spi0P component -also uses a parameterized Resource interface (Msp430Spi0P.UsartResource). -Whenever a client makes a call through the provided Resource interface -with id CLIENT_ID, an underlying call to the Msp430Spi0P.Resource interface -with the same id is implicitly made. By then wiring the Msp430Spi0P.UsartResource -interface with id CLIENT_ID to an instance of the Resource interface -provided by the instantiation of the Msp430Usart0C component, the mapping -is complete. Any calls to the Resource interface provided by a new -instantiation of the Msp430Spi0C component will now be made through a +Resource interface (Msp430Spi0P.Resource), the Msp430Spi0P component +also uses a parameterized Resource interface (Msp430Spi0P.UsartResource). +Whenever a client makes a call through the provided Resource interface +with id CLIENT_ID, an underlying call to the Msp430Spi0P.Resource interface +with the same id is implicitly made. By then wiring the Msp430Spi0P.UsartResource +interface with id CLIENT_ID to an instance of the Resource interface +provided by the instantiation of the Msp430Usart0C component, the mapping +is complete. Any calls to the Resource interface provided by a new +instantiation of the Msp430Spi0C component will now be made through a unique Resource interface on the underlying Msp430Usart0C component.

    This level of indirection is necessary because it may not always be desirable to directly wire the service level Resource interface to the underlying shared Resource interface. Sometimes we may want to perform some operations between a service level command being -called, and calling the underlying command on the shared resource. +called, and calling the underlying command on the shared resource. With such a mapping, inserting these operations is made possible.

    Having such a mapping is also important for services that need to explicitly keep track of the number of clients they have, @@ -829,8 +816,8 @@ reuse is encouraged.

    Implementations of components similar to this one can be found in the tinyos-2.x source tree in the tos/chips/msp430/uart directory

    -
    -

    5. Implementation

    +
    +

    5. Implementation

    Because most components use one of a small number of arbitration policies, tinyos-2.x includes a number of default resource arbiters. These arbiters can be found in tinyos-2.x/tos/system and are all @@ -849,19 +836,19 @@ generic module Arbiter { provides interface ResourceDefaultOwner; provides interface ArbiterInfo; uses interface ResourceConfigure[uint8_t id]; -} +} -

    The "Simple" arbiters are intended for use by resources that +

    The "Simple" arbiters are intended for use by resources that do not require the additional overhead incurred by providing the ResourceDefaultOwner interface.

    For many situations, changing an arbitration policy requires nothing more than changing the queuing policy it uses to decide the order in -which incoming requests should be granted. In this way, separating -queuing policy implementations from actual arbitration implementations -encourages code reuse. The introduction of the SimpleArbiterP and +which incoming requests should be granted. In this way, separating +queuing policy implementations from actual arbitration implementations +encourages code reuse. The introduction of the SimpleArbiterP and ArbiterP components found under tinyos-2.x/tos/system help in this separation. They can be wired to components providing -a particular queuing policy through the use of the ResourceQueue +a particular queuing policy through the use of the ResourceQueue interface.:

     interface ResourceQueue {
    @@ -869,9 +856,9 @@ interface ResourceQueue {
       async command bool isEnqueued(resource_client_id_t id);
       async command resource_client_id_t dequeue();
       async command error_t enqueue(resource_client_id_t id);
    -}   
    +}
     
    -

    An example of wiring a First-Come-First-Serve (FCFS) queuing policy to +

    An example of wiring a First-Come-First-Serve (FCFS) queuing policy to the SimpleArbiterP component using the ResourceQueue interface defined above can be seen below:

    @@ -900,8 +887,8 @@ implementation {
     

    This generic configuration can be instantiated by a resource in order to grant requests made by its clients in an FCFS fashion.

    -

    All of the default queuing policies provided in tinyos-2.x along with the -respective arbitration components that have been built using them are +

    All of the default queuing policies provided in tinyos-2.x along with the +respective arbitration components that have been built using them are given below:

    Queuing Policies:

      @@ -915,19 +902,19 @@ given below:

    • SimpleRoundRobinArbiterC
    • RoundRobinArbiterC
    -

    Keep in mind that neither the implementation of an arbiter nor its -queuing policy can be used to explicitly restrict access to an +

    Keep in mind that neither the implementation of an arbiter nor its +queuing policy can be used to explicitly restrict access to an underlying shared resource. The arbiter simply provides a standardized -way of managing client ids so that shared resources don't have to duplicate +way of managing client ids so that shared resources don't have to duplicate this functionality themselves every time they are implemented. In order to actually restrict clients from using a resource without first requesting it, a shared resource must use the functionality provided by the ArbiterInfo interface -to perform runtime checks on the current owner of a resource. Please refer +to perform runtime checks on the current owner of a resource. Please refer to the section on the ArbiterInfo interface in Appendix B for more information on how such runtime checks can be performed.

    -
    -

    6. Author's Address

    +
    +

    6. Author's Address

    Kevin Klues
    503 Bryan Hall
    @@ -970,8 +957,8 @@ on how such runtime checks can be performed.

    -
    -

    7. Citations

    +
    +

    7. Citations

    @@ -1003,10 +990,10 @@ on how such runtime checks can be performed.

    -
    -

    Appendix A: Resource Class Examples

    -
    -

    Dedicated Resource

    +
    +

    Appendix A: Resource Class Examples

    +
    +

    Dedicated Resource

    Timer 2 on the Atmega128 microprocessor is a dedicated resource represented by the HplAtm128Timer2C component:

    @@ -1020,19 +1007,19 @@ module HplAtm128Timer2C {
     

    Only a single client can wire to any of these interfaces as enforced through the nesC @exactlyonce attribute. Keep in mind that although the interfaces of -this component are only allowed to be wired to once, nothing prevents the -component wiring to them from virtualizing the services they provide at some -higher level. If you are unfamiliar with how @exactlyonce and other nesC -attributes are used to by the nesC compiler, please refer to section 9.1 of the +this component are only allowed to be wired to once, nothing prevents the +component wiring to them from virtualizing the services they provide at some +higher level. If you are unfamiliar with how @exactlyonce and other nesC +attributes are used to by the nesC compiler, please refer to section 9.1 of the TinyOS Programming Manual [5].

    -
    -

    Virtualized Resource

    -

    The TimerMilliC component provides a virtual abstraction of millisecond -precision timers to application components [2]. It encapsulates the required -parameterized Timer interface through the use of a generic configuration. -Clients wishing to use a millisecond timer need only instantiate a single -instance of the TimerMilliC generic, leaving the fact that it is virtualized +

    +

    Virtualized Resource

    +

    The TimerMilliC component provides a virtual abstraction of millisecond +precision timers to application components [2]. It encapsulates the required +parameterized Timer interface through the use of a generic configuration. +Clients wishing to use a millisecond timer need only instantiate a single +instance of the TimerMilliC generic, leaving the fact that it is virtualized underneath transparent.:

     generic configuration TimerMilliC {
    @@ -1043,9 +1030,9 @@ implementation {
       Timer = TimerMilliP.TimerMilli[unique(UQ_TIMER_MILLI)];
     }
     
    -

    The actual parameterized Timer interface is provided by the chip specific -HilTimerMilliC component. This interface is exposed through -the TimerMilliP component which wires HilTimerMilliC to the boot +

    The actual parameterized Timer interface is provided by the chip specific +HilTimerMilliC component. This interface is exposed through +the TimerMilliP component which wires HilTimerMilliC to the boot initialization sequence:

     configuration TimerMilliP {
    @@ -1059,19 +1046,19 @@ implementation {
     
    -
    -

    Appendix B: Arbiter Interface Examples

    +
    +

    Appendix B: Arbiter Interface Examples

    -
    -

    Resource

    +Most of the examples provided in this section use complex nesC syntax that may +be unfamiliar to the novice nesC programmer. Please refer to the TinyOS +programming Manual [5]_ for clarification as necessary. --> +
    +

    Resource

    Examples of how to use the Resource interface for arbitrating between multiple clients can be found in the tinyos-2.x source tree under tinyos-2.x/apps/tests/TestArbiter.

    -

    A specific example of where the Resource.isOwner() is used -can be seen in the HplTda5250DataP component of the Infineon +

    A specific example of where the Resource.isOwner() is used +can be seen in the HplTda5250DataP component of the Infineon Tda5250 radio implementation:

     async command error_t HplTda5250Data.tx(uint8_t data) {
    @@ -1102,8 +1089,8 @@ implementation {
       ...
     }
     
    -

    where I2CPacketImplP contains the actual implementation of the -I2C service, and I2CPacket.h contains the #define for the +

    where I2CPacketImplP contains the actual implementation of the +I2C service, and I2CPacket.h contains the #define for the name of the resource required by the arbiter:

     #ifndef I2CPACKETC_H
    @@ -1121,16 +1108,16 @@ generic configuration I2CPacketC {
     }
     implementation {
       enum { CLIENT_ID = unique(I2CPACKET_RESOURCE) };
    -      
    +
       components I2CPacketP as I2C;
       Resource = I2C.Resource[CLIENT_ID];
    -  I2CPacket = I2C.I2CPacket[CLIENT_ID]; 
    +  I2CPacket = I2C.I2CPacket[CLIENT_ID];
     }
     

    In this example, an instance of the I2CPacket interface is coupled with an instance of the Resource interface on every new instantiation of the I2CPacketC component. In this way, a single Resource and a -single I2CPacket interface can be exported by this component together +single I2CPacket interface can be exported by this component together for use by a client.

    Clients of the I2C service would use it as follows:

    @@ -1148,19 +1135,19 @@ implementation {
     }
     
    -
    -

    ArbiterInfo

    +
    +

    ArbiterInfo

    In the implementation of the ADC component on the Msp430 microcontroller, a simple arbiter is used to provide a round robin sharing policy between clients of the ADC:

    -configuration Msp430Adc12C { 
    -  provides interface Resource[uint8_t id]; 
    -  provides interface Msp430Adc12SingleChannel[uint8_t id]; 
    -  provides interface Msp430Adc12FastSingleChannel[uint8_t id]; 
    -} 
    -implementation { 
    -  components Msp430Adc12P,MainC, 
    +configuration Msp430Adc12C {
    +  provides interface Resource[uint8_t id];
    +  provides interface Msp430Adc12SingleChannel[uint8_t id];
    +  provides interface Msp430Adc12FastSingleChannel[uint8_t id];
    +}
    +implementation {
    +  components Msp430Adc12P,MainC,
                  new SimpleRoundRobinArbiterC(MSP430ADC12_RESOURCE) as Arbiter,
                  ...
     
    @@ -1173,12 +1160,12 @@ implementation {
       ...
     }
     
    -

    In this configuration we see that the Resource interface provided by +

    In this configuration we see that the Resource interface provided by Msp430Adc12C is wired directly to the instance of the SimpleRoundRobinArbiterC component that is created. The ArbiterInfo interface provided by -SimpleRoundRobinArbiterC is then wired to Msp430Adc12P. The Msp430Adc12P +SimpleRoundRobinArbiterC is then wired to Msp430Adc12P. The Msp430Adc12P component then uses this interface to perform run time checks to ensure that -only the client that currently has access to the ADC resource is able to +only the client that currently has access to the ADC resource is able to use it:

     async command error_t Msp430Adc12SingleChannel.getSingleData[uint8_t id]() {
    @@ -1188,7 +1175,7 @@ async command error_t Msp430Adc12SingleChannel.getSingleData[uint8_t id]() {
       }
       else return ERESERVE;
     }
    -       
    +
     async command error_t Msp430Adc12FastSingleChannel.configure[uint8_t id]() {
       if (call ADCArbiterInfo.clientId() == id){
         clientID = id
    @@ -1196,67 +1183,67 @@ async command error_t Msp430Adc12FastSingleChannel.configure[uint8_t id]() {
       }
       else return ERESERVE;
     }
    -       
    -async command error_t Msp430Adc12FastSingleChannel.getSingleData[uint8_t id]() 
    +
    +async command error_t Msp430Adc12FastSingleChannel.getSingleData[uint8_t id]()
     {
       if (clientID = id)
         // Start getting data
       else return ERESERVE;
     }
     
    -

    In order for these runtime checks to succeed, users of the -Msp430Adc12SingleChannel and Msp430Adc12FastSingleChannel interfaces will have -to match their client id's with the client id of a corresponding Resource +

    In order for these runtime checks to succeed, users of the +Msp430Adc12SingleChannel and Msp430Adc12FastSingleChannel interfaces will have +to match their client id's with the client id of a corresponding Resource interface. This can be done in the following way:

     generic configuration Msp430Adc12ClientC() {
       provides interface Resource;
       provides interface Msp430Adc12SingleChannel;
    -} 
    +}
     implementation {
       components Msp430Adc12C;
       enum { ID = unique(MSP430ADC12_RESOURCE) };
    -       
    +
       Resource = Msp430Adc12C.Resource[ID];
       Msp430Adc12SingleChannel = Msp430Adc12C.SingleChannel[ID];
    -}  
    +}
     
     generic configuration Msp430Adc12FastClientC() {
       provides interface Resource;
       provides interface Msp430Adc12FastSingleChannel;
    -} 
    +}
     implementation {
       components Msp430Adc12C;
       enum { ID = unique(MSP430ADC12_RESOURCE) };
    -     
    +
       Resource = Msp430Adc12C.Resource[ID];
       Msp430Adc12FastSingleChannel = Msp430Adc12C.SingleChannel[ID];
    -}  
    +}
     

    Since these are generic components, clients simply need to instantiate them in order to get access to a single Resource interface that is already properly coupled with a Msp430Adc12SingleChannel or Msp430Adc12FastSingleChannel interface.

    -

    Take a look in the tinyos-2.x source tree under tinyos-2.x/tos/chips/adc12 +

    Take a look in the tinyos-2.x source tree under tinyos-2.x/tos/chips/adc12 to see the full implementation of these components in their original context.

    -
    -

    ResourceRequested

    +
    +

    ResourceRequested

    On the eyesIFXv2 platform, both the radio and the flash need access to the bus -provided by the Usart0 component on the Msp430 microcontroller. Using -a simple cooperative arbitration policy, these two components should able to -share the Usart resource by only holding on to it as long as they need it and -then releasing it for use by the other component. In the case of the MAC -implementation of the Tda5250 radio component, however, the Msp430 Usart -resource needs be held onto indefinitely. It only ever considers releasing the -resource if a request from the flash component comes in through its -ResourceRequested interface. If it cannot release it right away (i.e. it is in -the middle of receiving a packet), it defers the release until some later point -in time. Once it is ready to release the resource, it releases it, but then -immediately requests it again. The flash is then able to do what it wants with +provided by the Usart0 component on the Msp430 microcontroller. Using +a simple cooperative arbitration policy, these two components should able to +share the Usart resource by only holding on to it as long as they need it and +then releasing it for use by the other component. In the case of the MAC +implementation of the Tda5250 radio component, however, the Msp430 Usart +resource needs be held onto indefinitely. It only ever considers releasing the +resource if a request from the flash component comes in through its +ResourceRequested interface. If it cannot release it right away (i.e. it is in +the middle of receiving a packet), it defers the release until some later point +in time. Once it is ready to release the resource, it releases it, but then +immediately requests it again. The flash is then able to do what it wants with the Usart, with the radio regaining control soon thereafter.

    -

    In the CsmaMacP implementation of the Tda5250 radio we see the ResourceRequested +

    In the CsmaMacP implementation of the Tda5250 radio we see the ResourceRequested event being implemented:

     async event void ResourceRequested.requested() {
    @@ -1287,27 +1274,27 @@ implementation {
       ...
     }
     
    -

    Although the full implementation of these components is not provided, the -functionality they exhibit should be clear. The CsmaMacP component receives the -ResourceRequested.requested() event when the flash requests the use of the -Msp430 Usart0 resource. If it is already in the receive state, it tries to -reset the receive state through a call to a lower level component. This -component checks to see if the radio is in the middle of doing anything (i.e. -the radioBusy() == FALSE check), and if not, releases the resource and then +

    Although the full implementation of these components is not provided, the +functionality they exhibit should be clear. The CsmaMacP component receives the +ResourceRequested.requested() event when the flash requests the use of the +Msp430 Usart0 resource. If it is already in the receive state, it tries to +reset the receive state through a call to a lower level component. This +component checks to see if the radio is in the middle of doing anything (i.e. +the radioBusy() == FALSE check), and if not, releases the resource and then requests it again.

    -

    To see the full implementations of these components and their wirings to one -another, please refer to the tinyos-2.x source tree under -tinyos-2.x/tos/chips/tda5250, tinyos-2.x/tos/chips/tda5250/mac, -tinyos-2.x/tos/platforms/eyesIFX/chips/tda5250, and +

    To see the full implementations of these components and their wirings to one +another, please refer to the tinyos-2.x source tree under +tinyos-2.x/tos/chips/tda5250, tinyos-2.x/tos/chips/tda5250/mac, +tinyos-2.x/tos/platforms/eyesIFX/chips/tda5250, and tinyos-2.x/tos/platforms/eyesIFX/chips/msp430.

    -
    -

    Resource Configure

    -

    The Msp430 Usart0 bus can operate in three modes: SPI, I2C, -and UART. Using all three concurrently is problematic: only one should +

    +

    Resource Configure

    +

    The Msp430 Usart0 bus can operate in three modes: SPI, I2C, +and UART. Using all three concurrently is problematic: only one should be enabled at any given time. However, different clients of the bus might require the bus to be configured for different protocols. On Telos, for example -many of the available sensors use an I2C bus, while the radio and flash chip use +many of the available sensors use an I2C bus, while the radio and flash chip use SPI.

    A component providing the SPI service on top of the shared Usart component looks like this:

    @@ -1320,7 +1307,7 @@ generic configuration Msp430Spi0C() { } implementation { enum { CLIENT_ID = unique( MSP430_SPIO_BUS ) }; - + components Msp430SpiNoDma0P as SpiP; components new Msp430Usart0C() as UsartC; SpiP.ResourceConfigure[ CLIENT_ID ] <- UsartC.ResourceConfigure; @@ -1331,10 +1318,10 @@ implementation {

    And one providing the I2C service looks like this:

    -generic configuration Msp430I2CC() {  
    +generic configuration Msp430I2CC() {
       provides interface Resource;
       provides interface I2CPacket<TI2CBasicAddr> as I2CBasicAddr;
    -   ... 
    +   ...
     }
     implementation {
       enum { CLIENT_ID = unique( MSP430_I2CO_BUS ) };
    @@ -1348,14 +1335,14 @@ implementation {
     }
     

    The implementation of the ResourceConfigure interface is -provided by both the Msp430SpiNoDma0P and the Msp430I2C0P. In the +provided by both the Msp430SpiNoDma0P and the Msp430I2C0P. In the two different components, the same Msp430Usart0C component is used, but wired to the proper implementation of the ResourceConfigure -interface. In this way, different instances of the Msp430Usart0C -can each have different configurations associated with them, but +interface. In this way, different instances of the Msp430Usart0C +can each have different configurations associated with them, but still provide the same functionality.

    -

    Take a look in the tinyos-2.x source tree under -tinyos-2.x/tos/chips/msp430/usart to see the full implementation of +

    Take a look in the tinyos-2.x source tree under +tinyos-2.x/tos/chips/msp430/usart to see the full implementation of these components along with the corresponding Uart implementation.

    diff --git a/doc/html/tep109.html b/doc/html/tep109.html index d353a66f..2ff9e438 100644 --- a/doc/html/tep109.html +++ b/doc/html/tep109.html @@ -3,7 +3,7 @@ - + Sensors and Sensor Boards +

    Sensors and Sensor Boards

    @@ -306,7 +302,6 @@ ul.auto-toc {
    -

    Note

    This memo documents a part of TinyOS for the TinyOS Community, and @@ -314,15 +309,15 @@ requests discussion and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with TEP 1.

    -
    -

    Abstract

    +
    +

    Abstract

    This memo documents how sensor drivers are organized in TinyOS and how sets of sensor drivers are combined into sensor boards and sensor platforms, along with general principles followed by the components that provide access to sensors.

    -
    -

    1. Principles

    +
    +

    1. Principles

    This section describes the basic organization principles for sensor drivers in TinyOS.

    For background, a sensor can be attached to the microcontroller on a @@ -374,8 +369,8 @@ the driver MAY provide additional interfaces that would allow higher-level clients to obtain information needed to properly interpret the value.

    -
    -

    2. Sensor HIL Components

    +
    +

    2. Sensor HIL Components

    A sensor HIL component MUST provide:

    • One or more SID interfaces [TEP114], for reading data.
    • @@ -467,8 +462,8 @@ implementation { }
    -
    -

    3. Sensor HAL Components

    +
    +

    3. Sensor HAL Components

    Sensors with a richer interface than would be supported by the SID interfaces MAY provide a HAL component in addition to a HIL component.

    @@ -497,8 +492,8 @@ implementation { }
    -
    -

    4. Directory Organization Guidelines

    +
    +

    4. Directory Organization Guidelines

    Because the same physical sensor can be attached to TinyOS platforms in many different ways, the organization of sensor drivers SHOULD reflect the distinction between sensor and sensor interconnect.

    @@ -567,8 +562,8 @@ code that will enter the core source tree. In general, sensor components can be placed anywhere as long as the nesC compiler receives enough -I directives to locate all of the necessary pieces.

    -
    -

    5. Authors' Addresses

    +
    +

    5. Authors' Addresses

    David Gay
    2150 Shattuck Ave, Suite 1300
    @@ -611,8 +606,8 @@ receives enough -I directives to locate all of the necessary pieces
    -
    -

    6. Citations

    +
    +

    6. Citations

    @@ -632,10 +627,10 @@ receives enough -I directives to locate all of the necessary pieces
    -
    -

    Appendix A: Sensor Driver Examples

    -
    -

    1. Analog ADC-Connected Sensor

    +
    +

    Appendix A: Sensor Driver Examples

    +
    +

    1. Analog ADC-Connected Sensor

    The Analog sensor requires two components

    • a component to present the sensor itself (HamamatsuS1087ParC)
    • @@ -696,8 +691,8 @@ implementation { }
    -
    -

    2. Binary Pin-Connected Sensor

    +
    +

    2. Binary Pin-Connected Sensor

    The Binary sensor gets a bit more complex, because it has three components:

      @@ -737,7 +732,7 @@ module UserButtonLogicP { provides interface DeviceMetadata; uses interface GeneralIO; - uses interface GpioInterrupt; + uses interface GpioInterrupt; } implementation { norace bool m_pinHigh; @@ -773,9 +768,9 @@ implementation { task void sendEvent() { bool pinHigh; pinHigh = m_pinHigh; - + signal Notify.notify( pinHigh ); - + if ( pinHigh ) { call GpioInterrupt.enableFallingEdge(); } else { @@ -809,8 +804,8 @@ implementation { }
    -
    -

    3. Digital Bus-Connected Sensor

    +
    +

    3. Digital Bus-Connected Sensor

    The Digital sensor is the most complex out of the set, and includes six components:

      @@ -833,7 +828,7 @@ on top of the I2C or SPI bus would likely require fewer components.

       tos/platforms/telosa/chips/sht11/SensirionSht11C.nc
       
      -generic configuration SensirionSht11C() {  
      +generic configuration SensirionSht11C() {
         provides interface Read<uint16_t> as Temperature;
         provides interface DeviceMetadata as TemperatureDeviceMetadata;
         provides interface Read<uint16_t> as Humidity;
      @@ -866,7 +861,7 @@ generic module SensirionSht11ReaderP() {
         provides interface DeviceMetadata as TemperatureDeviceMetadata;
         provides interface Read<uint16_t> as Humidity;
         provides interface DeviceMetadata as HumidityDeviceMetadata;
      -  
      +
         uses interface Resource as TempResource;
         uses interface Resource as HumResource;
         uses interface SensirionSht11 as Sht11Temp;
      @@ -943,7 +938,7 @@ implementation {
         SensirionSht11LogicP.DATA -> HplSensirionSht11C.DATA;
         SensirionSht11LogicP.CLOCK -> HplSensirionSht11C.SCK;
         SensirionSht11LogicP.InterruptDATA -> HplSensirionSht11C.InterruptDATA;
      -  
      +
         components new TimerMilliC();
         SensirionSht11LogicP.Timer -> TimerMilliC;
       
      @@ -982,7 +977,7 @@ configuration HplSensirionSht11C {
       }
       implementation {
         components HplMsp430GeneralIOC;
      -  
      +
         components new Msp430GpioC() as DATAM;
         DATAM -> HplMsp430GeneralIOC.Port15;
         DATA = DATAM;
      @@ -1009,7 +1004,7 @@ implementation {
       
         components new FcfsArbiterC( "Sht11.Resource" ) as Arbiter;
         Resource = Arbiter;
      -  
      +
         components new SplitControlPowerManagerC();
         SplitControlPowerManagerC.SplitControl -> HplSensirionSht11P;
         SplitControlPowerManagerC.ArbiterInit -> Arbiter.Init;
      @@ -1036,7 +1031,7 @@ implementation {
           call Timer.startOneShot( 11 );
           return SUCCESS;
         }
      -  
      +
         event void Timer.fired() {
           signal SplitControl.startDone( SUCCESS );
         }
      diff --git a/doc/html/tep110.html b/doc/html/tep110.html
      index ece6cd14..c21352a7 100644
      --- a/doc/html/tep110.html
      +++ b/doc/html/tep110.html
      @@ -3,7 +3,7 @@
       
       
       
      -
      +
       Virtualization
       
       
       
       
      +

      Virtualization

      @@ -310,7 +306,6 @@ ul.auto-toc {
      -

      Note

      This memo documents a part of TinyOS for the TinyOS Community, and @@ -318,15 +313,15 @@ requests discussion and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with TEP 1.

      -
      -

      Abstract

      +
      +

      Abstract

      This memo desribes how TinyOS 2.0 virtualizes common abstractions through a combination of static allocation and runtime arbitration. It describes the benefits and tradeoffs of this approach and how it is used in several major abstractions.

      -
      -

      1. Introduction

      +
      +

      1. Introduction

      The TinyOS component model allows flexible composition, but that flexibility is often limited by reasons which are not explicitly stated in components. These implicit assumptions can manifest as buggy @@ -350,8 +345,8 @@ System Key Interfaces). It describes the services OSKI provides and how their implementations are structured to simplify application writing.

      -
      -

      2. Distributions

      +
      +

      2. Distributions

      A distribution presents services to the programmer. A service is a set of generic (instantiable) components that represent API abstractions. To use an abstraction, a programmer instantiates the @@ -372,8 +367,8 @@ look something like this:

      Services often present abstractions at a fine grain. For example, the active message service has AMSender, AMReceiver, and AMSnooper, each of which is a separate abstraction.

      -
      -

      2.1 Controlling a Service

      +
      +

      2.1 Controlling a Service

      Every service has two abstractions: ServiceC, for powering it on and off, and ServiceNotifierC, for learning when the service's power state has changed. For example, active messages have the @@ -424,8 +419,8 @@ active messages being used by two components, RouterA and RouterB:

      application to use the service, at least one component has to call Service.start().

      -
      -

      2.2 Service Initialization

      +
      +

      2.2 Service Initialization

      Because distributions are collections of services that are designed to work together, they can avoid many of the common issues that arise when composing TinyOS programs. For example, user code does not have @@ -436,13 +431,13 @@ initialized. Section 4 goes into an example implementation of how a distribution can achieve this.

      -
      -

      3. OSKI Services

      +
      +

      3. OSKI Services

      This section briefly describes the services that OSKI, an example distribution provides. It is intended to give a feel for how a distribution presents its abstractions.

      -
      -

      3.1 Timers

      +
      +

      3.1 Timers

      OSKI provides timers at one fidelity: milliseconds. Timers do not have a Service abstraction, as their use implicitly defines whether the service is active or not (the timer service is off if there are no @@ -466,8 +461,8 @@ configuration:

      }
      -
      -

      3.2 Active Messages

      +
      +

      3.2 Active Messages

      OSKI provides four functional active messaging abstractions: AMSender, AMReceiver, AMSnooper, and AMSnoopingReceiver. Each one takes an am_id_t as a parameter, @@ -525,8 +520,8 @@ its topology formation:

      The active messages layer has control abstractions, named AMServiceC and AMServiceNotifierC. Active messages follow an OR policy.

      -
      -

      3.3 Broadcasts

      +
      +

      3.3 Broadcasts

      In addition to active messages, OSKI provides a broadcasting service. Unlike active messages, which are addressed in terms of AM addresses, broadcasts are address-free. Broadcast communication has two @@ -537,9 +532,9 @@ the Packet interface. The broadcast service has control abstractions, named BroadcastServiceC and BroadcastServiceNotifierC, which follow an OR policy.

      -
      -

      3.4 Tree Collection/Convergecast

      -

      NOTE: These services are not supported as of the 2.x prerelease. +

      +

      3.4 Tree Collection/Convergecast

      +

      NOTE: These services are not supported as of the 2.x prerelease. They will be supported by the first full release.

      OSKI's third communication service is tree-based collection routing. This service has four abstractions:

      @@ -572,16 +567,16 @@ or not. CollectionServiceNotifierC abstractions, which follow an OR policy.

      -
      -

      3.5 UART

      -

      NOTE: These services are not supported as of the 2.x prerelease. -They will be supported by the first full release. -They will be fully defined pending discussion/codification of +

      +

      3.5 UART

      +

      NOTE: These services are not supported as of the 2.x prerelease. +They will be supported by the first full release. +They will be fully defined pending discussion/codification of UART interfaces.

      -
      -

      4. OSKI Service Structure and Design

      +
      +

      4. OSKI Service Structure and Design

      Presenting services through abstractions hides the underlying wiring details and gives a distribution a great deal of implementation freedom. One issue that arises, however, is initialization. If a user @@ -589,8 +584,8 @@ component instantiates a service, then a distribution MUST make sure the service is initialized properly. OSKI achieves this by encapsulating a complete service as a working component; abstractions export the service's interfaces.

      -
      -

      4.1 Example: Timers

      +
      +

      4.1 Example: Timers

      For example, the timer service provides a single abstraction, OskiTimerMilliC, which is a generic component. OskiTimerMilliC provides a single instance of the Timer<TMilli> interface. It is implemented as a @@ -642,8 +637,8 @@ itself to one of the sub-Inits.

      underlying Service Instance pattern: the abstractions take care of that.

      -
      -

      4.2 Example: Active Messages

      +
      +

      4.2 Example: Active Messages

      Active messaging reprsent a slightly more complex service, as it has several abstractions and a control interface. However, it follows the same basic pattern: abstractions are generics that export wirings to @@ -653,7 +648,7 @@ the underlying service, named Act

      provides {
      -
      interface SplitControl;
      +
      interface SplitControl;
      interface AMSend[am_id_t id];
      interface Receive[am_id_t id];
      interface Receive as Snoop[am_id_t id];
      @@ -777,8 +772,8 @@ of AMServiceC. As with timers, encapsulating the service instance pattern in generic components relieves the programmer of having to deal with unique strings, a common source of bugs in TinyOS 1.x code.

      -
      -

      4.3 OSKI Requirements

      +
      +

      4.3 OSKI Requirements

      OSKI is a layer on top of system components: it presents a more usable, less error-prone, and simpler interface to common TinyOS functionality. For OSKI to work properly, a platform MUST be compliant @@ -793,11 +788,11 @@ o TEP 1XX: Collection Routing inoperable, exhibit strange behavior, or being uncompilable.

      -
      -

      5. Distribution Interfaces

      +
      +

      5. Distribution Interfaces

      The basic notion of a distribution is that it provides a self-contained, -tested, and complete (for an application domain) programming interface -to TinyOS. Layers can be added on top of a distribution, but as a +tested, and complete (for an application domain) programming interface +to TinyOS. Layers can be added on top of a distribution, but as a distribution is a self-contained set of abstractions, adding new services can lead to failures. A distribution represents a hard line above which all other code operates. One SHOULD NOT add new services, @@ -805,7 +800,7 @@ as they can disrupt the underlying organization. Of course, one MAY create a new distribution that extends an existing one, but this is in and of itself a new distribution.

      Generally, as distributions are intended to be higher-level abstractions, -they SHOULD NOT provide any asynchronous (async) events. They can, +they SHOULD NOT provide any asynchronous (async) events. They can, of course, provide async commands. The idea is that no code written on top of a distribution should be asynchronous, due to the complexity introduced by having to manage concurrency. Distributions are usually @@ -813,8 +808,8 @@ platform independent; if an application needs async events, then chances are it is operating close to the hardware, and so is not platform independent.

      -
      -

      6. Author's Address

      +
      +

      6. Author's Address

      Philip Levis
      467 Soda Hall
      @@ -826,8 +821,8 @@ platform independent.

      -
      -

      7. Citations

      +
      +

      7. Citations

      diff --git a/doc/html/tep111.html b/doc/html/tep111.html index 1f59f098..d8cd6fe6 100644 --- a/doc/html/tep111.html +++ b/doc/html/tep111.html @@ -3,7 +3,7 @@ - +message_t +

      message_t

      @@ -302,7 +298,6 @@ ul.auto-toc {
      Philip Levis
      -

      Note

      This memo documents a part of TinyOS for the TinyOS Community, and @@ -310,16 +305,16 @@ requests discussion and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with TEP 1.

      -
      -

      Abstract

      +
      +

      Abstract

      This memo covers the TinyOS 2.x message buffer abstraction, message_t. -It describes the message buffer design considerations, how and where +It describes the message buffer design considerations, how and where message_t is specified, and how data link layers should access it. The major goal of message_t is to allow datagrams to be passed between different link layers as a contiguous region of memory with zero copies.

      -
      -

      1. Introduction

      +
      +

      1. Introduction

      In TinyOS 1.x, a message buffer is a TOS_Msg. A buffer contains an active message (AM) packet as well as packet metadata, such as timestamps, acknowledgement bits, and signal strength if the packet was received. @@ -327,18 +322,18 @@ acknowledgement bits, and signal strength if the packet was received. AM payload length (the default is 29 bytes). Fixed sized buffers allows TinyOS 1.x to have zero-copy semantics: when a component receives a buffer, rather than copy out the contents it can return a pointer -to a new buffer for the underlying layer to use for the next received +to a new buffer for the underlying layer to use for the next received packet.

      One issue that arises is what defines the TOS_Msg structure, as different -link layers may require different layouts. For example, 802.15.4 radio -hardware (such as the CC2420, used in the Telos and micaZ platforms) +link layers may require different layouts. For example, 802.15.4 radio +hardware (such as the CC2420, used in the Telos and micaZ platforms) may require 802.15.4 headers, while a software stack built on top of -byte radios (such as the CC1000, used in the mica2 platform) can specify +byte radios (such as the CC1000, used in the mica2 platform) can specify its own packet format. This means that TOS_Msg may be different on different platforms.

      The solution to this problem in TinyOS 1.x is for there to be a standard definition of TOS_Msg, which a platform (e.g., the micaZ) can -redefine to match its radio. For example, a mica2 mote uses the standard +redefine to match its radio. For example, a mica2 mote uses the standard definition, which is:

       typedef struct TOS_Msg {
      @@ -375,13 +370,13 @@ typedef struct TOS_Msg {
         uint8_t type;
         uint8_t group;
         int8_t data[TOSH_DATA_LENGTH];
      -  
      +
         // The following fields are not actually transmitted or received
         // on the radio! They are used for internal accounting only.
         // The reason they are in this structure is that the AM interface
         // requires them to be part of the TOS_Msg that is passed to
         // send/receive operations.
      -  
      +
         uint8_t strength;
         uint8_t lqi;
         bool crc;
      @@ -394,11 +389,11 @@ the link layer fields leads components to directly access the packet
       structure. This introduces dependencies between higher level components
       and the structure layout. For example, many network services built on
       top of data link layers care whether sent packets are acknowledged. They
      -therefore check the ack field of TOS_Msg. If a link layer does not 
      +therefore check the ack field of TOS_Msg. If a link layer does not
       provide acknowledgements, it must still include the ack field
       and always set it to 0, wasting a byte of RAM per buffer.

      Second, this model does not easily support multiple data link layers. -Radio chip implementations assume that the fields they require are +Radio chip implementations assume that the fields they require are defined in the structure and directly access them. If a platform has two different link layers (e.g., a CC1000 and a CC2420 radio), then a TOS_Msg needs to allocate the right amount of space for both @@ -407,17 +402,17 @@ header fields. This is very difficult to do in C.

      The data payload is especially problematic. Many components refer to this field, so it must be at a fixed offset from the beginning of the structure. -Depending on the underlying link layer, the header fields +Depending on the underlying link layer, the header fields preceding it might have different lengths, and packet-level radios -often require packets to be contiguous memory regions. Overall, these +often require packets to be contiguous memory regions. Overall, these complexities make specifying the format of TOS_Msg very difficult.

      TinyOS has traditionally used statically sized packet buffers, rather than more dynamic approaches, such as scatter-gather I/O -in UNIX sockets (see the man page for recv(2) for details). +in UNIX sockets (see the man page for recv(2) for details). TinyOS 2.x continues this approach.

      -
      -

      2. message_t

      +
      +

      2. message_t

      In TinyOS 2.x, the standard message buffer is message_t. The message_t structure is defined in tos/types/message.h:

      @@ -428,26 +423,26 @@ typedef nx_struct message_t {
         nx_uint8_t metadata[sizeof(message_metadata_t)];
       } message_t;
       
      -

      This format keeps data at a fixed offset on a platform, which +

      This format keeps data at a fixed offset on a platform, which is important when passing a message buffer between two different link layers. If the data payload were at different offsets for different link layers, then passing a packet between two link layers would require a memmove(3) operation (essentially, a copy). Unlike in TinyOS 1.x, where TOS_Msg as explicitly an active messaging packet, message_t is a more general -data-link buffer. In practice, most data-link layers in TinyOS 2.x -provide active messaging, but it is possible for a non-AM stack to +data-link buffer. In practice, most data-link layers in TinyOS 2.x +provide active messaging, but it is possible for a non-AM stack to share message_t with AM stacks.

      The header, footer, and metadata formats are all opaque. Source code cannot access fields directly. Instead, data-link layers provide access -to fields through nesC interfaces. Section 3 discusses this in +to fields through nesC interfaces. Section 3 discusses this in greater depth.

      Every link layer defines its header, footer, and metadata -structures. These structures MUST be external structs (nx_struct), -and all of their fields MUST be external types (nx_*), for two +structures. These structures MUST be external structs (nx_struct), +and all of their fields MUST be external types (nx_*), for two reasons. First, external types ensure cross-platform compatibility [1]. -Second, it forces structures to be aligned on byte boundaries, -circumventing issues with the +Second, it forces structures to be aligned on byte boundaries, +circumventing issues with the alignment of packet buffers and field offsets within them. Metadata fields must be nx_structs for when complete packets are forwarded to the serial port in order to log traffic. @@ -485,7 +480,7 @@ or metadata section. The platform looks like this:

       typedef union message_header {
      -  cc1000_header_t cc1k; 
      +  cc1000_header_t cc1k;
         serial_header_t serial;
       } message_header_t;
       
      @@ -521,37 +516,37 @@ typedef union mega_mica_metadata {
       message_t fields to be a union of the underlying link layer structures.
       This ensures that enough space is allocated for all underlying link layers.

      -
      -

      3. The message_t fields

      +
      +

      3. The message_t fields

      TinyOS 2.x components treat packets as abstract data types (ADTs), rather than C structures, obtaining all of the traditional benefits of this approach. First and foremost, clients of a packet layer do not depend on particular field names or locations, allowing the implementations to choose packet formats and make a variety of optimizations.

      -

      Components above the basic data-link layer MUST always access -packet fields through interfaces. A component that introduces -new packet fields SHOULD provide an interface to those that +

      Components above the basic data-link layer MUST always access +packet fields through interfaces. A component that introduces +new packet fields SHOULD provide an interface to those that are of interest to other components. These interfaces SHOULD take the form of get/set operations that take and return values, rather than offsts into the structure.

      -

      For example, active messages have an interface named AMPacket -which provides access commands to AM fields. In TinyOS 1.x, a -component would directly access TOS_Msg.addr; in TinyOS 2.x, +

      For example, active messages have an interface named AMPacket +which provides access commands to AM fields. In TinyOS 1.x, a +component would directly access TOS_Msg.addr; in TinyOS 2.x, a component calls AMPacket.getAddress(msg). The most basic of these interfaces is Packet, which provides -access to a packet payload. TEP 116 describes common TinyOS +access to a packet payload. TEP 116 describes common TinyOS packet ADT interfaces [3].

      -

      Link layer components MAY access packet fields differently than other +

      Link layer components MAY access packet fields differently than other components, as they are aware of the actual packet format. They can therefore implement the interfaces that provide access to the fields for other components.

      -
      -

      3.1 Headers

      -

      The message_t header field is an array of bytes whose size is +

      +

      3.1 Headers

      +

      The message_t header field is an array of bytes whose size is the size of a platform's union of data-link headers. -Because radio stacks often prefer packets to be stored contiguously, -the layout of a packet in memory does not necessarily reflect the +Because radio stacks often prefer packets to be stored contiguously, +the layout of a packet in memory does not necessarily reflect the layout of its nesC structure.

      A packet header MAY start somewhere besides the beginning of the message_t. For example, consider the Telos platform:

      @@ -571,30 +566,30 @@ a 12-byte serial packet on the Telos platform:

      +-----------+-----------------------------+-------+ message_t | header | data | meta | +-----------+-----------------------------+-------+ - + +-----------+------------+ +-------+ CC2420 | header | data | | meta | +-----------+------------+ +-------+ - +-----+------------+ -Serial | hdr | data | - +-----+------------+ + +-----+------------+ +Serial | hdr | data | + +-----+------------+

      Neither the CC2420 nor the serial stack has packet footers, and the serial stack does not have any metadata.

      The packet for a link layer does not necessarily start at the beginning of the message_t. Instead, it starts at a negative offset from the -data field. When a link layer component needs to read or write protocol -header fields, it MUST compute the location of the header as a negative +data field. When a link layer component needs to read or write protocol +header fields, it MUST compute the location of the header as a negative offset from the data field. For example, the serial stack header has active message fields, such as the AM type. The command that returns the AM type, AMPacket.type(), looks like this:

       serial_header_t* getHeader(message_t* msg) {
         return (serial_header_t*)(msg->data - sizeof(serial_header_t));
      -} 
      +}
       command am_id_t AMPacket.type(message_t* msg) {
      -  serial_header_t* hdr = getheader(msg); 
      +  serial_header_t* hdr = getheader(msg);
         return hdr->type;
       }
       
      @@ -609,9 +604,9 @@ It is an example of what components MUST NOT do:

       serial_header_t* getHeader(message_t* msg) {
         return (serial_header_t*)(msg->header);
      -} 
      +}
       
      -

      In the case of Telos, for example, this would result in a packet +

      In the case of Telos, for example, this would result in a packet layout that looks like this:

                   11 bytes         TOSH_DATA_LENGTH           7 bytes
      @@ -619,27 +614,27 @@ layout that looks like this:

      message_t | header | data | meta | +-----------+-----------------------------+-------+ - +-----+ +------------+ -Serial | hdr | | data | - +-----+ +------------+ + +-----+ +------------+ +Serial | hdr | | data | + +-----+ +------------+
    -
    -

    3.2 Data

    +
    +

    3.2 Data

    The data field of message_t stores the single-hop packet payload. It is TOSH_DATA_LENGTH bytes long. The default size is 28 bytes. A TinyOS application can redefine TOSH_DATA_LENGTH at compile time with a command-line option to ncc: -DTOSH_DATA_LENGTH=x. Because this value can be reconfigured, it is possible that two different versions of an application can have different MTU sizes. -If a packet layer receives a packet whose payload size is +If a packet layer receives a packet whose payload size is longer than TOSH_DATA_LENGTH, it MUST discard the packet. As headers are right justified to the beginning of the data payload, the data payloads of all link layers on a platform start at the same fixed offset from the beginning of the message buffer.

    -