From 031c4e61e3bc3ec1386f37c061da4403856c3cac Mon Sep 17 00:00:00 2001 From: scipio Date: Wed, 2 May 2007 03:12:46 +0000 Subject: [PATCH] Updated instructions. --- doc/html/install-tinyos.html | 19 +- doc/html/tutorial/lesson11-200.html | 1594 +++++++++++++++++++++++++++ doc/html/upgrade-tinyos.html | 6 +- doc/index.html | 10 +- 4 files changed, 1615 insertions(+), 14 deletions(-) create mode 100644 doc/html/tutorial/lesson11-200.html diff --git a/doc/html/install-tinyos.html b/doc/html/install-tinyos.html index fff256e9..d135a445 100644 --- a/doc/html/install-tinyos.html +++ b/doc/html/install-tinyos.html @@ -8,7 +8,7 @@
Installing TinyOS 2.0
-
Last updated 8 April 2007
+
Last updated 1 May 2007

If you already have a 1.x tree or an existing 2.x tree, you are better off following the upgrade instructions at @@ -20,8 +20,9 @@ following the upgrade instructions at

One-step Install with a Live CD

Download a - Linux live CD that has a TinyOS installation on it. All you + HREF="http://toilers.mines.edu/Public/XubunTOS">Download a + Linux live CD that has a TinyOS installation on it. + All you need to do is download the CD image, burn it onto a CD, and install from there. This saves you all of the complexities of installation, and it's the recommended way to install @@ -33,7 +34,13 @@ following the upgrade instructions at

Currently, the TinyOS Core Working Group supports TinyOS on two platforms: Cygwin (Windows) and Linux. There have been some successful efforts to getting TinyOS environments working on Mac OSX, but OSX is not supported by the Core WG.

- + +

If you are running a version of Linux that supports Debian packages, then + you may want to use the TinyOS package repository. There is a story on www.tinyos.net + that describes how to use it. If you do this, then you do not have to + install the instructions here, except that you will need to check + that your environment is set up correctly (the final step)

+

Installing a TinyOS enviromnent has five basic steps; Windows requires an extra step, installing Cygwin, which is a UNIX-like environment. The steps are:

@@ -311,8 +318,8 @@ bypass the erroneous error by using 'rpm -ivh --ignoreos TinyOS - tinyos-2.0.0-3.cygwin.noarch.rpm - tinyos-2.0.0-3.noarch.rpm + tinyos-2.0.1-5.cygwin.noarch.rpm + tinyos-2.0.1-5.noarch.rpm diff --git a/doc/html/tutorial/lesson11-200.html b/doc/html/tutorial/lesson11-200.html new file mode 100644 index 00000000..a495f6a6 --- /dev/null +++ b/doc/html/tutorial/lesson11-200.html @@ -0,0 +1,1594 @@ + + + + Lesson 11: Simulation with TOSSIM + + + + +
Lesson 11: Simulation with TOSSIM
+
Last Modified: 18 May 2006
+ +

This lesson introduces the TOSSIM simulator. You will become + familiar with how to compile TOSSIM and use some of its + functionality. You will learn how to:

+ +

+ +

+

+ + +

Introduction

+ + TOSSIM simulates entire TinyOS applications. It works by + replacing components with simulation implementations. The + level at which components are replaced is very flexible: for + example, there is a simulation implementation of millisecond + timers that replaces HilTimerMilliC, while there is also an + implementation for atmega128 platforms that replaces the HPL + components of the hardware clocks. The former is general and + can be used for any platform, but lacks the fidelity of + capturing an actual chips behavior, as the latter + does. Similarly, TOSSIM can replace a packet-level + communication component for packet-level simulation, or + replace a low-level radio chip component for a more precise + simulation of the code execution. + + TOSSIM is a discrete event simulator. When it runs, it pulls + events of the event queue (sorted by time) and executes them. + Depending on the level of simulation, simulation events can + represent hardware interrupts or high-level system events + (such as packet reception). Additionally, tasks are simulation + events, so that posting a task causes it to run a short time + (e.g., a few microseconds) in the future. + + TOSSIM is a library: you must write a program that configures + a simulation and runs it. TOSSIM supports two programming + interfaces, Python and C++. Python allows you to interact with + a running simulation dynamically, like a powerful + debugger. However, as the interpretation can be a performance + bottleneck when obtaining results, TOSSIM also has a C++ + interface. Usually, transforming code from one to the other is + very simple. + + TOSSIM currently does not support gathering power + measurements. + +

Compiling TOSSIM

+ +

TOSSIM is a TinyOS library. Its core code lives in tos/lib/tossim. Every TinyOS + source directory has an optional sim subdirectory, + which contains simulation implementations of that package. For + example, tos/chips/atm128/timer/sim + contains TOSSIM implementations of some of the Atmega128 timer + abstractions.

+ +

To compile TOSSIM, you pass the sim option to make:

+ +
+          $ cd apps/Blink
+          $ make micaz sim
+        
+ + + +

Currently, the only platform TOSSIM supports is the + micaz. You should see output similar to this:

+
+          mkdir -p build/micaz
+            placing object files in build/micaz
+            writing XML schema to app.xml
+            compiling BlinkAppC to object file sim.o 
+          ncc -c -fPIC -o build/micaz/sim.o -g -O0 -tossim -fnesc-nido-tosnodes=1000 -fnesc-simulate -fnesc-nido-motenumber=sim_node\(\)   -finline-limit=100000 -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=micaz -fnesc-cfile=build/micaz/app.c -board=micasb  -Wno-nesc-data-race BlinkAppC.nc   -fnesc-dump=components -fnesc-dump=variables -fnesc-dump=constants -fnesc-dump=typedefs -fnesc-dump=interfacedefs -fnesc-dump=tags -fnesc-dumpfile=app.xml
+            compiling Python support into pytossim.o and tossim.o
+          g++ -c -shared -fPIC -o build/micaz/pytossim.o -g -O0  /home/pal/src/tinyos-2.x/tos/lib/tossim/tossim_wrap.cxx -I/usr/include/python2.3 -I/home/pal/src/tinyos-2.x/tos/lib/tossim -DHAVE_CONFIG_H
+          g++ -c -shared -fPIC -o build/micaz/tossim.o -g -O0  /home/pal/src/tinyos-2.x/tos/lib/tossim/tossim.c -I/usr/include/python2.3 -I/home/pal/src/tinyos-2.x/tos/lib/tossim
+            linking into shared object ./_TOSSIMmodule.so
+          g++ -shared build/micaz/pytossim.o build/micaz/sim.o build/micaz/tossim.o -lstdc++ -o _TOSSIMmodule.so
+          copying Python script interface TOSSIM.py from lib/tossim to local directory
+      
+ +

Depending on what OS you are using and what packages are installed, TOSSIM may + not properly compile on the first try. Appendix A + addresses some of the common causes and gives possible solutions.

+ + + + +

Compiling TOSSIM has five basic steps. Let's go through + them one by one.

+ +

Writing an XML schema

+ +
+          writing XML schema to app.xml
+        
+ +

The first thing the TOSSIM build process does is use + nesc-dump to produce an XML document that describes the + application. Among other things, this document descibes the + name and type of every variable.

+ +

Compiling the TinyOS Application

+ +

Besides introducing all of these new compilation steps, the + sim option changes the include paths of the + application. If the application has a series of includes

+ +
+          -Ia -Ib -Ic
+        
+ +

Then the sim option transforms the list to

+ +
+          -Ia/sim -Ib/sim -Ic/sim -I%T/lib/tossim -Ia -Ib -Ic
+        
+ +

This means that any system-specific simulation + implementations will be used first, followed by generic TOSSIM + implementations, followed by standard implementations. The + sim option also passes a bunch of arguments to the + compiler, so it knows to compile for simulation.

+ +

The product of this step is an object file, sim.o, + which lives in the platform's build directory. This object + file has a set of C functions which configure the simulation + and control execution.

+ +

Compiling the Programming Interface

+ +
+            compiling Python support into pytossim.o and tossim.o
+          g++ -c -shared -fPIC -o build/micaz/pytossim.o -g -O0 \
+          /home/pal/src/tinyos-2.x/tos/lib/tossim/tossim_wrap.cxx \
+          -I/usr/include/python2.3 -I/home/pal/src/tinyos-2.x/tos/lib/tossim \
+          -DHAVE_CONFIG_H
+          g++ -c -shared -fPIC -o build/micaz/tossim.o -g -O0 \
+          /home/pal/src/tinyos-2.x/tos/lib/tossim/tossim.c \
+          -I/usr/include/python2.3 -I/home/pal/src/tinyos-2.x/tos/lib/tossim
+        
+ +

The next step compiles the support for the C++ and Python + programming interfaces. The Python interface is actually built + on top of the C++ interface. Calling a Python object calls a + C++ object, which then calls TOSSIM through the C + interface. tossim.o contains the C++ code, while + pytossim.o contains the Python support. These files + have to be compiled separately because C++ doesn't understand + nesC, and nesC doesn't understand C++.

+ +

Building the shared object

+ +
+            linking into shared object ./_TOSSIMmodule.so
+          g++ -shared build/micaz/pytossim.o build/micaz/sim.o build/micaz/tossim.o -lstdc++ -o _TOSSIMmodule.so
+        
+ +

The next to last step is to build a shared library that + contains the TOSSIM code, the C++ support, and the Python + support.

+ +

Copying Python Support

+ +
+            copying Python script interface TOSSIM.py from lib/tossim to local directory
+        
+ +

Finally, there is the Python code that calls into the + shared object. This code exists in lib/tossim, and + the make process copies it into the local directory.

+ + +

Running TOSSIM with Python

+ +

Go into the RadioCountToLeds application and build + TOSSIM:

+ +
+$ cd tinyos-2.x/apps/RadioCountToLeds
+$ make micaz sim
+        
+ +

We'll start with running a simulation in Python. You can either + write a script and just tell Python to run it, or you can + use Python interactively. We'll start with the latter. Fire + up your Python interpreter:

+ +
+$ python
+        
+ +

You should see a prompt like this:

+ +
+Python 2.3.4 (#1, Nov  4 2004, 14:13:38)
+[GCC 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)] on linux2
+Type "help", "copyright", "credits" or "license" for more information.
+>>>
+        
+ +

The first thing we need to do is import TOSSIM and create a + TOSSIM object. Type

+ +
+>>> from TOSSIM import *
+>>> t = Tossim([])
+        
+ +

The square brackets are an optional argument that lets you + access variables in the simulation. We'll get to how to use + that later. In this case, we're telling TOSSIM that there are + no variables that we want to look at. The way you run a TOSSIM + simulation is with the runNextEvent function. For + example:

+ +
+>>> t.runNextEvent()
+0
+        
+ +

When you tell TOSSIM to run the next event, it returns + 0. This means that there was no next event to run. The reason + is simple: we haven't told any nodes to boot. This snippet of + code will tell mote 32 to boot at time 45654 and run its first + event (booting):

+ +
+>>> m = t.getNode(32);
+>>> m.bootAtTime(45654);
+>>> t.runNextEVent()
+1
+        
+ +

Instead of using raw simulation ticks, you can also use the + call ticksPerSecond(). However, you want to be careful + to add some random bits into this number: having every node + perfectly synchronized and only different in phase in terms of + seconds can lead to strange results.

+ +
+>>> m = t.getNode(32);
+>>> m.bootAtTime(4 * t.ticksPerSecond() + 242119);
+>>> t.runNextEVent()
+1
+      
+ +

Now, runNextEvent returns 1, because there was an + event to run. But we have no way of knowing whether the node + has booted or not. We can find this out in one of two ways. + The first is that we can just ask it:

+ +
+>>> m.isOn()
+1
+>>> m.turnOff()
+>>> m.isOn()
+0
+>>> m.bootAtTime(560000)
+>>> t.runNextEvent()
+0
+>>> t.runNextEvent()
+1
+        
+ +

Note that the first runNextEvent returned 0. This + is because when we turned the mote off, there was still an + event in the queue, for its next timer tick. However, since + the mote was off when the event was handled in that call, + runNextEvent returned 0. The second call to + runNextEvent returned 1 for the second boot event, at + time 560000.

+ + +

A Tossim object has several useful functions. In Python, + you can generally see the signature of an object with the + dir function. E.g.:

+ +
+>>> t = Tossim([])
+>>> dir(t)
+['__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__getattr__',
+'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
+'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
+'__swig_getmethods__', '__swig_setmethods__', '__weakref__', 'addChannel',
+'currentNode', 'getNode', 'init', 'mac', 'newPacket', 'radio', 'removeChannel',
+'runNextEvent', 'setCurrentNode', 'setTime', 'this', 'thisown', 'time', 'timeStr']
+        
+ +

The most common utility functions are:

+ + + +

The next section discusses the last two.

+ +

Debugging Statements

+ +

The second approach to know whether a node is on is to tell + it to print something out when it boots. TOSSIM has a + debugging output system, called dbg. There are four + dbg calls:

+ + + + +

Go into RadioCountToLedsC and modify the Boot.booted event + to print out a debug message when it boots, such as this:

+ +
+event void Boot.booted() {
+  call Leds.led0On();
+  dbg("Boot", "Application booted.\n");
+  call AMControl.start();
+}
+        
+ +

Calls to the debugging calls take two or more + parameters. The first parameter ("Boot" in the above example) + defines the output channel. An output channel is simply + a string. The second and subsequent parameters are the message + to output. They are identical to a printf statement. For example + RadioCountToLedsC has this call: + +

+event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len) {
+  dbg("RadioCountToLedsC", "Received packet of length %hhu.\n", len);
+  ...
+}
+        
+ + which prints out the length of received packet as an 8-bit unsigned value (%hhu).

+ +

Once you have added the debugging statement to the event, + recompile the application with make micaz sim and + start up your Python interpreter. Load the TOSSIM module and + schedule a mote to boot as before:

+ +
+>>> from TOSSIM import *
+>>> t = Tossim([])
+>>> m = t.getNode(32);
+>>> m.bootAtTime(45654);
+        
+ +

This time, however, we want to see the debugging message + that the mote has booted. TOSSIM's debugging output can be + configured on a per-channel basis. So, for example, you can + tell TOSSIM to send the "Boot" channel to standard output, but + another channel, say "AM", to a file. + By default, a channel has no destination, and so + messages to it are discarded.

+ +

In this case, we want to send the Boot channel to standard + output. To do this, we need to import the sys Python + package, which lets us refer to standard out. We can then tell + TOSSIM to send Boot messages to this destination: + +

+>>> import sys
+>>> t.addChannel("Boot", sys.stdout);
+1
+        
+ + The return value shows that the channel was added successfully. Run the first + simulation event, and the mote boots: + +
+>>> t.runNextEvent()
+DEBUG (32): Application booted.
+1
+        

+ +

The only difference between debug and error functions is + the string output at the beginning of a message. Debug + statements print DEBUG (n), while error statements + print ERROR (n).

+ +

A debugging statement can have multiple output + channels. Each channel name is delimited by commas: + +

+event void Boot.booted() {
+  call Leds.led0On();
+  dbg("Boot,RadioCountToLedsC", "Application booted.\n");
+  call AMControl.start();
+}
+          
+ + If a statement has multiple channels and those channels + share outputs, then TOSSIM only prints the message once. For + example, if both the Boot channel and RadioCountToLedsC + channel were connected to standard out, TOSSIM will only + print one message. For example, this series of debug statements + + +
+event void Boot.booted() {
+  call Leds.led0On();
+  dbg("Boot,RadioCountToLedsC", "Application booted.\n");
+  dbg("RadioCountToLedsC", "Application booted again.\n");
+  dbg("Boot", "Application booted a third time.\n");
+  call AMControl.start();
+}
+          
+ + when configured so + +
+>>> import sys
+>>> t.addChannel("Boot", sys.stdout)
+>>> t.addChannel("RadioCountToLedsC", sys.stdout)
+          
+ + will print out this: + +
+DEBUG (32): Application booted.
+DEBUG (32): Application booted again.
+DEBUG (32): Application booted a third time.
+          

+ + +

A channel can have multiple outputs. For example, this + script will tell TOSSIM to write RadioCountToLedsC messages to + standard output, but to write Boot messages to both standard + output and a file named log.txt: + +

+>>> import sys
+>>> f = open("log.txt", "w")
+>>> t.addChannel("Boot", f)
+>>> t.addChannel("Boot", sys.stdout)
+>>> t.addChannel("RadioCountToLedsC", sys.stdout)
+          
+

+ +

Configuring a Network

+ +

When you start TOSSIM, no node can communicate with any + other. In order to be able to simulate network behavior, you + have to specify a network topology. Internally, TOSSIM + is structured so that you can easily change the underlying + radio simulation, but that's beyond the scope of this + tutorial. The default TOSSIM radio model is signal-strength + based. You provide a graph to the simulator that describes the + propagation strengths. You also specify noise floor, and + receiver sensitivity. There are some very early results that + describe current sensor platforms (e.g., the mica2) in these + terms. Because all of this is through a scripting interface, + rather than provide a specific radio model, TOSSIM tries to + provide a few low-level primitives that can express a wide + range of radios and behavior.

+ +

You control the radio simulation through a Python Radio + object:

+ + +
+>>> from TOSSIM import *
+>>> t = Tossim([])
+>>> r = t.radio()
+>>> dir(r)
+['__class__', '__del__', '__delattr__', '__dict__', '__doc__',
+'__getattr__', '__getattribute__', '__hash__', '__init__',
+'__module__', '__new__', '__reduce__', '__reduce_ex__',
+'__repr__', '__setattr__', '__str__', '__swig_getmethods__',
+'__swig_setmethods__', '__weakref__', 'add', 'connected',
+'gain', 'remove', 'setNoise', 'this', 'thisown',
+]
+        
+ +

The first set of methods (with the double underscores) are + ones that you usually don't call. The important ones are at + the end. They are:

+ + + +

The Radio object only deals with physical layer + propagation. The MAC object deals with the data link layer, + packet lengths, and radio bandwidth. The default TOSSIM MAC + object is for a CSMA protocol. You get a reference to the MAC + object by calling mac() on a Tossim object: +

+>>> mac = t.mac()
+          
+ + The default MAC object has a large number of functions, for + controlling backoff behavior, packet preamble length, radio + bandwidth, etc. All time values are specified in terms of + radio symbols, and you can configure the number of symbols + per second and bits per symbol. By default, the MAC object + is configured to act like the standard TinyOS 2.0 CC2420 + stack: it has 4 bits per symbol and 64k symbols per second, + for 256kbps. This is a subset of the MAC functions that + could be useful for changing backoff behavior. Every + accessor function has a corresponding set function that + takes an integer as a parameter. E.g., there's int + initHigh() and void setInitHigh(int val). The + default value for each parameter is shown italicized in + parentheses.

+ + + +

Any and all of these configuration constants can be changed + at compile time with #define directives. Look at + tos/lib/tossim/sim_csma.h.

+ +

Because the radio connectivity graph can be scripted, you + can easily store topologies in files and then load the + file. Alternatively, you can store a topology as a script. + For example, this script will load a file which specifies each + link in the graph as a line with three values, the source, the + destination, and the gain, e.g.: + +

+1  2 -54.0
+          
+ + means that when 1 transmits 2 hears it at -54 dBm. Create a file topo.txt + that looks like this:

+ +
+1  2 -54.0
+2  1 -55.0
+1  3 -60.0
+3  1 -60.0
+2  3 -64.0
+3  2 -64.0
+        
+ +

This script will read such a file: + +

+>>> f = open("topo.txt", "r")
+>>> lines = f.readlines()
+>>> for line in lines:
+...   s = line.split()
+...   if (len(s) > 0):
+...     print " ", s[0], " ", s[1], " ", s[2];
+...     r.add(int(s[0]), int(s[1]), float(s[2]))
+          

+ + +

Now, when a node transmits a packet, other nodes will hear it. + This is a complete script for simulating packet transmission with + RadioCountToLedsC. Save it as a file test.py:

+
+from TOSSIM import *
+import sys
+
+t = Tossim([])
+r = t.radio()
+f = open("topo.txt", "r")
+
+lines = f.readlines()
+for line in lines:
+  s = line.split()
+  if (len(s) > 0):
+    print " ", s[0], " ", s[1], " ", s[2];
+    r.add(int(s[0]), int(s[1]), float(s[2]))
+
+t.addChannel("RadioCountToLedsC", sys.stdout)
+t.addChannel("Boot", sys.stdout)
+
+t.getNode(1).bootAtTime(100001);
+t.getNode(2).bootAtTime(800008);
+t.getNode(3).bootAtTime(1800009);
+
+r.setNoise(1, -100.0, 5.0)
+r.setNoise(2, -100.0, 5.0)
+r.setNoise(3, -100.0, 5.0)
+
+for i in range(0, 100):
+  t.runNextEvent()
+        
+ +

Run it by typing python test.py. You should see + output that looks like this:

+ +
+1  2 -54.0
+2  1 -55.0
+1  3 -60.0
+3  1 -60.0
+2  3 -64.0
+3  2 -64.0
+DEBUG (1): Application booted.
+DEBUG (1): Application booted again.
+DEBUG (1): Application booted a third time.
+DEBUG (2): Application booted.
+DEBUG (2): Application booted again.
+DEBUG (2): Application booted a third time.
+DEBUG (3): Application booted.
+DEBUG (3): Application booted again.
+DEBUG (3): Application booted a third time.
+DEBUG (1): RadioCountToLedsC: timer fired, counter is 1.
+DEBUG (1): RadioCountToLedsC: packet sent.
+DEBUG (2): RadioCountToLedsC: timer fired, counter is 1.
+DEBUG (2): RadioCountToLedsC: packet sent.
+DEBUG (3): RadioCountToLedsC: timer fired, counter is 1.
+DEBUG (3): RadioCountToLedsC: packet sent.
+DEBUG (1): Received packet of length 2.
+DEBUG (3): Received packet of length 2.
+DEBUG (2): Received packet of length 2.
+DEBUG (1): RadioCountToLedsC: timer fired, counter is 2.
+DEBUG (1): RadioCountToLedsC: packet sent.
+DEBUG (2): RadioCountToLedsC: timer fired, counter is 2.
+DEBUG (2): RadioCountToLedsC: packet sent.
+DEBUG (3): RadioCountToLedsC: timer fired, counter is 2.
+DEBUG (3): RadioCountToLedsC: packet sent.
+DEBUG (1): Received packet of length 2.
+        
+ +

If you set the noise to be 30 plus or minus 5 dBm instead + of 80 plus or minus 5 dBm, then nodes will never transmit, as + the default CCA threshold is -95 dBm. You'll see something + like this:

+
+1  2 -54.0
+2  1 -55.0
+1  3 -60.0
+3  1 -60.0
+2  3 -64.0
+3  2 -64.0
+DEBUG (1): Application booted.
+DEBUG (1): Application booted again.
+DEBUG (1): Application booted a third time.
+DEBUG (2): Application booted.
+DEBUG (2): Application booted again.
+DEBUG (2): Application booted a third time.
+DEBUG (3): Application booted.
+DEBUG (3): Application booted again.
+DEBUG (3): Application booted a third time.
+DEBUG (1): RadioCountToLedsC: timer fired, counter is 1.
+DEBUG (1): RadioCountToLedsC: packet sent.
+DEBUG (2): RadioCountToLedsC: timer fired, counter is 1.
+DEBUG (2): RadioCountToLedsC: packet sent.
+DEBUG (3): RadioCountToLedsC: timer fired, counter is 1.
+DEBUG (3): RadioCountToLedsC: packet sent.
+DEBUG (1): RadioCountToLedsC: timer fired, counter is 2.
+DEBUG (2): RadioCountToLedsC: timer fired, counter is 2.
+DEBUG (3): RadioCountToLedsC: timer fired, counter is 2.
+        
+ +

Because the nodes backoff perpetually, they never transmit + the packet and so subsequent attempts to send fail. Although + it only takes a few simulation events to reach the first timer + firings, it takes many simulation events (approximately 4000) + to reach the second timer firings. This is because the nodes + have MAC backoff events. If you want to simulate in terms of + time, rather than events, you can always do something like + this, which simulates 5 seconds from the first node boot:

+ +
+t.runNextEvent();
+time = t.time()
+while (time + 50000000000 > t.time()):
+  t.runNextEvent()
+
+ +

TOSSIM allows you to specify a network topology in terms of + gain. However, this raises the problem of coming up with a + topology. There are two approaches you can take. The first is + to take data from a real world network and input this into + TOSSIM. The second is to generate it from applying a + theoretical propagation model to a physical layout. The standard + file format is + +

+noise n avg std
+gain src dest g
+          
+ + where each statement is on a separate line. The noise + statement defines the noise observed at node n with + an average of avg and a standard deviation of + std. The gain statement defines a propagation + gain g when src transmits to dest. This + is a snippet of python code that will parse this file + format: + +
+f = open("mirage-1.txt", "r")
+
+lines = f.readlines()
+for line in lines:
+  s = line.split()
+  if (len(s) > 0):
+    if (s[0] == "gain"):
+      r.add(int(s[1]), int(s[2]), float(s[3]))
+    elif (s[0] == "noise"):
+      r.setNoise(int(s[1]), float(s[2]), float(s[3]))
+          

+ +

TOSSIM has a tool for the second option of generating a + network topology using a theoretical propagation model. The + tool is written in Java and is + net.tinyos.sim.PropagationModel. The tool takes a + single command line parameter, the name of a configuration + file, e.g.:

+ +
+java net.tinyos.sim.PropagationModel config.txt
+        
+ +

The format of a configuration file is beyond the scope of + this document: the tool has its own documentation. TOSSIM has two sample configuration + files generated from the tool in + tos/lib/tossim/topologies. The first is grid.txt, which is a 10x10 grid of nodes + spaced roughly 40 feet apart. Each node is placed randomly + within a 40'x40' "cell." The cells follow a strict grid. The + second file is scatter.txt, which is + 100 nodes scattered randomly (with a uniform distribution) + over a 360'x360' area. Note that the tool uses random numbers, + these configuration files can generate multiple different + network topologies. Network topology files generated from the + tool follow the same format as mirage-1.txt.

+ +

Variables

+ +

TOSSIM allows you to inspect variables in a running TinyOS + program. Currently, you can only inspect basic types. For + example, you can't look at fields of structs, but you can look + at state variables.

+ +

When you compile TOSSIM, the make system generates a large + XML file that contains a lot of information about the TinyOS + program, including every component variable and its type. If + you want to examine the state of your program, then you need + to give TOSSIM this information so it can parse all of the + variables properly. You do this by instantiating a Python + object that parses the XML file to extract all of the relevant + information. You have to import the Python support package for + TOSSIM to do this:

+ +
+from tinyos.tossim.TossimApp import *
+
+n = NescApp()
+        
+ +

Instantiating a NescApp can take quite a while: + Python has to parse through megabytes of XML. So be patient + (you only have to do it once). NescApp has two optional + arguments. The first is the name of the application being + loaded. The second is the XML file to load. The default for + the latter is app.xml, which is the name of the file + that the make system generates. The default for the former is + "Unknown App." So this code behaves identically to that + above:

+ +
+from tinyos.tossim.TossimApp import *
+
+n = NescApp("Unknown App", "app.xml")
+        
+ +

You fetch a list of variables from a NescApp object by + calling the function variables on the field + variables:

+ +
+vars = n.variables.variables()
+        
+ +

To enable variable inspection, you pass this list to a + Tossim object when you instantiate it:

+ +
+t = Tossim(vars)
+        
+ +

The TOSSIM object now knows the names, sizes, and types of + all of the variables in the TinyOS application. This + information allows the TOSSIM support code to take C variables + and properly tranform them into Python variables. This + currently only works for simple types: if a component declares + a structure, you can't access its fields. But let's say we + want to read the counter in RadioCountToLedsC. Since each mote + in the network has its own instance of the variable, we need + to fetch it from a specific mote:

+ +
+m = t.getNode(0)
+v = m.getVariable("RadioCountToLedsC.counter")
+        
+ +

The name of a variable is usually C.V, where + C is the component name and V is the variable. + In the case of generic components, the name is C.N.V, + where N is an integer that describes which instance. + Unfortunately, there is currently no easy way to know what + N is from nesC source, so you have to root through + app.c in order to know.

+ +

Once you have a variable object (v in the above + code), you can fetch its value with the getData() + function:

+ +
+counter = v.getData()
+        
+ +

Because getData() transforms the underlying C type + into a Python type, you can then use its return value in + Python expressions. For example, this script will start a + simulation of five nodes and run it until node 0's counter + reaches 10:

+ +
+from sys import *
+from random import *
+from TOSSIM import *
+from tinyos.tossim.TossimApp import *
+
+n = NescApp()
+t = Tossim(n.variables.variables())
+r = t.radio()
+
+f = open("topo.txt", "r")
+lines = f.readlines()
+for line in lines:
+  s = line.split()
+  if (len(s) > 0):
+    if (s[0] == "gain"):
+      r.add(int(s[1]), int(s[2]), float(s[3]))
+    elif (s[0] == "noise"):
+      r.setNoise(int(s[1]), float(s[2]), float(s[3]))
+
+for i in range (0, 4):
+  m = t.getNode(i)
+  m.bootAtTime(randint(1000, 2000) * 1000000)
+
+m = t.getNode(0)
+v = m.getVariable("RadioCountToLedsC.counter")
+
+while (v.getData() < 10):
+  t.runNextEvent()
+
+        
+ +

The TOSSIM examples + subdirectory also has an example script, named + variables.py.

+ +

Injecting Packets

+ +

TOSSIM allows you to dynamically inject packets into a + network. Packets can be scheduled to arrive at any time. If a + packet is scheduled to arrive in the past, then it arrives + immediately. Injected packets circumvent the radio stack: it is + possible for a node to receive an injected packet while it is in + the midst of receiving a packet from another node over its + radio.

+ +

TinyOS 2.0 has support for building Python packet objects. + Just like the standard Java toolchain, you can build a packet + class based on a C structure. The packet class gives you a full + set of packet field mutators and accessors. If an application + has a packet format, you can generate a packet class for it, + instantiate packet objects, set their fields, and have nodes + receive them.

+ +

The RadioCountToLeds application Makefile has an + example of how to do this. First, it adds the Python class as a + dependency for building the application. Whenever you compile + the app, if the Python class doesn't exist, make will build it + for you:

+ +
+BUILD_EXTRA_DEPS = RadioCountMsg.py RadioCountMsg.class
+      
+ +

The Makefile also tells make how to generate RadioCountMsg.py:

+ +
+RadioCountMsg.py: RadioCountToLeds.h
+        mig python -target=$(PLATFORM) $(CFLAGS) -python-classname=RadioCountMsg RadioCountToLeds.h RadioCountMsg -o $@
+      
+ +

The rule says to generate RadioCountMsg.py by calling mig + with the python parameter. The Makefile also has rules on how + to build Java class, but that's not important for TOSSIM. Since + we've been using RadioCountToLeds so far, the Python class + should be there already.

+ +

RadioCountMsg.py defines a packet format, but this packet is + contained in the data payload of another format. If a node is + sending a RadioCountMsg over AM, then the RadioCountMsg + structure is put into the AM payload, and might look something + like this:

+ +
+ + + + + + +
AM HeaderRadioCountMsgAM Footer
+
+ +

If it is sending it over a routing protocol. the packet is + put in the routing payload, and might look something like this:

+ +
+ + + + + + + +
AM HeaderRouting HeaderRadioCountMsgAM Footer
+
+ +

If you want to send a RadioCountMsg to a node, then you need + to decide how to deliver it. In the simple AM case, you place + the RadioCountMsg structure in a basic AM packet. In the routing + case, you put it in a routing packet, which you then put inside + an AM packet. We'll only deal with the simple AM case here.

+ +

To get an AM packet which you can inject into TOSSIM, you + call the newPacket function on a Tossim object. The + returned object has the standard expected AM fields: + destination, length, type, and data, + as well as strength.

+ +

To include support for a packet format, you must import + it. For example, to include RadioCountMsg, you have to import + it:

+ +
+from RadioCountMsg import *
+      
+ +

This snippet of code, for example, creates a RadioCountMsg, + sets its counter to 7, creates an AM packet, stores the + RadioCountMsg in the AM packet, and configures the AM packet so + it will be received properly (destination and type):

+ +
+from RadioCountMsg import *
+
+msg = RadioCountMsg()
+msg.set_counter(7);
+pkt = t.newPacket();
+pkt.setData(msg.data)
+pkt.setType(msg.get_amType())
+pkt.setDestination(0)
+      
+ + +

The variable pkt is now an Active Message of the AM + type of RadioCountMsg with a destination of 0 that contains a + RadioCountMsg with a counter of 7. You can deliver this packet + to a node with the deliver function. The + deliver function takes two parameters, the destination + node and the time to deliver:

+ +
+pkt.deliver(0, t.time() + 3)
+      
+ +

This call delivers pkt to node 0 at the current simulation + time plus 3 ticks (e.g., 3ns). There is also a + deliverNow, which has no time parameter. Note that if + the destination of pkt had been set to 1, then the + TinyOS application would not receive the packet, as it was + delivered to node 0.

+ +

Taken all together, the following script starts a simulation, + configures the topology based on topo.txt, and delivers a packet + to node 0. It can also be found as packets.py in the TOSSIM examples + subdirectory. + +

+import sys
+from TOSSIM import *
+from RadioCountMsg import *
+
+t = Tossim([])
+m = t.mac();
+r = t.radio();
+
+t.addChannel("RadioCountToLedsC", sys.stdout);
+t.addChannel("LedsC", sys.stdout);
+
+for i in range(0, 2):
+  m = t.getNode(i);
+  m.bootAtTime((31 + t.ticksPerSecond() / 10) * i + 1);
+  
+f = open("topo.txt", "r")
+lines = f.readlines()
+for line in lines:
+  s = line.split()
+  if (len(s) > 0):
+    if (s[0] == "gain"):
+      r.add(int(s[1]), int(s[2]), float(s[3]))
+    elif (s[0] == "noise"):
+      r.setNoise(int(s[1]), float(s[2]), float(s[3]))
+
+for i in range(0, 60):
+  t.runNextEvent();
+
+msg = RadioCountMsg()
+msg.set_counter(7);
+pkt = t.newPacket();
+pkt.setData(msg.data)
+pkt.setType(msg.get_amType())
+pkt.setDestination(0)
+
+print "Delivering " + msg.__str__() + " to 0 at " + str(t.time() + 3);
+pkt.deliver(0, t.time() + 3)
+
+
+for i in range(0, 20):
+  t.runNextEvent();
+      
+ + +

C++

+ +

Python is very useful because it is succinct, easy to write, + and can be used interactively. Interpretation, however, has a + significant cost: a Python/C transition on every event is a + significant cost (around 100%, so it runs at half the + speed). Additionally, it's often useful to step through code + with a standard debugger. TOSSIM also has support for C++, so + that it can be useful in these circumstances. Because many of + the Python interfaces are merely wrappers around C++ objects, + much of the scripting stays the same. The two major exceptions + are inspecting variables and injecting packets.

+ +

In a C++ TOSSIM, there is no variable inspection. While it is + possible to request memory regions and cast them to the expected + structures, currently there is no good and simple way to do + so. The Python support goes through several steps in order to + convert variables into Python types, and this gets in the way of + C++. However, as the purpose of C++ is usually to run high + performance simulations (in which inspecting variables is a big + cost) or debugging (when you have a debugger), this generally + isn't a big problem.

+ +

There is a C++ Packet class, which the Python + version is a simple wrapper around. In order to inject packets + in C++, however, you must build C support for a packet type and + manually build the packet. There currently is no support in mig + with which to generate C/C++ packet structures, and since most + packets are nx_struct types, they cannot be parsed by + C/C++. Furthermore, as many of the fields are nx types, they are + big endian, while x86 processors are little endian. Still, if you + want to deliver a packet through C++, you can do so.

+ +

Usually, the C++ and Python versions of a program look pretty + similar. For example:

+ + + + + + + + + +
PythonC++
+
+import TOSSIM
+import sys
+
+from RadioCountMsg import *
+
+t = TOSSIM.Tossim([])
+r = t.radio();
+
+for i in range(0, 999):
+  m = t.getNode(i);
+  m.bootAtTime(5000003 * i + 1);
+  r.setNoise(i, -99.0, 3.0);
+  for j in range (0, 2):
+    if (j != i):
+      r.add(i, j, -50.0);
+
+
+
+
+for i in range(0, 1000000):
+  t.runNextEvent();
+           
+
+
+#include <tossim.h>
+
+
+
+int main() {
+  Tossim* t = new Tossim(NULL);
+  Radio* r = t->radio();
+
+  for (int i = 0; i < 999; i++) {
+    Mote* m = t->getNode(i);
+    m->bootAtTime(5000003 * i + 1);
+    r->setNoise(i, -99.0, 3);
+    for (int j = 0; j < 2; j++) {
+      if (i != j) {
+        r->add(i, j, -50.0);
+      }
+    }
+  }
+
+  for (int i = 0; i < 1000000; i++) {
+    t->runNextEvent();
+  }
+}
+            
+
+ +

To compile a C++ TOSSIM, you have to compile the top-level + driver program (e.g, the one shown above) and link it against + TOSSIM. Usually the easiest way to do this is to link it against + the TOSSIM objects rather than the shared library. Often, it's + useful to have a separate Makefile to do this with. E.g., + Makefile.Driver:

+ +
+all:
+        make micaz sim
+        g++ -g -c -o Driver.o Driver.c -I../../tos/lib/tossim/
+        g++ -o Driver Driver.o build/micaz/tossim.o build/micaz/sim.o build/micaz/c-support.o
+      
+ + +

Using gdb

+ +

Since Driver is a C++ program, you can use gdb on it to + step through your TinyOS code, inspect variables, set + breakpoints, and do everything else you can normally do. + Unfortunately, as gdb is 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 redOff +command of the Leds interface of LedsC, one must type: + +

+$ gdb Driver
+GNU gdb Red Hat Linux (6.0post-0.20040223.19rh)
+Copyright 2004 Free Software Foundation, Inc.
+GDB is free software, covered by the GNU General Public License, and you are
+welcome to change it and/or distribute copies of it under certain conditions.
+Type "show copying" to see the conditions.
+There is absolutely no warranty for GDB.  Type "show warranty" for details.
+This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
+
+(gdb) break *LedsP$Leds$led0Toggle
+Breakpoint 1 at 0x804f184: file LedsP.nc, line 73.
+
+ +

nesC translates component names to C names using +$. $ is a legal but almost-never-used character in some versions +of C, so nesC prohibits it and uses it internally. The leading +* is necessary so dbg can parse the $s. With the above +breakpoint set, gdb will break whenever a mote toggles led0.

+ +

Variables have similar names. For example, to inspect the packet +of RadioCountToLedsC in the RadioCountToLeds application,

+ +
+(gdb) print RadioCountToLedsC$packet
+$1 = {{header = {{data = ""}, {data = ""}, {data = ""}, {data = ""}, {
+        data = ""}}, data = {{data = ""} }, footer = {{
+        data = ""}, {data = ""}}, metadata = {{data = ""}, {data = ""}, {
+        data = ""}, {data = ""}, {data = ""}}} }
+
+ +

For those who know gdb very well, you'll recognize this as a print +of an array, rather than a single variable: there are more than 1000 +instances of the message_t struct. This is because TOSSIM simulates +many motes; rather than there being a single RadioCountToLedsC$packet, +there is one for every node. To print the packet of a specific node, you +have to index into the array. This, for example, will print the variable +for node 6:

+ +
+(gdb) print RadioCountToLedsC$packet[6]
+$2 = {header = {{data = ""}, {data = ""}, {data = ""}, {data = ""}, {
+      data = ""}}, data = {{data = ""} }, footer = {{
+      data = ""}, {data = ""}}, metadata = {{data = ""}, {data = ""}, {
+      data = ""}, {data = ""}, {data = ""}}}
+
+ +

If you want to print out the variable for the node TOSSIM is currently +simulating, you can do this:

+ +
+(gdb) print RadioCountToLedsC$counter[sim_node()]
+$4 = 0
+
+ +

You can also set watchpoints (although, as to be expected, they are +slow:

+ +
+(gdb) watch UscGainInterferenceModelC$receiving[23]
+Hardware watchpoint 2: UscGainInterferenceModelC$receiving[23]
+
+ +

This variable happens to be an internal variable in the +packet-level network simulation, which keeps track of whether +the radio thinks it is receiving a packet. So setting the +above watchpoint will cause gdb to break whenever +node 23 starts receiving a packet or returns to searching +for packet preambles.

+ +

Generic components add another wrinkle. Since they use +a code-copying approach, each instance of a generic has its +own separate functions and variables (this is mostly due to the +fact that you can pass types to them). Take, for example, +AMQueueImplP, which is used in both the radio +AM stack and the serial AM stack. If you use gdb on an +application that uses both serial and radio communication and +try to break on its Send.send, you'll see an error:

+ +
+(gdb) break *AMQueueImplP$Send$send
+No symbol "AMQueueImplP$Send$send" in current context.
+
+ +

nesC gives each generic a unique number. So if you +have an application in which there is a single copy +of AMQueueImplP, its name will actually be AMQueueImplP$0. +For example, in RadioCountToLeds, this will work:

+ +
+(gdb) break *AMQueueImplP$0$Send$send
+Breakpoint 5 at 0x8051b29: file AMQueueImplP.nc, line 79.
+
+ +

If you have multiple instances of a generic in a +program, there is unfortunately no easy way to figure out each one's +name besides looking at the source code or stepping into them. +E.g., if you application uses serial and radio communication, +knowing which stack has AMQueueImpl$0 and which has AMQueueImplP$1 +requires either stepping through their send operation or looking +at their app.c files. +

+ +

Conclusions

+ +This lesson introduced the basics of the TOSSIM simulator. It showed +you how to configure a network, how to run a simulation, how to +inspect variables, how to inject packets, and how to compile with C++. + +
+

Previous LessonTop  |  Next +Lesson  > +

+

+ + +

Appendix A: Troubleshooting TOSSIM compilation

+ +

TOSSIM is a C/C++ shared library with an optional + Python translation layer. Almost all of the problems + encountered in compiling TOSSIM are due to C linking + issues. If you don't know what a linker is (or have never + linked a C program), then chances are the rest of this + appendix is going to be cryptic and + incomprehensible. You're best off starting with learning + about linkers, why they + are needed, and how you use the + gcc/g++ compilers to link code.

+ + +

Generally, when compiling TOSSIM using make micaz sim, + one of four things can go wrong:

+ +
    +
  1. You are using Cygwin but the sim compilation option + can't figure this out.
  2. + +
  3. You do not have the needed Python support installed.
  4. + +
  5. You have Python support installed, but the make + system can't find it.
  6. + +
  7. You have Python support installed, but it turns out to + be incompatible with TOSSIM.
  8. + +
  9. You have a variant of gcc/g++ installed that + expects slightly different compilation options than the + normal installation.
  10. +
+ +

We'll visit each in turn.

+ +

You are using Cygwin but the sim compilation option + can't figure this out

+ +

It turns out that the Cygwin and Linux versions of gcc/g++ + have different command-line flags and require different options + to compile TOSSIM properly. For example, telling the Linux + compiler to build a library requires -fPIC while + the Cygwin is -fpic. If you're using Cygwin and + you see the output look like this: + +

+  ncc -c -shared -fPIC -o build/micaz/sim.o ...
+	      
+ + rather than + +
+  ncc -c -DUSE_DL_IMPORT -fpic -o build/micaz/sim.o ...
+	      
+ + then you have encountered this problem. The problem + occurs because Cygwin installations do not have a + consistent naming scheme, and so it's difficult for the + compilation toolchain to always figure out whether it's + under Linux or Cygwin.

+ +

Symptom: You're running cygwin but you see the + -fPIC rather than -fpic option being + passed to the compiler.

+ +

Solution: Explicitly set the OSTYPE environment + variable to be cygwin either in your .bashrc + or when you compile. For example, in bash:

+ +
+$ OSTYPE=cygwin make micaz sim
+	    
+ + or in tcsh + +
+$ setenv OSTYPE cygwin
+$ make micaz sim
+	    
+ +

Note that often this problem occurs in addition to + other ones, due to using a nonstandard Cygwin + installation. So you might have more problems to track + down.

+ +

You do not have the needed Python support installed

+ +

If when you compile you see lots of errors such as + "undefined reference to" or "Python.h: No such file or + directory" then this might be your problem. It is a + subcase of the more general problem of TOSSIM not being + able to find needed libraries and files.

+ +

Compiling Python scripting support requires that you + have certain Python development libraries installed. First, check + that you have Python installed:

+ +
+$ python -V
+Python 2.4.2
+	    
+ +

In the above example, the system has Python 2.4.2. If + you see "command not found" then you do not have Python + installed. You'll need to track down an RPM and install + it. TOSSIM has been tested with Python versions 2.3 and + 2.4. You can install other versions, but there's no + assurance things will work.

+ +

In addition to the Python interpreter itself, you need + the libraries and files for Python development. This is + essentially a set of header files and shared libraries. If + you have the locate command, you can type + locate libpython, or if you don't, you can look + in /lib, /usr/lib and + /usr/local/lib. You're looking for a file with a + name such as libpython2.4.so and a file named + Python.h. If you can't find these files, then you + need to install a python-devel package.

+ + +

Symptom: Compilation can't find critical files + such as the Python interpreter, Python.h or a + Python shared library, and searching your filesystem shows + that you don't have them.

+ +

Solution: Installed the needed files from Python + and/or Python development RPMS.

+ +

If you have all of the needed files, but are still + getting errors such as "undefined reference" or "Python.h: + No such file or directory", then you have the next + problem: they're on your filesystem, but TOSSIM can't find + them.

+ +

You have Python support installed, but the make + system can't find it

+ +

You've found libpython and Python.h, but when TOSSIM compiles + it says that it can't find one or both of them. If it can't + find Python.h then compilation will fail pretty early, as g++ won't + be able to compile the Python glue code. If it can't find the python + library, then compilation will fail at linking, and you'll see + errors along the lines of "undefined reference to __Py...". You + need to point the make system at the right place.

+ +

Open up support/make/sim.extra. If the make + system can't find Python.h, then chances are it isn't in + one of the standard places (e.g., /usr/include). You need to tell + the make system to look in the directory where Python.h is with + a -I option. At the top of sim.extra, under the PFLAGS entry, + add + +

+CFLAGS += -I/path
+	    
+ + where /path is the path of the directory where Python.h + lives. For example, if it is in /opt/python/include, + then add CFLAGS += -I/opt/python/include.

+ +

If the make system can't find the python library for + linking (causing "undefined reference") error messages, + then you need to make sure the make system can find + it. The sim.extra file uses two variables to find the + library: PYDIR and PYTHON_VERSION. It + looks for a file named libpython$(PYTHON_VERSION).so. So + if you have Python 2.4 installed, make sure that + PYTHON_VERSION is 2.4 (be sure to use no spaces!) and if + 2.3, make sure it is 2.3.

+ +

Usually the Python library is found in + /usr/lib. If it isn't there, then you will need + to modify the PLATFORM_LIB_FLAGS variable. The + -L flag tells gcc in what directories to look for + libraries. So if libpython2.4.so is in + /opt/python/lib, then add + -L/opt/python/lib to the + PLATFORM_LIB_FLAGS. Note that there are three + different versions of this variable, depending on what OS + you're using. Be sure to modify the correct one (or be + paranoid and modify all three). + + +

Symptom: You've verified that you have the + needed Python files and libraries, but compilation is + still saying that it can't link to them ("undefined + reference") or can't find them ("cannot find -lpython2.4").

+ +

Solution: Change the sim.extra file to point to + the correct directories using -L and -I flags.

+ +

You have Python support installed, but it turns out to + be incompatible with TOSSIM.

+ +

Symptom: You get a "This python version requires + to use swig with the -classic option" error message.

+ +

Solution: Install SWIG and regenerate Python + support with the sing-generate script in + tos/lib/tossim, or install a different version of + Python.

+ +

You have a variant of gcc/g++ installed that + expects slightly different compilation options than the + normal installation.

+ +

Symptom: g++ complains that it cannot find + main() when you are compiling the shared library + ("undefined reference to `_WinMain@16'").

+ +

Solution: There are two possible solutions. + The first is to include a dummy main(), as described + in this tinyos-help posting. The + second is to add the -shared option, as described in + this web page. + +

Hopefully, these solutions worked and you can get back + to compiling, If not, then you + should email tinyos-help.

+ + + + diff --git a/doc/html/upgrade-tinyos.html b/doc/html/upgrade-tinyos.html index b74fd6a8..df4fcb77 100644 --- a/doc/html/upgrade-tinyos.html +++ b/doc/html/upgrade-tinyos.html @@ -8,7 +8,7 @@
Upgrading from TinyOS 1.x to TinyOS 2.x
-
Last updated 8 April 2007
+
Last updated 1 May 2007

This document describes how to upgrade your TinyOS 1.x environment to a TinyOS 2.x environment. This requires that you not only install the @@ -233,8 +233,8 @@ recommend removing it before installing the new one with a forced install.

TinyOS - tinyos-2.0.0-3.cygwin.noarch.rpm - tinyos-2.0.0-3.noarch.rpm + tinyos-2.0.1-5.cygwin.noarch.rpm + tinyos-2.0.1-5.noarch.rpm rpm -Uvh (to upgrade)
rpm -ivh (to install)
rpm -ivh --force (to force install)
diff --git a/doc/index.html b/doc/index.html index df424bff..bf256ffa 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,4 +1,4 @@ -1 + TinyOS 2.0 Documentation @@ -11,12 +11,12 @@ TinyOS 2.0 Documentation
-
Last Modified: April 19 20067
+
Last Modified: April 19 2007
-

TinyOS 2.0 has four sets of documentation. The first +

TinyOS 2.0 has three sets of documentation. The first set is the release notes and high-level overviews of the system. The second set is a series of tutorials and a TinyOS programming manual, which explore different parts @@ -28,7 +28,7 @@ documentation.

If you're just getting started, the best place to start - is with the tutorials.<.p> + is with the tutorials.

@@ -133,7 +133,7 @@ - TinyOS Java toolchain Code Documentation + 3C. TinyOS Java toolchain Code Documentation -- 2.39.2