<td>Philip Levis</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">10-Dec-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.9</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2007-03-21</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<p>The memo documents the interfaces used by packet protocol components in
TinyOS 2.x as well as the structure and implementation of ActiveMessageC,
the basic data-link HIL component. It also documents the virtualized
-active message interfaces AMSender and AMReceiver.</p>
+active message interfaces AMSenderC and AMReceiverC.</p>
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
<em>Packet</em> interfaces are for accessing message fields and payloads.
<em>Send</em> interfaces are for transmitting packets, and are
distinguished by their addressing scheme.
-Finally, the <em>Receive</em> interface is for handling packet reception events.</p>
+The <em>Receive</em> interface is for handling packet reception events.
+Finally, depending on whether the protocol has a dispatch identifier
+field, the Receive and Send interfaces may be parameterized in order
+to support multiple higher-level clients.</p>
<div class="section">
<h2><a id="packet-interfaces" name="packet-interfaces">2.1 Packet interfaces</a></h2>
<p>The basic TinyOS 2.x message buffer type is message_t, which is
interface AMPacket {
command am_addr_t address();
command am_addr_t destination(message_t* amsg);
+ command am_addr_t source(message_t* amsg);
command void setDestination(message_t* amsg, am_addr_t addr);
+ command void setSource(message_t* amsg, am_addr_t addr);
command bool isForMe(message_t* amsg);
command am_id_t type(message_t* amsg);
command void setType(message_t* amsg, am_id_t t);
</pre>
<p>The command address() returns the local AM address of the
node. AMPacket provides accessors for its two fields, destination and
-type. It does not provide commands to set these fields, as they are
-set in the sending call path (see Section 2.3). The <tt class="docutils literal"><span class="pre">setDestination</span></tt>
-and <tt class="docutils literal"><span class="pre">setType</span></tt> commands fulfill a similar purpose to
-<tt class="docutils literal"><span class="pre">Packet.setLength</span></tt>.</p>
+type. It also provides commands to set these fields, for the same
+reason that Packet allows a caller to set the payload length.
+Packet interfaces SHOULD provide accessors
+and mutators for all of their fields to enable queues and other
+buffering to store values in a packet buffer. Typically, a component
+stores these values in the packet buffer itself (where the field is),
+but when necessary it may use the metadata region of message_t or other
+locations.</p>
</div>
<div class="section">
<h2><a id="sending-interfaces" name="sending-interfaces">2.2 Sending interfaces</a></h2>
behave as if the length parameter of the <tt class="docutils literal"><span class="pre">Packet</span></tt> call were
NULL). Their inclusion is so that components do not have to wire to
both Packet and the sending interface for basic use cases.</p>
+<p>When called with a length that is too long for the underlying
+maximum transfer unit (MTU), the send command MUST return ESIZE.</p>
+<p>The <tt class="docutils literal"><span class="pre">Send</span></tt> and <tt class="docutils literal"><span class="pre">AMSend</span></tt> interfaces have an explicit queue of
+depth one. A call to <tt class="docutils literal"><span class="pre">send</span></tt> on either of these interfaces MUST
+return EBUSY if a prior call to <tt class="docutils literal"><span class="pre">send</span></tt> returned SUCCESS but no
+<tt class="docutils literal"><span class="pre">sendDone</span></tt> event has been signaled yet. More explicitly:</p>
+<pre class="literal-block">
+if (call Send.send(...) == SUCCESS &&
+ call Send.send(...) == SUCCESS) {
+ // This block is unreachable.
+}
+</pre>
+<p>Systems that need send queues have two options. They can
+use a QueueC (found in tos/system) to store pending packet pointers
+and serialize them onto sending interface, or they can introduce
+a new sending interface that supports multiple pending transmissions.</p>
+<p>The cancel command allows a sender to cancel the current transmission.
+A call to cancel when there is no pending sendDone event MUST return FAIL.
+If there is a pending sendDone event and the cancel returns SUCCESS, then
+the packet layer MUST NOT transmit the packet and MUST signal sendDone
+with ECANCEL as its error code. If there is a pending sendDone event
+and cancel returns FAIL, then sendDone SHOULD occur as if the cancel
+was not called.</p>
</div>
<div class="section">
<h2><a id="receive-interface" name="receive-interface">2.3 Receive interface</a></h2>
packet reception.</p>
<p>A <em>user</em> of the Receive interface has three basic options when it
handles a receive event:</p>
+<blockquote>
<ol class="arabic simple">
<li>Return <tt class="docutils literal"><span class="pre">msg</span></tt> without touching it.</li>
<li>Copy some data out of <tt class="docutils literal"><span class="pre">payload</span></tt> and return <tt class="docutils literal"><span class="pre">msg</span></tt>.</li>
<li>Store <tt class="docutils literal"><span class="pre">msg</span></tt> in its local frame and return a different <tt class="docutils literal"><span class="pre">message_t*</span></tt> for the lower layer to use.</li>
</ol>
+</blockquote>
<p>These are simple code examples of the three cases:</p>
<pre class="literal-block">
// Case 1
}
//Case 3
-message_t* ptr;
+message_t buf;
+message_t* ptr = &buf;
message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) {
message_t* tmp = ptr;
ptr = msg;
<div class="section">
<h2><a id="dispatch" name="dispatch">2.4 Dispatch</a></h2>
<p>A packet protocol MAY have a dispatch identifier. This generally manifests
-as the protocol component provided parameterized interfaces (rather than
-a single interface instances). A dispatch identifier allows multiple
+as the protocol component providing parameterized interfaces (rather than
+a single interface instance). A dispatch identifier allows multiple
services to use a protocol independently. If a protocol provides a
dispatch mechanism, then each dispatch identifier SHOULD correspond to
a single packet format: if an identifier corresponds to multiple packet
AMSnooperC, or AMReceiverC with the same am_id_t.</p>
</div>
<div class="section">
-<h2><a id="amsender" name="amsender">4.5 AMSender</a></h2>
+<h2><a id="amsenderc" name="amsenderc">4.5 AMSenderC</a></h2>
<p>AMSenderC has the following signature:</p>
<pre class="literal-block">
generic configuration AMSenderC(am_id_t AMId) {
packets receives a reasonable approximation of an equal share of the
available transmission bandwidth.</p>
</div>
+</div>
+<div class="section">
+<h1><a id="power-management-and-local-address" name="power-management-and-local-address">5. Power Management and Local Address</a></h1>
+<p>In addition to standard datapath interfaces for sending and
+receiving packets, an active message layer also has control interfaces.</p>
<div class="section">
-<h2><a id="power-management" name="power-management">4.6 Power Management</a></h2>
+<h2><a id="power-management" name="power-management">5.1 Power Management</a></h2>
<p>The communication virtualizations do not support power management.
ActiveMessageC provides SplitControl for explicit power control.
For packet communication to operate properly, a component in an
techniques, such as TDMA scheduling or low power listening, when
"on."</p>
</div>
+<div class="section">
+<h2><a id="local-active-message-address" name="local-active-message-address">5.2 Local Active Message Address</a></h2>
+<p>An application can change ActiveMessageC's local AM address
+at runtime. This will change which packets a node receives and
+the source address it embeds in packets. To change the local AM
+address at runtime, a component can wire to the component
+<tt class="docutils literal"><span class="pre">ActiveMessageAddressC</span></tt>. This component only changes the
+AM address of the default radio stack (AMSenderC, etc.); if
+a radio has multiple stacks those may have other components
+for changing their addresses in a stack-specific fashion.</p>
+</div>
</div>
<div class="section">
<h1><a id="hal-requirements" name="hal-requirements">5. HAL Requirements</a></h1>
can be passed to another data link layer (e.g., the UART) without
shifting the data payload. This means that the <tt class="docutils literal"><span class="pre">message_header_t</span></tt> must
include all data needed for AM fields, which might introduce headers
-in addition to those of the data link. For example, this is the
-structure of the CC2420 header:</p>
+in addition to those of the data link. For example, this is an example
+structure for a CC2420 (802.15.4) header:</p>
<pre class="literal-block">
typedef nx_struct cc2420_header_t {
nx_uint8_t length;