﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-Embedded_Systems-文章分类-tinyOS</title><link>http://www.cnitblog.com/Embedded_Systems/category/1470.html</link><description>嵌入式系统教学与研究实验室</description><language>zh-cn</language><lastBuildDate>Thu, 29 Sep 2011 23:22:33 GMT</lastBuildDate><pubDate>Thu, 29 Sep 2011 23:22:33 GMT</pubDate><ttl>60</ttl><item><title>Lesson 6: Displaying Data on a PC[转]</title><link>http://www.cnitblog.com/Embedded_Systems/articles/4947.html</link><dc:creator>井冈山</dc:creator><author>井冈山</author><pubDate>Sun, 27 Nov 2005 17:15:00 GMT</pubDate><guid>http://www.cnitblog.com/Embedded_Systems/articles/4947.html</guid><wfw:comment>http://www.cnitblog.com/Embedded_Systems/comments/4947.html</wfw:comment><comments>http://www.cnitblog.com/Embedded_Systems/articles/4947.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/Embedded_Systems/comments/commentRss/4947.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Embedded_Systems/services/trackbacks/4947.html</trackback:ping><description><![CDATA[&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="tahoma,arial,helvetica"><font size="-1">Lesson 6: 
Displaying Data on a PC</font></font></b> 
<p><font face="tahoma,arial,helvetica">Last updated 23 September 
2003</font></p></td></tr></tbody></table>
<p>To goal of this lesson is to integrate the sensor network with a PC, allowing 
us to display sensor readings on the PC as well as to communicate from the PC 
back to the motes. First, we'll introduce the basic tools used to read sensor 
network data on a desktop over the serial port. Next we'll demonstrate a Java 
application that displays sensor readings graphically. Finally, we'll close the 
communication loop by showing how to send data back to the motes. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The Oscilloscope 
application</font></nobr></b></td></tr></tbody></table></p>
<p>The mote application we use in this lesson is found in <tt><a href="../../apps/Oscilloscope">apps/Oscilloscope</a></tt>. It consists of a 
single module that reads data from the photo sensor. For each 10 sensor 
readings, the module sends a packet to the serial port containing those 
readings. The mote only sends the packets over the serial port.&nbsp; (To see how the 
data can be sent over the radio see <a href="../../apps/OscilloscopeRF">apps/OscilloscopeRF</a>.) </p>
<p>Compile and install the <tt>Oscilloscope</tt> application on a mote. You will 
need to connect a sensor board to the mote to get the light readings. Remember 
to set the <tt>SENSORBOARD</tt> option in <tt><a href="../../apps/Oscilloscope/Makefile">apps/Oscilloscope/Makefile</a></tt> to 
either <tt>micasb</tt> or <tt>basicsb</tt> depending on the type of sensor board 
you have. </p>
<p>This application requires that the mote with the sensor be connected to the 
serial port on the programming board. Note that the size of the current Mica 
sensor board prevents you from plugging the mote and board into the programming 
board directly. One workaround is to use a short cable to connect the 
programming board to the sensor board connector. </p>
<p>When the <tt>Oscilloscope</tt> application is running, the red LED lights 
when the sensor reading is over some threshold (set to <tt>0x0300)</tt> by 
default in the code - you might want to change this to a higher value if it 
never seems to go off in the dark). The yellow LED is toggled whenever a packet 
is sent to the serial port. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The 'listen' tool: 
displaying raw packet data</font></nobr></b></td></tr></tbody></table></p>
<p>The first step to establishing communication between the PC and the mote is 
to connect up your serial port cable to the programming board, and to make sure 
that you have Java and the <tt>javax.comm</tt> package installed. After 
programming your mote with the <tt>Oscilloscope</tt> code, <tt>cd</tt> to the 
<tt>tools/java</tt> directory, and type </p><pre>&nbsp; <tt>make</tt></pre><pre>&nbsp; <tt>export MOTECOM=serial@<i>serialport:baudrate</i></tt></pre>The 
environment variable <tt>MOTECOM</tt> tells the java Listen tool (and most other 
tools too) which packets it should listen to. Here 
<tt>serial@<i>serialport:baudrate</i></tt> says to listen to a mote connected to 
a serial port, where <tt>serialport</tt>is the serial port that you have 
connected the programming board to, and <tt>baudrate</tt> is the specific 
baudrate of the mote. For the mica and mica2dot motes, the baud rate is 19200, 
for the mica2 it is 57600 baud. You can also use a mote name as the baudrate (in 
which case that motes baudrate is selected). So you could do any of:<br><pre>&nbsp; <tt>export MOTECOM=serial@COM1:19200 # mica baud rate<br>  export MOTECOM=serial@COM1:mica  # mica baud rate, again<br>  export MOTECOM=serial@COM2:mica2 # the mica2 baud rate, on a different serial port<br>  export MOTECOM=serial@COM3:57600 # explicit mica2 baud rate<br></tt></pre>Set 
<span style="font-family: monospace;">MOTECOM</span> appropriately, then run <pre>&nbsp; <tt>java net.tinyos.tools.Listen</tt></pre>You should see some output 
resembling the following: <pre>% java net.tinyos.tools.Listen</pre><pre>serial@COM1:19200: resynchronising<br>7e 00 0a 7d 1a 01 00 0a 00 01 00 46 03 8e 03 96 03 96 03 96 03 97 03 97 03 97 03 97 03 97 03<br>7e 00 0a 7d 1a 01 00 14 00 01 00 96 03 97 03 97 03 98 03 97 03 96 03 97 03 96 03 96 03 96 03<br>7e 00 0a 7d 1a 01 00 1e 00 01 00 98 03 98 03 96 03 97 03 97 03 98 03 96 03 97 03 97 03 97 03</pre>The 
program is simply printing the raw data of each packet received from the serial 
port. 
<p>Before continuning, execute <tt>unset MOTECOM</tt> to avoid forcing all java 
applications to use the serial port to get packets. </p>
<p>If you don't have the <tt>javax.comm</tt> package installed properly, then 
the program will complain that it can't find the serial port. If you do not see 
that data lines on the screen, you may have chosen the wrong COM port or the 
mote may not be correctly connected to the computer. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Now what are you 
seeing?</font></nobr></b></td></tr></tbody></table></p>
<p>The application that you are running is simply printing out the packets that 
are coming from the mote. Each data packet that comes out of the mote contains 
several fields of data. Some of these fields are generic Active Message fields, 
and are defined in <tt><a href="../../tos/types/AM.h">tos/types/AM.h</a></tt>. 
The data payload of the message, which is defined by the application, is defined 
in <tt><a href="../../apps/Oscilloscope/OscopeMsg.h">apps/Oscilloscope/OscopeMsg.h</a></tt>. 
The overall message format for the Oscilloscope application is as follows: </p>
<ul><li><b>Destination address</b> (2 bytes) 
</li><li><b>Active Message handler ID</b> (1 byte) 
</li><li><b>Group ID</b> (1 byte) 
</li><li><b>Message length</b> (1 byte) 
</li><li><b>Payload</b> (up to 29 bytes): 
<ul><li><b>source mote ID</b> (2 bytes) 
</li><li><b>sample counter</b> (2 bytes) 
</li><li><b>ADC channel</b> (2 bytes) 
</li><li><b>ADC data readings</b> (10 readings of 2 bytes each) 
</li></ul></li></ul>So we can interpret the data packet as follows: 
<table border="0" cellpadding="0" cellspacing="10" hspace="0">
<tbody>
<tr bgcolor="#d0d0d0">
<td><b>dest addr</b></td>
<td><b>handlerID</b></td>
<td><b>groupID</b></td>
<td><b>msg len</b></td>
<td><b>source addr</b></td>
<td><b>counter</b></td>
<td><b>channel</b></td>
<td><b>readings</b></td>
<td><br></td></tr>
<tr>
<td bgcolor="#d0d0ff">7e 00</td>
<td bgcolor="#d0d0ff">0a</td>
<td bgcolor="#d0d0ff">7d</td>
<td bgcolor="#d0d0ff">1a</td>
<td bgcolor="#d0ffd0">01 00</td>
<td bgcolor="#d0ffd0">14 00</td>
<td bgcolor="#d0ffd0">01 00</td>
<td bgcolor="#ffd0d0">96 03 97 03 97 03 98 03 97 03 96 03 97 03 96 03 96 03 96 
03</td></tr></tbody></table>
<p>Note that the data is sent by the mote in <i>little-endian</i> format; so, 
for example, the two bytes <tt>96 03</tt> represent a single sensor reading with 
most-significant-byte <tt>0x03</tt> and least-significant-byte <tt>0x96</tt>. 
That is, <tt>0x0396</tt> or 918 decimal. </p>
<p>Here is an excerpt from <tt>OscilloscopeM.nc</tt> showing the data being 
written to the packet: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>OscilloscopeM.nc</b> <pre>&nbsp;&nbsp; async event result_t ADC.dataReady(uint16_t data) {<br>&nbsp;&nbsp;&nbsp; struct OscopeMsg *pack;<br><br>&nbsp;&nbsp;&nbsp; atomic {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pack = (struct OscopeMsg *)msg[currentMsg].data;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // add the new sensor reading to the packet&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // and update the number of bytes in this packet&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pack-&gt;data[packetReadingNumber++] = data;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readingNumber++; // increment total number of bytes<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbg(DBG_USR1, "data_event\n");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // if the packet is full, send the packet out&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (packetReadingNumber == BUFFER_SIZE) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post dataTask();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; if (data &gt; 0x0300)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call Leds.redOn();<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call Leds.redOff();<br><br>&nbsp;&nbsp;&nbsp; return SUCCESS;<br>&nbsp; }</pre><pre>&nbsp; task void dataTask() {<br>&nbsp;&nbsp;&nbsp; struct OscopeMsg *pack;<br>&nbsp;&nbsp;&nbsp; atomic {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pack = (struct OscopeMsg *)msg[currentMsg].data;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; packetReadingNumber = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pack-&gt;lastSampleNumber = readingNumber;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; pack-&gt;channel = 1;<br>&nbsp;&nbsp;&nbsp; pack-&gt;sourceMoteID = TOS_LOCAL_ADDRESS;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp; /* Try to send the packet. Note that this will return<br>&nbsp;&nbsp;&nbsp;&nbsp; * failure immediately if the packet could not be queued for<br>&nbsp;&nbsp;&nbsp;&nbsp; * transmission.<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; if (call DataMsg.send(TOS_UART_ADDR, sizeof(struct OscopeMsg),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;msg[currentMsg]))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; atomic {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentMsg ^= 0x1; // flip-flop between two message buffers<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call Leds.yellowToggle();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp; }</pre></td></tr></tbody></table></center><br>&nbsp; 

<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The SerialForwarder 
Program</font></nobr></b></td></tr></tbody></table>
<p>The <tt>Listen</tt> program is the most basic way of communicating with the 
mote; it directly opens the serial port and just dumps packets to the screen. 
Obviously it is not easy to visualize the sensor data using this program. What 
we'd really like is a better way of retrieving and observing data coming from 
the sensor network. </p>
<p>The <tt>SerialForwarder</tt> program is used to read packet data from a 
serial port and forward it over an Internet connection, so that other programs 
can be written to communicate with the sensor network over the Internet. To run 
the serial forwarder, cd to <tt>tools/java</tt> and run the program </p><pre>&nbsp; java net.tinyos.sf.SerialForwarder -comm serial@COM1:&lt;baud rate&gt;</pre>This 
will open up a GUI window that looks similar to the following: 
<center>
<p><img src="http://www.cnitblog.com/images/cnitblog_com/embedded_systems/SerialForwarder.JPG" alt="SerialForwarder.JPG" border="0" height="300" width="500"><br></p></center>
<p>The <tt>-comm</tt> argument tells <tt>SerialForwarder </tt>to communicate 
over serial port <span style="font-family: monospace;">COM1</span>.<tt> 
</tt>The<span style="font-family: monospace;">-comm</span> argument specifies 
where the packets <span style="font-family: monospace;">SerialForwarder</span> 
should forward come from, using the same syntax as the <span style="font-family: monospace;">MOTECOM</span> environment variable you saw above 
(you can run '<span style="font-family: monospace;">java 
net.tinyos.packet.BuildSource</span>' to get a list of valid sources). Unlike 
most other programs, SerialForwarder does not pay attention to the <span style="font-family: monospace;">MOTECOM</span> environment variable; you must use 
the <span style="font-family: monospace;">-comm</span> argument to specify the 
packet source (The rationale is that you would typically set <span style="font-family: monospace;">MOTECOM</span> to specify a serial forwarder, and 
that serial forwader should talk to, e.g., a serial port. You wouldn't want the 
<span style="font-family: monospace;">SerialForwarder</span> to talk to 
itself...). </p>
<p>The <tt>&lt;baud rate&gt;</tt> argument tells <tt>SerialForwarder </tt>to 
communicate at specified baud rate. </p>
<p><tt>SerialForwarder </tt>does not display the packet data itself, but rather 
updates the packet counters in the lower-right hand corner of the window. Once 
running, the serial forwarder listens for network client connections on a given 
TCP port (9001 is the default), and simply forwards TinyOS messages from the 
serial port to the network client connection, and vice versa. Note that multiple 
applications can connect to the serial forwarder at once, and all of them will 
receive a copy of the messages from the sensor network. </p>
<p>More information is available on <span style="font-family: monospace;">SerialForwarder</span> and packet sources is 
found in the <a href="../serialcomm/index.html">SerialForwarder 
Documentation</a><br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="arial,helvetica">Starting the Oscilloscope 
GUI</font></b></td></tr></tbody></table></p>
<p>It is now time to graphically display the data coming from the motes. Leaving 
the serial forwarder running, execute the command </p><pre>&nbsp; java net.tinyos.oscope.oscilloscope</pre>This will pop up a window 
containing a graphical display of the sensor readings from the mote (If you get 
an error like "port COM1 busy", you probably forgot to unset the MOTECOM 
environment variable at the end of the Listen example. Do that now). It connects 
to the serial forwarder over the network and retrieves packet data, parses the 
sensor readings from each packet, and draws it on the graph: 
<center>
<p><img src="http://www.cnitblog.com/images/cnitblog_com/embedded_systems/oscilloscope.JPG" alt="oscilloscope.JPG" border="0" height="600" width="600"><br></p></center>
<p>The <i>x</i>-axis of the graph is the packet counter number and the 
<i>y</i>-axis is the sensor light reading. If the mote has been running for a 
while, its packet counter might be quite large, so the readings might not appear 
on the graph; just power-cycle the mote to reset its packet counter to 0. If you 
don't see any light readings on the display, be sure that you have not zoomed in 
on the display. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="arial,helvetica">Using MIG to communicate with 
motes</font></b></td></tr></tbody></table></p>
<p><a href="../../nesc/doc/mig.html">MIG (Message Interface Generator)</a> is a 
tool that is used to automatically generate Java classes that correspond to 
Active Message types that you use in your mote applications. MIG reads in the 
nesC <tt>struct</tt> definitions for message types in your mote application and 
generates a Java class for each message type that takes care of the gritty 
details of packing and unpacking fields in the message's byte format. Using MIG 
saves you from the trouble of parsing message formats in your Java application. 
</p>
<p>MIG is used in conjunction with the <tt><a href="../../tools/java/net/tinyos/message">net.tinyos.message</a></tt> package, 
which provides a number of routines for sending and receiving messages through 
the MIG-generated message classes. <tt><a href="../../nesc/doc/ncg.html">NCG(nesC Constant Generator)</a></tt> is a tool 
to extract constants from nesC files for use with other applications and is 
typically used in conjunction with <tt>MIG</tt>. </p>
<p>Let's look at the code from <tt><a href="../../tools/java/net/tinyos/oscope/GraphPanel.java">tools/java/net/tinyos/oscope/GraphPanel.java</a></tt> 
(part of the <tt>oscilloscope</tt> program) that communicates with the serial 
forwarder. First, the program connects to the serial forwarder and registers a 
handler to be invoked when a packet arrives. All of this is done through the 
<tt><a href="../../tools/java/net/tinyos/message/MoteIF.java">net.tinyos.message.MoteIF</a></tt> 
interface: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>GraphPanel.java</b> <pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // OK, connect to the serial forwarder and start receiving data<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mote = new MoteIF(PrintStreamMessenger.err, oscilloscope.group_id);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mote.registerListener(new OscopeMsg(), this);</pre></td></tr></tbody></table></center>
<p><tt>MoteIF</tt> represents a Java interface for sending and receiving 
messages to and from motes. The host and port number of the serial forwarder are 
obtained from the environment variable <tt>MOTECOM</tt>. You initialize 
<tt>MoteIF</tt> with&nbsp; <tt><a href="../../tools/java/net/tinyos/util/PrintStreamMessenger.java">PrintStreamMessenger</a></tt> 
which indicates where to send status messages (<tt>System.err</tt>), as well as 
an (optional) Active Message group ID. This group ID must correspond to the 
group ID used by your motes. </p>
<p>We register a message listener (<tt>this</tt>) for the message type 
<tt>OscopeMsg</tt>.<tt>OscopeMsg</tt> is automatically generated by <tt>MIG</tt> 
from the nesC definition for <tt>struct OscopeMsg</tt>, which we saw earlier in 
<tt>OscopeMsg.h</tt>. Look at <tt><a href="../../tools/java/net/tinyos/oscope/Makefile">tools/java/net/tinyos/oscope/Makefile</a></tt> 
for an example of how this class is generated. You will see: </p><pre>&nbsp; OscopeMsg.java:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(MIG) -java-classname=$(PACKAGE).OscopeMsg $(APP)/OscopeMsg.h OscopeMsg -o $@</pre>Essentially, 
this generates <tt>OscopeMsg.java</tt> from the message type <tt>struct 
OscopeMsg</tt> in the header file <a href="../../apps/Oscilloscope/OscopeMsg.h">apps<tt>/Oscilloscope/OscopeMsg.h</tt></a>. 

<p><tt>GraphPanel</tt> implements the <tt>MessageListener</tt> interface, which 
defines the interface for receiving messages from the serial forwarder. Each 
time a message of the appropriate type is received, the 
<tt>messageReceived()</tt> method is invoked in <tt>GraphPanel</tt>. It looks 
like this: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>GraphPanel.java</b> <pre>  public void messageReceived(int dest_addr, Message msg) {<br>    if (msg instanceof OscopeMsg) {<br>      oscopeReceived( dest_addr, (OscopeMsg)msg);<br>    } else {<br>      throw new RuntimeException("messageReceived: Got bad message type: "+msg);<br>    }<br>  }<br><br>  public void oscopeReceived(int dest_addr, OscopeMsg omsg) {<br>    boolean foundPlot = false;<br>    int moteID, packetNum, channelID, channel = -1, i;<br><br>    moteID = omsg.get_sourceMoteID();<br>    channelID = omsg.get_channel();<br>    packetNum = omsg.get_lastSampleNumber();<br>&nbsp;&nbsp;  <br>&nbsp;&nbsp;&nbsp; /* ... */</pre></td></tr></tbody></table></center>
<p><tt>messageReceived()</tt> is called with two arguments: the destination 
address of the packet, and the message itself 
(<tt>net.tinyos.message.Message</tt>).<tt>Message</tt> is just the base class 
for the application-defined message types; in this case we want to cast it to 
<tt>OscopeMsg</tt> which represents the actual message format we are using here. 
</p>
<p>Once we have the <tt>OscopeMsg</tt> we can extract fields from it using the 
handy <tt>get_sourceMoteID()</tt>, <tt>get_lastSampleNumber()</tt>, and 
<tt>get_channel()</tt> methods. If we look at <tt>struct OscopeMsg</tt> in 
<tt>OscopeMsg.h</tt> we'll see that each of these methods corresponds to a field 
in the message type: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>OscopeMsg.h</b> <pre>struct OscopeMsg<br>{<br>&nbsp;&nbsp;&nbsp; uint16_t sourceMoteID;<br>&nbsp;&nbsp;&nbsp; uint16_t lastSampleNumber;<br>&nbsp;&nbsp;&nbsp; uint16_t channel;<br>&nbsp;&nbsp;&nbsp; uint16_t data[BUFFER_SIZE];<br>};</pre></td></tr></tbody></table></center>
<p>Each field in a MIG-generated class has at least eight methods associated 
with it: </p>
<ul><li><tt>isSigned_<i>fieldname</i></tt> - Indicates whether or not this field is 
a signed quantity. 
</li><li><tt>isArray_<i>fieldname</i></tt> - Indicates whether or not this field is 
an array. 
</li><li><tt>get_<i>fieldname</i></tt> - Return the value of this field. 
</li><li><tt>set_<i>fieldname</i></tt> - Set the value of this field. 
</li><li><tt>offset_<i>fieldname</i></tt> - Return the offset (in bytes) for this 
field. 
</li><li><tt>offsetBits_<i>fieldname</i></tt> - Return the offset (in bits) for this 
field. 
</li><li><tt>size_<i>fieldname</i></tt> - Return the length (in bytes) of this field. 

</li><li><tt>sizeBits_<i>fieldname</i></tt> - Return the length (in bits) of this 
field. </li></ul>Note that additional methods are generated for fields that are 
arrays.<br>
<p>The remainder of <tt>messageReceived()</tt> pulls the sensor readings out of 
the message and places them on the graph. 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="arial,helvetica">Sending a message through 
MIG</font></b></td></tr></tbody></table></p>
<p>It is also possible to send a message to the motes using MIG. The 
<tt>Oscilloscope</tt> application sends messages of type 
<tt>AM_OSCOPERESETMSG</tt>, which causes the mote to reset its packet counter. 
Looking at <tt>clear_data()</tt> in <tt>GraphPanel.java</tt>, we see how 
messages are sent to the motes: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>GraphPanel.java</b> <pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mote.send(MoteIF.TOS_BCAST_ADDR, new OscopeResetMsg());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (IOException ioe) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.err.println("Warning: Got IOException sending reset message: "+ioe);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ioe.printStackTrace();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre></td></tr></tbody></table></center>
<p>All we need to do is invoke <tt>MoteIF.send()</tt> with the destination 
address and the message that we wish to send. Here, 
<tt>MoteIF.TOS_BCAST_ADDR</tt> is used to represent the broadcast destination 
address, which is identical to <tt>TOS_BCAST_ADDR</tt> used in the nesC code. 
<br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Exercises</font></nobr></b></td></tr></tbody></table></p>
<p>Transmit the light sensor readings over the radio to another mote that sends 
them over the serial port! </p>
<p>The <tt>apps/Oscilloscope</tt> mote application is written to use the serial 
port and the light sensor. Instead, look at <tt><a href="../../apps/OscilloscopeRF">apps/OscillosopeRF</a></tt>, which transmits 
the sensor readings over the radio. In order to use this application, you need 
to use one mote as a gateway that receives data packets over the radio and 
transmits them over the serial port. <tt><a href="../../apps/TOSBase">apps/TOSBase</a></tt> is an application that does 
this; it simply forwards packets between the radio and the UART (in both 
directions). </p>
<p><b>Extra Credit</b>: Can you figure out how to display sensor readings on the 
oscilloscope GUI from two motes simultaneously? (Note that the oscillosope GUI 
is already capable of displaying sensor readings from multiple motes. You have 
to ensure that those readings are correctly transmitted and received over the 
network.) This setup would look like the following diagram. </p>
<center>
<p><img src="http://www.cnitblog.com/images/cnitblog_com/embedded_systems/Serial_Forward_topology.jpg" alt="Serial_Forward_topology.jpg" border="0" height="540" width="720"><br></p></center>

<hr>
<b><a href="lesson5.html"></a></b> <!--  LocalWords:  LedsC StdControl tos init TimerC redOn redOff uint redToggle
 --><!--  LocalWords:  metadata html nesdoc gcc exe avr objcopy srec uisp mib dprog
 --><!--  LocalWords:  towards dapa xff ThinkPad dlpt Makelocal micasb Wshadow DDEF
 --><!--  LocalWords:  finline fnesc cfile lm Atmel ATmega nesC's nesc SenseM rdata
 --><!--  LocalWords:  ADCControl SounderControl dataReady getData rcombine someval
 --><!--  LocalWords:  ADControl fooControl barControl MyTimer uniqueCount basicsb
 --><!--  LocalWords:  sensorboard Makerules sensorboards SenseTask taskname INTMSG
 --><!--  LocalWords:  SenseTaskM putdata processData CntToLedsAndRfm RfmToLeds Msg
 --><!--  LocalWords:  CntToRfmAndLeds IntToLeds IntToRfm IntOutput outputComplete
 --><!--  LocalWords:  IntToRfmM GenericComm SendMsg bool struct IntMsg src BCAST
 --><!--  LocalWords:  ADDR sizeof TOSH sendDone GenricComm AMStandard RfmToInt pc
 --><!--  LocalWords:  UARTNoCRCPacket RadioCRCPacket ActiveMessage RfmToIntM xfff
 --><!--  LocalWords:  ReceiveIntMsg ReceiveMsg MsgPtr addr SenseToRfm TOSSIM DBG
 --><!--  LocalWords:  TinyViz ffff crc usr dbg const printf prepended bitmask gdb
 --><!--  LocalWords:  ledsOn gdbinit plugin API TestTinyViz cd tinyviz plugins RFM
 --><!--  LocalWords:  FakeLocation RadioModelPlugin LocationPlugin afterwards disc
 --><!--  LocalWords:  DebugMsgEvent TestTinyVizM AutoRun autorun numsec stopstring
 --><!--  LocalWords:  gridrandom DebugMsgPlugin RadioLinkPlugin radiomodel precmd
 --><!--  LocalWords:  radioscaling nummotes logfile txt logfiles arConfig TOSSIM's
 --><img src ="http://www.cnitblog.com/Embedded_Systems/aggbug/4947.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Embedded_Systems/" target="_blank">井冈山</a> 2005-11-28 01:15 <a href="http://www.cnitblog.com/Embedded_Systems/articles/4947.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lesson 5: Simulating TinyOS Applications in TOSSIM[转]</title><link>http://www.cnitblog.com/Embedded_Systems/articles/4946.html</link><dc:creator>井冈山</dc:creator><author>井冈山</author><pubDate>Sun, 27 Nov 2005 17:11:00 GMT</pubDate><guid>http://www.cnitblog.com/Embedded_Systems/articles/4946.html</guid><wfw:comment>http://www.cnitblog.com/Embedded_Systems/comments/4946.html</wfw:comment><comments>http://www.cnitblog.com/Embedded_Systems/articles/4946.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/Embedded_Systems/comments/commentRss/4946.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Embedded_Systems/services/trackbacks/4946.html</trackback:ping><description><![CDATA[&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="tahoma,arial,helvetica"><font size="-1">Lesson 5: 
Simulating TinyOS Applications in TOSSIM</font></font></b> 
<p><font face="tahoma,arial,helvetica">Last updated 25 August&nbsp; 
2003</font></p></td></tr></tbody></table>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Introduction</font></nobr></b></td></tr></tbody></table>
<p>TOSSIM, the TinyOS simulator, compiles directly from TinyOS code. Built with 
<tt>make pc</tt>, the simulation runs natively on a desktop or laptop. TOSSIM 
can simulate thousands of nodes simultaneously. Every mote in a simulation runs 
the same TinyOS program. 
</p><p>TOSSIM provides run-time configurable debugging output, allowing a user to 
examine the execution of an application from different perspectives without 
needing to recompile. TinyViz is a Java-based GUI that allows you to visualize 
and control the simulation as it runs, inspecting debug messages, radio and UART 
packets, and so forth. The simulation provides several mechanisms for 
interacting with the network; packet traffic can be monitored, packets can be 
statically or dynamically injected into the network. In this lesson, we won't be 
dealing with packet injection, which is discussed in <a href="lesson7.html">Lesson 7</a> . <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Building and Running an 
Application</font></nobr></b></td></tr></tbody></table>
</p><p>TOSSIM is compiled by typing <tt>make pc</tt> in an application directory. In 
addition to the expected TinyOS components, a few simulator-specific files are 
compiled; these files provide functionality such as support for network 
monitoring over TCP sockets. 
</p><p>Enter the <tt><a href="../../apps/CntToLedsAndRfm">apps/CntToLedsAndRfm</a></tt> directory. This 
application runs a 4Hz counter. It assumes a Mica mote which has 3 LEDs. On each 
counter tick, the application displays the least significant three bits of the 
counter on the three mote LEDs and sends the entire 16-bit value in a packet. 
Build and install the application on a Mica mote as in Lesson 4. You should see 
the LEDs blink. 
</p><p>Build a TOSSIM version of the application with <tt>make pc</tt>. The TOSSIM 
executable is <tt>build/pc/main.exe</tt>. Type <tt>build/pc/main.exe --help</tt> 
to see a brief summary of its command-line usage. TOSSIM has a single required 
parameter, the number of nodes to simulate. Type <tt>build/pc/main.exe 1</tt> to 
run a simulation of a single node. You should see a long stream of output fly 
by, most of which refer to radio bit events. Hit control-C to stop the 
simulation. 
</p><p>By default, TOSSIM prints out all debugging information. As radio bit events 
are fired at 20 or 40 KHz, these are the most frequent events in the simulator, 
they comprise most of the output in CntToLedsAndRfm. Given the application, 
we're more concerned with the packet output and mote LEDs than individual radio 
bits. TOSSIM output can be configured by setting the <tt>DBG</tt> environment 
variable in a shell. Type <tt>export DBG=am,led</tt> in your shell; this makes 
only LED and AM (active messages) packet output enabled. Run the one-mote 
simulation again. You should see output similar to this: <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre><tt>0: LEDS: Yellow off.<br>0: LEDS: Green off.<br>0: LEDS: Red off.<br>0: Sending message: ffff, 4<br>&nbsp;&nbsp;&nbsp; ff ff 04 7d 08 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00<br>00 00 00 00 00 00 00 00 00 00 00 00 3b f3 00 00 01 00 00 00<br>0: LEDS: Yellow off.<br>0: LEDS: Green off.<br>0: LEDS: Red on.<br>0: Sending message: ffff, 4<br>&nbsp;&nbsp;&nbsp; ff ff 04 7d 08 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00<br>00 00 00 00 00 00 00 00 00 00 00 00 ac e6 00 00 01 00 00 00<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></pre></td></tr></tbody></table></center>
<p>The sixth byte of the packet contains the least significant byte of the two 
byte counter; in this example the first packet is hex 0x20 (32), in the second, 
it's hex 0x21 (33). As the LEDs show the bottom three bits of the counter, they 
are all off for the first packet and bit one is on for the second. 
</p><p>Almost every message is preceded by a <tt>0:</tt>; this means that the 
message pertains to the execution of mote 0. Run a simulation of two motes 
(<tt>build/pc/main.exe 2</tt>); after it runs for a few seconds, stop the 
simulation with control-C. You should see messages for both mote 0 and mote 1. 
</p><p>Set <tt>DBG</tt> to <tt>crc</tt>. Run two mote simulation of 
<tt>CntToLedsAndRfm</tt>. You should see output indicating that both nodes are 
successfully receiving packets from each-other. 
</p><p>The full set of DBG modes can be seen by typing <tt>build/pc/main.exe 
--help</tt>; they are listed at the bottom of the output. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Adding Debugging 
Statements</font></nobr></b></td></tr></tbody></table>
</p><p>Four DBG modes are reserved for application components and debugging use: 
<tt>usr1</tt>, <tt>usr2</tt>, <tt>usr3</tt>, and <tt>temp</tt>. In TinyOS code, 
debug message commands have this syntax: <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre>dbg(&lt;mode&gt;, const char* format, ...);</pre></td></tr></tbody></table></center>
<p>The mode parameter specifies which under which DBG modes this message will be 
printed. The full set of modes can be found in <tt><a href="../../tos/types/dbg_modes.h">tos/types/dbg_modes.h</a></tt>. The format 
and following parameters specify the string to output and have <tt>printf()</tt> 
semantics. For example, open <tt><a href="../../tos/lib/Counters/Counter.nc">tos/lib/Counters/Counter.nc</a></tt>in 
your editor. In <tt>Timer.fired()</tt>, add this line just before the return 
statement: <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre>dbg(DBG_TEMP, "Counter: Value is %i\n", (int)state);</pre></td></tr></tbody></table></center>
<p>Set <tt>DBG</tt> to be <tt>temp</tt> and run a single mote simulation. You'll 
see the counter increment. In general, the DBG mode name in TinyOS code is the 
name used when you run the simulator, with <tt>DBG_</tt>prepended. For example, 
<tt>am</tt> is <tt>DBG_AM</tt>, <tt>packet</tt> is <tt>DBG_PACKET</tt> and 
<tt>boot</tt> is <tt>DBG_BOOT</tt>. 
</p><p>Just as you can enable multiple modes when running the simulator, a single 
debug message can be activated on multiple modes. Each mode is a bit in a large 
bitmask; one can use all of the standard logical operators (e.g. <tt>|</tt>, 
<tt>~</tt>) . For example, change the debug message you just added to: <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre>dbg(DBG_TEMP|DBG_USR1, "Counter: Value is %i\n", (int)state);</pre></td></tr></tbody></table></center>
<p>It will now be printed if either <tt>temp</tt> or <tt>usr1</tt> is enabled. 
Run the application to see this is the case. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Using gdb with 
TOSSIM</font></nobr></b></td></tr></tbody></table>
</p><p>One significant advantage of TOSSIM is that, because it runs natively on a 
PC, you can use traditional debugging tools such as <tt>gdb</tt>. However, 
because TOSSIM is a discrete event simulation for large numbers of motes, 
traditional step-through debugging techniques only work on an event basis, and 
not cross-events. 
</p><p>Unfortunately, <tt>gdb</tt> is generally designed for C and not nesC; the 
component model of nesC means that a single command can have multiple providers; 
referring to a specific command requires specifying the component, interface, 
and command. For example, to break on entry to the <tt>redOff</tt> command of 
the <tt>Leds</tt> interface of <tt>LedsC</tt>, one must type: <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre>&nbsp;gdb build/pc/main.exe&nbsp; // start gdb<br><br>(gdb) break *LedsC$Leds$redOff<br>Breakpoint 1 at 0x804c644: file tos/system/LedsC.td, line 97.<br><br>run 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // run CntToLedsAndRfm with one mote</pre></td></tr></tbody></table></center>
<p>The leading * is necessary so <tt>gdb</tt> can parse the function name 
correctly; otherwise, it looks for the function <tt>LedsC</tt>. 
</p><p>Variables are similarly named. For example, to print the <tt>ledsOn</tt> 
variable of <tt>LedsC</tt> (which keeps track of on/off for the toggle 
commands), one types: <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre>(gdb) print LedsC$ledsOn<br>$3 = '\0' &lt;repeats 999 times&gt;</pre></td></tr></tbody></table></center>
<p>Actually, this isn't quite correct, as the output above shows; in TOSSIM, 
<tt>ledsOn</tt> isn't a single <tt>uint8_t</tt>, but an array of 1000 of them. 
This is how TOSSIM handles the state of many motes; it compiles fields to be 
arrays of <i>n</i> elements, where <i>n</i> is the maximum simulation size. 
Whenever a mote accesses a component's state, it indexes into the array based on 
its node ID. Therefore, to refer to a specific mote's state, one needs to index 
into the array properly: <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre>(gdb) print LedsC$ledsOn[tos_state.current_node]<br>$2 = 0 '\0'</pre></td></tr></tbody></table></center>
<p>We've supplied a simple <tt>gdb</tt> macro named <tt>VAR</tt> that handles 
this for you. Copy <tt><a href="../../tos/platform/pc/.gdbinit">tos/platform/pc/.gdbinit</a></tt> to your 
home directory (if there's already a <tt>.gdbinit</tt> there, just append this 
file).&nbsp; Type <tt>quit</tt> and start <tt>gdb</tt> it again. Break in 
<tt>LedsC$Leds$redOff</tt> as before. Now, instead of the above command line, 
you can type: <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre>(gdb) VAR LedsC$ledsOn<br>$3 = 0 '\0'</pre></td></tr></tbody></table></center><br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">TinyViz: The TOSSIM User 
Interface</font></nobr></b></td></tr></tbody></table>
<p>TinyViz provides an extensible graphical user interface for debugging, 
visualizing, and interacting with TOSSIM simulations of TinyOS applications. 
Using TinyViz, you can easily trace the execution of TinyOS apps, set 
breakpoints when interesting events occur, visualize radio messages, and 
manipulate the virtual position and radio connectivity of motes. In addition, 
TinyViz supports a simple "plugin" API that allows you to write your own TinyViz 
modules to visualize data in an application-specific way, or interact with the 
running simulation. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Getting 
Started</font></nobr></b></td></tr></tbody></table>
</p><p>To get started, look at the <tt><a href="../../apps/TestTinyViz/TestTinyVizM.nc">apps/TestTinyViz</a></tt> 
application, which causes motes to periodically send a message to a random 
neighbor. There isn't anything interesting about the application itself, but it 
will allow us to demonstrate the basic features of TinyViz. Go ahead and build 
the app with <tt>make pc</tt>. 
</p><p>To compile TinyViz, <tt>cd</tt> to the <tt>tools/java/net/tinyos/sim</tt> 
directory and type <tt>make</tt>. This will build the TinyOS program as 
<tt>tinyviz.jar</tt>, a stand-alone Java JAR file that you can run with the 
<tt>tinyviz</tt> script, found in this directory. Place this script on your PATH 
and you will be able to run <tt>tinyviz</tt> directly from the command line. 
</p><p>Start up TinyViz, running the <tt>TestTinyViz</tt> app, as follows: 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre><tt>export DBG=usr1<br>tinyviz -run build/pc/main.exe 30</tt></pre></td></tr></tbody></table></center>
<p>You will see a window looking something like the following: 
</p><center><a href="imgs/tinyviz-screenshot1.gif"><img src="http://www.cnitblog.com/images/cnitblog_com/embedded_systems/tinyviz-screenshot1.gif" alt="tinyviz-screenshot1.gif" border="0" height="673" width="1202"><br></a></center>
<p>On the left is the graphical display of the sensor network. On the right is 
the control panel where you can interact with a series of <b>plugins</b> that 
control how TinyViz works. 
</p><p>In the mote window, you can select motes by clicking on them, or select a 
group of motes by dragging a rectangle around the group. You can move motes 
around by dragging them around. Selecting motes is meaningful for certain 
plugins, and other operations, such as toggling the power state of the motes. 
</p><p>The "pause/play" button pauses or resumes the simulation. The "grid button" 
toggles grid-lines on the display. The "clear" button clears out the display 
state. The "stop" button kills the simulation. The "delay" slider introduces a 
delay between the handling of each TOSSIM event, which will slow down the 
display -- useful in cases where you have a small number of motes and want to 
watch the simulation operating in "real time". The "On/off" button toggles the 
power state of the selected motes. 
</p><p><b>Plugins</b> 
</p><p>A TinyViz <b>plugin</b> is a software module that watches for events coming 
from the simulation -- such as debug messages, radio messages, and so forth -- 
and reacts by drawing information on the display, setting simulation parameters, 
or actuating the simulation itself, for example, by setting the sensor values 
that simulated motes will read. TinyViz comes with a suite of built-in plugins, 
in the <tt><a href="../../tools/java/net/tinyos/sim/plugins">tools/java/net/tinyos/sim/plugins</a></tt> 
directory, and you can write your own. Not all plugins are used for all 
applications -- for example, the <tt>Calamari</tt> plugin is used mainly for 
testing the Calamari localization service -- but many of them are generally 
useful. 
</p><p>Plugins can be selectively enabled or disabled, depending on what information 
you are interested in seeing during the simulation. You select plugins from the 
<tt>Plugins</tt> menu. When a plugin is enabled, its corresponding tab in the 
right-hand control panel window is active, which may have additional information 
and controls provided by that plugin. Plugins are designed to be independent of 
each other so you can enable or disable any group of plugins you like. 
</p><p>The main plugins you are likely to use are: 
</p><ul><li><b>Debug messages:</b> Shows a window with all of the debug messages 
generated by the simulation. You can select debug messages just from the 
selected group of motes, and also highlight messages that match a certain 
pattern. Note that the set of debug messages you see are controlled by the value 
of the <tt>DBG</tt> environment variable, just as they are when running TOSSIM 
in a stand-alone setting. So, if you only want to see debug messages of type 
<tt>DBG_USR1</tt> and <tt>DBG_AM</tt>, start up TinyViz with: 
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre><tt>DBG=usr1,am tinyviz -run build/pc/main.exe 30</tt></pre></td></tr></tbody></table></center>
</li><li><b>Set breakpoint:</b> Allows you to set a breakpoint, which will pause the 
simulation when some condition is met. Right now, the possible conditions are 
(a) a substring match on a debug message, or (b) a match on the contents of a 
sent radio message. Multiple breakpoints can be set and they can be enabled or 
disabled by selecting them in the breakpoints list. 
</li><li><b>ADC readings:</b> Shows the most recent value of each ADC channel next to 
each mote. 
</li><li><b>Sent radio packets:</b> Shows a window with all sent radio packets, much 
like the <b>Debug messages</b> plugin. Note that the <b>Debug messages</b> 
plugin also shows this information. 
</li><li><b>Radio links:</b> Graphically displays radio message activity. When a mote 
broadcasts a message, a blue circle will be drawn around it. When a mote sends a 
message to another mote, a directed arrow will be drawn between the two motes. 
Note that this shows all message transmissions, regardless of whether they are 
successful; if a mote attempts to send a message but it is corrupted or lost, 
the arrow will still be drawn. 
</li><li><b>Set location:</b> Makes the virtual location of each mote available to 
that mote through the <tt>Location</tt> interface, found in <tt><a href="../../apps/TestTinyViz/Location.nc">apps/TestTinyViz/Location.nc</a></tt>. 
This is accomplished by setting the value of three "fake" ADC channels (one each 
for X, Y, and Z coordinates) on each mote, which the <tt>FakeLocation</tt> 
component reads to determine the mote's virtual location. This is meant to act 
as a stand-in for a real localization service when simulating TinyOS apps. 
</li><li><b>Radio model</b>: Sets the bit error rate between motes according to their 
location and various models of radio connectivity. Enabling this plugin allows 
you to use realistic connectivity models in your simulations. There are two 
built-in models: "Empirical" (based on an outdoor trace of packet connectivity 
with the RFM1000 radios) and "Fixed radius" (all motes within a given fixed 
distance of each other have perfect connectivity, and no connectivity to other 
motes). Setting the "scaling factor" in the control panel simply scales the 
distance parameter of the model. <b>Increasing</b> the scaling factor will 
<b>decrease</b> the connectivity range of the chosen model. By selecting a mote 
in the display you can see its connectivity to other motes -- the number shown 
next to each edge is the probability of a packet getting through. Changing the 
scaling factor and clicking "update model" will update the model parameters, as 
will moving motes around in the display. </li></ul><b>Layout</b> 
<p>Layout of the motes is controlled by the <tt>Layout</tt> menu, which gives 
you several options including random, grid-based, or a "grid+random" (grid-based 
but with a random perturbation) layout. You can also save and load layouts from 
a file. The location of the motes on the display is used in two ways. First, it 
is used to determine radio connectivity, when the <tt>RadioModelPlugin</tt> is 
enabled. Second, it is used to set the virtual location of the motes, when using 
the <tt>LocationPlugin</tt>. 
</p><p><b>Trying it out</b> 
</p><p>OK, now we're ready to try out the various features. 
</p><ol><li>Startup TinyViz with <tt>DBG=usr1, tinyviz -run build/pc/main.exe 30</tt> if 
it is not already running. 
</li><li>Select the <b>Debug messages</b>, <b>Radio links</b>, and <b>Set 
breakpoint</b> plugins from the Plugins menu, and resume the simulation by 
clicking the pause/play button. 
</li><li>Clicking on the <b>Debug messages</b> tab in the control panel will show you 
all of the debug messages generated by the simulation. Click on a given mote 
(say, mote 3) then click "Selected motes only" to restrict the display to just 
that mote. 
</li><li>Type a phrase (for example, "Received") in the box at the bottom of the 
control panel, then click "Highlight". This will highlight all messages matching 
the chosen string - very useful for visually scanning for "interesting" 
messages. 
</li><li>Pause the simulation, then click on the "Set breakpoint" tab. Pull down the 
bar at the top of the control panel (which says "Current breakpoints") and 
choose "Add debug message breakpoint". In the "Message contains" box, type 
"Received message", then click "Enable breakpoint". This will add a new 
breakpoint that pauses the simulation whenever a matching debug message is 
printed. Click on the pause/play button to resume the simulation. Very soon 
afterwards, the simulation will pause and the control panel at the bottom of the 
screen will print something like <pre>Breakpoint 0 fired: Debug message: [24] DebugMsgEvent [24: TestTinyVizM: Received message from 13]</pre>which 
simply means that this debug message triggered the breakpoint. Clicking the play 
button again will resume the simulation, causing the breakpoint to be hit again. 

</li><li>Select "Current breakpoints" from the bar at the top of the control panel. 
Disable the breakpoint by clicking on it in the breakpoints list, then click 
"Disable breakpoint". 
</li><li>Select the <b>Radio model</b> plugin from the Plugins menu and click on the 
"Radio model" tab in the control panel, then pick "Fixed radius (100.0)" from 
the list of radio models. Drag the mouse across the mote display to select all 
motes; you will see a very densely-connected mesh, indicating that nearly every 
mote has connectivity with all others, due to the large radius of the radio 
model. Type "4" in the "Distance scaling factor" box, then click "Update model". 
The radio model will be updated -- which may take some time -- and the resulting 
connectivity mesh will be much more sparse. <br>&nbsp; 
<p>&nbsp; 
</p><p>Note that once you restart the simulation, nodes that can no longer 
communicate (due to no connectivity) will still be sending messages to each 
other; this is because the <tt>TestTinyViz</tt> application accumulates a list 
of nodes to send messages to, but changing the underlying connectivity model 
does not modify this list. <i>However,</i> if you watch the debug messages from 
each node, you will notice that nodes are only <b>receiving</b> messages from 
those nodes they are connected to, as you would expect.</p></li></ol><b>AutoRun 
- Scripting TOSSIM runs</b> 
<p>The TinyViz <b>AutoRun</b> feature allows you to "script" the configuration 
and execution of a TinyOS simulation, by setting parameters in a file that 
controls TinyViz. This allows you to automatically enable plugins, set 
breakpoints, run multiple simulations, log data to files, and execute commands 
both before and after each simulation runs. This is useful when you are using 
TinyViz as an analysis tool. 
</p><p>Look at the file <tt><a href="../../apps/TestTinyViz/sample.autorun">apps/TestTinyViz/sample.autorun</a></tt> 
in the <tt>TestTinyViz</tt> directory. The autorun file specifies one or more 
simulations to run; a simulation stops either when a specified number of 
simulated seconds have elapsed (the "<tt>numsec</tt>" option), when a substring 
match on a debug message occurs (the "<tt>stopstring</tt>" option), or when the 
simulation exits itself (e.g., a crash or deliberate call to <tt>exit()</tt>). 
The parameters for each simulation are separated by a blank line. When a 
parameter is set in the file for one simulation, it will carry forward for 
subsequent simulations in the file, saving you from having to re-specify 
parameters for each run. 
</p><p>Here is the sample file: 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre><tt># This is a sample TinyViz autorun file. To use it, run<br>#&nbsp;&nbsp; tinyviz -autorun sample.autorun<br># Set the layout<br>layout gridrandom<br># Enable some plugins<br>plugin DebugMsgPlugin<br>plugin RadioLinkPlugin<br>plugin RadioModelPlugin<br># Total number of simulated seconds to run<br>numsec 20<br># Name of the executable file<br>executable build/pc/main.exe<br># DBG messages to include<br>dbg usr1<br># The radio model and scaling factor to use<br>radiomodel disc100<br>radioscaling 5<br># Number of motes<br>nummotes 10<br># Command to run before starting<br>precmd echo "This is a command that will run before the simulation"<br># File to log all DBG messages to<br>logfile logfile-20.txt<br><br># The blank line above indicates that we are starting another simulation<br># This time run with a different number of motes<br>nummotes 30<br>logfile logfile-30.txt</tt></pre></td></tr></tbody></table></center>
<p>The AutoRun file specifies two simulations, one with 20 motes and another 
with 30. All debug messages are logged to two different logfiles. We enable a 
few different plugins (specified by the Java class names as they are found in 
<tt>tools/java/net/tinyos/sim/plugins</tt>. 
</p><p>To run the simulations with this autorun file, just type: 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><pre><tt>tinyviz -autorun sample.autorun</tt></pre></td></tr></tbody></table></center>
<p>TinyViz starts up, enables and configures the appropriate plugins, and 
automatically runs each simulation for 10 simulated seconds, then exits. You can 
set up AutoRun to run a series of simulations and then go to lunch -- the data 
will be waiting for you in your logfiles when you get back. 
</p><p>AutoRun supports a number of features not shown here -- just look at the 
<tt>arConfig</tt> class in the <tt><a href="../../tools/java/net/tinyos/sim/AutoRun.java">tools/java/net/tinyos/sim/AutoRun.java</a></tt>source 
file. Note that all options specified in the file that aren't used by AutoRun 
itself, however they made available to plugins. So, for example, the 
<tt>radiomodel</tt> option is interpreted by the <tt>RadioModelPlugin</tt> to 
configure the radio model. You can write your own plugins that are configured 
through AutoRun in this way. 
</p><p><b>Writing TinyViz plugins</b> 
</p><p>By far the most useful feature of TinyViz is the ability to write your own 
plugins to interact with the simulation. Writing plugins is beyond the scope of 
this document, but we wanted to give you a couple of pointers on where to start. 
Look at <tt><a href="../../tools/java/net/tinyos/sim/plugins/RadioLinkPlugin.java">tools/java/net/tinyos/sim/plugins/RadioLinkPlugin.java</a></tt>for 
a simple, well-documented plugin implementation. Essentially, plugins must 
provide a method that receives events from the TOSSIM simulation and the TinyViz 
framework. Plugins react to events by changing internal state, updating the 
display, or possibly sending commands back into the simulation. TinyViz delivers 
events to plugins for initialization, debug messages, radio messages, a change 
in the location of a mote (e.g., when the user moves it), and when new motes 
join the simulation. Plugins provide additional methods that are called when the 
plugin is enabled or disabled, as well as when the mote window is redrawn. 
</p><p>Using <tt>RadioLinkPlugin.java</tt> as an example, it is straightforward to 
write your own plugins. Currently, all plugins must be located in the 
<tt>plugins</tt> subdirectory of the TinyViz directory. (In the future we will 
add support for a "plugin path"). Note that when you modify a plugin you need to 
recompile the <tt>tinyviz.jar</tt> file by typing <tt>make </tt>in the main 
TinyViz directory (tools/java/net/tinyos/sim); just typing <tt>make</tt> in the 
plugins directory is not adequate. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Further 
Use</font></nobr></b></td></tr></tbody></table>
</p><p>This tutorial only covers some of the functionality and usefulness of TOSSIM; 
for example, as TOSSIM simulates the TinyOS networking stack at bit granularity, 
radio models can simulate some of the difficult issues that arise. Similarly, 
one can test and debug low-level protocols (such as start symbol detection) in 
addition to application components and routing protocols. The <a href="../nido.pdf">TOSSIM System Description</a> goes into greater details on 
these capabilities and presents some information on TOSSIM's implementation.<br>&nbsp;<!--  LocalWords:  TinyOS nesC nc async norace BlinkM FooM ncc SingleTimer Leds
 --><!--  LocalWords:  LedsC StdControl tos init TimerC redOn redOff uint redToggle
 --><!--  LocalWords:  metadata html nesdoc gcc exe avr objcopy srec uisp mib dprog
 --><!--  LocalWords:  towards dapa xff ThinkPad dlpt Makelocal micasb Wshadow DDEF
 --><!--  LocalWords:  finline fnesc cfile lm Atmel ATmega nesC's nesc SenseM rdata
 --><!--  LocalWords:  ADCControl SounderControl dataReady getData rcombine someval
 --><!--  LocalWords:  ADControl fooControl barControl MyTimer uniqueCount basicsb
 --><!--  LocalWords:  sensorboard Makerules sensorboards SenseTask taskname INTMSG
 --><!--  LocalWords:  SenseTaskM putdata processData CntToLedsAndRfm RfmToLeds Msg
 --><!--  LocalWords:  CntToRfmAndLeds IntToLeds IntToRfm IntOutput outputComplete
 --><!--  LocalWords:  IntToRfmM GenericComm SendMsg bool struct IntMsg src BCAST
 --><!--  LocalWords:  ADDR sizeof TOSH sendDone GenricComm AMStandard RfmToInt pc
 --><!--  LocalWords:  UARTNoCRCPacket RadioCRCPacket ActiveMessage RfmToIntM xfff
 --><!--  LocalWords:  ReceiveIntMsg ReceiveMsg MsgPtr addr SenseToRfm TOSSIM DBG
 --><!--  LocalWords:  TinyViz ffff crc usr dbg const printf prepended bitmask gdb
 --><!--  LocalWords:  ledsOn gdbinit plugin API TestTinyViz cd tinyviz plugins RFM
 --><!--  LocalWords:  FakeLocation RadioModelPlugin LocationPlugin afterwards disc
 --><!--  LocalWords:  DebugMsgEvent TestTinyVizM AutoRun autorun numsec stopstring
 --><!--  LocalWords:  gridrandom DebugMsgPlugin RadioLinkPlugin radiomodel precmd
 --><!--  LocalWords:  radioscaling nummotes logfile txt logfiles arConfig TOSSIM's
 --></p><img src ="http://www.cnitblog.com/Embedded_Systems/aggbug/4946.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Embedded_Systems/" target="_blank">井冈山</a> 2005-11-28 01:11 <a href="http://www.cnitblog.com/Embedded_Systems/articles/4946.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lesson 4: Component Composition and Radio Communication[转]</title><link>http://www.cnitblog.com/Embedded_Systems/articles/4945.html</link><dc:creator>井冈山</dc:creator><author>井冈山</author><pubDate>Sun, 27 Nov 2005 17:08:00 GMT</pubDate><guid>http://www.cnitblog.com/Embedded_Systems/articles/4945.html</guid><wfw:comment>http://www.cnitblog.com/Embedded_Systems/comments/4945.html</wfw:comment><comments>http://www.cnitblog.com/Embedded_Systems/articles/4945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/Embedded_Systems/comments/commentRss/4945.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Embedded_Systems/services/trackbacks/4945.html</trackback:ping><description><![CDATA[&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="tahoma,arial,helvetica"><font size="-1">Lesson 4: 
Component Composition and Radio Communication</font></font></b> 
<p><font face="tahoma,arial,helvetica">Last updated 31 July 
2003</font></p></td></tr></tbody></table>
<p>This lesson introduces two concepts: hierarchical decomposition of component 
graphs, and using radio communication. The applications that we will consider 
are <tt>CntToLedsAndRfm</tt> and <tt>RfmToLeds</tt>. <tt>CntToLedsAndRfm</tt> is 
a variant of <tt>Blink</tt> that outputs the current counter value to multiple 
output interfaces: both the LEDs, and the radio communication stack. 
<tt>RfmToLeds</tt> receives data from the radio and displays it on the LEDs. 
Programming one mote with <tt>CntToLedsAndRfm</tt> will cause it to transmit its 
counter value over the radio; programming another with <tt>RfmToLeds</tt> causes 
it to display the received counter on its LEDs - your first distributed 
application!<br></p>
<p>If you're using mica2 or mica2dot motes, you will need to ensure that you've 
selected a radio frequency compatible with your motes (433MHz vs 916MHz motes). 
If your motes are unlabeled, see "<a href="../mica2radio/mica2freq.html">How to 
determine the operating frequency range of a MICA2 or MICA2DOT mote</a>" for 
information on recognizing which kind of mote you have. To tell the compiler 
which frequency you are using, edit the <a href="buildenv.html">Makelocal</a> 
file in the apps directory, defining either <span style="font-family: monospace;">CC1K_DEF</span><span style="font-family: monospace;">_PRESET</span> (see <a href="../../tos/platform/mica2/CC1000Const.h">tinyos-1.x/tos/platform/mica2/CC1000Const.h</a> 
for preset values), or <span style="font-family: monospace;">CC1K_DEF_FREQ</span> 
with an explicit frequency (see example in <a href="file:///home/dgay/motes/tinyos-1.x/doc/tutorial/buildenv.html">Makelocal</a>).<br></p>
<p>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The CntToRfmAndLeds 
Application</font></nobr></b></td></tr></tbody></table></p>
<p>Look at <tt>CntToRfmAndLeds.nc</tt>. Note that this application only consists 
of a configuration; all of the component modules are located in libraries! </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>CntToLedsAndRfm.nc</b> <pre>configuration CntToLedsAndRfm {<br>}<br>implementation {<br>&nbsp; components Main, Counter, IntToLeds, IntToRfm, TimerC;<br><br>&nbsp; Main.StdControl -&gt; Counter.StdControl;<br>&nbsp; Main.StdControl -&gt; IntToLeds.StdControl;<br>&nbsp; Main.StdControl -&gt; IntToRfm.StdControl;<br>&nbsp; Main.StdControl -&gt; TimerC.StdControl;<br>&nbsp; Counter.Timer -&gt; TimerC.Timer[unique("Timer")];<br>&nbsp; IntToLeds &lt;- Counter.IntOutput;<br>&nbsp; Counter.IntOutput -&gt; IntToRfm;<br>}</pre></td></tr></tbody></table></center>
<p>The first thing to note is that a single interface requirement (such as 
<tt>Main.StdControl</tt> or <tt>Counter.IntOutput</tt>) can be <i>fanned out</i> 
to multiple implementations. Here we wire <tt>Main.StdControl</tt> to the 
<tt>Counter</tt>, <tt>IntToLeds</tt>, <tt>IntToRfm</tt>, and 
<tt>TimerC</tt>components. (All of these components can be found in the <tt><a href="../../tos/lib/Counters">tos/lib/Counters</a></tt> directory.) The names of 
the various components tell you what they do: <tt>Counter</tt> receives 
<tt>Timer.fired()</tt> events to maintain a counter. <tt>IntToLeds</tt> and 
<tt>IntToRfm</tt> provide the <tt>IntOutput</tt> interface, that has one 
command, <tt>output()</tt>, which is called with a 16-bit value, and one event, 
<tt>outputComplete()</tt>, which is called with <tt>result_t</tt> . 
<tt>IntToLeds</tt> displays the lower three bits of its value on the LEDs, and 
<tt>IntToRfm</tt> broadcasts the 16-bit value over the radio. </p>
<p>So we're wiring the <tt>Counter.Timer</tt> interface to 
<tt>TimerC.Timer</tt>, and <tt>Counter.IntOutput</tt> to <b>both</b> 
<tt>IntToLeds</tt> and <tt>IntToRfm</tt>. The NesC compiler generates code so 
that all invocations of the <tt>Counter.IntOutput.output()</tt> command will 
invoke the command in both <tt>IntToLeds</tt> and <tt>IntToRfm</tt>. Also note 
that the wiring arrow can go in either direction: the arrow always points 
<i>from</i> a used interface <i>to</i> a provided implementation. </p>
<p>Assuming you are using a Mica mote, try building and installing this 
application with <tt>make mica install</tt>; you should see a 3-bit binary 
counter on the mote's LEDs. Of course the mote is also transmitting the value 
over the radio, which we describe next. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">IntToRfm: Sending a 
message</font></nobr></b></td></tr></tbody></table><tt>IntToRfm</tt> is a simple 
component that receives an output value (through the <tt>IntOutput</tt> 
interface) and broadcasts it over the radio. Radio communication in TinyOS 
follows the Active Message (AM) model, in which each packet on the network 
specifies a <i>handler ID</i> that will be invoked on recipient nodes. Think of 
the handler ID as an integer or "port number" that is carried in the header of 
the message. When a message is received, the receive event associated with that 
handler ID is signaled. Different motes can associate different receive events 
with the same handler ID. </p>
<p>In any messaging layer, there are 5 aspects involved in successful 
communication: </p>
<ol><li>Specifying the message data to send; 
</li><li>Specifying which node is to receive the message; 
</li><li>Determining when the memory associated with the outgoing message can be 
reused; 
</li><li>Buffering the incoming message; and, 
</li><li>Processing the message on reception </li></ol>In Tiny Active Messages, 
memory management is very constrained as you would expect from a small-scale 
embedded environment. 
<p>Let's look at <tt>IntToRfm.nc</tt>: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>IntToRfm.nc</b> <pre>configuration IntToRfm<br>{<br>&nbsp; provides interface IntOutput;<br>&nbsp; provides interface StdControl;<br>}<br>implementation<br>{<br>&nbsp; components IntToRfmM, GenericComm as Comm;<br><br>&nbsp; IntOutput = IntToRfmM;<br>&nbsp; StdControl = IntToRfmM;<br><br>&nbsp; IntToRfmM.Send -&gt; Comm.SendMsg[AM_INTMSG];<br>&nbsp; IntToRfmM.StdControl -&gt; Comm;<br>}</pre></td></tr></tbody></table></center>
<p>This component provides the <tt>IntOutput</tt> and <tt>StdControl</tt> 
interfaces. This is the first time that we have seen a <i>configuration</i> 
provide an <i>interface</i>. In the previous lessons we have always used 
configurations just to wire other components together; in this case, the 
<tt>IntToRfm</tt> configuration is itself a component that another configuration 
can wire to. Got it? </p>
<p>In the implementation section, we see: </p><pre>&nbsp; components IntToRfmM, GenericComm as Comm;</pre>The phrase 
"<tt>GenericComm as Comm</tt>" is stating that this configuration uses the 
<tt>GenericComm</tt> component, but gives it the (local) name <tt>Comm</tt>. The 
idea here is that you can easily swap in a different communication module in 
place of <tt>GenericComm</tt>, and only need to change this one line to do so; 
you don't need to change every line that wires to <tt>Comm</tt>. 
<p>We also see some new syntax here in the lines: </p><pre>&nbsp; IntOutput = IntToRfmM;<br>&nbsp; StdControl = IntToRfmM;</pre>The equal sign 
(<tt>=</tt>) is used to indicate that the <tt>IntOutput</tt> interface provided 
by <tt>IntToRfm</tt> is<b> "equivalent to"</b> the implementation in 
<tt>IntToRfmM</tt>. We can't use the arrow (<tt>-&gt;</tt>) here, because the 
arrow is used to wire a used interface to a provided implementation. In this 
case we are "equating" the interfaces provided by <tt>IntToRfm</tt> with the 
implementation found in <tt>IntToRfmM</tt>. 
<p>The last two lines of the configuration are: </p><pre>&nbsp; IntToRfmM.Send -&gt; Comm.SendMsg[AM_INTMSG];<br>&nbsp; IntToRfmM.StdControl -&gt; Comm;</pre>The 
last line is simple; we're wiring <tt>IntToRfmM.StdControl</tt> to 
<tt>GenericComm.StdControl</tt>. The first line shows us another use of 
<b>parameterized interfaces</b>, in this case, wiring up the <tt>Send</tt> 
interface of <tt>IntToRfmM</tt> to the <tt>SendMsg</tt> interface provided by 
<tt>Comm</tt>. 
<p>The <tt>GenericComm</tt> component declares: </p><pre>&nbsp; provides {</pre><pre>&nbsp;&nbsp;&nbsp; ...<br>&nbsp;&nbsp;&nbsp; interface SendMsg[uint8_t id];</pre><pre>&nbsp;&nbsp;&nbsp; ...<br>&nbsp; }</pre>In other words, it provides 256 different instances of 
the <tt>SendMsg</tt> interface, one for each <tt>uint8_t</tt> value. This is the 
way that Active Message handler IDs are wired together. In <tt>IntToRfm</tt>, we 
are wiring the <tt>SendMsg</tt> interface corresponding to the handler ID 
<tt>AM_INTMSG</tt> to <tt>GenericComm.SendMsg</tt>. (<tt>AM_INTMSG</tt> is a 
global value defined in <tt><a href="../../tos/lib/Counters/IntMsg.h">tos/lib/Counters/IntMsg.h</a></tt>.) When 
the <tt>SendMsg</tt> command is invoked, the handler ID is provided to it, 
essentially as an extra argument. You can see how this works by looking at 
<tt>tos/system/AMStandard.nc</tt> (the implementation module for 
<tt>GenericComm</tt>): <pre>&nbsp; command result_t SendMsg.send[uint8_t id]( ... ) { ... };</pre>Of course, 
parameterized interfaces aren't strictly necessary here - the same thing could 
be accomplished if <tt>SendMsg.send</tt> took the handler ID as an argument. 
This is just an example of the use of parameterized interfaces in nesC. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">IntToRfmM: Implementing 
Network Communication</font></nobr></b></td></tr></tbody></table>
<p>Now we know how <tt>IntToRfm</tt> is wired up, but we don't know how message 
communication is implemented. Take a look at the <tt>IntOutput.output()</tt> 
command in <tt>IntToRfmM.nc</tt>: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>IntToRfmM.nc</b> <pre>&nbsp; bool pending;<br>&nbsp; struct TOS_Msg data;<br><br>&nbsp; /* ... */&nbsp;<br><br>&nbsp; command result_t IntOutput.output(uint16_t value) {<br>&nbsp;&nbsp;&nbsp; IntMsg *message = (IntMsg *)data.data;<br><br>&nbsp;&nbsp;&nbsp; if (!pending) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pending = TRUE;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; message-&gt;val = value;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; atomic {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; message-&gt;src = TOS_LOCAL_ADDRESS;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (call Send.send(TOS_BCAST_ADDR, sizeof(IntMsg), &amp;data))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SUCCESS;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pending = FALSE;<br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp; return FAIL;<br>&nbsp; }</pre></td></tr></tbody></table></center>
<p>The command is using a message structure called <tt>IntMsg</tt>, declared in 
<tt>tos/lib/Counters/IntMsg.h</tt>. It is a simple struct with <tt>val</tt> and 
<tt>src</tt> fields; the first being the data value and the second being the 
message's source address. We assign these two fields (using the global constant 
<tt>TOS_LOCAL_ADDRESS</tt> for the local source address) and call 
<tt>Send.send()</tt> with the destination address (<tt>TOS_BCAST_ADDR</tt> is 
the radio broadcast address), the message size, and the message data. </p>
<p>The "raw" message data structure used by <tt>SendMsg.send()</tt> is 
<tt>struct TOS_Msg</tt>, declared in <tt>tos/system/AM.h</tt>. It contains 
fields for the destination address, message type (the AM handler ID), length, 
payload, etc. The maximum payload size is <tt>TOSH_DATA_LENGTH</tt> and is set 
to 29 by default; you are welcome to experiment with larger data packets but 
some nontrivial hacking of the code may be required :-) Here we are 
encapsulating an <tt>IntMsg</tt> within the data payload field of the 
<tt>TOS_Msg</tt> structure. </p>
<p>The <tt>SendMsg.send()</tt> command is split-phase; it signals the 
<tt>SendMsg.sendDone()</tt> event when the message transmission has completed. 
If <tt>send()</tt> succeeds, the message is queued for transmission, and if it 
fails, the messaging component was unable to accept the message. </p>
<p>TinyOS Active Message buffers follow a strict alternating ownership protocol 
to avoid expensive memory management, while still allowing concurrent operation. 
If the message layer accepts the <tt>send()</tt> command, it owns the send 
buffer and the requesting component should not modify the buffer until the send 
is complete (as indicated by the <tt>sendDone()</tt> event). </p>
<p><tt>IntToRfmM</tt> uses a <tt>pending</tt> flag to keep track of the status 
of the buffer. If the previous message is still being sent, we cannot modify the 
buffer, so we drop the <tt>output()</tt> operation and return <tt>FAIL</tt>. If 
the send buffer is available, we can fill in the buffer and send a message. 
<br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The GenericComm Network 
Stack</font></nobr></b></td></tr></tbody></table></p>
<p>Recall that <tt>IntToRfm</tt>'s <tt>SendMsg</tt> interface is wired to 
<tt>GenericComm</tt>, a "generic" TinyOS network stack implementation (found in 
<tt>tos/system/GenericComm.nc</tt>). If you look at the <tt>GenricComm.nc</tt>, 
you'll see that it makes use of a number of low-level interfaces to implement 
communication: <tt>AMStandard</tt> to implement Active Message sending and 
reception, <tt>UARTNoCRCPacket</tt> to communicate over the mote's serial port, 
<tt>RadioCRCPacket</tt> to communicate over the radio, and so forth. You don't 
need to understand all of the details of these modules but you should be able to 
follow the <tt>GenericComm.nc</tt> wiring configuration by now. </p>
<p>If you're really curious, check out <tt>AMStandard.nc</tt> for some details 
on how the ActiveMessage layer is built. For example, it implements 
<tt>SendMsg.send()</tt> by posting a task to take the message buffer and send it 
over the serial port (if the destination address is <tt>TOS_UART_ADDR</tt> or 
the radio radio (if the destination is anything else). You can dig down through 
the various layers of code until you see the mechanism that actually transmits a 
byte over the radio or UART. 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Receiving Messages with 
RfmToLeds</font></nobr></b></td></tr></tbody></table></p>
<p>The <tt>RfmToLeds</tt> application is defined by a simple configuration that 
uses the <tt>RfmToInt</tt> component to receive a message, and the 
<tt>IntToLeds</tt> component to display the received value on the LEDs. Like 
<tt>IntToRfm</tt>, the <tt>RfmToInt</tt> component uses <tt>GenericComm</tt> to 
receive messages. Most of <tt>RfmToInt.nc</tt> should be familiar to you by now, 
but look at the line: </p><pre>&nbsp; RfmToIntM.ReceiveIntMsg -&gt; GenericComm.ReceiveMsg[AM_INTMSG];</pre>This 
is how we specify that Active Messages received with the <tt>AM_INTMSG</tt> 
handler ID should be wired to the <tt>RfmToIntM.ReceiveMsg</tt> interface. The 
direction of the arrow might be a little confusing here. The <tt>ReceiveMsg</tt> 
interface (found in <tt>tos/interfaces/ReceiveMsg.nc</tt>)<b>only</b> declares 
an event: <tt>receive()</tt>, which is signaled with a pointer to the received 
message. So <tt>RfmToIntM</tt> <i>uses</i> the <tt>ReceiveMsg</tt> interface, 
although that interface does not have any commands to call -- just an event that 
can be signaled. 
<p>Memory management for incoming messages is inherently dynamic. A message 
arrives and fills a buffer, and the Active Message layer decodes the handler 
type and dispatches it. The buffer is handed to the application component 
(through the <tt>ReceiveMsg.receive()</tt> event), but, critically, <b>the 
application component must return a pointer to a buffer upon completion</b>. 
</p>
<p>For example, looking at <tt>RfmToIntM.nc</tt>, </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>RfmToIntM.nc</b> <pre>&nbsp; /* ... */<br>&nbsp; event TOS_MsgPtr ReceiveIntMsg.receive(TOS_MsgPtr m) {<br>&nbsp;&nbsp;&nbsp; IntMsg *message = (IntMsg *)m-&gt;data;<br>&nbsp;&nbsp;&nbsp; call IntOutput.output(message-&gt;val);<br><br>&nbsp;&nbsp;&nbsp; return m;<br>&nbsp; }</pre></td></tr></tbody></table></center>
<p>Note that the last line returns the original message buffer, since the 
application is done with it. If your component needs to save the message 
contents for later use, it needs to copy the message to a new buffer, or return 
a new (free) message buffer for use by the network stack. 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Underlying 
Details</font></nobr></b></td></tr></tbody></table></p>
<p>TinyOS messages contain a "group ID" in the header, which allows multiple 
distinct groups of motes to share the same radio channel. If you have multiple 
groups of motes in your lab, you should set the group ID to a unique 8-bit value 
to avoid receiving messages for other groups. The default group ID is 
<tt>0x7D</tt>. You can set the group ID by defining the preprocessor symbol 
<tt>DEFAULT_LOCAL_GROUP</tt>.</p><pre>&nbsp; DEFAULT_LOCAL_GROUP = 0x42&nbsp;&nbsp;&nbsp; # for example...</pre>
<p>Use the <tt><a href="buildenv.html">Makelocal</a></tt> file to set the group 
ID for all your applications.</p>
<p>In addition, the message header carries a 16-bit destination node address. 
Each communicating node within a group is given a unique address assigned at 
compile time.&nbsp; Two common reserved destination addresses we've introduced thus 
far are <tt>TOS_BCAST_ADDR (0xfff)</tt> to broadcast to all nodes or 
<tt>TOS_UART_ADDR (0x007e)</tt> to send to the serial port. </p>
<p>The node address may be any value EXCEPT the two reserved values described 
above.&nbsp; To specify the local address of your mote, use the following install 
syntax: </p><pre>&nbsp; make mica install.&lt;addr&gt;</pre>where <i>&lt;addr&gt;</i> is the 
local node ID that you wish to program into the mote.&nbsp; For example, <pre>&nbsp; make mica install.38</pre>compiles the application for a mica and 
programs the mote with ID 38. Read <a href="programmers.html">Programming 
Devices</a> for additional information.
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Exercises</font></nobr></b></td></tr></tbody></table>
<ol><li>Question: What would happen if you built multiple <tt>CntToLedsAndRfm</tt> 
nodes and turned them on? 
</li><li>Program one mote with <tt>CntToLedsAndRfm</tt> and another with 
<tt>RfmToLeds</tt>. When you turn on <tt>CntToLedsAndRfm</tt>, you should see 
the count displayed on the <tt>RfmToLeds</tt> device. Congratulations - you are 
doing wireless networking. Can you change this to implement a wireless sensor? 
(Hint: Check out <tt><a href="../../apps/SenseToRfm">apps/SenseToRfm</a></tt>.) 
</li></ol>
<hr>
<b><a href="lesson3.html"></a></b> <!--  LocalWords:  TinyOS nesC nc async norace BlinkM FooM ncc SingleTimer Leds
 --><!--  LocalWords:  LedsC StdControl tos init TimerC redOn redOff uint redToggle
 --><!--  LocalWords:  metadata html nesdoc gcc exe avr objcopy srec uisp mib dprog
 --><!--  LocalWords:  towards dapa xff ThinkPad dlpt Makelocal micasb Wshadow DDEF
 --><!--  LocalWords:  finline fnesc cfile lm Atmel ATmega nesC's nesc SenseM rdata
 --><!--  LocalWords:  ADCControl SounderControl dataReady getData rcombine someval
 --><!--  LocalWords:  ADControl fooControl barControl MyTimer uniqueCount basicsb
 --><!--  LocalWords:  sensorboard Makerules sensorboards SenseTask taskname INTMSG
 --><!--  LocalWords:  SenseTaskM putdata processData CntToLedsAndRfm RfmToLeds Msg
 --><!--  LocalWords:  CntToRfmAndLeds IntToLeds IntToRfm IntOutput outputComplete
 --><!--  LocalWords:  IntToRfmM GenericComm SendMsg bool struct IntMsg src BCAST
 --><!--  LocalWords:  ADDR sizeof TOSH sendDone GenricComm AMStandard RfmToInt
 --><!--  LocalWords:  UARTNoCRCPacket RadioCRCPacket ActiveMessage RfmToIntM xfff
 --><!--  LocalWords:  ReceiveIntMsg ReceiveMsg MsgPtr addr SenseToRfm
 --><img src ="http://www.cnitblog.com/Embedded_Systems/aggbug/4945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Embedded_Systems/" target="_blank">井冈山</a> 2005-11-28 01:08 <a href="http://www.cnitblog.com/Embedded_Systems/articles/4945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lesson 2: Event-Driven Sensor Acquisition[转]</title><link>http://www.cnitblog.com/Embedded_Systems/articles/4944.html</link><dc:creator>井冈山</dc:creator><author>井冈山</author><pubDate>Sun, 27 Nov 2005 17:06:00 GMT</pubDate><guid>http://www.cnitblog.com/Embedded_Systems/articles/4944.html</guid><wfw:comment>http://www.cnitblog.com/Embedded_Systems/comments/4944.html</wfw:comment><comments>http://www.cnitblog.com/Embedded_Systems/articles/4944.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/Embedded_Systems/comments/commentRss/4944.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Embedded_Systems/services/trackbacks/4944.html</trackback:ping><description><![CDATA[&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="tahoma,arial,helvetica"><font size="-1">Lesson 2: 
Event-Driven Sensor Acquisition</font></font></b> 
<p><font face="tahoma,arial,helvetica">Last updated 9 September&nbsp; 
2003</font></p></td></tr></tbody></table>
<p>This lesson demonstrates a simple sensor application that takes light 
intensity readings (from the sensor board's photo sensor) and displays those 
readings on the LEDs. This is based on the <tt>Sense</tt> application, found in 
<tt><a href="../../apps/Sense">apps/Sense</a></tt>. This is a very simple 
application that reads a value from the light sensor and displays the lower 3 
bits of the value on the LEDs. The application configuration is found in 
<tt>Sense.nc</tt> and the implementation module in <tt>SenseM.nc</tt>. 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The SenseM.nc 
component</font></nobr></b></td></tr></tbody></table>
</p><p>Let's first look at the top portion of <tt>SenseM.nc</tt>: 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>SenseM.nc</b> <pre>module SenseM {<br>&nbsp; provides {<br>&nbsp;&nbsp;&nbsp; interface StdControl;<br>&nbsp; }<br>&nbsp; uses {<br>&nbsp;&nbsp;&nbsp; interface Timer;<br>&nbsp;&nbsp;&nbsp; interface ADC;<br>&nbsp;&nbsp;&nbsp; interface StdControl as ADCControl;<br>&nbsp;&nbsp;&nbsp; interface Leds;<br>&nbsp; }<br>}<br>// Implementation not shown ...</pre></td></tr></tbody></table></center>
<p>Like <tt>BlinkM</tt>, this component provides the <tt>StdControl</tt> 
interface and uses <tt>Timer</tt> and <tt>Leds</tt>. It also uses two more 
interfaces: <tt>ADC</tt>, which is used to access data from the 
analogue-to-digital converter, and <tt>StdControl</tt>, which is used to 
initialize the ADC component. 
</p><p>This application uses a new component, <tt>TimerC</tt>, in place of 
<tt>SingleTimer</tt>. The reason is that <tt>TimerC</tt> allows multiple 
instance of timers, while <tt>SingleTimer</tt> only provides a single one that 
only one component can use. We'll discuss more on <tt>Timer</tt> a bit later. 
</p><p>Note the line </p><pre>&nbsp; interface StdControl as ADCControl;</pre>This is saying that this 
component uses the <tt>StdControl</tt> interface but gives the <b>interface 
instance</b> the name <tt>ADCControl</tt>. In this way a component can require 
multiple instances of the same interface, but give them different names. For 
example, a component might need to use the <tt>StdControl</tt> interface to 
control both the ADC and the sounder components. In this case we might say: <pre>&nbsp; interface StdControl as ADCControl;<br>&nbsp; interface StdControl as SounderControl;</pre>The configuration that uses this 
module will be responsible for wiring each interface instance to some actual 
implementation. 
<p>One related note: if you don't provide an interface instance name then the 
instance is named the same as the interface. That is, the line </p><pre>&nbsp; interface ADC;</pre>is just shorthand for <pre>&nbsp; interface ADC as ADC;</pre>Take a look at the <tt>StdControl</tt> and 
<tt>ADC</tt> interfaces (both in tos/interfaces). You'll see that <tt><a href="../../tos/interfaces/StdControl.nc">StdControl</a></tt> is used to 
initialize and power a component (usually a piece of physical hardware) and 
<tt><a href="../../tos/interfaces/ADC.nc">ADC</a></tt> is used to get data from 
an ADC channel. <tt>ADC</tt> signals an event, <tt>dataReady()</tt>, when data 
is ready on the channel. Notice the <b>async</b> keyword is used in the ADC 
interface. This is declaring the commands and events as asynchronous code, i.e., 
code which can run in response to a hardware interrupt. 
<p>Open the file <tt><a href="../../apps/Sense/SenseM.nc">apps/Sense/SenseM.nc</a></tt>.&nbsp; You'll see the 
code simply calls <tt>ADC.getData()</tt> each time <tt>Timer.fired()</tt> is 
signaled. Likewise, when <tt>ADC.dataReady()</tt> is signaled, the internal 
function <tt>display()</tt> is invoked, which sets the LEDs to the low-order 
bits of the ADC value. 
</p><p>Notice the use of the function <tt>rcombine()</tt> in the implementation of 
<tt>StdControl.init()</tt>. </p><pre>&nbsp; return rcombine(call ADCControl.init(), call Leds.init());</pre>The 
function <tt>rcombine()</tt> is a special nesC combining function which returns 
the logical-and of two commands who result type is result_t. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The Sense.nc 
configuration</font></nobr></b></td></tr></tbody></table>
<p>At this point you should be wondering, "how does the <tt>Sense</tt> 
application know that the ADC channel should access the light sensor?" This is 
exactly what the <tt>Sense.nc</tt> configuration wires up for us. 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>Sense.nc</b> <pre>configuration Sense {<br>&nbsp; // this module does not provide any interface<br>}<br>implementation<br>{<br>&nbsp; components Main, SenseM, LedsC, TimerC, Photo;<br><br>&nbsp; Main.StdControl -&gt; SenseM;<br>&nbsp; Main.StdControl -&gt; TimerC;<br><br>&nbsp; SenseM.ADC -&gt; Photo;<br>&nbsp; SenseM.ADCControl -&gt; Photo;<br>&nbsp; SenseM.Leds -&gt; LedsC;<br>&nbsp; SenseM.Timer -&gt; TimerC.Timer[unique("Timer")];<br>}</pre></td></tr></tbody></table></center>
<p>Most of this should be familiar from <tt>Blink</tt>. We're wiring up the 
<tt>Main.StdControl</tt> to <tt>SenseM.StdControl</tt>, as before. The 
<tt>Leds</tt> wirings is also similar to <tt>Blink</tt>, and we'll discuss 
<tt>Timer</tt> in a minute. The wiring for the ADC is: </p><pre>&nbsp; SenseM.ADC -&gt; Photo;<br>&nbsp; SenseM.ADCControl -&gt; Photo;</pre>All we're doing is wiring up the 
<tt>ADC</tt> interface (used by <tt>SenseM</tt>) to a new component called 
<tt>Photo</tt>. Same goes for the <tt>ADCControl</tt> interface, which you'll 
recall is an instance of the <tt>StdControl</tt> interface used by 
<tt>SenseM</tt>. 
<p>Remember that </p><pre>&nbsp; SenseM.ADC -&gt; Photo;</pre>is just shorthand for <pre>&nbsp; SenseM.ADC -&gt; Photo.ADC;</pre>On the other hand, <pre>&nbsp; SenseM.ADControl -&gt; Photo;</pre>is <b>not shorthand</b> for <pre>&nbsp; SenseM.ADC -&gt; Photo.ADCControl;</pre>What's going on here? If you look 
at the <tt>Photo.nc</tt> component (found in <tt>tos/sensorboards/micasb</tt>), 
you'll see that it provides both the <tt>ADC</tt> and <tt>StdControl</tt> 
interfaces -- it doesn't have an interface called <tt>ADCControl</tt>. 
(<tt>ADCControl</tt> was just the name that we gave to the instance of 
<tt>StdControl</tt> in the <tt>SenseM</tt> component.) Rather, the nesC compiler 
is smart enough to figure out that because <tt>SenseM.ADCControl</tt> is <i>an 
instance of</i> the <tt>StdControl</tt> interface, that it needs to be wired up 
to <i>an instance of</i> the <tt>StdControl</tt> interface provided by 
<tt>Photo</tt>. (If <tt>Photo</tt> were to provide two instances of 
<tt>StdControl</tt>, this would be an error because the wiring would be 
ambiguous.) In other words, <pre>&nbsp; SenseM.ADControl -&gt; Photo;</pre>is shorthand for <pre>&nbsp; SenseM.ADControl -&gt; Photo.StdControl;</pre>Whew! <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Timer and parameterized 
interfaces</font></nobr></b></td></tr></tbody></table>
<p>Let's look at the line </p><pre>&nbsp; SenseM.Timer -&gt; TimerC.Timer[unique("Timer")];</pre>This is 
introducing a new bit of syntax, called a <b>parameterized interface</b>. 
<p>A parameterized interface allows a component to provide <i>multiple 
instances</i> of an interface that are parameterized by a runtime or 
compile-time value. Recall that it's possible for a component to provide 
multiple instances of an interface and to give them different names, e.g., </p><pre>&nbsp; provides {<br>&nbsp;&nbsp;&nbsp; interface StdControl as fooControl;<br>&nbsp;&nbsp;&nbsp; interface StdControl as barControl;<br>&nbsp; }</pre>This is just a generalization of the same idea. The <tt>TimerC</tt> 
component declares: <pre>&nbsp; provides interface Timer[uint8_t id];</pre>In other words, it provides 
256 different instances of the <tt>Timer</tt> interface, one for each 
<tt>uint8_t</tt> value! 
<p>In this case, we want TinyOS applications to create and use multiple timers, 
each of which can be managed independently. For example, an application 
component might need one timer to fire at a certain rate (say, once per second) 
to gather sensor readings, while another component might need the a timer to 
fire at a different rate to manage radio transmission. By wiring the 
<tt>Timer</tt> interface in each of these components to a separate instance of 
the <tt>Timer</tt> interface provided by <tt>TimerC</tt>, each component can 
effectively get its own "private" timer. 
</p><p>When we say <tt>TimerC.Timer[someval]</tt>, we are specifying that 
<tt>BlinkM.Timer</tt> should be wired to the instance of the <tt>Timer</tt> 
interface specified by the value (<tt>someval</tt>) in the square brackets. This 
can be any 8-bit positive number. If we were to specify a particular value here, 
such as 38 or 42, we might accidentally conflict with the timer being used by 
another component (if that component used the same value in the brackets). So, 
we use the compile-time constant function <tt>unique()</tt>, which generates a 
unique 8-bit identifier from the string given as an argument. Here, </p><pre>&nbsp; unique("Timer")</pre>generates a unique 8-bit number from a set 
corresponding to the string <tt>"Timer"</tt>. Therefore, Every component that 
uses <tt>unique("Timer")</tt> is guaranteed to get a <i>different</i> 8-bit 
value as long as the string used in the argument is the same. Note that if one 
component uses <tt>unique("Timer")</tt> and another uses 
<tt>unique("MyTimer")</tt>, they might get the <i>same</i> 8-bit value. 
Therefore it's good practice to use the name of the parameterized interface as 
an argument to the <tt>unique()</tt> function. The compile-time constant 
function 
<p><tt>&nbsp; uniqueCount("Timer")</tt> 
</p><p>will count the number of uses of <tt>unique("Timer"</tt>). <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Running the Sense 
application</font></nobr></b></td></tr></tbody></table>
</p><p>As before, just do a <tt>make mica install</tt> in the <tt>Sense</tt> 
directory to compile and install the application on your mote. You'll need a 
sensor board attached to the mote with a photo sensor. The Mica sensor board, 
for example, snaps into place via the 51 pin connector. The type of sensorboard 
is selected by the <tt>-board</tt> command line option to <tt>ncc</tt>. On the 
Mica mote, the default sensor board type is <tt>micasb</tt>. However, if you 
have an older ("basic") sensor board, you might need to pass in the <tt>-board 
basicsb</tt> option to <tt>ncc</tt>. To do this, edit the <tt><a href="../../apps/Sense/Makefile">Makefile</a></tt> in the <tt>Sense</tt> 
directory and add the line <tt>SENSORBOARD=basicsb </tt>before the line that 
includes <tt>Makerules</tt>. The sensor boards supported by TinyOS are 
represented by the directory names in <a href="../../tos/sensorboards">tos/sensorboards</a> . 
</p><p>The operation of the photo sensor is a bit unusual. The ADC yields a 10-bit 
digitized sample of the photo sensor. What we would like is for the LEDs to be 
off when the node is in the light, and on when the node is in the dark. Here, we 
are looking at the upper three bits of this data coming from the ADC, and 
inverting the value. Note the line: </p><pre>&nbsp; display(7 - ((data &gt;&gt; 7) &amp; 0x7));</pre>in the 
<tt>ADC.dataReady()</tt> function of <tt>SenseM</tt>. 
<p>Note that when running the application you may really have to cover up the 
photo sensor pretty well to get it to respond - we'll admit that this is not the 
best application to really see the photo sensor at work! <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Exercises</font></nobr></b></td></tr></tbody></table>
</p><p>Extend the capability of the application by chirping the sensor board's 
sounder when it is dark! The TinyOS component for the Sounder is located in 
<tt>tos/sensorboards/micasb/Sounder.nc</tt> and provides the <tt>StdControl</tt> 
interface. Modify <tt>SenseM.nc</tt> to add a <tt>StdControl</tt> as 
<tt>SounderControl</tt>, wiring it as appropriate in <tt>Sense.nc</tt>.&nbsp; 
Remember to call init() to initialize the Sounder component. To make the sounder 
turn on from SenseM.nc, call <tt>SounderControl.start()</tt>. To turn off the 
sounder, call <tt>SounderControl.stop()</tt>. Be sure to test this new 
application many times to annoy everyone sitting around you. 
</p><p>
</p><hr>
<b><a href="lesson1.html"></a></b> <!--  LocalWords:  TinyOS nesC nc async norace BlinkM FooM ncc SingleTimer Leds
 --><!--  LocalWords:  LedsC StdControl tos init TimerC redOn redOff uint redToggle
 --><!--  LocalWords:  metadata html nesdoc gcc exe avr objcopy srec uisp mib dprog
 --><!--  LocalWords:  towards dapa xff ThinkPad dlpt Makelocal micasb Wshadow DDEF
 --><!--  LocalWords:  finline fnesc cfile lm Atmel ATmega nesC's nesc SenseM
 --><!--  LocalWords:  ADCControl SounderControl dataReady getData rcombine someval
 --><!--  LocalWords:  ADControl fooControl barControl MyTimer uniqueCount basicsb
 --><!--  LocalWords:  sensorboard Makerules sensorboards
 --><img src ="http://www.cnitblog.com/Embedded_Systems/aggbug/4944.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Embedded_Systems/" target="_blank">井冈山</a> 2005-11-28 01:06 <a href="http://www.cnitblog.com/Embedded_Systems/articles/4944.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lesson 3: Introducing Tasks for Application Data Processing[转]</title><link>http://www.cnitblog.com/Embedded_Systems/articles/4943.html</link><dc:creator>井冈山</dc:creator><author>井冈山</author><pubDate>Sun, 27 Nov 2005 17:05:00 GMT</pubDate><guid>http://www.cnitblog.com/Embedded_Systems/articles/4943.html</guid><wfw:comment>http://www.cnitblog.com/Embedded_Systems/comments/4943.html</wfw:comment><comments>http://www.cnitblog.com/Embedded_Systems/articles/4943.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/Embedded_Systems/comments/commentRss/4943.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Embedded_Systems/services/trackbacks/4943.html</trackback:ping><description><![CDATA[&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="tahoma,arial,helvetica"><font size="-1">Lesson 3: 
Introducing Tasks for Application Data Processing</font></font></b> 
<p><font face="tahoma,arial,helvetica">Last updated 15 August 
2003</font></p></td></tr></tbody></table>
<p>This lesson introduces the TinyOS notion of <b>tasks</b>, which can be used 
to perform general-purpose "background" processing in an application. This 
lesson makes use of the <tt>SenseTask</tt> application, which is a revision of 
the <tt>Sense</tt> application from the previous lesson. 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Task creation and 
scheduling</font></nobr></b></td></tr></tbody></table>
</p><p>TinyOS provides a two-level scheduling hierarchy consisting of <b>tasks</b> 
and <b>hardware event handlers</b>. Remember that the keyword <b>async</b> 
declares a command or event that can be executed by a hardware event handler. 
This means it could be executed at any time (preempting other code), so 
<b>async</b> commands and events should do small amounts of work and complete 
quickly. Additionally, you should pay attention to the possibility of data races 
on all shared data accessed by an <b>async</b> command or event. <b>Tasks</b> 
are used to perform longer processing operations, such as background data 
processing, and can be preempted by hardware event handler. 
</p><p>A task is declared in your implementation module using the syntax </p><pre>&nbsp; task void taskname() { ... }</pre>where <tt>taskname()</tt> is whatever 
symbolic name you want to assign to the task. Tasks must return <tt>void</tt> 
and may not take any arguments. 
<p>To dispatch a task for (later) execution, use the syntax </p><pre>&nbsp; post taskname();</pre>A task can be posted from within a command, an 
event, or even another task. 
<p>The <tt>post</tt> operation places the task on an internal <b>task queue</b> 
which is processed in FIFO order. When a task is executed, it runs to completion 
before the next task is run; therefore, a task should not spin or block for long 
periods of time. Tasks do not preempt each other, but a task can be preempted by 
a hardware event handler. If you need to run a series of long operations, you 
should dispatch a separate task for each operation, rather than using one big 
task. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The SenseTask 
Application</font></nobr></b></td></tr></tbody></table>
</p><p>To illustrate tasks, we have modified the Sense application from Lesson 2, 
which is found in <tt><a href="../../apps/SenseTask">apps/SenseTask</a></tt>. 
The <tt>SenseTaskM</tt> component maintains a circular data buffer, 
<tt>rdata</tt>, that contains recent photo sensor samples; the 
<tt>putdata()</tt> function is used to insert a new sample into the buffer. The 
<tt>dataReady()</tt> event simply deposits data into the buffer and posts a 
task, called <tt>processData()</tt>, for processing. <br>&nbsp; 
</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>SenseTaskM.nc</b> <pre>&nbsp; // ADC data ready event handler<br>&nbsp; async event result_t ADC.dataReady(uint16_t data) {<br>&nbsp;&nbsp;&nbsp; putdata(data);<br>&nbsp;&nbsp;&nbsp; post processData();<br>&nbsp;&nbsp;&nbsp; return SUCCESS;<br>&nbsp; }</pre></td></tr></tbody></table></center>
<p>Some time after the async event completes (there may be other tasks pending 
for execution), the <tt>processData()</tt> task will run. It computes the sum of 
the recent ADC samples and displays the upper three bits of the sum on the LEDs. 

</p><center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>SenseTaskM.nc, continued</b> <pre>&nbsp; task void processData() {<br>&nbsp;&nbsp;&nbsp; int16_t i, sum=0;<br><br>&nbsp;&nbsp;&nbsp; atomic {<br>&nbsp;&nbsp;&nbsp; for (i=0; i &lt; size; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sum += (rdata[i] &gt;&gt; 7);<br>&nbsp;&nbsp;&nbsp; }&nbsp;<br>&nbsp;&nbsp;&nbsp; display(sum &gt;&gt; log2size);<br>&nbsp; }</pre></td></tr></tbody></table></center>
<p>The keyword <b>atomic </b>in the task <tt>processData() </tt>illustrates the 
use of nesC <i>atomic statements</i>. This means the code section within the 
<tt>atomic</tt> curly braces will execute without preemption. In this example, 
access to the shared buffer <tt>rdata</tt> is being protected. Where else should 
this be used ? 
</p><p>Atomic statements delay interrupt handling which makes the system less 
responsive. To minimize this effect, atomic statements in nesC should avoid 
calling commands or signaling events when possible (the execution time of an 
external command or event will depend on what the component is wired to). <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Exercises</font></nobr></b></td></tr></tbody></table>
</p><p>Try to break up the <tt>processData()</tt> task so that each invocation of 
the task only adds one element of the <tt>rdata</tt> array to <tt>sum</tt>. 
<tt>processData()</tt> should then post itself to continue processing the 
complete <tt>sum</tt>, and display the LEDs when the final element of the array 
has been processed. Be careful of concurrency issues - since 
<tt>processData()</tt> is also posted from <tt>ADC.dataReady()</tt>, you might 
want to add a flag to prevent a new instance of the task from being started 
before the previous sum has been computed! 
</p><p>
</p><hr>
<b><a href="lesson2.html"></a></b> <!--  LocalWords:  TinyOS nesC nc async norace BlinkM FooM ncc SingleTimer Leds
 --><!--  LocalWords:  LedsC StdControl tos init TimerC redOn redOff uint redToggle
 --><!--  LocalWords:  metadata html nesdoc gcc exe avr objcopy srec uisp mib dprog
 --><!--  LocalWords:  towards dapa xff ThinkPad dlpt Makelocal micasb Wshadow DDEF
 --><!--  LocalWords:  finline fnesc cfile lm Atmel ATmega nesC's nesc SenseM rdata
 --><!--  LocalWords:  ADCControl SounderControl dataReady getData rcombine someval
 --><!--  LocalWords:  ADControl fooControl barControl MyTimer uniqueCount basicsb
 --><!--  LocalWords:  sensorboard Makerules sensorboards SenseTask taskname
 --><!--  LocalWords:  SenseTaskM putdata processData
 --><img src ="http://www.cnitblog.com/Embedded_Systems/aggbug/4943.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Embedded_Systems/" target="_blank">井冈山</a> 2005-11-28 01:05 <a href="http://www.cnitblog.com/Embedded_Systems/articles/4943.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lesson 1: Getting Started with TinyOS and nesC[转]</title><link>http://www.cnitblog.com/Embedded_Systems/articles/4941.html</link><dc:creator>井冈山</dc:creator><author>井冈山</author><pubDate>Sun, 27 Nov 2005 16:54:00 GMT</pubDate><guid>http://www.cnitblog.com/Embedded_Systems/articles/4941.html</guid><wfw:comment>http://www.cnitblog.com/Embedded_Systems/comments/4941.html</wfw:comment><comments>http://www.cnitblog.com/Embedded_Systems/articles/4941.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/Embedded_Systems/comments/commentRss/4941.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Embedded_Systems/services/trackbacks/4941.html</trackback:ping><description><![CDATA[<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><font face="tahoma,arial,helvetica"><font size="-1">Lesson 1: 
Getting Started with TinyOS and nesC</font></font></b> 
<p><font face="tahoma,arial,helvetica">Last updated 9 September 
2003</font></p></td></tr></tbody></table>
<p>This lesson introduces the basic concepts of TinyOS and the nesC language in 
which the system is written. It includes a quick overview of the nesC language 
concepts and syntax to help you get started with programming in this 
environment. 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Introduction</font></nobr></b></td></tr></tbody></table></p>
<p>The <span style="text-decoration: underline;">TinyOS system, libraries, and applications are written in nesC</span>, a new 
language for programming <span style="font-style: italic; color: rgb(0, 0, 255);">structured component-based applications</span>. The nesC 
language is primarily intended for embedded systems such as sensor networks<span style="color: rgb(0, 100, 0);">. 
nesC has a C-like syntax, but supports the <span style="font-style: italic;">TinyOS concurrency model</span>, as well as 
mechanisms for structuring, naming, and linking together software components 
into robust network embedded systems.（<span style="color: rgb(169, 169, 169);">不只是一个简单的语言编译器，还包含了一种基于组件和并发的OS模型在里面，直接生成一个含OS的完整系统，有必要对NesC进行进一步的分析了解</span>）</span></p><p><span style="color: rgb(0, 100, 0);">&nbsp;&nbsp; </span>The principal goal is to allow application 
designers to build components that can be easily composed into complete, 
concurrent systems, and yet perform extensive checking at compile time. </p>
<p>TinyOS defines a number of important concepts that are expressed in nesC：</p><ul><li>First, nesC applications are built out of <b>components</b> with well-defined, 
bidirectional <b>interfaces</b>.&nbsp;</li><li>Second, <span style="font-weight: bold;">nesC defines</span> a concurrency model, based 
on <b>tasks</b> and <b>hardware event handlers</b>, and <span style="text-decoration: underline;">detects </span><b style="text-decoration: underline;">data 
races</b><span style="text-decoration: underline;"> at compile time</span>.<span style="color: rgb(169, 169, 169);">（NesC定义了一个基于Task和硬件事件处理的并发模型）</span> </li></ul>
<p><b>Components</b> <br></p><p><i style="font-weight: bold;">&nbsp; Specification</i><span style="font-weight: bold;"> </span><br>&nbsp; <span style="text-decoration: underline;">一个nesC应用包含一个或多个</span><i style="text-decoration: underline;">components，它们连接在一起构成一个可执行的应用</i><span style="text-decoration: underline;">.</span></p><p><span style="text-decoration: underline;"></span> &nbsp; 一个component 提供和使用接口. 这些接口是双向的，是访问component的唯一访问点.</p><p>&nbsp; interface声明称为<b>commands</b>的interface提供者必须实现的函数集合，同时声明另一个称为<b>events</b>的函数集，该接口的使用者必须实现这些事件处理函数.当一个component调用接口中的commands时，它必须实现该接口的events. 单个component可以use或provide多个interfaces和同一接口的多个实例. </p>
<p><i style="font-weight: bold;">&nbsp; Implementation</i> <br></p><p>&nbsp; nesC中包含两类components: <br></p><ul><li><b>modules</b>：提供应用代码，实现一个或多个interface.</li><li><b>configurations</b>：用来组装其他components到一起, 连接这些components使用的interfaces到其他组件提供的interfaces. 这也称为<b>wiring</b><span style="color: rgb(169, 169, 169);">(连线，类似VHDL中的结构模型)</span>. 每个nesC应用通过把内部组建连接起来的<b>top-level configuration</b>进行描述. </li></ul>
<p>&nbsp;&nbsp; nesC对所有源文件使用"<tt>.nc</tt>"扩展名 -- 
interfaces, modules, and configurations. Please see <a href="naming.html">TinyOS 
Coding and Naming Conventions</a> for more information on naming conventions. 
</p>
<p><b>Concurrency Model</b> <br></p><p>&nbsp;&nbsp; TinyOS仅执行一个程序，包含运行应用所需的系统组件和定制组件<span style="color: rgb(169, 169, 169);">(用户定义编制的)</span>. 存在两条执行threads: <i><br></i></p><ul><li><i><span style="font-weight: bold;">tasks：</span></i>任务就是函数，其执行是预留的（defered），一旦调度，它们就被执行，直至完成，无法被剥夺. </li><li><i style="font-weight: bold;">hardware 
event handlers</i><span style="font-weight: bold;">：</span>硬件中断响应程序，同样运行到完成，但是可以剥夺task和其他hardware event 
handler的执行。作为硬件事件处理程序的一部分执行的Commands和events必须用<span style="font-weight: bold;">async</span>关键字声明. </li></ul>
<p>&nbsp;&nbsp;&nbsp; 因为任务和硬件事件处理程序可以被其他异步(asynchronous)代码占先执行，nesC程序可能会出现某种竞争条件(race conditions). 这可以通过访问任务间互斥的共享数据来避免，也可以通过在atomic语句内完成所有对共享数据的访问. nesC编译器可以在编译时报告潜在的<i>data races</i>，存在误报的可能，这种情况可以使用norace关键字来声明相关变量，但是该关键字的使用要非常慎重. </p>
<p>&nbsp;&nbsp; Please see the <a href="../../nesc/doc/ref.pdf">nesC Language Reference 
Manual</a> for more information on programming in nesC. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">An example application: 
Blink</font></nobr></b></td></tr></tbody></table></p>
<p>&nbsp;&nbsp; So far this is all fairly abstract - let's look at a concrete example: the 
simple test program "Blink" found in <tt><a href="../../apps/Blink">apps/Blink</a></tt> in the TinyOS tree. This application 
simply causes the red LED on the mote to turn on and off at 1Hz. </p>
<p>&nbsp;&nbsp; Blink application is composed of two <b>components</b>: <br></p><ul><li>a <b>module：</b>"<tt>BlinkM.nc</tt>"</li><li>a <b>configuration：</b>"<tt>Blink.nc</tt>".&nbsp;</li></ul>&nbsp;&nbsp; Remember that <span style="text-decoration: underline;">all applications require a top-level 
configuration file, which is typically named after the application itself</span>. In 
this case <tt style="font-weight: bold;">Blink.nc</tt> is the configuration for the Blink application and 
the source file that the nesC compiler uses to generate an executable file. 
<tt style="font-weight: bold;">BlinkM.nc</tt>, on the other hand, actually provides the 
<i style="font-weight: bold;">implementation</i> of the Blink application. As you might guess, 
<tt style="text-decoration: underline;">Blink.nc</tt><span style="text-decoration: underline;"> is used to wire the </span><tt style="text-decoration: underline;">BlinkM.nc</tt><span style="text-decoration: underline;"> module to other 
components that the Blink application requires.</span> 
<p>The reason for the distinction between modules and configurations is to allow 
a system designer to quickly "snap together" applications. For example, a 
designer could provide a configuration that simply wires together one or more 
modules, none of which she actually designed. Likewise, another developer can 
provide a new set of "library" modules that can be used in a range of 
applications. </p>
<p>Sometimes (as is the case with <tt>Blink</tt> and <tt>BlinkM</tt>) you will 
have a configuration and a module that go together. When this is the case, the 
convention used in the TinyOS source tree is that <tt>Foo.nc</tt> represents a 
configuration and <tt>FooM.nc</tt> represents the corresponding module. While 
you could name an application's implementation module and associated top-level 
configuration anything, to keep things simple we suggest that you adopt this 
convention in your own code. There are several other naming conventions used in 
TinyOS code; a <a href="naming.html">summary</a> is provided 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The Blink.nc 
configuration</font></nobr></b></td></tr></tbody></table></p>
<p>The nesC compiler, <a href="../nesc/ncc.html">ncc</a>, compiles a nesC 
application when given the file <span style="font-weight: bold;">containing the top-level configuration</span>. Typical 
TinyOS applications come with a standard Makefile that allows platform selection 
and invokes ncc with appropriate options on the application's top-level 
configuration. </p>
<p>Let's look at <tt>Blink.nc</tt>, the configuration for this application 
first: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>Blink.nc</b> <pre><span style="font-weight: bold;">configuration </span>Blink {<br> &nbsp;//其中可以说明uses和provides语句，配置可以使用和提供接口<br>}<br><span style="font-weight: bold;">implementation</span> { //配置的具体实现<br>&nbsp; components Main, BlinkM, SingleTimer, LedsC;//本配置涉及到的组件<br><br>  //下面是连线，类似VHDL语言中的结构模型中信号的连接<br>  //左边的接口(use)绑定到右边的接口实现(provide)<br>&nbsp; Main.StdControl -&gt; BlinkM.StdControl;<br>&nbsp; Main.StdControl -&gt; SingleTimer.StdControl;<br>&nbsp; BlinkM.Timer -&gt; SingleTimer.Timer;<br>&nbsp; BlinkM.Leds -&gt; LedsC;  //相当于BlinkM.Leds -&gt; LedsC.Leds<br>}</pre></td></tr></tbody></table></center>
<p>The first thing to notice is the key word <tt>configuration</tt>, which 
indicates that this is a configuration file. The first two lines, </p><pre>&nbsp; configuration Blink {<br>&nbsp; }</pre>simply state that this is a 
configuration called <tt>Blink</tt>. <span style="font-weight: bold;">Within the empty braces here it is possible 
to specify </span><tt style="font-weight: bold;">uses</tt><span style="font-weight: bold;"> and </span><tt style="font-weight: bold;">provides</tt><span style="font-weight: bold;"> clauses,</span> as with a module. This 
is important to keep in mind: <span style="font-weight: bold;">a configuration can use and provide interfaces</span>! 
<p>The actual configuration is implemented within the pair of curly bracket 
following key word <tt>implementation </tt>. The <tt>components</tt>line 
specifies the set of components that this configuration references, in this case 
<tt>Main</tt>, <tt>BlinkM</tt>, <tt>SingleTimer</tt>, and <tt>LedsC</tt>. The 
remainder of the implementation consists of connecting interfaces used by 
components to interfaces provided by others. </p>
<p><tt style="font-weight: bold;">Main</tt><span style="font-weight: bold;">是TinyOS应用第一个执行的组件.</span>更精确的说，<tt><span style="font-weight: bold;">Main.StdControl.init()命令</span>是</tt>TinyOS执行的第一个命令，紧跟着是<span style="font-weight: bold;">Main.StdControl.start()</span>命令<span style="font-weight: bold;">. 因此任何TinyOS应用必须在其顶层配置中包含Main组件</span>。<tt><span style="font-weight: bold;">StdControl</span>是一个<span style="font-weight: bold;">用于初始化和启动TinyOS组件的公共</span></tt><span style="font-weight: bold;">interface</span>. Let us 
have a look at <tt>tos/interfaces/StdControl.nc</tt>: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>StdControl.nc</b> <pre>interface StdControl {<br>&nbsp; command result_t init(); //组件初始化时被调用，可调用多次但必须在start和stop之前<br>&nbsp; command result_t start();//组件启动，即组件实际第一次执行，可调用多次<br>&nbsp; command result_t stop(); //停止组件，可调用多次<br>}</pre></td></tr></tbody></table></center>
<p>We see that <tt>StdControl</tt> defines three <b>commands</b>：</p><ul><li><tt>init()</tt>：called 
when a component is first initialized,<tt>init()</tt> can be called multiple times, but will never be 
called after either <tt>start()</tt> or <tt>stop</tt> are called.</li><li><tt>start()：called </tt>when a component is started, 
that is, actually executed for the first time；</li><li><tt>stop()：</tt>called when 
the component is stopped, for example, in order to power off the device that it 
is controlling.&nbsp;&nbsp;</li></ul>&nbsp;&nbsp;&nbsp; Specifically, 
the valid call patterns of StdControl are <tt><span style="font-weight: bold;">init*(start | stop)*</span> . </tt>All 
three of these commands have <span style="font-weight: bold;">"deep" semantics</span>; <span style="font-weight: bold;">calling </span><tt style="font-weight: bold;">init()</tt><span style="font-weight: bold;"> on a 
component must make it call </span><tt style="font-weight: bold;">init()</tt><span style="font-weight: bold;"> on all of its subcomponents</span>. The 
following 2 lines in Blink configuration <pre>&nbsp; Main.StdControl -&gt; SingleTimer.StdControl;<br>&nbsp; Main.StdControl -&gt; BlinkM.StdControl;</pre><span style="font-weight: bold;">wire 
the </span><tt style="font-weight: bold;">StdControl</tt><span style="font-weight: bold;"> interface in </span><tt style="font-weight: bold;">Main</tt><span style="font-weight: bold;"> to the </span><tt style="font-weight: bold;">StdControl</tt><span style="font-weight: bold;"> 
interface in both </span><tt style="font-weight: bold;">BlinkM</tt><span style="font-weight: bold;"> and </span><tt style="font-weight: bold;">SingleTimer</tt><span style="font-weight: bold;">.</span> 
<tt>SingleTimer.StdControl.init()</tt>and<tt>BlinkM.StdControl.init()</tt> will 
be called by <tt>Main.StdControl.init()</tt>. The same rule applies to the 
<tt>start() and <font color="#000000">stop() </font></tt>commands. 
<p>Concerning <i>used</i> interfaces, it is important to note that <span style="font-weight: bold;">subcomponent 
initialization functions must be <span style="text-decoration: underline;">explicitly</span> called by the using component</span>. For 
example, the BlinkM module uses the interface Leds, so Leds.init() is called 
explicitly in BlinkM.init(). </p>
<p>nesC uses <span style="font-weight: bold;">arrows</span> to determine relationships between interfaces. Think of the 
right arrow (<tt>-&gt;</tt>) as "<span style="font-weight: bold;">binds to</span>". The left side of the arrow binds an 
interface to an implementation on the right side. In other words, the <span style="text-decoration: underline;">component 
that </span><b style="text-decoration: underline;">uses</b><span style="text-decoration: underline;"> an interface is on the left</span>, and the <span style="text-decoration: underline;">component </span><b style="text-decoration: underline;">provides 
</b><span style="text-decoration: underline;">the interface is on the right</span>. </p>
<p>The line </p><pre>&nbsp; BlinkM.Timer -&gt; SingleTimer.Timer;</pre>is used to <span style="font-weight: bold;">wire the 
</span><tt style="font-weight: bold;">Timer</tt><span style="font-weight: bold;"> interface used by BlinkM to the Timer interface provided by 
SingleTimer.</span> <tt>BlinkM.Timer</tt> on the left side of the arrow is referring to 
the <i>interface</i> called Timer (<tt>tos/interfaces/Timer.nc</tt>), while 
SingleTimer.Timer on the right side of the arrow is referring to the 
<i>implementation </i>of Timer (<tt>tos/lib/SingleTimer.nc)</tt>. <span style="font-weight: bold;">Remember that 
the arrow always binds interfaces (on the left) to implementations (on the 
right).</span> 
<p><span style="font-weight: bold;">nesC supports multiple implementations of the same interface</span>. The 
<tt>Timer</tt> interface is such a example. The <tt>SingleTimer </tt>component 
implements a single <tt>Timer</tt> interface while another component, 
<tt style="font-weight: bold;">TimerC, </tt><span style="font-weight: bold;">implements multiple timers using timer id as a parameter</span>. 
Further discussions on timers can be found in Lesson 2. </p>
<p><span style="font-weight: bold;">Wirings can also be implicit</span>. For example, </p><pre>&nbsp; BlinkM.Leds -&gt; <span style="font-weight: bold;">LedsC</span>;</pre>is really shorthand for <pre>&nbsp; BlinkM.Leds -&gt; <span style="font-weight: bold;">LedsC.Leds;</span></pre><span style="font-weight: bold;">If no interface name is given on the 
right side of the arrow, the nesC compiler by default tries to bind to the same 
interface as on the left side of the arrow. </span><br>&nbsp; <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">The BlinkM.nc 
module</font></nobr></b></td></tr></tbody></table>
<p>Now let's look at the module <tt>BlinkM.nc</tt>: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>BlinkM.nc</b> <pre><span style="font-weight: bold;">module</span> BlinkM {<br>&nbsp; <span style="font-weight: bold;">provides</span> {<br>&nbsp;&nbsp;&nbsp; interface StdControl;<br>&nbsp; }<br>&nbsp; <span style="font-weight: bold;">uses</span> {<br>&nbsp;&nbsp;&nbsp; interface Timer;<br>&nbsp;&nbsp;&nbsp; interface Leds;<br>&nbsp; }<br>}<br>// Continued below...</pre></td></tr></tbody></table></center>
<p>The first part of the code states that this is a module called 
<tt>BlinkM</tt>and declares the interfaces it provides and uses.&nbsp; <span style="text-decoration: underline;">The 
</span><tt style="text-decoration: underline;">BlinkM</tt><span style="text-decoration: underline;">&nbsp; module </span><b style="text-decoration: underline;">provides</b><span style="text-decoration: underline;"> the</span><b style="text-decoration: underline;"> </b><span style="text-decoration: underline;">interface 
</span><tt style="text-decoration: underline;">StdControl</tt><span style="text-decoration: underline;">.&nbsp; This means that </span><tt style="text-decoration: underline;">BlinkM</tt><span style="text-decoration: underline;"> <span style="font-weight: bold;">implements</span> the 
</span><tt style="text-decoration: underline;">StdControl</tt><span style="text-decoration: underline;"> interface.</span>&nbsp; As explained above, this is necessary to get the 
Blink component initialized and started.&nbsp; The BlinkM module also <b>uses</b> two 
interfaces: <tt>Leds</tt> and <tt>Timer. </tt>这意味着<span style="font-weight: bold;">BlinkM可以调用它use的接口中声明的任何command，而且必须实现这些接口中声明的任何events.</span> </p>
<p><tt>The Leds </tt>interface defines several commands like 
<tt>redOn()</tt>,<tt>redOff()</tt>, and so forth, which turn the different LEDs 
(red, green, or yellow) on the mote on and off. Because <tt>BlinkM</tt> uses the 
<tt>Leds</tt> interface, it can invoke any of these commands. Keep in mind, 
however, that <tt>Leds</tt> is just an interface: the implementation is 
specified in the Blink.nc configuration file. </p>
<p><tt>Timer.nc</tt> is a little more interesting: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>Timer.nc</b> <pre><span style="font-weight: bold;">interface</span> Timer {<br>&nbsp; <span style="font-weight: bold;">command</span> result_t start(char type, uint32_t interval);<br>&nbsp; <span style="font-weight: bold;">command</span> result_t stop();<br>&nbsp; <span style="font-weight: bold;">event</span> result_t fired();//本接口会触发fired事件，使用者必须实现该事件的响应程序<br>}</pre></td></tr></tbody></table></center>
<p>Here we see that <tt>Timer</tt> interface defines the <tt>start()</tt> and 
<tt>stop()</tt> commands, and the <tt>fired() </tt>event. </p>
<p>The <tt>start()</tt> command is used to specify the type of the timer and the 
interval at which the timer will expire. The unit of the interval argument is 
millisecond. The valid types are <tt>TIMER_REPEAT</tt> and 
<tt>TIMER_ONE_SHOT</tt>. A one-shot timer ends after the specified interval, 
while a repeat timer goes on and on until it is stopped by the <tt>stop() 
</tt>command. </p>
<p>How does an application know that its timer has expired? The answer is when 
it receives an event. The <tt>Timer</tt> interface provides an event: </p><pre>&nbsp; event result_t fired();</pre>An <b>event</b> is a function that the 
implementation of an interface will signal when a certain event takes place. In 
this case, the <tt>fired()</tt> event is signaled when the specified interval 
has passed. This is an example of a <b>bi-directional interface</b>: interface不仅提供<b>commands供</b> 接口使用者调用, 同时也会触发<b>events</b>，这将调用使用者接口中定义的事件处理程序。可以把event当成一个接口实现将调用的回调函数. 使用某个接口的模块必须实现该接口中使用的事件处理程序. 
<p>Let's look at the rest of <tt>BlinkM.nc</tt> to see how this all fits 
together: </p>
<center>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="80%">
<tbody>
<tr bgcolor="#e0e0e0">
<td width="100%"><b>BlinkM.nc, continued</b> <pre>implementation {<br><br>&nbsp; command result_t <span style="font-weight: bold;">StdControl</span>.init() {<br>&nbsp;&nbsp;&nbsp; call Leds.init();//显式调用init<br>&nbsp;&nbsp;&nbsp; return SUCCESS;<br>&nbsp; }<br><br>&nbsp; command result_t StdControl.start() {<br>&nbsp;&nbsp;&nbsp; return call Timer.start(TIMER_REPEAT, 1000) ;<br>&nbsp; }<br><br>&nbsp; command result_t StdControl.stop() {<br>&nbsp;&nbsp;&nbsp; return call Timer.stop();<br>&nbsp; }<br><br>&nbsp; event result_t Timer.fired()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; call Leds.redToggle();<br>&nbsp;&nbsp;&nbsp; return SUCCESS;<br>&nbsp; }<br>}</pre></td></tr></tbody></table></center>
<p>This is simple enough. As we see the <tt>BlinkM</tt> module implements the 
<tt>StdControl.init()</tt>, <tt>StdControl.start()</tt>, and 
<tt>StdControl.stop()</tt> commands, since it provides the <tt>StdControl</tt> 
interface. It also implements the <tt>Timer.fired()</tt> event, which is 
necessary since <tt>BlinkM</tt> must implement any event from an interface it 
uses. </p>
<p>The <tt>init()</tt> command in the implemented <tt>StdControl </tt>interface 
simply initializes the Leds subcomponent with the call to <tt>Leds.init()</tt>. 
The <tt>start()</tt> command invokes <tt>Timer.start()</tt> to create a repeat 
timer that expires every 1000 ms. <tt>stop()</tt> terminates the timer. Each 
time <tt>Timer.fired()</tt> event is triggered, the <tt>Leds.redToggle()</tt> 
toggles the red LED. </p>
<p>You can view a graphical representation of the component relationships within 
an application. TinyOS source files include metadata within comment blocks that 
ncc, the nesC compiler, uses to automatically generate html-formatted 
documentation. To generate the documentation, type <tt>make &lt;platform&gt; 
docs</tt> from the application directory. The resulting documentation is located 
in 
<tt>docs/nesdoc/&lt;platform&gt;</tt>.<tt>docs/nesdoc/&lt;platform&gt;/index.html</tt> 
is the main index to all documented applications. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Compiling the Blink 
application</font></nobr></b></td></tr></tbody></table></p>
<p>TinyOS supports multiple platforms. Each platform has its own directory in 
the <a href="../../tos/platform">tos/platform</a> directory. In this tutorial, 
we will use the mica platform as an example. If you are in the TinyOS source 
tree, compiling the <tt>Blink</tt> application for the Mica mote is as simple as 
typing </p><pre>&nbsp; <span style="font-weight: bold;">make</span> mica</pre>in the <tt><a href="../../apps/Blink">apps/Blink</a></tt> 
directory. Of course this doesn't tell you anything about how the nesC compiler 
is invoked. 
<p>nesC itself is invoked using the <a href="../nesc/ncc.html"><tt>ncc</tt></a> 
command which is based on <tt style="font-weight: bold;">gcc</tt>. For example, you can type </p><pre>&nbsp; <span style="font-weight: bold;">ncc</span> -o main.exe -target=mica Blink.nc</pre>to compile the <tt>Blink</tt> 
application (from the <tt>Blink.nc</tt> top-level configuration) to 
<tt>main.exe</tt>, an executable file for the Mica mote. Before you can upload 
the code to the mote, you use <pre>&nbsp; <span style="font-weight: bold;">avr-objcopy</span> --output-target=srec main.exe main.srec</pre>to produce 
<tt>main.srec</tt>, which essentially represents <span style="text-decoration: underline;">the binary </span><tt style="text-decoration: underline;">main.exe</tt><span style="text-decoration: underline;"> 
file in a text format that can be used for programming the mote.</span> You then use 
another tool (such as <tt style="font-weight: bold;">uisp</tt>) to actually upload the code to the mote, 
depending on your environment. In general you will never need to invoke 
<tt>ncc</tt> or <tt>avr-objcopy</tt> by hand, the Makefile does all this for 
you, but it's nice to see that all you need to compile a nesC application is to 
run <tt>ncc</tt> on the top-level configuration file for your application. 
<tt>ncc</tt> takes care of locating and compiling all of the different 
components required by your application, linking them together, and ensuring 
that all of the component wiring matches up. <br>&nbsp; <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Programming the mote and 
running Blink</font></nobr></b></td></tr></tbody></table>
<p>Now that we've compiled the application it's time to program the mote and run 
it. This example will use the Mica mote and the parallel-port-based programming 
board (<span style="font-family: monospace;">mib500</span>). Instructions on how 
to use the other programming boards are <a href="programmers.html">here</a>. To 
download your program onto the mote, place the mote board (or mote and sensor 
stack) into the bay on the programming board, as shown below. You can either 
supply a 3 volt supply to the connector on the programming board or power the 
node directly. The red LED (labeled D2) on the programming board will be on when 
power is supplied. If you are using batteries to power the mote, be sure the 
mote is switched on (the power switch should be towards the connector). </p>
<p>Plug the 32-pin connector into the parallel port of a computer configured 
with the TinyOS tools, using a standard DB32 parallel port cable. </p>
<center><img src="http://www.cnitblog.com/images/cnitblog_com/embedded_systems/mica-offboard.jpg" alt="mica-offboard.jpg" border="0" height="240" width="320"><img src="http://www.cnitblog.com/images/cnitblog_com/embedded_systems/mica-onboard.jpg" alt="mica-onboard.jpg" border="0" height="240" width="320"><br></center>
<p>Type: <tt>make mica install</tt>. If you get the error: </p><pre>&nbsp; uisp -dprog=dapa --erase&nbsp;<br>&nbsp; pulse<br>&nbsp; An error has occurred during the AVR initialization.<br>&nbsp;&nbsp; * Target status:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vendor Code = 0xff, Part Family = 0xff, Part Number = 0xff<br><br>&nbsp; Probably the wiring is incorrect or target might be `damaged'.<br>&nbsp; make: *** [install] Error 2</pre>check 
whether the power is on. You can also get this error message if the mote is low 
on batteries (if you are using batteries), or if the wrong version of the 
<tt>uisp</tt> programming utility is installed (be sure to use the version in 
the TinyOS distribution). 
<p>If you are using an IBM ThinkPad, it may be necessary to tell the tools to 
use a different parallel port. You can do this by adding the line </p><pre>&nbsp; PROGRAMMER_EXTRA_FLAGS = -dlpt=3</pre>to the <tt>apps/Makelocal</tt> file 
(create it if it doesn't exist). The <a href="buildenv.html"><tt>Makelocal</tt></a> file is for user-specific 
<tt>Makefile</tt> configuration. 
<p>If the installation is successful you should see something like the 
following: </p><pre>&nbsp; compiling Blink to a mica binary<br>&nbsp; ncc -board=micasb -o build/mica/main.exe -Os -target=mica&nbsp; -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -finline-limit=200 -fnesc-cfile=build/mica/app.c&nbsp; Blink.nc -lm<br>&nbsp; avr-objcopy --output-target=srec build/mica/main.exe<br>&nbsp; build/mica/main.srec<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compiled Blink to build/mica/main.srec<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; installing mica binary<br>&nbsp; uisp -dprog=dapa&nbsp; --erase&nbsp;<br>&nbsp; pulse<br>&nbsp; Atmel AVR ATmega128 is found.<br>&nbsp; Erasing device ...<br>&nbsp; pulse<br>&nbsp; Reinitializing device<br>&nbsp; Atmel AVR ATmega128 is found.<br>&nbsp; sleep 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp; uisp -dprog=dapa&nbsp; --upload if=build/mica/main.srec<br>&nbsp; pulse<br>&nbsp; Atmel AVR ATmega128 is found.<br>&nbsp; Uploading: flash<br>&nbsp; sleep 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp; uisp -dprog=dapa&nbsp; --verify if=build/mica/main.srec<br>&nbsp; pulse<br>&nbsp; Atmel AVR ATmega128 is found.<br>&nbsp; Verifying: flash</pre>You 
can now test the program by unplugging the mote from the programming board and 
turning on the power switch (if it's not already on). With any luck the red LED 
should light up every second - congratulations! 
<p>Typing <tt>make clean</tt> in the <tt>Blink</tt> directory will clean up the 
compiled binary files. </p>
<p>If you are still having errors, then you need to check your TinyOS 
installation and check the Mica hardware. See <a href="verifyhw.html">System and 
Hardware Verification</a> for details. <br>&nbsp; 
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Exercises</font></nobr></b></td></tr></tbody></table></p>
<p>To test your new-found TinyOS programming skills, try out the following: </p>
<ul><li>Modify <tt>Blink</tt> to display the lower three bits of a counter in the 
LEDs. </li></ul>
<table border="0" cellpadding="3" cellspacing="2" hspace="4" width="100%">
<tbody>
<tr bgcolor="#e0e0ff">
<td width="100%"><b><nobr><font face="arial,helvetica">Conclusion</font></nobr></b></td></tr></tbody></table>
<p>This tutorial has just scratched the surface of nesC's syntax and features. 
Rather than document everything extensively, we refer the reader to the <a href="http://www.sourceforge.net/projects/nescc/">nesC Project Pages</a> as well 
as the documentation included with the nesC distribution in <tt>nesc/doc</tt>. 
These sources contain more complete documentation on the language. </p>
<p>Hopefully this should be enough of a start to get you going on programming in 
this fun new language. </p><img src ="http://www.cnitblog.com/Embedded_Systems/aggbug/4941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Embedded_Systems/" target="_blank">井冈山</a> 2005-11-28 00:54 <a href="http://www.cnitblog.com/Embedded_Systems/articles/4941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>