]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - doc/html/tep114.html
debug: add cfprintf macro
[tinyos-2.x.git] / doc / html / tep114.html
index 5476f57cec4bb343ae08dc2f2bc07a9327bfaa85..19e1f243842baa51662ed776c81dfa42a494b9de 100644 (file)
@@ -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 }
 
@@ -296,19 +291,11 @@ ul.auto-toc {
 <tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
 </tr>
 <tr><th class="docinfo-name">Status:</th>
-<td>Draft</td></tr>
+<td>Final</td></tr>
 <tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
 </tr>
 <tr><th class="docinfo-name">Author:</th>
 <td>Gilman Tolle, Philip Levis, and David Gay</td></tr>
-<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">30-Oct-2005</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.4</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-08-30</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List &lt;tinyos-devel at mail.millennium.berkeley.edu&gt;</td>
-</tr>
 </tbody>
 </table>
 <div class="note">
@@ -325,15 +312,16 @@ for data sources and sinks in TinyOS 2.x.</p>
 </div>
 <div class="section">
 <h1><a id="introduction" name="introduction">1. Introduction</a></h1>
-<p>Sensing is an integral part of any sensor network application.  Having
-a wide variety of sensor interfaces usually does not impose a large
-burden on an application developer, as any given application uses a
-small and static set. However, applications often build on top of more
-general systems, such as management or database layers, which may need
-to sample sensors. Since these are general and sensor-independent
-systems, they require a sensor-independent interface. TinyOS 2.0
-therefore has telescoping sensor abstractions, providing both simple
-and sensor-independent as well as sensor-specific interfaces.</p>
+<p>Sensing is an integral part of any sensor network application. The
+diversity of sensors can lead to a wide variety of different software
+interfaces to these sensors. However, the burden of connecting a
+general sensor data management application to every one of these
+different interfaces suggests that sensors also provide a simple,
+general-purpose interface for data acquisition. Therefore, TinyOS 2.0
+has telescoping sensor abstractions, providing both sensor-independent
+and sensor-specific interfaces. This memo documents a set of hardware-
+and sensor-independent interfaces for data sources and sinks in TinyOS
+2.x.</p>
 </div>
 <div class="section">
 <h1><a id="sensors-in-tinyos-1-x" name="sensors-in-tinyos-1-x">2. Sensors in TinyOS 1.x</a></h1>
@@ -345,50 +333,89 @@ the ADC interface was originally designed for inexpensive,
 interrupt-driven sampling.  All of its commands and events are async
 and sensor values are always 16 bits, although only some subset of the
 bits may be significant (e.g., a 12-bit value).</p>
-<p>Because sensing can be a part of high-level application logic,
-the asynchronicity of these events means that high-level components
-must deal with atomic sections and possible race conditions, even
-if the sampling rate is very low (e.g., every five minutes)
-and so could be easily placed in a task.</p>
+<p>Because sensing is an integral part of high-level application logic,
+having asynchronous events means that high-level components
+must work with atomic sections, even if the sampling rate is very low
+(e.g., every five minutes) and so could be easily placed in a
+task. Race conditions are problematic and possible in any real time
+multi-tasking design. Race conditions are a failure in design, and
+especially difficult to detect at low sampling rates.</p>
 <p>Additionally, not all sensors require ADC conversions from the MCU.
 Many sensors today are digital. To sample these sensors, the MCU sends
 a sample command and receives the corresponding data over a bus (e.g.,
 SPI, I2C). The latency involved, combined with possible Resource
-arbitration [_tep108], means that these bus operations are often
+arbitration <a class="footnote-reference" href="#id2" id="id1" name="id1">[1]</a>, means that these bus operations are often
 synchronous code. In the command direction, this can force a task
 allocation to convert async to sync; in the event direction, the
 application has to deal with async code even though the event is, in
 practice, in a task.</p>
-<p>Finallly, the simplicity of the ADC interface has led many sensors to
-introduce several new ones for calibration and control, such as
-<tt class="docutils literal"><span class="pre">Mic</span></tt> and <tt class="docutils literal"><span class="pre">MagSetting</span></tt>. Because ADCs generally do not have error
-conditions, the ADC interface has no way to signal that a sample
-failed. This turns out to be important for sensors where the sampling
-request is split-phase, such as sensors over a bus. In these cases, it
-is possible that the driver accepts the request to sample, but once
-acquiring the bus discovers something is wrong with the sensor. This
-property has led bus-based sensors to also have a separate
-<tt class="docutils literal"><span class="pre">ADCError</span></tt> interface; this interface breaks the basic TinyOS pattern
-of a tight coupling between split-phase commands and their completion
-events, as the command is in ADC but the completion event is in
-ADCError.</p>
-<p>All of these complications can make it difficult to write high-level
-code that is sensor independent, unless the sensor is a simple ADC
-reading. Sensors, when possible, should follow an approach similar to
-the HAA[_haa], where they have sensor- or sensor-class-specific
-interfaces for high performance or special case use, but also simple
-and common interfaces for basic and portable use. Providing a
-telescoping sensor abstraction allows both classes of use.</p>
+<p>Finally, the simplicity of the ADC interface has led many sensor
+modules to introduce several new interfaces for calibration and
+control, such as <tt class="docutils literal"><span class="pre">Mic</span></tt> and <tt class="docutils literal"><span class="pre">MagSetting</span></tt>. Because ADCs generally do
+not have error conditions, the ADC interface has no way to signal that
+a sample failed. This turns out to be important for sensors where the
+sampling request is split-phase, such as sensors over a bus. In these
+cases, it is possible that the driver accepts the request to sample,
+but once acquiring the bus discovers something is wrong with the
+sensor. This property has led bus-based sensors to also have a
+separate <tt class="docutils literal"><span class="pre">ADCError</span></tt> interface; this interface breaks the basic
+TinyOS pattern of a tight coupling between split-phase commands and
+their completion events, as the command is in ADC but the completion
+event is in ADCError.</p>
+<p>All of these complications provide the context of the challenge to
+write high-level code that is sensor independent. Sensors, when
+possible, should follow an approach similar to the HAA[_haa], where
+they have sensor- or sensor-class-specific interfaces for high
+performance or special case use, but also simple and common interfaces
+for basic and portable use. Providing a telescoping sensor abstraction
+allows both classes of use.</p>
 </div>
 <div class="section">
 <h1><a id="sensors-in-tinyos-2-x" name="sensors-in-tinyos-2-x">3. Sensors in TinyOS 2.x</a></h1>
-<p>TinyOS 2.x has several sensor-independent interfaces, which cover a
-range of common use cases. These interfaces can be used to write a
-Source- or Sink-Independent Driver (SID). A SID is source/sink
-independent because its interfaces do not themselves contain
-information on the sort of sensor or device they sit on top of.  A SID
-SHOULD provide one or more of the interfaces described in this
-section, depending on its expected uses and underlying data model.</p>
+<p>TinyOS 2.x contains several nesC interfaces that can be used to
+provide sensor-independent interfaces which cover a range of common
+use cases. This document describes these interfaces, and explains how
+to use these interfaces to write a Source- or Sink-Independent Driver
+(SID). A SID is source/sink independent because its interfaces do not
+themselves contain information on the sort of sensor or device they
+sit on top of.  A SID SHOULD provide one or more of the interfaces
+described in this section.</p>
+<p>This table summarizes the SID interfaces:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="42%" />
+<col width="19%" />
+<col width="19%" />
+<col width="19%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>Name</td>
+<td>Phase</td>
+<td>Data type</td>
+<td>Section</td>
+</tr>
+<tr><td>Read</td>
+<td>Split</td>
+<td>Scalar</td>
+<td>3.1</td>
+</tr>
+<tr><td>Get</td>
+<td>Single</td>
+<td>Scalar</td>
+<td>3.2</td>
+</tr>
+<tr><td>Notify</td>
+<td>Trigger</td>
+<td>Scalar</td>
+<td>3.3</td>
+</tr>
+<tr><td>ReadStream</td>
+<td>Split</td>
+<td>Stream</td>
+<td>3.4</td>
+</tr>
+</tbody>
+</table>
 <div class="section">
 <h2><a id="split-phase-small-scalar-i-o" name="split-phase-small-scalar-i-o">3.1 Split-Phase Small Scalar I/O</a></h2>
 <p>The first set of interfaces can be used for low-rate scalar I/O:</p>
@@ -397,121 +424,35 @@ interface Read&lt;val_t&gt; {
   command error_t read();
   event void readDone( error_t result, val_t val );
 }
-
-interface Write&lt;val_t&gt; {
-  command error_t write( val_t val );
-  event void writeDone( error_t result );
-}
-</pre>
-<p>A component that provides both read and write functionality might want
-to use a combined version of the interface, to reduce the amount of
-wiring required by the client application:</p>
-<pre class="literal-block">
-interface ReadWrite&lt;val_t&gt; {
-  command error_t read();
-  event void readDone( error_t result, val_t val );
-
-  command error_t write( val_t val );
-  event void writeDone( error_t result );
-}
 </pre>
-<p>A component that can support concurrent reads and writes SHOULD
-provide separate Read/Write interfaces. A component whose internal
-logic will cause a read to fail while a write is pending or a write to
-fail while a read is pending MUST provide a ReadWrite interface.</p>
 <p>If the <tt class="docutils literal"><span class="pre">result</span></tt> parameter of the <tt class="docutils literal"><span class="pre">Read.readDone</span></tt> and
 <tt class="docutils literal"><span class="pre">ReadWrite.readDone</span></tt> events is not SUCCESS, then the memory of the
 <tt class="docutils literal"><span class="pre">val</span></tt> parameter MUST be filled with zeroes.</p>
+<p>If the call to <tt class="docutils literal"><span class="pre">read</span></tt> has returned SUCCESS, but the <tt class="docutils literal"><span class="pre">readDone</span></tt>
+event has not yet been signaled, then a subsequent call to <tt class="docutils literal"><span class="pre">read</span></tt>
+MUST return EBUSY or FAIL.  This simple locking technique, as opposed
+to a more complex system in which multiple read/readDone pairs may be
+outstanding, is intended to reduce the complexity of SID client code.</p>
 <p>Examples of sensors that would be suited to this class of interface
 include many basic sensors, such as photo, temp, voltage, and ADC
 readings.</p>
 </div>
 <div class="section">
-<h2><a id="split-phase-large-scalar-i-o" name="split-phase-large-scalar-i-o">3.2 Split-Phase Large Scalar I/O</a></h2>
-<p>If the SID's data object is too big to be passed efficienctly on the
-stack, it can provide read/write interfaces that pass parameters by
-pointer rather than value:</p>
-<pre class="literal-block">
-interface ReadRef&lt;val_t&gt; {
-  command error_t read( val_t* val );
-  event void readDone( error_t result, val_t* val );
-}
-
-interface WriteRef&lt;val_t&gt; {
-  command error_t write( val_t* val );
-  event void writeDone( error_t result, val_t* val );
-}
-
-interface ReadWriteRef&lt;val_t&gt; {
-  command error_t read( val_t* val );
-  event void readDone( error_t result, val_t* val );
-
-  command error_t write( val_t* val );
-  event void writeDone( error_t result, val_t* val );
-}
-</pre>
-<p>The caller is responsible for allocating storage pointed to by the val
-pointer which is passed to read() or write(). The SID MUST then
-take ownership of the storage, store a new value into it or copy a
-value out of it, and then relinquish it before signaling readDone() or
-writeDone(). If read or write() returns SUCCESS then the caller MUST
-NOT access or modify the storage pointed to by the val pointer until
-it handles the readDone() or writeDone() event.</p>
-<p>As is the case with the parameters by value, whether a component
-provides separate ReadRef and WriteRef or ReadWriteRef affects the
-concurrency it allows. If a component can allow the two to execute
-concurrently, then it SHOULD provide separate ReadRef and WriteRef
-interfaces. If the two cannot occur concurrently, then it MUST provide
-ReadWriteRef.</p>
-<p>If the <tt class="docutils literal"><span class="pre">result</span></tt> parameter of the <tt class="docutils literal"><span class="pre">ReadRef.readDone</span></tt> and
-<tt class="docutils literal"><span class="pre">ReadWriteRef.readDone</span></tt> events is not SUCCESS, then the memory the
-<tt class="docutils literal"><span class="pre">val</span></tt> parameter points to MUST be filled with zeroes.</p>
-<p>Examples of sensors that are suited to this set of interfaces include
-those that generate multiple simultaneous readings for which
-passing by value is inefficient, such as a two-axis digital
-accelerometer.</p>
-</div>
-<div class="section">
-<h2><a id="single-phase-scalar-i-o" name="single-phase-scalar-i-o">3.4 Single-Phase Scalar I/O</a></h2>
+<h2><a id="single-phase-scalar-i-o" name="single-phase-scalar-i-o">3.2 Single-Phase Scalar I/O</a></h2>
 <p>Some devices may have their state cached or readily available. In
 these cases, the device can provide a single-phase instead of
 split-phase operation.  Examples include a node's MAC address (which
 the radio stack caches in memory), profiling information (e.g.,
-packets received), or a GPIO pin. These devices MAY use these
-single-phase interfaces:</p>
+packets received), or a GPIO pin. These devices MAY use the
+Get interface:</p>
 <pre class="literal-block">
 interface Get&lt;val_t&gt; {
   command val_t get();
 }
-
-interface Set&lt;val_t&gt; {
-  command void set( val_t val );
-}
-
-interface GetSet&lt;val_t&gt; {
-  command val_t get();
-  command void set( val_t val );
-}
-</pre>
-<p>If a device's data object is readily available but still too large to
-be passed on the stack, then the device MAY use these interfaces:</p>
-<pre class="literal-block">
-interface GetRef&lt;val_t&gt; {
-  command error_t get( val_t* val );
-}
-
-interface SetRef&lt;val_t&gt; {
-  command error_t set( val_t* val );
-}
-
-interface GetSetRef&lt;val_t&gt; {
-  command error_t get( val_t* val );
-  command error_t set( val_t* val );
-}
 </pre>
 </div>
 <div class="section">
-<h2><a id="notification-based-scalar-i-o" name="notification-based-scalar-i-o">3.5 Notification-Based Scalar I/O</a></h2>
+<h2><a id="notification-based-scalar-i-o" name="notification-based-scalar-i-o">3.3 Notification-Based Scalar I/O</a></h2>
 <p>Some sensor devices represent triggers, rather than request-driven
 data acquisition. Examples of such sensors include switches,
 passive-IR (PIR) motion sensors, tone detectors, and smoke
@@ -530,12 +471,15 @@ more platform- or hardware-specific async interfaces.</p>
 <p>The enable() and disable() command enable and disable notification
 events for the interface instance used by a single particular
 client. They are distinct from the sensor's power state. For example,
-if an enabled sensor is powered down, then when powered up it MUST
+if an enabled sensor is powered down, then when powered up it will
 remain enabled.</p>
+<p>If <tt class="docutils literal"><span class="pre">enable</span></tt> returns SUCCESS, the interface MUST subsequently
+signal notifications when appropriate. If <tt class="docutils literal"><span class="pre">disable</span></tt> returns SUCCESS,
+the interface MUST NOT signal any notifications.</p>
 <p>The val parameter is used as defined in the Read interface.</p>
 </div>
 <div class="section">
-<h2><a id="split-phase-streaming-i-o" name="split-phase-streaming-i-o">3.7 Split-Phase Streaming I/O</a></h2>
+<h2><a id="split-phase-streaming-i-o" name="split-phase-streaming-i-o">3.4 Split-Phase Streaming I/O</a></h2>
 <p>Some sensors can provide a continuous stream of readings, and some
 actuators can accept a continuous stream of new data. Depending on the
 rate needed and jitter bounds that higher level components can
@@ -544,7 +488,7 @@ blocks instead of singly.  For example, a microphone or accelerometer
 may provide data at a high rate that cannot be processed quickly
 enough when each new reading must be transferred from asynchronous to
 synchronous context through the task queue.</p>
-<p>The ReadStreaming interface MAY be provided by a device that can
+<p>The ReadStream interface MAY be provided by a device that can
 provide a continuous stream of readings:</p>
 <pre class="literal-block">
 interface ReadStream&lt;val_t&gt; {
@@ -570,36 +514,40 @@ drivers that may store the queue of buffers and count sizes by
 building a linked list.</p>
 <p>After posting at least one buffer, the client can call read() with a
 specified sample period in terms of microseconds. The driver then
-begins to fill the buffers in the queue, signalling the bufferDone()
+begins to fill the buffers in the queue, signaling the bufferDone()
 event when a buffer has been filled. The client MAY call postBuffer()
 after read() in order to provide the device with new storage for
 future reads.</p>
-<p>If the device ever takes a sample that it cannot store (e.g., no
-buffers are available), it MUST signal readDone(). If an error occurs
-during a read, then the device MUST signal readDone() with an
-appropriate failure code. Before a device signals readDone(), it MUST
-signal bufferDone() for all outstanding buffers. If a readDone() is
-pending, calls to postBuffer MUST return FAIL.</p>
-<p>The following interface can be used for bulk writes:</p>
-<pre class="literal-block">
-interface WriteStream&lt;val_t&gt; {
-
-  command error_t postBuffer( val_t* buf, uint16_t count );
-
-  command error_t write( uint32_t period );
-
-  event void bufferDone( error_t result,
-                         val_t* buf, uint16_t count );
-
-  event void writeDone( error_t result );
-}
-</pre>
-<p>postBuffer() and bufferDone() are matched in the same way described
-for the ReadStream interface, as are write() and writeDone().</p>
+<p>If the device ever takes a sample that it cannot store (e.g., due to
+buffer underrun), it MUST signal readDone() with an appropriate
+failure code. If an error occurs during a read, then the device MUST
+signal readDone() with an appropriate failure code. Before a device
+signals readDone(), it MUST signal bufferDone() for all outstanding
+buffers. If a readDone() is pending, calls to postBuffer MUST return
+FAIL.</p>
+<p>In the ReadStream interface, <tt class="docutils literal"><span class="pre">postBuffer</span></tt> returns SUCCESS if the buffer
+was successfully added to the queue, FAIL otherwise. A return value
+of SUCCESS from <tt class="docutils literal"><span class="pre">read</span></tt> indicates reading has begun and the interface
+will signal <tt class="docutils literal"><span class="pre">bufferDone</span></tt> and/or <tt class="docutils literal"><span class="pre">readDone</span></tt> in the future. A
+return value of FAIL means the read did not begin and the interface
+MUST NOT signal <tt class="docutils literal"><span class="pre">readDone</span></tt> or <tt class="docutils literal"><span class="pre">bufferDone</span></tt>. Calls to <tt class="docutils literal"><span class="pre">read</span></tt>
+MAY return EBUSY if the component cannot service the request.</p>
 </div>
 </div>
 <div class="section">
-<h1><a id="summary" name="summary">4. Summary</a></h1>
+<h1><a id="implementation" name="implementation">4. Implementation</a></h1>
+<p>An implementation of the Read interface can be found in
+<tt class="docutils literal"><span class="pre">tos/system/SineSensorC.nc</span></tt> and <tt class="docutils literal"><span class="pre">tos/system/ArbitratedReadC.nc</span></tt>.</p>
+<p>An implementation of the Get interface can be found in
+<tt class="docutils literal"><span class="pre">tos/platforms/telosb/UserButtonC.nc</span></tt>.</p>
+<p>An implementation of the ReadStream interface can be found in
+<tt class="docutils literal"><span class="pre">tos/sensorboards/mts300/MageXStreamC.nc</span></tt>.</p>
+<p>Implementations of the Notify interface can be found in
+<tt class="docutils literal"><span class="pre">tos/platforms/telosb/SwitchToggleC.nc</span></tt> and
+<tt class="docutils literal"><span class="pre">tos/platforms/telosb/UserButtonP.nc</span></tt>.</p>
+</div>
+<div class="section">
+<h1><a id="summary" name="summary">5. Summary</a></h1>
 <p>According to the design principles described in the HAA[_haa], authors
 should write device drivers that provide rich, device-specific
 interfaces that expose the full capabilities of each device. In
@@ -610,15 +558,15 @@ who only need simple interfaces, and can reduce the effort needed to
 connect a sensor into a more general system.</p>
 </div>
 <div class="section">
-<h1><a id="author-s-address" name="author-s-address">5. Author's Address</a></h1>
+<h1><a id="author-s-address" name="author-s-address">6. Author's Address</a></h1>
 <div class="line-block">
 <div class="line">Gilman Tolle</div>
-<div class="line">2168 Shattuck Ave.</div>
-<div class="line">Arched Rock Corporation</div>
-<div class="line">Berkeley, CA 94704</div>
+<div class="line">501 2nd St. Ste 410</div>
+<div class="line">Arch Rock Corporation</div>
+<div class="line">San Francisco, CA 94107</div>
 <div class="line"><br /></div>
-<div class="line">phone - +1 510 981 8714</div>
-<div class="line">email - <a class="reference" href="mailto:gtolle&#64;archedrock.com">gtolle&#64;archedrock.com</a></div>
+<div class="line">phone - +1 415 692 0828</div>
+<div class="line">email - <a class="reference" href="mailto:gtolle&#64;archrock.com">gtolle&#64;archrock.com</a></div>
 <div class="line"><br /></div>
 <div class="line"><br /></div>
 <div class="line">Philip Levis</div>
@@ -641,6 +589,15 @@ connect a sensor into a more general system.</p>
 <div class="line"><br /></div>
 </div>
 </div>
+<div class="section">
+<h1><a id="citations" name="citations">7. Citations</a></h1>
+<table class="docutils footnote" frame="void" id="id2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id2">[1]</a></td><td>TEP 108: Resource Arbitration.</td></tr>
+</tbody>
+</table>
+</div>
 </div>
 </body>
 </html>