-\r
-<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">\r
-<html>\r
-<head>\r
- <title>Installing TinyOS 2.0</title>\r
- <link href="../stylesheets/tutorial.css" rel="stylesheet" type="text/css">\r
-</head>\r
-<body>\r
-\r
-<div class="title">Installing TinyOS 2.0</div>\r
-<div class="subtitle">Last updated 12 June 2006</div>\r
-\r
-<p>If you already have a 1.x tree, you are better off following the <i>upgrade</i> \r
-instructions at <a href="upgrade-tinyos.html">upgrade-tinyos.html</a>.\r
-\r
-<p>Currently, the TinyOS Core Working Group supports TinyOS on two platforms: Cygwin (Windows)\r
-and Linux. There have been some <A HREF="">successful efforts</A> to getting TinyOS environments working\r
-on Mac OSX, but OSX is not supported by the Core WG.</p>\r
-\r
-<p>Installing a TinyOS enviromnent has four basic steps; Windows requires an extra step,\r
-installing Cygwin, which is a UNIX-like environment. The steps are:</p>\r
-\r
-<ol>\r
- <li><b>Installing a Java 1.5 (Java 5) JDK.</b> Java is the most common way of interacting\r
- with mote base stations or gateways that are plugged into a PC or laptop.</li>\r
- <li><b><font color=red>Windows only.</font> Install Cygwin.</b> This gives you a shell\r
- and many UNIX tools which the TinyOS environment uses, such as perl and shell\r
- scripts.</li>\r
- <li><b>Installing native compilers.</b> As you're compiling code for low-power\r
- microcontrollers, you need compilers that can generate the proper assembly code.\r
- If you using mica-family motes, you need the AVR toolchain; if you're using\r
- telos-family motes, you need the MSP430 toolchain.</li>\r
- <li><b>Installing the nesC compiler.</b> TinyOS is written in nesC, a dialect\r
- of C with support for the TinyOS concurrency model and component-based\r
- programming. The nesC compiler is platform-independent: it passes its output\r
- to the native compilers, so that it can take advantage of all of the effort\r
- put into their optimizations.</li>\r
- <li><b>Installing the TinyOS source tree.</b> If you want to compile and\r
- install TinyOS programs, you need the code.</li>\r
- <li><b>Installing the Graphviz visualization tool.</b> The TinyOS\r
- environment includes <tt>nesdoc</tt>, a tool that automatically\r
- generates HTML documentation from source code. Part of this process\r
- involves drawing diagrams that show the relationships between\r
- different TinyOS components. <A HREF="http://www.graphviz.org">Graphviz</A>\r
- is an open source tool\r
- that nesdoc uses to draw the diagrams.</li>\r
-</ol>\r
-\r
-<h1>Step 1: Install Java 1.5 JDK</h1>\r
-\r
-<b>Windows</b><br>\r
-Download and install Sun's 1.5 JDK from <a href="http://java.sun.com">http://java.sun.com</a>.\r
-\r
-<p>\r
-<b>Linux</b><br>\r
-Download and install IBM's 1.5 JDK from <a href="http://www-128.ibm.com/developerworks/java/jdk/">http://www-128.ibm.com/developerworks/java/jdk/</a>.\r
-\r
-<h1>Step 2: Install Cygwin</h1>\r
-\r
-<font color=red> This step is required for Windows installations only. If you are installing\r
-on Linux, skip to step 3.</font>\r
-\r
-<p>We have put online the cygwin packages that we've confirmed to be\r
-compatible with TinyOS. The instructions below use those packages. You\r
-can also upgrade your cygwin environment according to the instructions\r
-at www.cygwin.com and your environment will most likely work. A large\r
-number of TinyOS users, upgrade their cygwin packages at least monthly\r
-from cygnus. However, since we can't test what packages are compatible\r
-as they become available daily, we can't confirm that today's set will\r
-work.\r
-\r
-<p>\r
-<ol>\r
-<li> Download the confirmed-compatible cygwin packages from the tinyos web site <a href="http://www.tinyos.net/dist-1.2.0/tools/windows/cygwin-1.2a.tgz">here</a>.\r
-<p>\r
-<li> In a cygwin shell, unzip the above package into some directory. In these instructions the directory is /cygdrive/c/newcygpkgs.\r
-<pre>\r
- $ cd /cygdrive/c/newcygpkgs\r
- $ tar zxvf cygwin-1.2a.tgz \r
-</pre>\r
-This unzips the packages.\r
-<p>\r
-<li> In Windows Explorer, navigate to /cygdrive/c/newcygpkgs and click on the file setup.exe. Setup.exe is the setup program distributed by Cygnus Solutions.\r
-<p>\r
-<li> Follow these steps when the Cygwin Setup windows appears:\r
-<ol>\r
-</ol>\r
-<li> Opt to disable the virus scanner (it will be enabled when you're finished).\r
-<p>\r
-<li> Opt to Install from Local Directory.\r
-<p>\r
-<li> Specify the Root directory to be where your <i>current</i> cygwin installation is. This would be the directory that directories like 'opt' and 'usr' are in. For example, mine is rooted at c:\tinyos\cygwin, so I enter that. \r
-<p>\r
-<li> Select to Install for All Users\r
-<p>\r
-<li> Select the Unix file type (very important!)\r
-<p>\r
-<li> For the Local Packages Directory, specify where you unzipped the cygwin packages tarfile. For example, I would specify c:\newcygpkgs. (The setup.exe program will probably select the right default directory.)\r
-<p>\r
-<li> The next window will allow you to select packages to install. You should see that most of the packages have an X-ed box next to them; these are the packages that are to be installed. \r
-<p>\r
-<li> Click install. Some notes: \r
-<ul>\r
-<li> You might see a message explaining that you need to reboot because some files are in use. This most likely means that your cygwin DLL is loaded and in-use and, therefore, cannot be replaced. When you reboot, the new DLL will be loaded. \r
-<li> Related to the above warnings, if you see warnings about the cygwin1.dll not being found, don't worry. All will be well once you reboot and the right DLL is loaded. \r
-</ul>\r
-</ol>\r
-</ol>\r
-\r
-<h1>Step 3: Install native compilers </h1>\r
-\r
-Install the appropriate version of the following (Windows or Linux,\r
-avr or msp430 or both) with the rpm command 'rpm -ivh <rpm>'. \r
-On\r
-windows, if you get an error claiming that the rpm was build for an NT\r
-computer and you're on a windows NT computer, bypass the erroneous\r
-error by using 'rpm -ivh --ignoreos <i>rpmname</i>'.\r
-(We have xscale\r
-compiler tools online at \r
-<a href="http://www.tinyos.net/dist-1.2.0/tools/">http://www.tinyos.net/dist-1.2.0/tools/</a>\r
-but they have not yet been extensively tested by a large community.)\r
-\r
-<!----- AVR external tools -------->\r
-</p><p><b><em>Atmel AVR Tools</em></b>\r
-<table border="0">\r
-<tbody><tr>\r
- <td bgcolor="#dddddd"><b>Tool</b></td>\r
- <td bgcolor="#dddddd"><b>Windows/Cygwin</b></td>\r
- <td bgcolor="#dddddd"><b>Linux</b></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>avr-binutils<font color="red">†</font></td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/avr-binutils-2.15tinyos-3.cygwin.i386.rpm">avr-binutils-2.15tinyos-3.cygwin.i386.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avr-binutils-2.15tinyos-3.i386.rpm">avr-binutils-2.15tinyos-3.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td bgcolor="#dddddd">avr-gcc</td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/avr-gcc-3.4.3-1.cygwin.i386.rpm">avr-gcc-3.4.3-1.cygwin.i386.rpm </a></td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avr-gcc-3.4.3-1.i386.rpm">avr-gcc-3.4.3-1.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>avr-libc</td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/avr-libc-1.2.3-1.cygwin.i386.rpm">avr-libc-1.2.3-1.cygwin.i386.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avr-libc-1.2.3-1.i386.rpm">avr-libc-1.2.3-1.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td bgcolor="#dddddd">avarice</td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/avarice-2.4-1.cygwin.i386.rpm">avarice-2.4-1.cygwin.i386.rpm</a></td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avarice-2.4-1.i386.rpm">avarice-2.4-1.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>insight (avr-gdb)</td>\r
- <td><a href="http://www.tinyos.net/dist-1.2.0/tools/windows/avr-insight-6.3-1.cygwin.i386.rpm">avr-insight-6.3-1.cygwin.i386.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avr-insight-6.3-1.i386.rpm">avr-insight-6.3-1.i386.rpm</a></td>\r
-</tr>\r
-\r
-</tbody></table>\r
-<i><font color="red">†</font>If you receive an rpm error that indicates that you have a newer version already installed, try <code>rpm -Uvh --force</code></i>\r
-\r
-<!----- MSP external tools -------->\r
-</p><p><b><em>TI MSP430 Tools</em></b>\r
-<table border="0">\r
-<tbody><tr>\r
- <td bgcolor="#dddddd"><b>Tool</b></td>\r
- <td bgcolor="#dddddd"><b>Windows/Cygwin</b></td>\r
- <td bgcolor="#dddddd"><b>Linux</b></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>base</td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-base-0.1-20050607.cygwin.i386.rpm">msp430tools-base-0.1-20050607.cygwin.i386.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-base-0.1-20050607.i386.rpm">msp430tools-base-0.1-20050607.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td bgcolor="#dddddd">python tools</td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-python-tools-1.0-1.cygwin.noarch.rpm">msp430tools-python-tools-1.0-1.cygwin.noarch.rpm</a></td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-python-tools-1.0-1.noarch.rpm">msp430tools-python-tools-1.0-1.noarch.rpm</a></td>\r
-</tr>\r
-\r
-\r
-<tr>\r
- <td>binutils</td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-binutils-2.16-20050607.cygwin.i386.rpm"> msp430tools-binutils-2.16-20050607.cygwin.i386.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-binutils-2.16-20050607.i386.rpm">msp430tools-binutils-2.16-20050607.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td bgcolor="#dddddd">gcc</td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-gcc-3.2.3-20050607.cygwin.i386.rpm">msp430tools-gcc-3.2.3-20050607.cygwin.i386.rpm</a></td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-gcc-3.2.3-20050607.i386.rpm">msp430tools-gcc-3.2.3-20050607.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>libc</td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-libc-20050308cvs-20050608.cygwin.i386.rpm">msp430tools-libc-20050308cvs-20050608.cygwin.i386.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-libc-20050308cvs-20050608.i386.rpm">msp430tools-libc-20050308cvs-20050608.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td bgcolor="#dddddd">jtag</td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/"></a>Not yet available</td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-jtag-lib-20031101cvs-20050610.i386.rpm">msp430tools-jtag-lib-20031101cvs-20050610.i386.rpm</a></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>gdb</td>\r
-<!-- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-gdb-6.0-20050609.cygwin.i386.rpm">msp430tools-gdb-6.0-20050609.cygwin.i386.rpm</a></td> -->\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/"></a>Not yet available</td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-gdb-6.0-20050609.i386.rpm">msp430tools-gdb-6.0-20050609.i386.rpm</a></td>\r
-</tr>\r
-\r
-</tbody></table>\r
-\r
-<h1>Step 4: Install TinyOS toolchain</h1>\r
-\r
-The TinyOS-specific tools are the NesC compiler and a set of tools\r
-developed in the tinyos-2.x/tools source code repository. They are\r
-also installed using rpms. If you using the Cygwin version recommended\r
-in these install\r
-instructions, you should install the "Recommended" Windows/Cygwin\r
-nesC RPM (1.2.7b). If you install it and it does not work (e.g., you\r
-get strange errors when you try to execute it), this may be due\r
-to a Cygwin version incompatibility: try the "Other" Windows/Cygwin \r
-RPM (1.2.7a). \r
-\r
-<!----- tinyos-2.x/tinyos rpms -------->\r
-</p><p><b><em>TinyOS-specific Tools</em></b>\r
-<table border="0">\r
-<tbody><tr>\r
- <td bgcolor="#dddddd"><b>Tool</b></td>\r
- <td bgcolor="#dddddd"><b>Recommended Windows/Cygwin</b></td>\r
- <td bgcolor="#dddddd"><b>Other Windows/Cygwin</b></td>\r
- <td bgcolor="#dddddd"><b>Linux</b></td>\r
- <td bgcolor="#dddddd"><b>Command</b></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>NesC</td>\r
- <td><a href="http://csl.stanford.edu/~pal/tinyos/nesc-1.2.7b-1.cygwin.i386.rpm">nesc-1.2.7b-1.cygwin.i386.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-1.2.0/tinyos/windows/nesc-1.2.7a-1.cygwin.i386.rpm">nesc-1.2.7a-1.cygwin.i386.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-1.2.0/tinyos/linux/nesc-1.2.7a-1.i386.rpm">nesc-1.2.7a-1.i386.rpm </a></td>\r
- <td><a href=""></a><code>rpm -Uvh</code></td>\r
-</tr>\r
-\r
-<tr>\r
- <td bgcolor="#dddddd">tinyos-tools</td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-tools-1.2.2-1.cygwin.i386.rpm">tinyos-tools-1.2.2-1.cygwin.i386.rpm</a></td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-tools-1.2.2-1.cygwin.i386.rpm">tinyos-tools-1.2.2-1.cygwin.i386.rpm</a></td>\r
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/linux/tinyos-tools-1.2.2-1.i386.rpm">tinyos-tools-1.2.2-1.i386.rpm</a></td>\r
- <td bgcolor="#dddddd"><a href=""></a><code>rpm -ivh --force</code> (1.x tree)<br><code>rpm -Uvh</code> (no 1.x tree)<br></td>\r
-</tr>\r
-\r
-</tbody></table>\r
-\r
-<h1>Step 5: Install the TinyOS 2.x source tree </h1>\r
-\r
-Now that the tools are installed, you need only install the tinyos 2.x \r
-source tree and then set your environment variables.\r
-Install the appropriate version of the following (Window or Linux)\r
-with the rpm command 'rpm -ivh <rpm>'. \r
-As with the previous rpms, if you get an error claiming that the rpm\r
-was build for an NT computer and you're on a windows NT computer,\r
-bypass the erroneous error by using 'rpm -ivh --ignoreos\r
-<i>rpmname</i>'.\r
-\r
-<ul>\r
-<li> Install tinyos-2.x\r
-<p>\r
-<!----- TinyOS -------->\r
-\r
-\r
-</p><p><b><em>TinyOS 2.x</em></b>\r
-<table border="0">\r
-<tbody><tr>\r
- <td bgcolor="#dddddd"><b></b></td>\r
- <td bgcolor="#dddddd"><b>Windows/Cygwin</b></td>\r
- <td bgcolor="#dddddd"><b>Linux</b></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>TinyOS</td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-2.0.0beta2-3.cygwin.noarch.rpm">tinyos-2.0.0beta2-3.cygwin.noarch.rpm</a></td>\r
- <td><a href="http://www.tinyos.net/dist-2.0.0/tinyos/linux/tinyos-2.0.0beta2-3.noarch.rpm">tinyos-2.0.0beta2-3.noarch.rpm</a></td>\r
-</tr>\r
-\r
-</tbody></table>\r
-</p></li><li> Configure your environment\r
-<p>\r
-Ideally, you'll put these environment variables in a shell script that will run when your shell starts, but you needn't \r
-put such a script under /etc/profile.d. \r
-</p><p>\r
-The example\r
-settings below assume that the tinyos-2.x installation is in /opt/tinyos-2.x.\r
-Change the settings to be correct for where you've put your tinyos-2.x tree. Note\r
-that the windows CLASSPATH must be a windows-style path, not a cygwin path. You can \r
-generate a windows style path from a cygwin-style path using 'cygpath -w'. For example:\r
-</p><pre>export CLASSPATH=`cygpath -w $TOSROOT/support/sdk/java/tinyos.jar`\r
-export CLASSPATH="$CLASSPATH;."\r
-</pre>\r
-\r
-<p><b><em>TinyOS 2.x</em></b>\r
-<table border="0">\r
-<tbody><tr>\r
- <td bgcolor="#dddddd"><b>Environment Variable</b></td>\r
- <td bgcolor="#dddddd"><b>Windows</b></td>\r
- <td bgcolor="#dddddd"><b>Linux</b></td>\r
-</tr>\r
-\r
-<tr>\r
- <td>TOSROOT</td>\r
- <td>/opt/tinyos-2.x</td>\r
- <td>same as in Cygwin</td>\r
-<td>\r
-\r
-</td></tr><tr>\r
- <td bgcolor="#dddddd">TOSDIR</td>\r
- <td bgcolor="#dddddd">$TOSROOT/tos</td>\r
- <td bgcolor="#dddddd">same as in Cygwin</td>\r
-<td>\r
-\r
-</td></tr><tr>\r
- <td>CLASSPATH</td>\r
- <td>C:\tinyos\cygwin\opt\tinyos-2.x\support\sdk\java\tinyos.jar;.</td>\r
- <td>$TOSROOT/support/sdk/java/tinyos.jar:.</td>\r
-<td>\r
-\r
-</td></tr><tr>\r
- <td bgcolor="#dddddd">MAKERULES</td>\r
- <td bgcolor="#dddddd">$TOSROOT/support/make/Makerules</td>\r
- <td bgcolor="#dddddd">same as in Cygwin</td>\r
-<td>\r
-\r
-</td></tr><tr>\r
- <td>PATH<font color="red">†</font></td>\r
- <td>/opt/msp430/bin:$PATH</td>\r
- <td>same as in Cygwin</td>\r
-<td>\r
-\r
-</td></tr></tbody></table>\r
-\r
-<i><font color="red">†</font>Only necessary if you're using the MSP430 platform/tools.</i>\r
-\r
-</p><p>\r
-In addition to the above environment variables, do the following on Linux machines:\r
-</p><ol>\r
-<li> Change the ownership on your /opt/tinyos-2.x files: <code>chown -R <your uid> /opt/tinyos-2.x\r
-</code></li><li> Change the permissions on any serial (/dev/ttyS<N>), usb\r
-(/dev/tts/usb<N>, /dev/ttyUSB<N>), or parallel (/dev/parport) devices you\r
-are going to use: <code>chmod 666 /dev/<devicename><code>\r
-<!-- \r
-<li> Add any users who will be using TinyOS to the uucp, lp, and lock \r
-groups: </li>\r
--->\r
-</code></code></li></ol>\r
-\r
-</li></ul>\r
-\r
-<h1>Step 6: Installing Graphviz</h1>\r
-\r
-<p>Go to <A HREF="http://www.graphviz.org/Download..php">download page</A> of the Graphviz project\r
-and download the appropriate RPM. You only need the basic graphviz RPM (<tt>graphviz-</tt>);\r
-you don't need all of the add-ons, such as -devel, -doc, -perl, etc.\r
-If you're not sure what version of Linux you're running,</p>\r
-\r
-<pre>uname -a</pre>\r
-\r
-<p>might give you some useful information. Install the rpm with <tt>rpm -i </tt> <i>rpm-name</i>.\r
-In the case of Windows, there is a simple install program, so you don't need to deal with RPMs.</p>\r
-\r
-</body>\r
-</html>\r
+
+<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <title>Installing TinyOS 2.0</title>
+ <link href="../stylesheets/tutorial.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+
+<div class="title">Installing TinyOS 2.0</div>
+<div class="subtitle">Last updated 5 November 2006</div>
+
+<p>If you already have a 1.x tree or an existing 2.x tree, you are better off
+following the <i>upgrade</i> instructions at
+<a href="upgrade-tinyos.html">upgrade-tinyos.html</a>.</p>
+
+<p>Currently, the TinyOS Core Working Group supports TinyOS on two platforms: Cygwin (Windows)
+and Linux. There have been some <A HREF="">successful efforts</A> to getting TinyOS environments working
+on Mac OSX, but OSX is not supported by the Core WG.</p>
+
+<p>Installing a TinyOS enviromnent has five basic steps; Windows requires an extra step,
+installing Cygwin, which is a UNIX-like environment. The steps are:</p>
+
+<ol>
+ <li><b>Installing a Java 1.5 (Java 5) JDK.</b> Java is the most common way of interacting
+ with mote base stations or gateways that are plugged into a PC or laptop.</li>
+ <li><b><font color=red>Windows only.</font> Install Cygwin.</b> This gives you a shell
+ and many UNIX tools which the TinyOS environment uses, such as perl and shell
+ scripts.</li>
+ <li><b>Installing native compilers.</b> As you're compiling code for low-power
+ microcontrollers, you need compilers that can generate the proper assembly code.
+ If you using mica-family motes, you need the AVR toolchain; if you're using
+ telos-family motes, you need the MSP430 toolchain.</li>
+ <li><b>Installing the nesC compiler.</b> TinyOS is written in nesC, a dialect
+ of C with support for the TinyOS concurrency model and component-based
+ programming. The nesC compiler is platform-independent: it passes its output
+ to the native compilers, so that it can take advantage of all of the effort
+ put into their optimizations.</li>
+ <li><b>Installing the TinyOS source tree.</b> If you want to compile and
+ install TinyOS programs, you need the code.</li>
+ <li><b>Installing the Graphviz visualization tool.</b> The TinyOS
+ environment includes <tt>nesdoc</tt>, a tool that automatically
+ generates HTML documentation from source code. Part of this process
+ involves drawing diagrams that show the relationships between
+ different TinyOS components. <A HREF="http://www.graphviz.org">Graphviz</A>
+ is an open source tool
+ that nesdoc uses to draw the diagrams.</li>
+</ol>
+
+<h1>Step 1: Install Java 1.5 JDK</h1>
+
+<b>Windows</b><br>
+Download and install Sun's 1.5 JDK from <a href="http://java.sun.com">http://java.sun.com</a>.
+
+<p>
+<b>Linux</b><br>
+Download and install IBM's 1.5 JDK from <a href="http://www-128.ibm.com/developerworks/java/jdk/">http://www-128.ibm.com/developerworks/java/jdk/</a>.
+
+<h1>Step 2: Install Cygwin</h1>
+
+<font color=red> This step is required for Windows installations only. If you are installing
+on Linux, skip to step 3.</font>
+
+<p>We have put online the cygwin packages that we've confirmed to be
+compatible with TinyOS. The instructions below use those packages. You
+can also upgrade your cygwin environment according to the instructions
+at www.cygwin.com and your environment will most likely work. A large
+number of TinyOS users, upgrade their cygwin packages at least monthly
+from cygnus. However, since we can't test what packages are compatible
+as they become available daily, we can't confirm that today's set will
+work.
+
+<p>
+<ol>
+<li> Download the confirmed-compatible cygwin packages from the tinyos web site <a href="http://www.tinyos.net/dist-1.2.0/tools/windows/cygwin-1.2a.tgz">here</a>.
+<p>
+<li> In a cygwin shell, unzip the above package into some directory. In these instructions the directory is /cygdrive/c/newcygpkgs.
+<pre>
+ $ cd /cygdrive/c/newcygpkgs
+ $ tar zxvf cygwin-1.2a.tgz
+</pre>
+This unzips the packages.
+<p>
+<li> In Windows Explorer, navigate to /cygdrive/c/newcygpkgs and click on the file setup.exe. Setup.exe is the setup program distributed by Cygnus Solutions.
+<p>
+<li> Follow these steps when the Cygwin Setup windows appears:
+<ol>
+</ol>
+<li> Opt to disable the virus scanner (it will be enabled when you're finished).
+<p>
+<li> Opt to Install from Local Directory.
+<p>
+<li> Specify the Root directory to be where your <i>current</i> cygwin installation is. This would be the directory that directories like 'opt' and 'usr' are in. For example, mine is rooted at c:\tinyos\cygwin, so I enter that.
+<p>
+<li> Select to Install for All Users
+<p>
+<li> Select the Unix file type (very important!)
+<p>
+<li> For the Local Packages Directory, specify where you unzipped the cygwin packages tarfile. For example, I would specify c:\newcygpkgs. (The setup.exe program will probably select the right default directory.)
+<p>
+<li> The next window will allow you to select packages to install. You should see that most of the packages have an X-ed box next to them; these are the packages that are to be installed.
+<p>
+<li> Click install. Some notes:
+<ul>
+<li> You might see a message explaining that you need to reboot because some files are in use. This most likely means that your cygwin DLL is loaded and in-use and, therefore, cannot be replaced. When you reboot, the new DLL will be loaded.
+<li> Related to the above warnings, if you see warnings about the cygwin1.dll not being found, don't worry. All will be well once you reboot and the right DLL is loaded.
+</ul>
+</ol>
+</ol>
+
+<h1>Step 3: Install native compilers </h1>
+
+Install the appropriate version of the following (Windows or Linux,
+avr or msp430 or both) with the rpm command 'rpm -ivh <rpm>'.
+On
+windows, if you get an error claiming that the rpm was build for an NT
+computer and you're on a windows NT computer, bypass the erroneous
+error by using 'rpm -ivh --ignoreos <i>rpmname</i>'.
+(We have xscale
+compiler tools online at
+<a href="http://www.tinyos.net/dist-1.2.0/tools/">http://www.tinyos.net/dist-1.2.0/tools/</a>
+but they have not yet been extensively tested by a large community.)
+
+<!----- AVR external tools -------->
+</p><p><b><em>Atmel AVR Tools</em></b>
+<table border="0">
+<tbody><tr>
+ <td bgcolor="#dddddd"><b>Tool</b></td>
+ <td bgcolor="#dddddd"><b>Windows/Cygwin</b></td>
+ <td bgcolor="#dddddd"><b>Linux</b></td>
+</tr>
+
+<tr>
+ <td>avr-binutils<font color="red">†</font></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/avr-binutils-2.15tinyos-3.cygwin.i386.rpm">avr-binutils-2.15tinyos-3.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avr-binutils-2.15tinyos-3.i386.rpm">avr-binutils-2.15tinyos-3.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td bgcolor="#dddddd">avr-gcc</td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/avr-gcc-3.4.3-1.cygwin.i386.rpm">avr-gcc-3.4.3-1.cygwin.i386.rpm </a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avr-gcc-3.4.3-1.i386.rpm">avr-gcc-3.4.3-1.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td>avr-libc</td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/avr-libc-1.2.3-1.cygwin.i386.rpm">avr-libc-1.2.3-1.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avr-libc-1.2.3-1.i386.rpm">avr-libc-1.2.3-1.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td bgcolor="#dddddd">avarice</td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/avarice-2.4-1.cygwin.i386.rpm">avarice-2.4-1.cygwin.i386.rpm</a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avarice-2.4-1.i386.rpm">avarice-2.4-1.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td>insight (avr-gdb)</td>
+ <td><a href="http://www.tinyos.net/dist-1.2.0/tools/windows/avr-insight-6.3-1.cygwin.i386.rpm">avr-insight-6.3-1.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/avr-insight-6.3-1.i386.rpm">avr-insight-6.3-1.i386.rpm</a></td>
+</tr>
+
+</tbody></table>
+<i><font color="red">†</font>If you receive an rpm error that indicates that you have a newer version already installed, try <code>rpm -Uvh --force</code></i>
+
+<!----- MSP external tools -------->
+</p><p><b><em>TI MSP430 Tools</em></b>
+<table border="0">
+<tbody><tr>
+ <td bgcolor="#dddddd"><b>Tool</b></td>
+ <td bgcolor="#dddddd"><b>Windows/Cygwin</b></td>
+ <td bgcolor="#dddddd"><b>Linux</b></td>
+</tr>
+
+<tr>
+ <td>base</td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-base-0.1-20050607.cygwin.i386.rpm">msp430tools-base-0.1-20050607.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-base-0.1-20050607.i386.rpm">msp430tools-base-0.1-20050607.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td bgcolor="#dddddd">python tools</td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-python-tools-1.0-1.cygwin.noarch.rpm">msp430tools-python-tools-1.0-1.cygwin.noarch.rpm</a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-python-tools-1.0-1.noarch.rpm">msp430tools-python-tools-1.0-1.noarch.rpm</a></td>
+</tr>
+
+
+<tr>
+ <td>binutils</td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-binutils-2.16-20050607.cygwin.i386.rpm"> msp430tools-binutils-2.16-20050607.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-binutils-2.16-20050607.i386.rpm">msp430tools-binutils-2.16-20050607.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td bgcolor="#dddddd">gcc</td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-gcc-3.2.3-20050607.cygwin.i386.rpm">msp430tools-gcc-3.2.3-20050607.cygwin.i386.rpm</a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-gcc-3.2.3-20050607.i386.rpm">msp430tools-gcc-3.2.3-20050607.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td>libc</td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-libc-20050308cvs-20050608.cygwin.i386.rpm">msp430tools-libc-20050308cvs-20050608.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-libc-20050308cvs-20050608.i386.rpm">msp430tools-libc-20050308cvs-20050608.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td bgcolor="#dddddd">jtag</td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/"></a>Not yet available</td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-jtag-lib-20031101cvs-20050610.i386.rpm">msp430tools-jtag-lib-20031101cvs-20050610.i386.rpm</a></td>
+</tr>
+
+<tr>
+ <td>gdb</td>
+<!-- <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/msp430tools-gdb-6.0-20050609.cygwin.i386.rpm">msp430tools-gdb-6.0-20050609.cygwin.i386.rpm</a></td> -->
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/windows/"></a>Not yet available</td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tools/linux/msp430tools-gdb-6.0-20050609.i386.rpm">msp430tools-gdb-6.0-20050609.i386.rpm</a></td>
+</tr>
+
+</tbody></table>
+
+<h1>Step 4: Install TinyOS toolchain</h1>
+
+The TinyOS-specific tools are the NesC compiler and a set of tools
+developed in the tinyos-2.x/tools source code repository. They are
+also installed using rpms. If you using the Cygwin version recommended
+in these install
+instructions, you should install the "Recommended" Windows/Cygwin
+nesC RPM.
+Try installing it and if it does not work (e.g., you
+get strange errors when you try to execute it), this may be due
+to a Cygwin version incompatibility: try the "Other" Windows/Cygwin
+RPM (1.2.7a). If you are using Cygwin and installing the nesC RPM
+causes an error that the RPM was built for Cygwin,
+add the <code>--ignoreos</code> option.
+
+<!----- tinyos-2.x/tinyos rpms -------->
+</p><p><b><em>TinyOS-specific Tools</em></b>
+<table border="0">
+<tbody><tr>
+ <td bgcolor="#dddddd"><b>Tool</b></td>
+ <td bgcolor="#dddddd"><b>Recommended Windows/Cygwin</b></td>
+ <td bgcolor="#dddddd"><b>Other Windows/Cygwin</b></td>
+ <td bgcolor="#dddddd"><b>Linux</b></td>
+ <td bgcolor="#dddddd"><b>Command</b></td>
+</tr>
+
+<tr>
+ <td>NesC</td>
+ <td><a href="http://www.tinyos.net/dist-1.2.0/tinyos/windows/nesc-1.2.7b-1.cygwin.i386.rpm">nesc-1.2.7b-1.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-1.2.0/tinyos/windows/nesc-1.2.7a-1.cygwin.i386.rpm">nesc-1.2.7a-1.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-1.2.0/tinyos/linux/nesc-1.2.7a-1.i386.rpm">nesc-1.2.7a-1.i386.rpm </a></td>
+ <td><a href=""></a><code>rpm -Uvh</code><br>
+ <code>rpm -Uvh --ignoreos</code> (if Cygwin complains)</td>
+</tr>
+
+<tr>
+ <td bgcolor="#dddddd">tinyos-tools</td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-tools-1.2.3-1.cygwin.i386.rpm">tinyos-tools-1.2.3-1.cygwin.i386.rpm</a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-tools-1.2.3-1.cygwin.i386.rpm">tinyos-tools-1.2.3-1.cygwin.i386.rpm</a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/linux/tinyos-tools-1.2.3-1.i386.rpm">tinyos-tools-1.2.3-1.i386.rpm</a></td>
+ <td bgcolor="#dddddd"><a href=""></a><code>rpm -ivh --force</code> (1.x tree)<br><code>rpm -Uvh</code> (no 1.x tree)<br></td>
+</tr>
+
+</tbody></table>
+
+<h1>Step 5: Install the TinyOS 2.x source tree </h1>
+
+Now that the tools are installed, you need only install the tinyos 2.x
+source tree and then set your environment variables.
+Install the appropriate version of the following (Window or Linux)
+with the rpm command 'rpm -ivh <rpm>'.
+As with the previous rpms, if you get an error claiming that the rpm
+was build for an NT computer and you're on a windows NT computer,
+bypass the erroneous error by using 'rpm -ivh --ignoreos
+<i>rpmname</i>'.
+
+<ul>
+<li> Install tinyos-2.x
+<p>
+<!----- TinyOS -------->
+
+
+</p><p><b><em>TinyOS 2.x</em></b>
+<table border="0">
+<tbody><tr>
+ <td bgcolor="#dddddd"><b></b></td>
+ <td bgcolor="#dddddd"><b>Windows/Cygwin</b></td>
+ <td bgcolor="#dddddd"><b>Linux</b></td>
+</tr>
+
+<tr>
+ <td>TinyOS</td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-2.0.0-1.cygwin.noarch.rpm">tinyos-2.0.0-1.cygwin.noarch.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tinyos/linux/tinyos-2.0.0-1.noarch.rpm">tinyos-2.0.0-1.noarch.rpm</a></td>
+</tr>
+
+</tbody></table>
+</p></li><li> Configure your environment
+<p>
+Ideally, you'll put these environment variables in a shell script that will run when your shell starts, but you needn't
+put such a script under /etc/profile.d.
+</p><p>
+The example
+settings below assume that the tinyos-2.x installation is in /opt/tinyos-2.x.
+Change the settings to be correct for where you've put your tinyos-2.x tree. Note
+that the windows CLASSPATH must be a windows-style path, not a cygwin path. You can
+generate a windows style path from a cygwin-style path using 'cygpath -w'. For example:
+</p><pre>export CLASSPATH=`cygpath -w $TOSROOT/support/sdk/java/tinyos.jar`
+export CLASSPATH="$CLASSPATH;."
+</pre>
+
+<p><b><em>TinyOS 2.x</em></b>
+<table border="0">
+<tbody><tr>
+ <td bgcolor="#dddddd"><b>Environment Variable</b></td>
+ <td bgcolor="#dddddd"><b>Windows</b></td>
+ <td bgcolor="#dddddd"><b>Linux</b></td>
+</tr>
+
+<tr>
+ <td>TOSROOT</td>
+ <td>/opt/tinyos-2.x</td>
+ <td>same as in Cygwin</td>
+<td>
+
+</td></tr><tr>
+ <td bgcolor="#dddddd">TOSDIR</td>
+ <td bgcolor="#dddddd">$TOSROOT/tos</td>
+ <td bgcolor="#dddddd">same as in Cygwin</td>
+<td>
+
+</td></tr><tr>
+ <td>CLASSPATH</td>
+ <td>C:\tinyos\cygwin\opt\tinyos-2.x\support\sdk\java\tinyos.jar;.</td>
+ <td>$TOSROOT/support/sdk/java/tinyos.jar:.</td>
+<td>
+
+</td></tr><tr>
+ <td bgcolor="#dddddd">MAKERULES</td>
+ <td bgcolor="#dddddd">$TOSROOT/support/make/Makerules</td>
+ <td bgcolor="#dddddd">same as in Cygwin</td>
+<td>
+
+</td></tr><tr>
+ <td>PATH<font color="red">†</font></td>
+ <td>/opt/msp430/bin:$PATH</td>
+ <td>same as in Cygwin</td>
+<td>
+
+</td></tr></tbody></table>
+
+<i><font color="red">†</font>Only necessary if you're using the MSP430 platform/tools.</i>
+
+</p><p>
+In addition to the above environment variables, do the following on Linux machines:
+</p><ol>
+<li> Change the ownership on your /opt/tinyos-2.x files: <code>chown -R <your uid> /opt/tinyos-2.x
+</code></li><li> Change the permissions on any serial (/dev/ttyS<N>), usb
+(/dev/tts/usb<N>, /dev/ttyUSB<N>), or parallel (/dev/parport) devices you
+are going to use: <code>chmod 666 /dev/<devicename><code>
+<!--
+<li> Add any users who will be using TinyOS to the uucp, lp, and lock
+groups: </li>
+-->
+</code></code></li></ol>
+
+</li></ul>
+
+<h1>Step 6: Installing Graphviz</h1>
+
+<p>Go to <A HREF="http://www.graphviz.org/Download..php">download page</A> of the Graphviz project
+and download the appropriate RPM. You only need the basic graphviz RPM (<tt>graphviz-</tt>);
+you don't need all of the add-ons, such as -devel, -doc, -perl, etc.
+If you're not sure what version of Linux you're running,</p>
+
+<pre>uname -a</pre>
+
+<p>might give you some useful information. Install the rpm with <tt>rpm -i </tt> <i>rpm-name</i>.
+In the case of Windows, there is a simple install program, so you don't need to deal with RPMs.</p>
+
+</body>
+</html>
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>TinyOS 2.0 Overview</title>
<meta name="author" content="Philip Levis" />
-<meta name="date" content="Feb 8 2006" />
+<meta name="date" content="Oct 30 2006" />
<style type="text/css">
/*
<tr><th class="docinfo-name">Author:</th>
<td>Philip Levis</td></tr>
<tr><th class="docinfo-name">Date:</th>
-<td>Feb 8 2006</td></tr>
+<td>Oct 30 2006</td></tr>
</tbody>
</table>
<div class="note">
component of the CC1000 on the mica2 is <tt class="docutils literal"><span class="pre">ActiveMessageC</span></tt>, representing
a full active message communication layer.</p>
<p>The HAA is described in TEP 2: Hardware Abstraction Architecture[<a class="reference" href="#tep2">TEP2</a>].</p>
-<p>Currently (as of the 2.0 beta2 release in July 2006), TinyOS 2.0 supports
+<p>Currently (as of the 2.0 release in November 2006), TinyOS 2.0 supports
the following platforms:</p>
<blockquote>
<ul class="simple">
<li>btnode3</li>
</ul>
</blockquote>
-<p>The btnode3 platform is not included in the beta2 RPM.</p>
+<p>The btnode3 platform is not included in the RPM.</p>
</div>
<div class="section">
<h1><a id="scheduler" name="scheduler">3. Scheduler</a></h1>
each one will receive its fair share of transmission opportunities.</p>
<p>Further information on message_t can be found in TEP 111:
message_t[<a class="reference" href="#tep111">TEP111</a>], while further information on AM can be
-found in TEP 116: Packet Protocoks[<a class="reference" href="#tep116">TEP116</a>].</p>
+found in TEP 116: Packet Protocols[<a class="reference" href="#tep116">TEP116</a>].</p>
+<p>The current TinyOS release has a low-power stack for the CC1000
+radio (mica2 platform) and an experimental low-power stack for
+the CC2420 radio (micaz, telosb, and intelmote2 platforms).</p>
</div>
<div class="section">
<h1><a id="sensors" name="sensors">8. Sensors</a></h1>
TEP 115: Power Management of Non-Virtualised Devices{<a class="reference" href="#tep115">TEP115</a>], is handled
through resource abiters. Fully virtualized services have their
own, individual power management policies.</p>
+<p>TinyOS 2.0 provides low-power stacks for the CC1000 (mica2)
+and CC2420 (micaz, telosb, imote2) radios. Both use a low-power
+listening apporach, where transmitters send long preambles or
+repeatedly send packets and receivers wake up periodically to
+sense the channel to hear if there is a packet being
+transmitted. The low-power stack CC1000 is standard, while
+the CC2420 stack is experimental. That is, the default CC1000
+stack (chips/cc1000) has low-power-listening, while the default
+CC2420 stack (chips/cc2420) does not. To use the low-power CC2420
+stack, you must include chips/cc2420_lpl in your application Makefile.</p>
</div>
<div class="section">
<h1><a id="network-protocols" name="network-protocols">12. Network Protocols</a></h1>
than 20 byte) data items to every node in a network, while
collection builds a routing tree rooted at a sink node. Together,
these two protocols enable a wide range of data collection
-applications.</p>
+applications. Collection has advanced significantly since the
+most recent beta release; experimental tests in multiple
+network conditions have seen very high (>98%) deliver rates
+as long as the network is not saturated.</p>
</div>
<div class="section">
-<h1><a id="conclusion" name="conclusion">12. Conclusion</a></h1>
+<h1><a id="conclusion" name="conclusion">13. Conclusion</a></h1>
<p>TinyOS 2.0 represents the next step of TinyOS development. Building on
user experiences over the past few years, it has taken the basic
TinyOS architecture and pushed it forward in several directions,
dissemination), and further power management abstractions.</p>
</div>
<div class="section">
-<h1><a id="acknowledgments" name="acknowledgments">13. Acknowledgments</a></h1>
+<h1><a id="acknowledgments" name="acknowledgments">14. Acknowledgments</a></h1>
<p>TinyOS 2.0 is the result of a lot of hard work from a lot of people,
including (but not limited to) David Gay, Philip Levis, Cory Sharp,
Vlado Handziski, Jan Hauer, Kevin Klues, Joe Polastre, Jonathan Hui,
Gilman Tolle, Martin Turon, Phil Buonodonna, Ben Greenstein, David Culler,
Kristin Wright, Ion Yannopoulos, Henri Dubois-Ferriere, Jan Beutel,
Robert Szewczyk, Rodrigo Fonseca, Kyle Jamieson, Omprakash Gnawali,
-and Kristin Wright.</p>
+David Moss, and Kristin Wright.</p>
</div>
<div class="section">
-<h1><a id="author-s-address" name="author-s-address">14. Author's Address</a></h1>
+<h1><a id="author-s-address" name="author-s-address">15. Author's Address</a></h1>
<div class="line-block">
<div class="line">Philip Levis</div>
<div class="line">358 Gates</div>
</div>
</div>
<div class="section">
-<h1><a id="citations" name="citations">15. Citations</a></h1>
+<h1><a id="citations" name="citations">16. Citations</a></h1>
<table class="docutils citation" frame="void" id="tep1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<td>Philip Levis</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">18-Oct-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.5</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-10-19</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
describe systems that do not have a reference implementation.</p>
<p>The fourth field is "Status," which specifies the status of the TEP.
A TEP status can either be "Draft," which means it is a work in
-progress, "Final," which means it is complete and will not change, or
-"Obsolete," which means it should no longer be considered. If a TEP is
-"Obsolete" because it has been replaced by another TEP, then the new
-TEP number should follow "Obsolete," such as "Obsolete by TEP 1231."</p>
+progress, "Final," which means it is complete and will not change.
+Once a TEP has the status "Final," its body MUST NOT change.
+The values of its header fields MUST NOT change. The header of a
+Final TEP MAY have an "Obsoleted By" field added.</p>
+<p>The "Obsoletes" field is a backward pointer to an earlier TEP which
+the current TEP renders obsolete. An Obsoletes field MAY have multiple
+TEPs listed. For example, if TEP 191 were to replace TEPs 111 and 116, it
+would have the field "Obsoletes: 111, 116".</p>
+<p>The "Obsoleted By" field is added to a Final TEP when another TEP has
+rendered it obsolete. The field contains the number of the obsoleting
+TEP. For example, if TEP 111 were obsoleted by TEP 191, it would have
+the field "Obsoleted By: 191".</p>
+<p>"Obsoletes" and "Obsoleted By" fields MUST agree. For a TEP to list another
+TEP in its Obsoletes field, then that TEP MUST list it in the Obsoleted By
+field.</p>
+<p>The obsoletion fields are used to keep track of evolutions and modifications
+of a single abstraction. They are not intended to force a single approach or
+mechanism over alternative possibilities.</p>
<p>If a TEP is Best Current Practices or Documentary, then it MUST
include an additional field, "TinyOS-Version:," which states what
version(s) of TinyOS the document pertains to. This document pertains
to all versions of TinyOS, until made obsolete by a future TEP. This
field MUST appear after the Status field and before the Author field.</p>
-<p>The final required field is Author, which states the names of the
+<p>The final required field is "Author," which states the names of the
authors of the document. Full contact information should not be listed
here (see Section 3.2).</p>
+<p>There is an optional field, "Extends." The "Extends" field refers to
+another TEP. The purpose of this field is to denote when a TEP represents
+an addition to an existing TEP. Meeting the requirements of a TEP with an
+Extends field requires also meeting the requirements of all TEPs listed
+in the Extends field.</p>
<p>If a TEP is a Draft, then four additional fields MUST be included:
Draft-Created, Draft-Modified, Draft-Version, and Draft-Discuss.
Draft-Created states the date the document was created, Draft-Modified
<td>Jan-Hinrich Hauer, Philip Levis, Vlado Handziski, David Gay</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">20-Dec-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.3</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.9</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-09-08</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-10-12</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
</div>
<div class="section">
<h1><a id="abstract" name="abstract">Abstract</a></h1>
-<p>This TEP proposes a hardware abstraction for TinyOS 2.x analog-to-digital
-converters (ADCs). It focuses on aligning the ADC abstraction with the
-three-layer Hardware Abstraction Architecture (HAA) described in <a class="citation-reference" href="#tep2" id="id2" name="id2">[TEP2]</a>, but
-addresses only the HPL and HAL, because the highest level abstraction of an
-ADC is platform-dependent.</p>
+<p>This TEP proposes a hardware abstraction for analog-to-digital converters (ADCs)
+in TinyOS 2.x, which is aligned to the three-layer Hardware Abstraction
+Architecture (HAA) specified in [TEP2]. It describes some design principles and
+documents the set of hardware-independent interfaces to an ADC.</p>
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
components that had nothing to do with an ADC to still resemble one
programatically, even though the semantics and forms of operation were
completely different. To compensate for the difference non-ADC sensors
-introduced additional interfaces, such as ADCError, that were tightly bound to
-sensor acquisition but separate in wiring. The separation between the ADC and
-ADCError interface is bug prone and problematic, as is the equation of a
+introduced additional interfaces, such as <tt class="docutils literal"><span class="pre">ADCError</span></tt>, that were tightly bound
+to sensor acquisition but separate in wiring. The separation between the ADC and
+<tt class="docutils literal"><span class="pre">ADCError</span></tt> interface is bug prone and problematic, as is the equation of a
sensor and an ADC. TinyOS 2.x separates the structure and interfaces of an ADC
from those of sensors (which may be on top of an ADC, but this fact is hidden
-from higher level components). This TEP presents how TinyOS 2.x decomposes and
-structures ADC software. TEP 109 (Sensor Boards) shows how a platform can
-present actual named sensors <a class="citation-reference" href="#tep109" id="id3" name="id3">[TEP109]</a>.</p>
+from higher level components). This TEP presents how TinyOS 2.x structures ADC
+software. TEP 109 (Sensor Boards) shows how a platform can present actual named
+sensors <a class="citation-reference" href="#tep109" id="id2" name="id2">[TEP109]</a>.</p>
<p>As can be seen in Appendix A the ADC hardware used on TinyOS platforms differ
in many respects, which makes it difficult to find a chip independent
representation for an ADC. Even if there were such a representation, the
producing the input signal (sensor). Neither a platform independent
application nor the ADC hardware stack itself has access to this information,
as it can only be determined on a platform or sensorboard level. For example,
-determining which ADC port a sensor is attached to and how a conversion result
-is to be interpreted is a platform-specific determination.</p>
+determining which ADC port a sensor is attached to and how conversion results
+need to be interpreted is a platform specific determination. Although the
+actual configuration details may be different the procedure of configuring an
+ADC can be unified on all ADCs with the help of <strong>hardware independent
+interfaces</strong>: in a similar way as the <tt class="docutils literal"><span class="pre">Read</span></tt> interface definition does not
+predefine the type or semantics of the exchanged data (see <a class="citation-reference" href="#tep114" id="id3" name="id3">[TEP114]</a>), a
+configuration interface definition can abstract from the data type and
+semantics of the involved configuration settings. For example, like a
+component can provide a <tt class="docutils literal"><span class="pre">Read<uint8_t></span></tt> or <tt class="docutils literal"><span class="pre">Read<uint16_t></span></tt> interface
+depending on the data it can offer, a component can also use a
+<tt class="docutils literal"><span class="pre">AdcConfigure<atm128_adc_config_t></span></tt> or
+<tt class="docutils literal"><span class="pre">AdcConfigure<msp430adc12_channel_config_t></span></tt> interface depending on what ADC
+it represents. This TEP proposes the (typed) <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface as the
+standard interface for configuring an ADC in TinyOS 2.x.</p>
<p>In spite of their hardware differences, one aspect represents a common
-denominator of all ADCs: they produce conversion results. In order to
-facilitate sensor software development this capability can be made available
-via chip-independent interfaces for every ADC. However, conversion results
-depend on and have to be interpreted with respect to the platform-specific
-configuration settings (the ADC channel, the applied reference voltage, etc.).
-Therefore the highest level of ADC abstraction consists of
-platform-independent interfaces for ADC data collection and chip-specific
-interfaces for ADC hardware configuration. The top layer of the ADC stack
-thus remains platform-dependent and consequently the ADC abstraction does not
-include an HIL, but ends with the HAL. Following the principles of the
-HAA <a class="citation-reference" href="#tep2" id="id4" name="id4">[TEP2]</a> the HAL of an ADC should also expose the chip-specific capabilities
-for ADC data collection. For example, the ADC12 on the MSP430 MCU supports a
-complex repeat conversion mode for a set of different input channels, which is
-too specific to be represented by a platform-independent data collection
-interface. Therefore the HAL of an ADC abstraction is broken into two
-sublayers: The bottom HAL layer, called HAL1, exposes the full capabilities of
-the respective ADC in a chip-specific way. It realizes the standard HAL in the
-HAA <a class="citation-reference" href="#tep2" id="id5" name="id5">[TEP2]</a> and the HPL lies below it. On top of the HAL1 sits the HAL2 which
-maps the interfaces it uses from HAL1 to a set of platform-independent
-interfaces for data collection and chip-specific configuration interfaces.</p>
+denominator of all ADCs: they produce conversion results. To facilitate sensor
+software development conversion results are returned by the ADC hardware stack
+using the standard TinyOS interfaces <tt class="docutils literal"><span class="pre">Read</span></tt>, <tt class="docutils literal"><span class="pre">ReadNow</span></tt> and <tt class="docutils literal"><span class="pre">ReadStream</span></tt>
+(see <a class="reference" href="#interfaces">2. Interfaces</a> and <a class="citation-reference" href="#tep114" id="id4" name="id4">[TEP114]</a>). Conversion results are returned as
+uninterpreted values and translating them to engineering units can only be done
+with the configuration knowledge of the respective platform, for example, the
+reference voltage or the resistance of a reference resistor in ratiometric
+measurements. Translating uninterpreted values to engineering units is
+performed by components located on top of the ADC hardware stack and out of the
+scope of this TEP.</p>
+<p>The top layer of abstraction of an ADC - the Hardware Interface Layer (HIL) -
+thus provides the standard TinyOS interfaces <tt class="docutils literal"><span class="pre">Read</span></tt>, <tt class="docutils literal"><span class="pre">ReadNow</span></tt> and
+<tt class="docutils literal"><span class="pre">ReadStream</span></tt> and uses the <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface for hardware
+configuration (why it <strong>uses</strong> and does not <strong>provide</strong> <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> is
+explained below). Since the type and semantics of the parameters passed
+through these interfaces is dependent on the actual ADC implementation, it is
+only a "weak" HIL (see <a class="citation-reference" href="#tep2" id="id5" name="id5">[TEP2]</a>).</p>
+<p>Following the principles of the HAA <a class="citation-reference" href="#tep2" id="id6" name="id6">[TEP2]</a> the Hardware Adaptation Layer (HAL,
+which resides below the HIL) of an ADC should expose all the chip-specific
+capabilities of the chip. For example, the ADC12 on the MSP430 MCU supports a
+"Repeat-Sequence-of-Channels Mode" and therefore this function should be
+accessible on the HAL of the <strong>MSP430 ADC12</strong> hardware abstraction. Other ADCs
+might not exhibit such functionality and might therefore - on the level of HAL
+- provide only an interface to perform single conversions. Since all ADCs have
+the same HIL representation it may thus be necessary to perform some degree of
+software emulation in the HIL implementation. For example, a <tt class="docutils literal"><span class="pre">ReadStream</span></tt>
+command can be emulated by multiple single conversion commands. Below the HAL
+resides the Hardware Presentation Layer (HPL), a stateless component that
+provides access to the hardware registers (see <a class="citation-reference" href="#tep2" id="id7" name="id7">[TEP2]</a>). The general structure
+(without virtualization) of the ADC hardware stack is as follows</p>
+<pre class="literal-block">
+ ^ |
+ | |
+ | Read,
+ AdcConfigure ReadNow (+ Resource),
+ | ReadStream
+ | |
+ | V
+ +----------------------------------+
+ | Hardware Interface Layer (HIL) |
+ | (chip-specific implementation) |
+ +----------------------------------+
+ |
+ |
+ chip-specific interface(s) + Resource
+(e.g. Msp430Adc12SingleChannel + Resource)
+ |
+ V
+ +----------------------------------+
+ | Hardware Adaptation Layer (HAL) |
+ | (chip-specific implementation) |
+ +----------------------------------+
+ |
+ |
+ chip-specific interface(s)
+ (e.g. HplAdc12)
+ |
+ V
+ +----------------------------------+
+ | Hardware Presentation Layer (HPL)|
+ | (chip-specific implementation) |
+ +----------------------------------+
+</pre>
<p>The rest of this TEP specifies:</p>
<ul class="simple">
-<li>the set of platform-independent interfaces for the collection of ADC
-conversion results (<a class="reference" href="#interfaces">2. Interfaces</a>)</li>
-<li>guidelines on how an ADC's HAL should be split into HAL1 and HAL2 and
-how the HAL1 should expose chip-specific interfaces (<a class="reference" href="#hal1-guidelines">3. HAL1 guidelines</a>)</li>
-<li>what components an ADC's HAL2 MUST implement (<a class="reference" href="#hal2-requirements">4. HAL2 requirements</a>)</li>
-<li>guidelines on how the HAL2 may be structured (<a class="reference" href="#hal2-implementation-guidelines">5. HAL2 implementation guidelines</a>)</li>
-<li>a section pointing to the current implementation (<a class="reference" href="#implementation">6. Implementation</a>)</li>
+<li>the set of standard TinyOS interfaces for collecting ADC conversion
+results and for configuring an ADC (<a class="reference" href="#interfaces">2. Interfaces</a>)</li>
+<li>guidelines on how an ADC's HAL should expose chip-specific
+interfaces (<a class="reference" href="#hal-guidelines">3. HAL guidelines</a>)</li>
+<li>what components an ADC's HIL MUST implement (<a class="reference" href="#hil-requirements">4. HIL requirements</a>)</li>
+<li>guidelines on how the HIL should be implemented
+(<a class="reference" href="#hil-guidelines">5. HIL guidelines</a>)</li>
+<li>a section pointing to current implementations (<a class="reference" href="#implementation">6. Implementation</a>)</li>
</ul>
-<p>This TEP ends with appendices documenting, as an example, the ADC
-implementation for the TI MSP430 MCU.</p>
+<p>This TEP ends with appendices documenting, as an example, the ADC implementation
+for the TI MSP430 MCU.</p>
</div>
<div class="section">
<h1><a id="interfaces" name="interfaces">2. Interfaces</a></h1>
-<p>This TEP proposes to adopt the following three generic, source-independent
-data collection interfaces from <a class="citation-reference" href="#tep114" id="id6" name="id6">[TEP114]</a> for the collection of ADC conversion
-results:</p>
+<p>This TEP proposes the <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface for ADC hardware configuration
+and the <tt class="docutils literal"><span class="pre">Read</span></tt>, <tt class="docutils literal"><span class="pre">ReadNow</span></tt> and <tt class="docutils literal"><span class="pre">ReadStream</span></tt> interfaces to acquire
+conversion results. A <tt class="docutils literal"><span class="pre">Read[Now|Stream]</span></tt> interface is always provided in
+conjunction with a <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface.</p>
+<div class="section">
+<h2><a id="interface-for-configuring-the-adc-hardware" name="interface-for-configuring-the-adc-hardware">Interface for configuring the ADC hardware</a></h2>
+<p>The <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface is defined as follows:</p>
+<pre class="literal-block">
+interface AdcConfigure< config_type >
+{
+ async command config_type getConfiguration();
+}
+</pre>
+<p>This interface is used by the ADC implementation to retrieve the hardware
+configuration of an ADC client. <tt class="docutils literal"><span class="pre">config_type</span></tt> is a chip-specific data type
+(simple or structured) that contains all information necessary to configure the
+respective ADC hardware. For example, on the ADC12 of the MSP430 the
+<tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface will be instantiated with the <tt class="docutils literal"><span class="pre">const</span>
+<span class="pre">msp430adc12_channel_config_t*</span></tt> data type. A client MUST always return the same
+configuration through a <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface and, if configuration data
+is passed as a pointer, the HIL component (see <a class="reference" href="#hil-requirements">4. HIL requirements</a>) MUST NOT
+reference it after the return of the <tt class="docutils literal"><span class="pre">getConfiguration()</span></tt> command. If a
+client wants to use the ADC with different configurations it must provide
+multiple instances of the <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface.</p>
+</div>
+<div class="section">
+<h2><a id="interfaces-for-acquiring-conversion-results" name="interfaces-for-acquiring-conversion-results">Interfaces for acquiring conversion results</a></h2>
+<p>This TEP proposes to adopt the following three generic, source-independent data
+collection interfaces from <a class="citation-reference" href="#tep114" id="id8" name="id8">[TEP114]</a> for the collection of ADC conversion
+results on the level of HIL:</p>
<pre class="literal-block">
interface Read< size_type >
interface ReadNow< size_type >
interface ReadStream< size_type >
</pre>
-<p>Every data collection interface is associated with certain chip-specific
-configuration data (e.g. input channel, sample-hold-time, etc.). How this
-association can be realized is explained in Section <a class="reference" href="#hal2-requirements">4. HAL2 requirements</a>.
-As the resolution of conversion results is chip-specific, the 'size_type'
-parameter reflects an upper bound for the chip-specific resolution of the
-conversion results - the actual resolution may be smaller, depending on the
-ADC and/or data source (e.g. uint16_t for a 12-bit ADC). The above interfaces
-are specified in <a class="citation-reference" href="#tep114" id="id7" name="id7">[TEP114]</a>, in the following their usage is explained with
-respect to ADCs.</p>
+<p>Every data collection interface is associated with an <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt>
+interface (how this association is realized is explained in Section <a class="reference" href="#hil-requirements">4. HIL
+requirements</a>). As the resolution of conversion results is chip-specific, the
+<tt class="docutils literal"><span class="pre">size_type</span></tt> parameter reflects an upper bound for the chip-specific
+resolution of the conversion results - the actual resolution may be smaller
+(e.g. uint16_t for a 12-bit ADC). The above interfaces are specified in
+<a class="citation-reference" href="#tep114" id="id9" name="id9">[TEP114]</a>, in the following their usage is explained with respect to ADCs.</p>
<div class="section">
-<h2><a id="read" name="read">Read</a></h2>
-<p>The Read interface can be used to sample an ADC channel and return a single
-conversion result. It provides no guarantees about when exactly the sampling
-occurs (the request may be buffered).</p>
+<h3><a id="read" name="read">Read</a></h3>
+<p>The <tt class="docutils literal"><span class="pre">Read</span></tt> interface can be used to sample an ADC channel and return a single
+conversion result as an uninterpreted value. The meaning of the <tt class="docutils literal"><span class="pre">Read</span></tt>
+interface is explained in <a class="citation-reference" href="#tep114" id="id10" name="id10">[TEP114]</a>.</p>
</div>
<div class="section">
-<h2><a id="readnow" name="readnow">ReadNow</a></h2>
-<p>The ReadNow interface provides more precise control over the time of the
-sampling: If a call to ReadNow.read() succeeds, the ADC starts to sample the
-channel immediately (the request is not buffered). Due to its timing
-constraints the ReadNow interface is always provided in conjunction with an
-instance of the Resource interface. Refer to <a class="citation-reference" href="#tep108" id="id8" name="id8">[TEP108]</a> on how the 'Resource'
+<h3><a id="readnow" name="readnow">ReadNow</a></h3>
+<p>The <tt class="docutils literal"><span class="pre">ReadNow</span></tt> interface is similar to the <tt class="docutils literal"><span class="pre">Read</span></tt> interface. The difference
+is that if a call to <tt class="docutils literal"><span class="pre">ReadNow.read()</span></tt> succeeds, the ADC starts to sample the
+channel immediately (precisely: when <tt class="docutils literal"><span class="pre">SUCCESS</span></tt> is returned the hardware has
+started the sampling process). Due to its timing constraints the <tt class="docutils literal"><span class="pre">ReadNow</span></tt>
+interface is always provided in conjunction with an instance of the
+<tt class="docutils literal"><span class="pre">Resource</span></tt> interface (a client must reserve the ADC before the client may
+call <tt class="docutils literal"><span class="pre">ReadNow.read()</span></tt>). Please refer to <a class="citation-reference" href="#tep108" id="id11" name="id11">[TEP108]</a> on how the <tt class="docutils literal"><span class="pre">Resource</span></tt>
interface should be used by a client component.</p>
</div>
<div class="section">
-<h2><a id="readstream" name="readstream">ReadStream</a></h2>
-<p>The ReadStream interface can be used to sample an ADC channel multiple times
-with a specified sampling period. It provides no guarantees about when exactly
-the first sampling occurs, but all subsequent samplings occur with the
-specified sampling period.</p>
+<h3><a id="readstream" name="readstream">ReadStream</a></h3>
+<p>The <tt class="docutils literal"><span class="pre">ReadStream</span></tt> interface can be used to sample an ADC channel multiple times
+with a specified sampling period. The meaning of the <tt class="docutils literal"><span class="pre">ReadStream</span></tt> interface
+is explained in <a class="citation-reference" href="#tep114" id="id12" name="id12">[TEP114]</a> .</p>
+</div>
</div>
</div>
<div class="section">
-<h1><a id="hal1-guidelines" name="hal1-guidelines">3. HAL1 guidelines</a></h1>
-<p>As explained in <a class="reference" href="#introduction">1. Introduction</a> the HAL of an ADC abstraction consists of
-two sublayers, HAL1 and HAL2. In the ADC component stack the HAL1 resides
-below HAL2 and above the HPL. It exposes the full capabilities of the ADC in a
-chip-specific way and has the same function as the 'traditional' HAL in the
-HAA <a class="citation-reference" href="#tep2" id="id9" name="id9">[TEP2]</a>. Therefore only chip- and platform-dependent clients MAY wire to
-the HAL1. Although the HAL1 is chip-specific, both, in terms of implementation
+<h1><a id="hal-guidelines" name="hal-guidelines">3. HAL guidelines</a></h1>
+<p>As explained in <a class="reference" href="#introduction">1. Introduction</a> the HAL exposes the full capabilities of the
+ADC hardware. Therefore only chip- and platform-dependent clients can wire to
+the HAL. Although the HAL is chip-specific, both, in terms of implementation
and representation, its design should follow the guidelines described below to
-facilitate the mapping to platform-independent interfaces on the level of
-HAL2. Appendix B shows the HAL1 specification for the TI MSP430 MCU.</p>
+facilitate the mapping to the HIL representation. Appendix B shows the
+signature of the HAL for the MSP430.</p>
<div class="section">
<h2><a id="resource-reservation" name="resource-reservation">Resource reservation</a></h2>
-<p>As the ADC hardware is a shared resource that is multiplexed between several
-clients, it requires access arbitration. Therefore the HAL1 configuration
-component should provide a parameterized 'Resource' interface, instantiate a
-generic arbiter component and connect the 'Resource' interface to the arbiter
-as described in <a class="citation-reference" href="#tep108" id="id10" name="id10">[TEP108]</a>. To ensure fair and uniform arbitration on all
-platforms the standard round robin arbiter is recommended. Refer to <a class="citation-reference" href="#tep108" id="id11" name="id11">[TEP108]</a>
-on how the 'Resource' interface is to be used by a client wiring to HAL1.</p>
+<p>As the ADC hardware is a shared resource that is usually multiplexed between
+several clients some form of access arbitration is necessary. The HAL should
+therefore provide a parameterized <tt class="docutils literal"><span class="pre">Resource</span></tt> interface, instantiate a
+standard arbiter component and connect the <tt class="docutils literal"><span class="pre">Resource</span></tt> interface to the
+arbiter as described in <a class="citation-reference" href="#tep108" id="id13" name="id13">[TEP108]</a>. To ensure fair and uniform arbitration on
+all platforms the standard round robin arbiter is recommended. Resource
+arbiters and the <tt class="docutils literal"><span class="pre">Resource</span></tt> interface are the topic of <a class="citation-reference" href="#tep108" id="id14" name="id14">[TEP108]</a>.</p>
</div>
<div class="section">
<h2><a id="configuration-and-sampling" name="configuration-and-sampling">Configuration and sampling</a></h2>
-<p>As the ADC hardware is a shared resource the HAL1 should support hardware
-configuration and sampling on a per-client basis (although per-port
-configuration is possible, it is not recommended, because it forces all
-clients to use the same settings for a given port). Therefore an HAL1 should
-provide sampling interfaces parameterized by a client identifier. An HAL1
-client can use its instance of the sampling interface to configure the ADC
-hardware, start the sampling process and get conversion results. It wires to a
-sampling interface using a unique client identifier. All commands and events
-in the sampling interface should be 'async' to reflect the potential timing
-requirements of clients. An HAL1 may provide multiple different parameterized
-sampling interfaces, depending on the hardware capabilities. This allows to
+<p>As the ADC hardware is a shared resource the HAL should support hardware
+configuration and sampling per client (although per-port configuration is
+possible, it is not recommended, because it forces all clients to use the same
+configuration for a given port). Therefore the HAL should provide sampling
+interfaces parameterized by a client identifier. A HAL client can use its
+instance of the sampling interface to configure the ADC hardware, start the
+sampling process and acquire conversion results. It wires to a sampling
+interface using a unique client identifier (this may be hidden by a
+virtualization component). All commands and events in the sampling interface
+should be 'async' to reflect the potential timing requirements of clients on
+the level of HAL. A HAL may provide multiple different parameterized sampling
+interfaces, depending on the hardware capabilities. This allows to
differentiate/group ADC functionality, for example single vs. repeated
-sampling, single channel vs. multiple channels or low-frequency vs.
+sampling, single channel vs. multiple channels or low-frequency vs.
high-frequency sampling. Every sampling interface should allow the client to
individually configure the ADC hardware, for example by including the
configuration data as parameters in the sampling commands. However, if
-configuration data is passed as a pointer, the HAL1 component MUST NOT
-reference it after the return of the respective command. Appendix B shows the
-HAL1 interfaces for the TI MSP430 MCU.</p>
+configuration data is passed as a pointer, the HAL component MUST NOT reference
+it after the return of the respective command. Appendix B shows the HAL
+interfaces for the MSP430.</p>
</div>
<div class="section">
-<h2><a id="hal1-virtualization" name="hal1-virtualization">HAL1 virtualization</a></h2>
+<h2><a id="hal-virtualization" name="hal-virtualization">HAL virtualization</a></h2>
<p>In order to hide wiring complexities and/or export only a subset of all ADC
-functions generic ADC wrapper components may be provided on the level of HAL1
-to be instantiated by chip- and platform-dependent clients.</p>
+functions generic ADC wrapper components may be provided on the level of HAL.
+Such components can also be used to ensure that a sampling interface is always
+provided with a <tt class="docutils literal"><span class="pre">Resource</span></tt> interface and both are instantiated with the same
+client ID if this is required by the HAL implementation.</p>
</div>
</div>
<div class="section">
-<h1><a id="hal2-requirements" name="hal2-requirements">4. HAL2 requirements</a></h1>
-<p>The following components MUST be provided on all platforms that have an ADC:</p>
+<h1><a id="hil-requirements" name="hil-requirements">4. HIL requirements</a></h1>
+<p>The following generic components MUST be provided on all platforms that have an
+ADC:</p>
<pre class="literal-block">
-AdcReadClient
-AdcReadNowClient
-AdcReadStreamClient
+AdcReadClientC
+AdcReadNowClientC
+AdcReadStreamClientC
</pre>
-<p>These generic components are instantiated and provide access to the ADC on a
-per-client basis via a platform-independent interface for data collection and
-a chip-specific ADC configuration interface. This section describes the
-representation of the HAL2. Guidelines on how the HAL2 can be implemented are
-discussed in Section <a class="reference" href="#hal2-implementation-guidelines">5. HAL2 implementation guidelines</a>. Appendix C shows
-the AdcReadClient for the TI MSP430 MCU.</p>
-<p>The fact that the components use chip-specific ADC configuration interfaces
-(see below) and the fact that the provided interfaces for data-collection must
-be interpreted with respect to the configuration data - for example the
-reference voltage - makes the HAL2 representation chip dependent. Therefore
-the ADC abstraction does not include an HIL.</p>
+<p>These components provide virtualized access to the HIL of an ADC. They are
+instantiated by an ADC client and provide/use the four interfaces described in
+Section <a class="reference" href="#interfaces">2. Interfaces</a>. An ADC client may instantiate multiple such
+components. The following paragraphs describe their signatures. Note that this
+TEP does not address the issue of how to deal with multiple ADCs on the same
+platform (the question of how to deal with multiple devices of the same class
+is a general one in TinyOS 2.x). Appendix C shows the <tt class="docutils literal"><span class="pre">AdcReadClientC</span></tt> for
+the MSP430.</p>
<div class="section">
-<h2><a id="adcreadclient" name="adcreadclient">AdcReadClient</a></h2>
+<h2><a id="adcreadclientc" name="adcreadclientc">AdcReadClientC</a></h2>
<pre class="literal-block">
-generic configuration AdcReadClient() {
+generic configuration AdcReadClientC() {
provides {
interface Read< size_type >;
}
uses {
- // chip-dependent configuration interface
+ interface AdcConfigure< config_type >;
}
}
</pre>
-<p>The AdcReadClient provides platform-independent access for data collection via
-the 'Read' interface. The actual ADC channel (port) and further configuration
-details are determined by a chip-dependent configuration interface. It is the
-task of the client to wire this interface to a component that provides its ADC
-configuration. The HAL2 implementation will use this interface to "pull" the
-client's ADC settings when it translates the 'Read.read()' command to a
-chip-specific sampling command. The resolution of the conversion result is
-chip-specific, the 'size_type' parameter represents an upper bound for the
-resolution of the conversion results.</p>
+<p>The <tt class="docutils literal"><span class="pre">AdcReadClientC</span></tt> component provides a <tt class="docutils literal"><span class="pre">Read</span></tt> interface for acquiring
+single conversion results. The associated ADC channel (port) and further
+configuration details are returned by the <tt class="docutils literal"><span class="pre">AdcConfigure.getConfiguration()</span></tt>
+command. It is the task of the client to wire this interface to a component
+that provides the client's ADC configuration. The HIL implementation will use
+the <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface to dynamically "pull" the client's ADC settings
+when it translates the <tt class="docutils literal"><span class="pre">Read.read()</span></tt> command to a chip-specific sampling
+command. Note that both, <tt class="docutils literal"><span class="pre">size_type</span></tt> and <tt class="docutils literal"><span class="pre">config_type</span></tt>, are only
+placeholders and will be instantiated by the respective HIL implementation (for
+an example, see the AdcReadClientC for the MSP430 in Appendix C).</p>
</div>
<div class="section">
-<h2><a id="adcreadnowclient" name="adcreadnowclient">AdcReadNowClient</a></h2>
+<h2><a id="adcreadnowclientc" name="adcreadnowclientc">AdcReadNowClientC</a></h2>
<pre class="literal-block">
-generic configuration AdcReadNowClient() {
+generic configuration AdcReadNowClientC() {
provides {
interface Resource;
interface ReadNow< size_type >;
}
uses {
- // chip-dependent configuration interface
+ interface AdcConfigure< config_type >;
}
}
</pre>
-<p>The AdcReadNowClient provides platform-independent access for data collection
-via the 'ReadNow' and 'Resource' interface. The actual ADC channel (port) and
-further configuration details are determined by a chip-dependent configuration
-interface. It is the task of the client to wire this interface to a component
-that provides its ADC configuration. The HAL2 implementation will use this
-interface to "pull" the client's ADC settings when it translates the
-'ReadNow.read()' command to a chip-specific sampling command. A client MUST
-use the 'Resource' interface to request access to the ADC as described in
-<a class="citation-reference" href="#tep108" id="id12" name="id12">[TEP108]</a> (the HAL2 implementation SHOULD return the error code 'ERESERVE' if
-the client has not reserved access). The resolution of the conversion result
-is chip-specific, the 'size_type' parameter represents an upper bound for the
-resolution of the conversion result.</p>
+<p>The <tt class="docutils literal"><span class="pre">AdcReadNowClientC</span></tt> component provides a <tt class="docutils literal"><span class="pre">ReadNow</span></tt> interface for
+acquiring single conversion results. In contrast to <tt class="docutils literal"><span class="pre">Read.read()</span></tt> when a call
+to <tt class="docutils literal"><span class="pre">ReadNow.read()</span></tt> succeeds, the ADC starts to sample the channel
+immediately (a successful <tt class="docutils literal"><span class="pre">Read.read()</span></tt> command may not have this
+implication, see <a class="citation-reference" href="#tep114" id="id15" name="id15">[TEP114]</a> and <a class="reference" href="#interfaces">2. Interfaces</a>). A client MUST reserve the ADC
+through the <tt class="docutils literal"><span class="pre">Resource</span></tt> interface before the client may call
+<tt class="docutils literal"><span class="pre">ReadNow.read()</span></tt> and it must release the ADC through the <tt class="docutils literal"><span class="pre">Resource</span></tt>
+interface when it no longer needs to access it (for more details on the
+<tt class="docutils literal"><span class="pre">Resource</span></tt> interface please refer to <a class="citation-reference" href="#tep108" id="id16" name="id16">[TEP108]</a>). The associated ADC channel
+(port) and further configuration details are returned by the
+<tt class="docutils literal"><span class="pre">AdcConfigure.getConfiguration()</span></tt> command. It is the task of the client to
+wire this interface to a component that provides the client's ADC
+configuration. The HIL implementation will use the <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface
+to dynamically "pull" the client's ADC settings when it translates the
+<tt class="docutils literal"><span class="pre">ReadNow.read()</span></tt> command to a chip-specific sampling command. Note that both,
+<tt class="docutils literal"><span class="pre">size_type</span></tt> and <tt class="docutils literal"><span class="pre">config_type</span></tt>, are only placeholders and will be
+instantiated by the respective HIL implementation (for an example how this is
+done for the AdcReadClientC see Appendix C).</p>
</div>
<div class="section">
-<h2><a id="adcreadstreamclient" name="adcreadstreamclient">AdcReadStreamClient</a></h2>
+<h2><a id="adcreadstreamclientc" name="adcreadstreamclientc">AdcReadStreamClientC</a></h2>
<pre class="literal-block">
-generic configuration AdcReadStreamClient() {
+generic configuration AdcReadStreamClientC() {
provides {
interface ReadStream< size_type >;
}
uses {
- // chip-dependent configuration interface
+ interface AdcConfigure< config_type>;
}
}
</pre>
-<p>The AdcReadStreamClient provides platform-independent access for data
-collection via the 'ReadStream' interface. The actual ADC channel (port) and
-further configuration details are determined by a chip-dependent configuration
-interface. It is the task of the client to wire this interface to a component
-that provides its ADC configuration. The HAL2 implementation will use this
-interface to "pull" the client's ADC settings when it translates the
-'ReadStream.read()' command to a chip-specific sampling command. The
-resolution of the conversion results is chip-specific, the 'size_type'
-parameter represents an upper bound for the resolution of the conversion
-results.</p>
+<p>The <tt class="docutils literal"><span class="pre">AdcReadStreamClientC</span></tt> component provides a <tt class="docutils literal"><span class="pre">ReadStream</span></tt> interface for
+acquiring multiple conversion results at once. The <tt class="docutils literal"><span class="pre">ReadStream</span></tt> interface is
+explained in <a class="citation-reference" href="#tep114" id="id17" name="id17">[TEP114]</a> and <a class="reference" href="#interfaces">2. Interfaces</a>. The <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface is
+used in the same way as described in the section on the <tt class="docutils literal"><span class="pre">AdcReadClientC</span></tt>.
+Note that both, <tt class="docutils literal"><span class="pre">size_type</span></tt> and <tt class="docutils literal"><span class="pre">config_type</span></tt>, are only placeholders and
+will be instantiated by the respective HIL implementation (for an example how
+this is done for the AdcReadClientC see Appendix C).</p>
</div>
</div>
<div class="section">
-<h1><a id="hal2-implementation-guidelines" name="hal2-implementation-guidelines">5. HAL2 implementation guidelines</a></h1>
-<p>The HAL2 implementation of an ADC stack has two main tasks: It translates a
-platform-independent HAL2 request (from the 'Read', 'ReadNow' or 'ReadStream'
-interface) to a chip-specific HAL1 sampling command and it abstracts from the
-'Resource' interface. The first task cannot be solved in a chip-independent
-way, because it involves chip-specific configuration data. The second task MAY
-be performed by the following library components: ArbitratedReadC, and
-ArbitratedReadStreamC (in tinyos-2.x/tos/system) - refer to the Atmel Atmega
-128 HAL2 implementation (in tinyos-2.x/tos/chips/atm128/adc), for an example.
-Note that since the 'ReadNow' interface is always provided in conjunction with
-a 'Resource' interface the HAL2 implementation does not have to perform the
-ADC resource reservation in this case, but can simply forward an instance of
-the 'Resource' interface from the HAL1 (to AdcReadNowClient).</p>
-<p>To support multiple ADC clients the HAL2 implementation should provide
-parameterized 'Read', 'ReadNow' and 'ReadStream' interfaces as well as a
-parameterized chip-specific configuration interface. It should also use an
-instance of the 'Resource' interface (provided by the HAL1) per provided
-'Read' and 'ReadStream' interface to perform automatic resource reservation.
-The HAL2 representation ('AdcReadClient', 'AdcReadNowClient' and
-'AdcReadStreamClient') should ensure the correct wiring between the HAL1 and
-HAL2.</p>
-<p>From the perspective of the HAL2 the typical sequence of events is as follows:
-After a client has requested data via the 'Read' or 'ReadStream' interface the
-HAL2 will request access to the HAL1 via the 'Resource' interface, e.g. using
-the library components mentioned above. When it is signalled the 'granted'
-event, the HAL2 will 'pull' the client's ADC settings and translate the
-client's command to a chip-specific HAL1 sampling command. Once it is
-signalled the conversion result(s) it releases the ADC via the 'Resource'
-interface and forwards the conversion result(s) to the client. When a client
-has requested data via the 'ReadNow' interface the HAL2 translates the
-client's command to the chip-specific HAL1 sampling command without using the
-'Resource' interface (it may check ownership of the client via the
-'ArbiterInfo' interface). In order to reduce state in the HAL2 and facilitate
-the mapping between used and provided interfaces the 'AdcReadClient',
-'AdcReadNowClient' and 'AdcReadStreamClient' should use the same interface
-identifier when it connects the HAL2 to HAL1 (see, for example, the MSP430
-ADC12 implementation in Appendix C).</p>
+<h1><a id="hil-guidelines" name="hil-guidelines">5. HIL guidelines</a></h1>
+<p>The HIL implementation of an ADC stack has two main tasks: it translates a
+<tt class="docutils literal"><span class="pre">Read</span></tt>, <tt class="docutils literal"><span class="pre">ReadNow</span></tt> or <tt class="docutils literal"><span class="pre">ReadStream</span></tt> request to a chip-specific HAL sampling
+command and it abstracts from the <tt class="docutils literal"><span class="pre">Resource</span></tt> interface (the latter only for
+the <tt class="docutils literal"><span class="pre">AdcReadClientC</span></tt> and <tt class="docutils literal"><span class="pre">AdcReadStreamClientC</span></tt>). The first task is solved
+with the help of the <tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface which is used by the HIL
+implementation to retrieve a client's ADC configuration. The second task MAY
+be performed by the following library components: <tt class="docutils literal"><span class="pre">ArbitratedReadC</span></tt>, and
+<tt class="docutils literal"><span class="pre">ArbitratedReadStreamC</span></tt> (in tinyos-2.x/tos/system) - please refer to the
+Atmel Atmega 128 HAL implementation (in tinyos-2.x/tos/chips/atm128/adc) for an
+example. Note that since the <tt class="docutils literal"><span class="pre">ReadNow</span></tt> interface is always provided in
+conjunction with a <tt class="docutils literal"><span class="pre">Resource</span></tt> interface the HIL implementation does not have
+to perform the ADC resource reservation for an <tt class="docutils literal"><span class="pre">AdcReadNowClientC</span></tt>, but may
+simply forward an instance of the <tt class="docutils literal"><span class="pre">Resource</span></tt> interface from the HAL to the
+<tt class="docutils literal"><span class="pre">AdcReadNowClientC</span></tt>.</p>
+<p>The typical sequence of events is as follows: when a client requests data
+through the <tt class="docutils literal"><span class="pre">Read</span></tt> or <tt class="docutils literal"><span class="pre">ReadStream</span></tt> interface the HIL will request access to
+the HAL using the <tt class="docutils literal"><span class="pre">Resource</span></tt> interface. After the HIL has been granted
+access, it will "pull" the client's ADC configuration using the
+<tt class="docutils literal"><span class="pre">AdcConfigure</span></tt> interface and translate the client's <tt class="docutils literal"><span class="pre">Read</span></tt> or
+<tt class="docutils literal"><span class="pre">ReadStream</span></tt> command to a chip-specific HAL command. Once the HIL is
+signalled the conversion result(s) from the HAL it releases the ADC through the
+<tt class="docutils literal"><span class="pre">Resource</span></tt> interface and signals the conversion result(s) to the client
+though the <tt class="docutils literal"><span class="pre">Read</span></tt> or <tt class="docutils literal"><span class="pre">ReadStream</span></tt> interface. When a client requests data
+through the <tt class="docutils literal"><span class="pre">ReadNow</span></tt> interface the HIL translates the client's command to
+the chip-specific HAL command without using the <tt class="docutils literal"><span class="pre">Resource</span></tt> interface (it may
+check ownership of the client through the <tt class="docutils literal"><span class="pre">ArbiterInfo</span></tt> interface - this
+check can also be done in the HAL implementation). Once the HIL is signalled
+the conversion result(s) it forwards it to the respective <tt class="docutils literal"><span class="pre">ReadNow</span></tt> client.</p>
</div>
<div class="section">
<h1><a id="implementation" name="implementation">6. Implementation</a></h1>
<blockquote>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">HplAdc12P.nc</span></tt> is the HPL implementation</li>
-<li><tt class="docutils literal"><span class="pre">Msp430Adc12P.nc</span></tt> is the HAL1 implementation</li>
-<li><tt class="docutils literal"><span class="pre">AdcC.nc</span></tt> is the HAL2 implementation</li>
+<li><tt class="docutils literal"><span class="pre">Msp430Adc12P.nc</span></tt> is the HAL implementation</li>
+<li><tt class="docutils literal"><span class="pre">AdcP.nc</span></tt> is the HIL implementation</li>
<li><tt class="docutils literal"><span class="pre">AdcReadClientC.nc</span></tt>, <tt class="docutils literal"><span class="pre">AdcReadNowClientC.nc</span></tt> and
-<tt class="docutils literal"><span class="pre">AdcReadStreamClientC.nc</span></tt> provide access to the ADC on a per-client
-basis via the interfaces 'Read', 'ReadNow' and 'ReadStream',
-respectively, and the msp430-specific ADC configuration
-interface <tt class="docutils literal"><span class="pre">Msp430Adc12Config.nc</span></tt></li>
+<tt class="docutils literal"><span class="pre">AdcReadStreamClientC.nc</span></tt> provide virtualized access to the HIL</li>
+<li>the use of DMA or the reference voltage generator and the
+HAL virtualization components are explained in <tt class="docutils literal"><span class="pre">README.txt</span></tt></li>
</ul>
</blockquote>
<p>The Atmel Atmega 128 ADC implementation can be found in
<blockquote>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">HplAtm128AdcC.nc</span></tt> is the HPL implementation</li>
-<li><tt class="docutils literal"><span class="pre">Atm128AdcP.nc</span></tt> is the HAL1 implementation</li>
+<li><tt class="docutils literal"><span class="pre">Atm128AdcP.nc</span></tt> is the HAL implementation</li>
<li><tt class="docutils literal"><span class="pre">WireAdcP.nc</span></tt> and the library components for arbitrating 'Read',
'ReadNow' and 'ReadStream', <tt class="docutils literal"><span class="pre">ArbitratedReadC</span></tt> and
<tt class="docutils literal"><span class="pre">ArbitratedReadStreamC</span></tt> (in <tt class="docutils literal"><span class="pre">tinyos-2.x/tos/system</span></tt>), realize
-the HAL2</li>
+the HAL</li>
<li><tt class="docutils literal"><span class="pre">AdcReadClientC.nc</span></tt>, <tt class="docutils literal"><span class="pre">AdcReadNowClientC.nc</span></tt> and
-<tt class="docutils literal"><span class="pre">AdcReadStreamClientC.nc</span></tt> provide access to the ADC on a per-client
-basis via the platform-independent interfaces 'Read', 'ReadNow' and
-'ReadStream', respectively, and the atmega-specific ADC configuration
-interface <tt class="docutils literal"><span class="pre">Atm128AdcConfig.nc</span></tt></li>
+<tt class="docutils literal"><span class="pre">AdcReadStreamClientC.nc</span></tt> provide virtualized access to the HIL</li>
</ul>
</blockquote>
</div>
</table>
</div>
<div class="section">
-<h1><a id="appendix-b-an-hal1-representation-msp430-adc12" name="appendix-b-an-hal1-representation-msp430-adc12">Appendix B: an HAL1 representation: MSP430 ADC12</a></h1>
-<p>The following shows the HAL1 representation for the ADC12 of the TI MSP430
-MCU. It reflects the four MSP430 ADC12 conversion modes as it lets a client
-sample an ADC channel once ("Single-channel-single-conversion") or repeatedly
+<h1><a id="appendix-b-a-hal-representation-msp430-adc12" name="appendix-b-a-hal-representation-msp430-adc12">Appendix B: a HAL representation: MSP430 ADC12</a></h1>
+<p>This section shows the HAL signature for the ADC12 of the TI MSP430 MCU. It
+reflects the four MSP430 ADC12 conversion modes as it lets a client sample an
+ADC channel once ("Single-channel-single-conversion") or repeatedly
("Repeat-single-channel"), multiple times ("Sequence-of-channels") or multiple
times repeatedly ("Repeat-sequence-of-channels"). In contrast to the single
channel conversion modes the sequence conversion modes trigger a single
-interrupt after multiple samples and thus enable high-frequency sampling (a
-sequence conversion mode for multiple different channels is not (yet)
-implemented).:</p>
+interrupt after multiple samples and thus enable high-frequency sampling. The
+<tt class="docutils literal"><span class="pre">DMAExtension</span></tt> interface is used to reset the state machine when the DMA is
+responsible for data transfer (managed in an exterior component):</p>
<pre class="literal-block">
-configuration Msp430Adc12C
+configuration Msp430Adc12P
{
- provides interface Resource[uint8_t id];
- provides interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
+ provides {
+ interface Resource[uint8_t id];
+ interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
+ interface AsyncStdControl as DMAExtension[uint8_t id];
+ }
}
interface Msp430Adc12SingleChannel
{
- async command error_t getSingleData(const msp430adc12_channel_config_t *config);
- async command error_t getSingleDataRepeat(const msp430adc12_channel_config_t *config,
- uint16_t jiffies);
- async command error_t getMultipleData( const msp430adc12_channel_config_t *config,
- uint16_t *buffer, uint16_t numSamples, uint16_t jiffies);
- async command error_t getMultipleDataRepeat(const msp430adc12_channel_config_t *config,
- uint16_t *buffer, uint8_t numSamples, uint16_t jiffies);
+ async command error_t configureSingle(const msp430adc12_channel_config_t *config);
+ async command error_t configureSingleRepeat(const msp430adc12_channel_config_t *config, uint16_t jiffies);
+ async command error_t configureMultiple( const msp430adc12_channel_config_t *config, uint16_t buffer[], uint16_t numSamples, uint16_t jiffies);
+ async command error_t configureMultipleRepeat(const msp430adc12_channel_config_t *config, uint16_t buffer[], uint8_t numSamples, uint16_t jiffies);
+ async command error_t getData();
async event error_t singleDataReady(uint16_t data);
- async event uint16_t* multipleDataReady(uint16_t *buffer, uint16_t
- numSamples);
+ async event uint16_t* multipleDataReady(uint16_t buffer[], uint16_t numSamples);
}
+
+typedef struct {
+ unsigned int inch: 4; // input channel
+ unsigned int sref: 3; // reference voltage
+ unsigned int ref2_5v: 1; // reference voltage level
+ unsigned int adc12ssel: 2; // clock source sample-hold-time
+ unsigned int adc12div: 3; // clock divider sample-hold-time
+ unsigned int sht: 4; // sample-hold-time
+ unsigned int sampcon_ssel: 2; // clock source sampcon signal
+ unsigned int sampcon_id: 2; // clock divider sampcon signal
+} msp430adc12_channel_config_t;
</pre>
-<p>There exist two wrapper components, Msp430Adc12ClientC and
-Msp430Adc12RefVoltAutoClientC, which SHOULD be used to eliminate wiring
-errors.</p>
</div>
<div class="section">
-<h1><a id="appendix-c-an-hal2-representation-msp430-adc12" name="appendix-c-an-hal2-representation-msp430-adc12">Appendix C: an HAL2 representation: MSP430 ADC12</a></h1>
-<p>The AdcReadClientC component for the MSP430 ADC12 is implemented as follows:</p>
+<h1><a id="appendix-c-a-hil-representation-msp430-adc12" name="appendix-c-a-hil-representation-msp430-adc12">Appendix C: a HIL representation: MSP430 ADC12</a></h1>
+<p>The signature of the AdcReadClientC component for the MSP430 ADC12 is as
+follows:</p>
<pre class="literal-block">
generic configuration AdcReadClientC() {
provides interface Read<uint16_t>;
- uses interface Msp430Adc12Config;
-} implementation {
- components AdcC;
-#ifdef REF_VOLT_AUTO_CONFIGURE
- components new Msp430Adc12RefVoltAutoClientC() as Msp430AdcClient;
-#else
- components new Msp430Adc12ClientC() as Msp430AdcClient;
-#endif
-
- enum {
- CLIENT = unique(ADCC_SERVICE),
- };
-
- Read = AdcC.Read[CLIENT];
- Msp430Adc12Config = AdcC.Config[CLIENT];
- AdcC.SingleChannel[CLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
- AdcC.Resource[CLIENT] -> Msp430AdcClient.Resource;
-#ifdef REF_VOLT_AUTO_CONFIGURE
- Msp430Adc12Config = Msp430AdcClient.Msp430Adc12Config;
-#endif
+ uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
}
</pre>
-<p>Note that the same CLIENT identifier is used for all involved interfaces to
-facilitate the mapping between the HAL2 and HAL1 interfaces. The conditional
-compile directive REF_VOLT_AUTO_CONFIGURE can be used to automatically enable
-the internal reference voltage generator during the sampling process.</p>
<table class="docutils citation" frame="void" id="tep1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<table class="docutils citation" frame="void" id="tep2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a name="tep2">[TEP2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>, <a class="fn-backref" href="#id5">3</a>, <a class="fn-backref" href="#id9">4</a>)</em> TEP 2: Hardware Abstraction Architecture.</td></tr>
+<tr><td class="label"><a name="tep2">[TEP2]</a></td><td><em>(<a class="fn-backref" href="#id5">1</a>, <a class="fn-backref" href="#id6">2</a>, <a class="fn-backref" href="#id7">3</a>)</em> TEP 2: Hardware Abstraction Architecture.</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep108" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a name="tep108">[TEP108]</a></td><td><em>(<a class="fn-backref" href="#id8">1</a>, <a class="fn-backref" href="#id10">2</a>, <a class="fn-backref" href="#id11">3</a>, <a class="fn-backref" href="#id12">4</a>)</em> TEP 108: Resource Arbitration.</td></tr>
+<tr><td class="label"><a name="tep108">[TEP108]</a></td><td><em>(<a class="fn-backref" href="#id11">1</a>, <a class="fn-backref" href="#id13">2</a>, <a class="fn-backref" href="#id14">3</a>, <a class="fn-backref" href="#id16">4</a>)</em> TEP 108: Resource Arbitration.</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep109" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a class="fn-backref" href="#id3" name="tep109">[TEP109]</a></td><td>TEP 109: Sensor Boards.</td></tr>
+<tr><td class="label"><a class="fn-backref" href="#id2" name="tep109">[TEP109]</a></td><td>TEP 109: Sensor Boards.</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep114" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a name="tep114">[TEP114]</a></td><td><em>(<a class="fn-backref" href="#id6">1</a>, <a class="fn-backref" href="#id7">2</a>)</em> TEP 114: SIDs: Source and Sink Independent Drivers.</td></tr>
+<tr><td class="label"><a name="tep114">[TEP114]</a></td><td><em>(<a class="fn-backref" href="#id3">1</a>, <a class="fn-backref" href="#id4">2</a>, <a class="fn-backref" href="#id8">3</a>, <a class="fn-backref" href="#id9">4</a>, <a class="fn-backref" href="#id10">5</a>, <a class="fn-backref" href="#id12">6</a>, <a class="fn-backref" href="#id15">7</a>, <a class="fn-backref" href="#id17">8</a>)</em> TEP 114: SIDs: Source and Sink Independent Drivers.</td></tr>
</tbody>
</table>
</div>
<td>Cory Sharp, Martin Turon, David Gay</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">22-Sep-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.3</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.9</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-09-06</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-10-18</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<p>Three fundamental properties of timers are <em>precision</em>, <em>width</em> and
<em>accuracy</em>.</p>
<p>Examples of precision are millisecond, a cycle of a 32kHz clock, and
-microseconds. All precisions are in "binary" units with respect to
-one second. That is, one second contains 1024 binary milliseconds,
-32768 32kHz ticks, or 1048576 microseconds. This TEP emphasizes
-millisecond and 32kHz tick precisions while reasonably accommodating
-other precisions.</p>
+microseconds. All precisions presented in this TEP are in "binary"
+units with respect to one second. That is, one second contains 1024
+binary milliseconds, 32768 32kHz ticks, or 1048576 microseconds.
+This TEP emphasizes millisecond and 32kHz tick precisions while
+reasonably accommodating other precisions.</p>
<p>Examples of widths are 8-bit, 16-bit, 32-bit, and 64-bit. The width
for timer interfaces and components SHOULD be 32-bits. That is, for
lack of a good reason, timer interfaces should expose a 32-bit
<p>Precision is expressed as an empty type -- TMilli, T32khz, and
TMicro -- written in the standard Timer.h header like this:</p>
<pre class="literal-block">
-typedef struct { } TMilli;
-typedef struct { } T32khz;
-typedef struct { } TMicro;
+typedef struct { } TMilli; // 1024 ticks per second
+typedef struct { } T32khz; // 32768 ticks per second
+typedef struct { } TMicro; // 1048576 ticks per second
</pre>
<p>Note that the precision names are expressed as either frequency or
period, whichever is convenient.</p>
<dt>get()</dt>
<dd>return the current time.</dd>
<dt>isOverflowPending()</dt>
-<dd>return TRUE if an overflow interrupt will occur after the outermost
-atomic block is exits. FALSE otherwise.</dd>
+<dd>return TRUE if the overflow flag is set for this counter, i.e., if and
+only if an overflow interrupt will occur after the outermost atomic
+block exits. Return FALSE otherwise. This command only returns the
+state of the overflow flag and causes no side effect. It is expected
+that the underlying hardware platform sets the overflow flag when
+appropriate.</dd>
<dt>clearOverflow()</dt>
-<dd>cancel the pending overflow interrupt.</dd>
+<dd>cancel the pending overflow interrupt clearing the overflow flag.</dd>
<dt>overflow()</dt>
<dd>signals that an overflow in the current time. That is, the current
time has wrapped around from its maximum value to zero.</dd>
<div class="section">
<h2><a id="alarm" name="alarm">Alarm</a></h2>
<p>Alarm components are extensions of Counters that signal an event
-when their Compare register detects the alarm time has been hit.
+when their compare register detects the alarm time has been hit.
All commands and events of the Alarm interface are asynchronous (or
in "interrupt context"). The Alarm interface provides a set of
"basic" commands for common usage and provides a set of "extended"
<dt>isRunning()</dt>
<dd>return TRUE if the alarm has been started and has not been cancelled
or has not yet fired. FALSE is returned otherwise.</dd>
-<dt>startAt(t0,dt)</dt>
-<dd>cancel any previously running alarm and set to fire at time t1 =
-t0+dt. This form allows a delay to be anchored to some time t0
-taken before the invocation of start. This is also the form used
-internally in the timer subsystem to allow the use of the full width
-of an alarm while being able to detect if the alarm time for a short
-alarm prematurely elapsed.</dd>
+</dl>
+<p>startAt(t0,dt)</p>
+<blockquote>
+cancel any previously running alarm and set to fire at time t1 =
+t0+dt. This form allows a delay to be anchored to some time t0 taken
+before the invocation of startAt. The timer subsystem uses this form
+internally, to be able to use of the full width of an alarm while also
+detecting when a short alarm elapses prematurely.</blockquote>
+<dl class="docutils">
<dt>getNow()</dt>
<dd>return the current time in the precision and width of the alarm.</dd>
<dt>getAlarm()</dt>
<dd>return the time the currently running alarm will fire or the time
-that the previously running alarm was set to fire.</dd>
+that the previously running alarm was set to fire. getAlarm can
+be used with startAt to set an alarm from the previous alarm time,
+as in startAt(getAlarm(),dt). This pattern is used within the
+fired() event to construct periodic alarms.</dd>
</dl>
</div>
<div class="section">
<h2><a id="busywait" name="busywait">BusyWait</a></h2>
-<p>The BusyWait interface replaces the TOSH_uwait macro from TinyOS
-1.x.</p>
+<p>The BusyWait interface allows for very short synchronous delays.
+BusyWait should be used sparingly and when an Alarm would not be
+reasonably efficient or accurate. The BusyWait interface replaces
+the TOSH_uwait macro from TinyOS 1.x.</p>
+<p>BusyWait blocks for no less than the specified amount of time. No
+explicit upper bound is imposed on the enacted delay, though it is
+expected the underlying implementation spins in a busy loop until
+the specified amount of time has elapsed.</p>
<pre class="literal-block">
interface BusyWait<precision_tag,size_type>
{
</pre>
<dl class="docutils">
<dt>wait(dt)</dt>
-<dd>block for no less than the specified amount of time.</dd>
+<dd>block until at least dt time units have elapsed</dd>
</dl>
</div>
<div class="section">
</div>
<div class="section">
<h1><a id="hal-guidelines" name="hal-guidelines">3. HAL guidelines</a></h1>
-<p>Platforms typically select a clocking option for each of their
-hardware counters, based on their hardware design (e.g., the mica
-family of motes all run their hardware timer 0 at 32kHz, and the micaz
-mote runs its timer 1 at cpu frequency/256). Platforms SHOULD expose
-the timing functionality of these timers using the Alarm and Counter
-interfaces, in the fashion described below. Platforms MAY expose the
-same hardware timer with different frequencies - use of conflicting
-frequences in the same program SHOULD produce compile-time
-errors.</p>
-<p>A hardware timer with precision <em>P</em> and width <em>W</em> SHOULD be exposed as a
-several components:</p>
+<p>Platforms SHOULD expose their relevant timing capabilities using
+standard Alarm and Counter interfaces. The design pattern presented
+here defines a component naming convention to allow platform
+independent access to particular Alarms and Counters if they exist
+and to cause compile errors if they do not.</p>
+<p>A platform specific hardware timer with precision ${P} and width
+${W} SHOULD be exposed as these two conventional Counter and Alarm
+components:</p>
<pre class="literal-block">
-configuration CounterPWC {
- provides interface Counter<TP, uintW_t>;
-} ...
-generic configuration AlarmPWC {
- provides interface Alarm<TP,uintW_t>;
-} ...
+configuration Counter${P}${W}C
+{
+ provides interface Counter< T${P}, uint${W}_t >;
+}
+
+generic configuration Alarm${P}${W}C()
+{
+ provides interface Alarm< T${P}, uint${W}_t >;
+}
</pre>
-<p>and, except if <em>W</em> is 32:</p>
+<p>Instantiating an Alarm${P}${W}C component provides a new and
+independent Alarm. If the platform presents a limited number of
+Alarm resources, then allocating more Alarms in an application than
+are available for the platform SHOULD produce a compile-time error.
+See Appendix B for an example of how to make allocatable Alarms that
+are each implemented on independent hardware timers.</p>
+<p>For example, if a platform has an 8-bit 32kHz counter and three
+8-bit 32kHz alarms, then the Counter and Alarm interfaces for
+${P}=32khz and ${W}=16 are:</p>
<pre class="literal-block">
-configuration CounterP32C {
- provides interface Counter<TP, uint32_t>;
-} ...
-generic configuration AlarmP32C {
- provides interface Alarm<TP,uint32_t>;
-} ...
+configuration Counter32khz8C
+{
+ provides interface Counter< T32khz, uint8_t >;
+}
+
+generic configuration Alarm32khz8C()
+{
+ provides interface Alarm< T32khz, uint8_t >;
+}
</pre>
-<p>Instantiating the Alarm... components provides a new Alarm independent
-of all prior instantiations. Instantiating such a component "consumes"
-a compare register from the corresponding hardware timer; when no more
-compare registers are available, instantiation SHOULD produce a
-compile-time error (see Appendix B for an example of how to achieve
-this).</p>
-<p>For example, the micaz platform includes an AlarmMilli8C and
-AlarmMilli32C components for timer 0 (one instantiation allowed), and
-Alarm32kHz16C and Alarm32kHz32C for timer 1 (three instantiations
-allowed).</p>
+<p>This pattern MAY be used to defined components for the platform that
+are mutually incompatible in single application. Incompatible
+components SHOULD produce compile-time errors when compiled
+together.</p>
</div>
<div class="section">
<h1><a id="hil-requirements" name="hil-requirements">4. HIL requirements</a></h1>
<dl class="docutils">
<dt>The following component MUST be provided on all platforms::</dt>
-<dd>TimerMilliC
+<dd>HilTimerMilliC
BusyWaitMicroC</dd>
</dl>
<div class="section">
-<h2><a id="timermillic" name="timermillic">TimerMilliC</a></h2>
+<h2><a id="hiltimermillic" name="hiltimermillic">HilTimerMilliC</a></h2>
<pre class="literal-block">
-#define TIMERMILLIC_SERVICE ...
-configuration TimerMilliC
+configuration HilTimerMilliC
{
provides interface Init;
- provides interface Timer<TMilli>[uint8_t num];
- provides interface LocalTime<TMilli>;
+ provides interface Timer<TMilli> as TimerMilli[ uint8_t num ];
}
</pre>
-<p>A timer is allocated using unique(TIMERMILLIC_SERVICE) to obtain a new
-unique timer number. This timer number is used to index the TimerMilli
-parameterised interface.</p>
+<p>A new timer is allocated using unique(UQ_TIMER_MILLI) to obtain a
+new unique timer number. This timer number is used to index the
+TimerMilli parameterised interface. UQ_TIMER_MILLI is defined in
+Timer.h. HilTimerMilliC is used by the generic component
+TimerMilliC found in <tt class="docutils literal"><span class="pre">tos/system/</span></tt>.</p>
</div>
<div class="section">
<h2><a id="busywaitmicroc" name="busywaitmicroc">BusyWaitMicroC</a></h2>
}
</pre>
<p>BusyWaitMicroC allows applications to busy-wait for a number of
-microseconds. It's use should be restricted to situations where the
+microseconds. Its use should be restricted to situations where the
delay is small and setting a timer or alarm would be impractical,
inefficient or insufficiently precise.</p>
</div>
<pre class="literal-block">
new TransformAlarmC( TMilli, uint32_t, T32khz, uint16_t, 5 )
</pre>
+<p>It is the exclusive responsibility of the developer using
+TransformAlarmC to ensure that all five of its arguments are self
+consistent. No compile errors are generated if the parameters
+passed to TransformAlarmC are inconsistent.</p>
</div>
<div class="section">
<h2><a id="transformcounterc" name="transformcounterc">TransformCounterC</a></h2>
</div>
</div>
<div class="section">
-<h1><a id="author-s-address" name="author-s-address">6. Author's Address</a></h1>
+<h1><a id="implementation" name="implementation">6. Implementation</a></h1>
+<p>The definition of the HIL interfaces are found in <tt class="docutils literal"><span class="pre">tinyos-2.x/tos/lib/timer</span></tt>:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">Alarm.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">BusyWait.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">Counter.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">LocalTime.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">Timer.h</span></tt> defines precision tags and strings for unique()</li>
+<li><tt class="docutils literal"><span class="pre">Timer.nc</span></tt></li>
+</ul>
+</blockquote>
+<p>The implementation of the utility components are also found in
+<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/lib/timer</span></tt>:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">AlarmToTimerC.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">BusyWaitCounterC.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">CounterToLocalTimeC.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TransformAlarmC.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TransformAlarmCounterC.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">TransformCounterC.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">VirtualizeAlarmC.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">VirtualizeTimerC.nc</span></tt></li>
+</ul>
+</blockquote>
+<p>The implementation of Timers for the MSP430 is in
+<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/chips/msp430/timer</span></tt>:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">Alarm32khz16C.nc</span></tt> is generic and provides a new <tt class="docutils literal"><span class="pre">Alarm<T32khz,uint16_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">Alarm32khz32C.nc</span></tt> is generic and provides a new <tt class="docutils literal"><span class="pre">Alarm<T32khz,uint32_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">AlarmMilli16C.nc</span></tt> is generic and provides a new <tt class="docutils literal"><span class="pre">Alarm<TMilli,uint16_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">AlarmMilli32C.nc</span></tt> is generic and provides a new <tt class="docutils literal"><span class="pre">Alarm<TMilli,uint32_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">BusyWait32khzC.nc</span></tt> provides <tt class="docutils literal"><span class="pre">BusyWait<T32khz,uint16_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">BusyWaitMicroC.nc</span></tt> provides <tt class="docutils literal"><span class="pre">BusyWait<TMicro,uint16_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">Counter32khz16C.nc</span></tt> provides <tt class="docutils literal"><span class="pre">Counter<T32khz,uint16_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">Counter32khz32C.nc</span></tt> provides <tt class="docutils literal"><span class="pre">Counter<T32khz,uint32_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">CounterMilli16C.nc</span></tt> provides <tt class="docutils literal"><span class="pre">Counter<TMilli,uint16_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">CounterMilli32C.nc</span></tt> provides <tt class="docutils literal"><span class="pre">Counter<TMilli,uint32_t></span></tt></li>
+<li><tt class="docutils literal"><span class="pre">GpioCaptureC.nc</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">HilTimerMilliC.nc</span></tt> provides <tt class="docutils literal"><span class="pre">Timer<TMilli></span> <span class="pre">as</span> <span class="pre">TimerMilli[uint8_t</span> <span class="pre">num]</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">Msp430AlarmC.nc</span></tt> is generic and converts an MSP430 timer to a 16-bit Alarm</li>
+<li><tt class="docutils literal"><span class="pre">Msp430Capture.nc</span></tt> HPL interface definition for MSP430 timer captures</li>
+<li><tt class="docutils literal"><span class="pre">Msp430ClockC.nc</span></tt> exposes MSP430 hardware clock initialization</li>
+<li><tt class="docutils literal"><span class="pre">Msp430ClockInit.nc</span></tt> HPL interface definition for hardware clock initialization</li>
+<li><tt class="docutils literal"><span class="pre">Msp430ClockP.nc</span></tt> implements MSP430 hardware clock initialization and
+calibration and startup</li>
+<li><tt class="docutils literal"><span class="pre">Msp430Compare.nc</span></tt> HPL interface definition for MSP430 timer compares</li>
+<li><tt class="docutils literal"><span class="pre">Msp430Counter32khzC.nc</span></tt> provides <tt class="docutils literal"><span class="pre">Counter<T32khz,uint16_t></span></tt> based on
+MSP430 TimerB</li>
+<li><tt class="docutils literal"><span class="pre">Msp430CounterC.nc</span></tt> is generic and converts an Msp430Timer to a Counter</li>
+<li><tt class="docutils literal"><span class="pre">Msp430CounterMicroC.nc</span></tt> provides <tt class="docutils literal"><span class="pre">Counter<TMicro,uint16_t></span></tt> based on
+MSP430 TimerA</li>
+<li><tt class="docutils literal"><span class="pre">Msp430Timer.h</span></tt> defines additional MSP430 timer bitmasks and structs</li>
+<li><tt class="docutils literal"><span class="pre">Msp430Timer.nc</span></tt> HPL interface definition</li>
+<li><tt class="docutils literal"><span class="pre">Msp430Timer32khzC.nc</span></tt> is generic and allocates a new 32khz hardware timer</li>
+<li><tt class="docutils literal"><span class="pre">Msp430Timer32khzMapC.nc</span></tt> exposes the MSP430 hardware timers as a
+parameterized interface allocatable using Msp430Timer32khzC</li>
+<li><tt class="docutils literal"><span class="pre">Msp430TimerC.nc</span></tt> exposes the MSP430 hardware timers</li>
+<li><tt class="docutils literal"><span class="pre">Msp430TimerCapComP.nc</span></tt> is generic and implements the HPL for MSP430
+capture/compare special function registers</li>
+<li><tt class="docutils literal"><span class="pre">Msp430TimerCommonP.nc</span></tt> maps the MSP430 timer interrupts to Msp430TimerEvents</li>
+<li><tt class="docutils literal"><span class="pre">Msp430TimerControl.nc</span></tt> HPL interface definition</li>
+<li><tt class="docutils literal"><span class="pre">Msp430TimerEvent.nc</span></tt> HPL interface definition</li>
+<li><tt class="docutils literal"><span class="pre">Msp430TimerP.nc</span></tt> is generic and implements the HPL for MSP430 timer
+special function registers</li>
+</ul>
+</blockquote>
+</div>
+<div class="section">
+<h1><a id="author-s-address" name="author-s-address">7. Author's Address</a></h1>
<div class="line-block">
<div class="line">Cory Sharp</div>
<div class="line">Moteiv Corporation</div>
<div class="line">55 Hawthorne St, Suite 550</div>
<div class="line">San Francisco, CA 94105</div>
<div class="line"><br /></div>
+<div class="line">phone - +1 415 692 0963</div>
<div class="line">email - <a class="reference" href="mailto:cory@moteiv.com">cory@moteiv.com</a></div>
<div class="line"><br /></div>
<div class="line"><br /></div>
<tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
</tr>
<tr><th class="docinfo-name">Status:</th>
-<td>Draft</td></tr>
+<td>Final</td></tr>
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>David Gay, Jonathan Hui</td></tr>
-<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">27-Sep-2004</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
-</tr>
</tbody>
</table>
<div class="note">
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
-<p>Flash chips are a form of EEPROM (electrically-eraseable, programmable
+<p>Flash chips are a form of EEPROM (electrically-erasable, programmable
read-only memory), distinguished by a fast erase capability. However,
erases can only be done in large units (from 256B to 128kB depending on the
flash chip). Erases are the only way to switch bits from 0 to 1, and
flash chips by their underlying technology (NOR vs NAND). We also
include a column for Atmel's AT45DB flash chip family, as it has
significantly different tradeoffs than other flash chips:</p>
-<pre class="literal-block">
- NOR AT45DB NAND
-
-Erase : Slow (seconds) Fast (ms) Fast (ms)
-Erase unit : Large (64KB-128KB) Small (256B) Medium (8K-32KB)
-Writes : Slow (100s kB/s) Slow (60kB/s) Fast (MBs/s)
-Write unit : 1 bit 256B 100's of bytes
-Bit-errors : Low Low High (requires ECC,
- bad-block mapping)
-Read : Fast* Slow+I/O bus Fast (but limited by
- I/O bus)
-Erase cycles : 10^4 - 10^5 10^4 ** 10^5 - 10^7
-Intended use : Code storage Data storage Data storage
-Energy/byte : 1uJ 1uJ .01uJ
-
-* Intel Mote2 NOR flash is memory mapped (reads are very fast and can
- directly execute code)
-** Or infinite? Data sheet just says that every page within a sector
- must be written every 10^4 writes within that sector
-</pre>
+<blockquote>
+<table border="1" class="docutils">
+<colgroup>
+<col width="19%" />
+<col width="27%" />
+<col width="25%" />
+<col width="28%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">X</th>
+<th class="head">NOR
+(ex: ST M25P40,
+Intel PXA27x)</th>
+<th class="head">AT45DB</th>
+<th class="head"><dl class="first last docutils">
+<dt>NAND</dt>
+<dd>(ex: Samsung
+K9K1G08R0B)</dd>
+</dl>
+</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>Erase</td>
+<td>Slow (seconds)</td>
+<td>Fast (ms)</td>
+<td>Fast (ms)</td>
+</tr>
+<tr><td>Erase unit</td>
+<td>Large (64KB-128KB)</td>
+<td>Small (256B)</td>
+<td>Medium (8KB-32KB)</td>
+</tr>
+<tr><td>Writes</td>
+<td>Slow (100s kB/s)</td>
+<td>Slow (60kB/s)</td>
+<td>Fast (MBs/s)</td>
+</tr>
+<tr><td>Write unit</td>
+<td>1 bit</td>
+<td>256B</td>
+<td>100's of bytes</td>
+</tr>
+<tr><td>Bit-errors</td>
+<td>Low</td>
+<td>Low</td>
+<td>High (requires ECC,
+bad-block mapping)</td>
+</tr>
+<tr><td>Read</td>
+<td>Bus limited <a class="footnote-reference" href="#id3" id="id1" name="id1">[*]</a></td>
+<td>Slow+Bus limited</td>
+<td>Bus limited</td>
+</tr>
+<tr><td>Erase cycles</td>
+<td>10^4 - 10^5</td>
+<td>10^4 <a class="footnote-reference" href="#id4" id="id2" name="id2">[†]</a></td>
+<td>10^5 - 10^7</td>
+</tr>
+<tr><td>Intended use</td>
+<td>Code storage</td>
+<td>Data storage</td>
+<td>Data storage</td>
+</tr>
+<tr><td>Energy/byte</td>
+<td>1uJ</td>
+<td>1uJ</td>
+<td>.01uJ</td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+<table class="docutils footnote" frame="void" id="id3" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id3">[*]</a></td><td>M25P40 reads are limited by the use of a 25MHz SPI bus. The PXA27x flash
+is memory mapped (reads are very fast and can directly execute code).</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="id4" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2" name="id4">[†]</a></td><td>Or infinite? Data sheet just says that every page within a sector
+must be written every 10^4 writes within that sector</td></tr>
+</tbody>
+</table>
<p>The energy/byte is the per-byte cost of erasing plus programming. It is
derived from the timing and power consumption of erase and write operations
(for NOR flash, values are for the STMicroelectronics M25P family, for NAND
-flash, values are from a Samsung datasheet). Energy/byte for reads appears
+flash, values are from the Samsung datasheet). Energy/byte for reads appears
to depend mostly on how long the read takes (the power consumptions are
comparable), i.e., on the efficiency of the bus + processor.</p>
<p>Early TinyOS platforms all used a flash chip from the AT45DB
<li>Using a high-level memory-like interface (<tt class="docutils literal"><span class="pre">ByteEEPROMC</span></tt>) with
read, write and logging operations.</li>
<li>Using a simple file system (<tt class="docutils literal"><span class="pre">Matchbox</span></tt>) with sequential-only
-files [<a class="reference" href="#id1">1</a>].</li>
+files [<a class="reference" href="#id5">1</a>].</li>
</ul>
<p>Some more recent platforms use different flash chips: the ST M25P family (Telos
rev. B, eyes) and the Intel Strataflash (Intel Mote2). None of the
reimplemented for these other chips, in part because it does not
support some applications (e.g., network reprogramming) very well.</li>
</ul>
+</div>
+<div class="section">
+<h1><a id="storage-in-tinyos-2-x" name="storage-in-tinyos-2-x">2. Storage in TinyOS 2.x</a></h1>
<p>One approach to hiding the differences between different flash chips is to
provide a disk-like, block interface (with, e.g., 512B blocks). This is the
approach taken by compact flash cards. However, in the context of TinyOS,
requires remapping blocks. We believe that maintaining this remapping
table is too expensive on many mote-class devices.</li>
</ul>
-<p>Another approach to supporting multiple flash chips is to build a
-file system (like Matchbox) which can be implemented for multiple
-flash chips. However, TinyOS is currently targeted at running a
-single application, and many applications know their storage needs
-in advance: for instance, a little space for configuration data, and
-everything else for a log of all sampled data. In such cases, the
-flexibility offered by a filing system (e.g., arbitrary numbers of
-files) is overkill, and may come at the expense of implementation
-and runtime complexity.</p>
-<p>Instead, TinyOS 2.x, divides flash chips into separate volumes (with
-sizes fixed at compile-time). Each volume provides a single storage
-abstraction (the abstraction defines the format). So far there are three
-such abstractions: large objects written in a single session,
-small objects with arbitrary reads and writes, and logs. This approach
-has two advantages:</p>
+<p>A second approach is to provide a generic low-level interface providing
+operations (read, write, erase) corresponding to the basic flash
+operations, along with information describing the flash chip's layout
+(minimum write and erase unit, timing information, etc). However,
+we believe that the large differences between NAND and NOR flash (see the
+table above), in particular the differences in reliability, write and
+erase units, make the design of a useful generic low-level interface
+tricky at best.</p>
+<p>We thus believe it is best, for now at least, to define high-level
+storage abstractions that are useful for sensor network applications,
+and leave their implementation up to each flash chip - such abstractions
+will be necessary anyway. We leave open the possibility that a future
+TEP may define portable lower-level flash interfaces (either for all
+flash chips, or, e.g., for NOR-family flashes). Such low-level
+interfaces would allow implementations of the storage abstractions
+defined in this TEP to be used for multiple flash chips.</p>
+<p>This TEP describes three high-level storage abstractions: large objects
+written in a single session, small objects with arbitrary reads and
+writes, and logs. TinyOS 2.x, divides flash chips into separate volumes
+(with sizes fixed at compile-time). Each volume provides a single
+storage abstraction (the abstraction defines the format).</p>
+<p>We prefer the use of single abstractions over fixed-size volumes over
+the use of a more general filing system (like Matchbox) for several
+reasons:</p>
<ul class="simple">
+<li>TinyOS is currently targeted at running a single application, and many
+applications know their storage needs in advance: for instance, a
+little space for configuration data, and everything else for a log of
+all sampled data. In such cases, the flexibility offered by a filing
+system (e.g., arbitrary numbers of files) is overkill,</li>
<li>Each abstraction is relatively easy to implement on a new flash chip, and
has relatively little overhead.</li>
<li>The problem of dealing with the limited number of erase cycles/block
"wear levelling" (ensuring that each block of the flash is erased
the same number of time, to maximise flash chip lifetime).</li>
</ul>
-<p>New abstractions (including a filing system) can easily be added to this
-framework, or can be built on top of these abstractions.</p>
+<p>New abstractions (including a filing system) can easily be added to
+this framework.</p>
<p>The rest of this TEP covers some principles for the organisation of
-flash chips (Section 2), then describes the flash volumes and
-storage abstractions in detail (Section 3).</p>
+flash chips (Section 3), then describes the flash volumes and
+storage abstractions in detail (Section 4).</p>
</div>
<div class="section">
-<h1><a id="hpl-hal-hil-architecture" name="hpl-hal-hil-architecture">2. HPL/HAL/HIL Architecture</a></h1>
-<p>The flash chip architecture dollows the three-layer Hardware
+<h1><a id="hpl-hal-hil-architecture" name="hpl-hal-hil-architecture">3. HPL/HAL/HIL Architecture</a></h1>
+<p>The flash chip architecture follows the three-layer Hardware
Abstraction Architecture (HAA), with each chip providing a presentation
-layer (HPL, Section 2.1), adaptation layer (HAL, Section 2.2) and
-platform-independent interface layer (the storage abstractions described in
-Section 3) [<a class="reference" href="#id2">2</a>]. The implementation of these layers SHOULD be found in the
+layer (HPL, Section 3.1), adaptation layer (HAL, Section 3.2) and
+platform-independent interface layer (HIL, Section 3.3) [<a class="reference" href="#id6">2</a>].
+The implementation of these layers SHOULD be found in the
<tt class="docutils literal"><span class="pre">tos/chips/CHIPNAME</span></tt> directory. If a flash chip is part of a larger
family with a similar interface, the HAA SHOULD support all family members
by relying, e.g., on platform-provided configuration information.</p>
<p>Appendix A shows example HPL and HAL specifications for the AT45DB
and ST M25P chip families.</p>
<div class="section">
-<h2><a id="hardware-presentation-layer-hpl" name="hardware-presentation-layer-hpl">2.1 Hardware Presentation Layer (HPL)</a></h2>
-<p>The flash HPL has a chip-dependent, system-independent interface. The
-implementation of this HPL is system-dependent. The flash HPL SHOULD be
+<h2><a id="hardware-presentation-layer-hpl" name="hardware-presentation-layer-hpl">3.1 Hardware Presentation Layer (HPL)</a></h2>
+<p>The flash HPL has a chip-dependent, platform-independent interface. The
+implementation of this HPL is platform-dependent. The flash HPL SHOULD be
stateless.</p>
<p>To remain platform independent, a flash chip's HPL SHOULD connect to
platform-specific components
particular flash chip found on the platform.</p>
</div>
<div class="section">
-<h2><a id="hardware-adaptation-layer-hal" name="hardware-adaptation-layer-hal">2.2 Hardware Adaptation Layer (HAL)</a></h2>
-<p>The flash HAL has a chip-dependent, system-independent interface and
+<h2><a id="hardware-adaptation-layer-hal" name="hardware-adaptation-layer-hal">3.2 Hardware Adaptation Layer (HAL)</a></h2>
+<p>The flash HAL has a chip-dependent, platform-independent interface and
implementation. Flash families with a common HPL SHOULD have a common
HAL. Flash HAL's SHOULD expose a <tt class="docutils literal"><span class="pre">Resource</span></tt> interface and automatically
power-manage the underlying flash chip. Finally, the flash HAL MUST
programmer (see Section 3). This allows users to build new flash
abstractions that interact cleanly with the rest of the flash system.</p>
</div>
+<div class="section">
+<h2><a id="hardware-interface-layer-hil" name="hardware-interface-layer-hil">3.3 Hardware Interface Layer (HIL)</a></h2>
+<p>Each flash chip MUST support at least one of the storage abstractions
+described in Section 4. These abstractions SHOULD be presented in
+components named <tt class="docutils literal"><span class="pre">ChipAbstractionC</span></tt>, e.g., <tt class="docutils literal"><span class="pre">At45dbLogStorageC</span></tt>.
+Additionally, a flash chip implementation MAY support platforms
+with multiple instances of the same storage chip. The way in which
+this is achieved is not specified further in this TEP.</p>
+<p>Each platform MUST have <tt class="docutils literal"><span class="pre">AbstractionC</span></tt> components (e.g.,
+<tt class="docutils literal"><span class="pre">LogStorageC</span></tt>) implementing the storage abstractions of Section 4
+supported by its flash chip(s). On platforms with multiple storage chips
+SHOULD redirect uses of <tt class="docutils literal"><span class="pre">AbstractionC</span></tt> to the appropriate storage
+chip, based on the requested volume.</p>
+</div>
</div>
<div class="section">
-<h1><a id="non-volatile-storage-abstracitons-in-tinyos-2-x" name="non-volatile-storage-abstracitons-in-tinyos-2-x">3. Non-Volatile Storage Abstracitons in TinyOS 2.x</a></h1>
-<p>The HIL implementations are system-independent, but chip (family)
+<h1><a id="non-volatile-storage-abstractions" name="non-volatile-storage-abstractions">4. Non-Volatile Storage Abstractions</a></h1>
+<p>The HIL implementations are platform-independent, but chip (family)
dependent. They implement the three storage abstractions and
volume structure discussed in the introduction.</p>
<div class="section">
-<h2><a id="volumes" name="volumes">3.1. Volumes</a></h2>
+<h2><a id="volumes" name="volumes">4.1. Volumes</a></h2>
<p>The division of the flash chip into fixed-size volumes is specified by
an XML file that is placed in the application's directory (where one
types 'make'). The XML file specifies the allocation as follows:</p>
except that the specification to physical allocation MUST be one-to-one
(i.e. a given specification should always have the same resulting physical
allocation on a given chip) and the result MUST be placed in the build
-directory. When not specified, the tool may give any suitable physical
-location to a volume. If there is any reason that the physical allocation
+directory. When not specified, the tool picks a suitable physical
+location for a volume. If there is any reason that the physical allocation
cannot be satisfied, an error should be given at compile time. The tool
SHOULD be named <tt class="docutils literal"><span class="pre">tos-storage-CHIPNAME</span></tt> and be distributed with the other
-tools supporting a platform.</p>
+tools supporting a platform. The XML file SHOULD be named
+<tt class="docutils literal"><span class="pre">volumes-CHIPNAME.xml</span></tt>.</p>
<p>The compile-time tool MUST prepend 'VOLUME_' to each volume name in
the XML file and '#define' each resulting name to map to a unique
integer.</p>
<p>A volume MUST NOT be used with more than one storage abstraction instance.</p>
</div>
<div class="section">
-<h2><a id="large-objects" name="large-objects">3.2 Large objects</a></h2>
-<p>The motivating example for large objects is the transmission or long-term
-storage of large pieces of data. For instance, programs in a network-reprogramming
-system, or large data-packets in a reliable data-transmission system. Such
-objects have two interesting characteristics: each byte in the object is
-written at most once, and a full object is written in a single "session"
-(i.e., without the mote rebooting).</p>
+<h2><a id="large-objects" name="large-objects">4.2 Large objects</a></h2>
+<p>The motivating example for large objects is the transmission or
+long-term storage of large pieces of data. For instance, programs in a
+network-reprogramming system, or large data-packets in a reliable
+data-transmission system. Such objects have an interesting
+characteristic: each byte in the object is written at most once.</p>
<p>This leads to the definition of the <tt class="docutils literal"><span class="pre">BlockStorageC</span></tt> abstraction for storing
-large objects:</p>
+large objects or other "write-once" objects:</p>
<ul class="simple">
<li>A large object ranges from a few kilobytes upwards.</li>
-<li>A large object must be erased before use.</li>
-<li>A large object must be committed to ensure it survives a reboot or crash;
-after a commit no more writes may be performed.</li>
-<li>Random reads are allowed.</li>
-<li>Random writes are allowed are allowed between erase and commit; data
-cannot be overwritten.</li>
+<li>A large object is erased before the first write.</li>
+<li>A sync ensures that a large object survives a reboot or crash</li>
+<li>Reads are unrestricted</li>
+<li>Each byte can only be written once between two erases</li>
</ul>
<p>Large objects are accessed by instantiating a BlockStorageC component
which takes a volume id argument:</p>
}
} ...
</pre>
-<p>The <tt class="docutils literal"><span class="pre">BlockRead</span></tt> and <tt class="docutils literal"><span class="pre">BlockWrite</span></tt> interfaces contain the following
-operations (all split-phase, except <tt class="docutils literal"><span class="pre">BlockRead.getSize</span></tt>):</p>
+<p>The <tt class="docutils literal"><span class="pre">BlockRead</span></tt> and <tt class="docutils literal"><span class="pre">BlockWrite</span></tt> interfaces (briefly presented in
+Appendix B) contain the following operations (all split-phase, except
+<tt class="docutils literal"><span class="pre">BlockRead.getSize</span></tt>):</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">BlockWrite.erase</span></tt>: erase the volume. After a reboot or a commit, a
-volume must be erased before it can be written to.</li>
-<li><tt class="docutils literal"><span class="pre">BlockWrite.write</span></tt>: write some bytes starting at a given offset. Each
-byte can only be written once between an erase and the subsequent commit.</li>
-<li><tt class="docutils literal"><span class="pre">BlockWrite.commit</span></tt>: commit all writes to a given volume. No writes can
-be performed after a commit until a subsequent erase.</li>
-<li><tt class="docutils literal"><span class="pre">BlockRead.verify</span></tt>: verify that the volume contains the results of a
-successful commit.</li>
+volume MUST be erased before it can be written to.</li>
+<li><tt class="docutils literal"><span class="pre">BlockWrite.write</span></tt>: write some bytes starting at a given
+offset. Each byte MUST NOT be written more than once between two erases.</li>
+<li><tt class="docutils literal"><span class="pre">BlockWrite.sync</span></tt>: ensure all previous writes are present on a given
+volume. Sync MUST be called to ensure written data survives a reboot
+or crash.</li>
<li><tt class="docutils literal"><span class="pre">BlockRead.read</span></tt>: read some bytes starting at a given offset.</li>
<li><tt class="docutils literal"><span class="pre">BlockRead.computeCrc</span></tt>: compute the CRC of some bytes starting at a
given offset.</li>
</ul>
<p>For full details on arguments and other considerations, see the comments in
the interface definitions.</p>
+<p>Note that these interfaces contain no direct support for verifying the
+integrity of the BlockStorage data, but such support can easily be built
+by using the <tt class="docutils literal"><span class="pre">computeCrc</span></tt> command and storing the result in a
+well-defined location, and checking this CRC when desired.</p>
</div>
<div class="section">
-<h2><a id="logging" name="logging">3.3 Logging</a></h2>
-<p>Event and reuslt logging is a common requirement in sensor
+<h2><a id="logging" name="logging">4.3 Logging</a></h2>
+<p>Event and result logging is a common requirement in sensor
networks. Such logging should be reliable (a mote crash should not
lose data). It should also be easy to extract data from the log,
either partially or fully. Some logs are <em>linear</em> (stop logging when
the volume is full), others are <em>circular</em> (the oldest data is
overwritten when the volume is full).</p>
-<p>The <tt class="docutils literal"><span class="pre">LogStorageC</span></tt> abstraction supports these requirements. The log is record
-based: each call to <tt class="docutils literal"><span class="pre">LogWrite.append</span></tt> (see below) creates a new
-record. On failure (crash or reboot), the log is guaranteed to only lose
-whole records from the end of the log. Additionally, once a circular log
-wraps around, calls to <tt class="docutils literal"><span class="pre">LogWrite.append</span></tt> only lose whole records from the
-beginning of the log. These guarantees mean that applications do not to
-have worry about incomplete or inconsistent log entries.</p>
+<p>The <tt class="docutils literal"><span class="pre">LogStorageC</span></tt> abstraction supports these requirements. The log is
+record based: each call to <tt class="docutils literal"><span class="pre">LogWrite.append</span></tt> (see below) creates a new
+record. On failure (crash or reboot), the log MUST only lose whole
+records from the end of the log. Additionally, once a circular log wraps
+around, calls to <tt class="docutils literal"><span class="pre">LogWrite.append</span></tt> MUST only lose whole records from
+the beginning of the log.</p>
<p>Logs are accessed by instantiating a LogStorageC component which takes a
volume id and a boolean argument:</p>
<pre class="literal-block">
</pre>
<p>If the <tt class="docutils literal"><span class="pre">circular</span></tt> argument is TRUE, the log is circular; otherwise
it is linear.</p>
-<p>The <tt class="docutils literal"><span class="pre">LogRead</span></tt> and <tt class="docutils literal"><span class="pre">LogWrite</span></tt> interfaces contain the following
-operations (all split-phase except <tt class="docutils literal"><span class="pre">LogWrite.currentOffset</span></tt>,
-<tt class="docutils literal"><span class="pre">LogRead.currentOffset</span></tt> and <tt class="docutils literal"><span class="pre">LogRead.getSize</span></tt>):</p>
+<p>The <tt class="docutils literal"><span class="pre">LogRead</span></tt> and <tt class="docutils literal"><span class="pre">LogWrite</span></tt> interfaces (briefly presented in
+Appendix B) contain the following operations (all split-phase except
+<tt class="docutils literal"><span class="pre">LogWrite.currentOffset</span></tt>, <tt class="docutils literal"><span class="pre">LogRead.currentOffset</span></tt> and
+<tt class="docutils literal"><span class="pre">LogRead.getSize</span></tt>):</p>
<ul>
-<li><p class="first"><tt class="docutils literal"><span class="pre">LogWrite.erase</span></tt>: erase the log.</p>
+<li><p class="first"><tt class="docutils literal"><span class="pre">LogWrite.erase</span></tt>: erase the log. A log MUST be erased (possibly in
+some previous session) before any other operation can be used.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">LogWrite.append</span></tt>: append some bytes to the log. In a circular log,
this may overwrite the current read position. In this case, the
-read position is implicitly advanced to the log's current beginning
-(i.e., as if <tt class="docutils literal"><span class="pre">LogRead.seek</span></tt> had been called with <tt class="docutils literal"><span class="pre">SEEK_BEGINNING</span></tt>).</p>
+read position MUST be advanced to the log's current beginning
+(i.e., as if <tt class="docutils literal"><span class="pre">LogRead.seek</span></tt> had been called with <tt class="docutils literal"><span class="pre">SEEK_BEGINNING</span></tt>).
+Additionally, the <tt class="docutils literal"><span class="pre">LogWrite.appendDone</span></tt> event reports whenever, in a
+circular log, an append MAY have erased old records.</p>
<p>Each append creates a separate record. Log implementations may have a
maximum record size; all implementations MUST support records of up
to 255 bytes.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">LogWrite.sync</span></tt>: guarantee that data written so far will not be lost to
a crash or reboot (it can still be overwritten when a circular log wraps
-around). Using <tt class="docutils literal"><span class="pre">sync</span></tt> may waste some space in the log.</p>
+around). Using <tt class="docutils literal"><span class="pre">sync</span></tt> MAY waste some space in the log.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">LogWrite.currentOffset</span></tt>: return cookie representing current
append position (for use with <tt class="docutils literal"><span class="pre">LogRead.seek</span></tt>).</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">LogRead.read</span></tt>: read some bytes from the current read position in
the log and advance the read position.</p>
+<p><tt class="docutils literal"><span class="pre">LogStorageC</span></tt> implementations MUST include error detection codes
+to increase the likelihood of detection of corrupted or invalid log
+data. Data returned by a successful read MUST have passed this
+error detection check. The behaviour on failure of this check is
+unspecified (e.g., the at45db believes as if the end of the log has
+been reached; other implementations may behave differently).</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">LogRead.currentOffset</span></tt>: return cookie representing current
read position (for use with <tt class="docutils literal"><span class="pre">LogRead.seek</span></tt>).</p>
<tt class="docutils literal"><span class="pre">SEEK_BEGINNING</span></tt> was requested.</p>
<p><tt class="docutils literal"><span class="pre">SEEK_BEGINNING</span></tt> positions the read position at the beginning of
the oldest record still present in the log.</p>
+<p>After reboot, the current read position is <tt class="docutils literal"><span class="pre">SEEK_BEGINNING</span></tt>.</p>
</li>
-<li><p class="first"><tt class="docutils literal"><span class="pre">LogRead.getSize</span></tt>: return an approximation of the log's capacity.
-Uses of <tt class="docutils literal"><span class="pre">sync</span></tt> and other overhead may reduce this number.</p>
+<li><p class="first"><tt class="docutils literal"><span class="pre">LogRead.getSize</span></tt>: return an approximation of the log's capacity
+in bytes. Uses of <tt class="docutils literal"><span class="pre">sync</span></tt> and other overhead may reduce this number.</p>
</li>
</ul>
<p>For full details on arguments, etc, see the comments in the interface
definitions.</p>
+<p>Note that while each call to <tt class="docutils literal"><span class="pre">append</span></tt> logically creates a separate
+record, the <tt class="docutils literal"><span class="pre">LogStorageC</span></tt> API does not report record
+boundaries. Additionally, crashes, reboots, and appends after
+wrap-around in a circular log can cause the loss of multiple consecutive
+records. Taken together, these restrictions mean that a <tt class="docutils literal"><span class="pre">LogStorageC</span></tt>
+implementation MAY internally aggregate several consecutive appends into
+a single record. However, the guarantee that only whole records are lost
+is sufficient to ensure that applications do not to have worry about
+incomplete or inconsistent log entries.</p>
</div>
<div class="section">
-<h2><a id="small-objects" name="small-objects">3.4 Small objects:</a></h2>
-<p>Sensor network applications may need to store configuration data, e.g.,
-mote id, radio frequency, sample rates, etc. Such data is not large, but
+<h2><a id="small-objects" name="small-objects">4.4 Small objects:</a></h2>
+<p>Sensor network applications need to store configuration data, e.g.,
+mote identity, radio frequency, sample rates, etc. Such data is not large, but
losing it may lead to a mote misbehaving or losing contact with the
network.</p>
<p>The <tt class="docutils literal"><span class="pre">ConfigStorageC</span></tt> abstraction stores a single small object in a volume. It:</p>
</pre>
<p>A small object MUST be mounted (via the <tt class="docutils literal"><span class="pre">Mount</span></tt> interface) before
the first use.</p>
-<p>The <tt class="docutils literal"><span class="pre">Mount</span></tt> and <tt class="docutils literal"><span class="pre">ConfigStorage</span></tt> interfaces contain the following
-operations (all split-phase except <tt class="docutils literal"><span class="pre">ConfigStorage.getSize</span></tt> and
-<tt class="docutils literal"><span class="pre">ConfigStorage.valid</span></tt>):</p>
+<p>The <tt class="docutils literal"><span class="pre">Mount</span></tt> and <tt class="docutils literal"><span class="pre">ConfigStorage</span></tt> interfaces (briefly presented in
+Appendix B) contain the following operations (all split-phase except
+<tt class="docutils literal"><span class="pre">ConfigStorage.getSize</span></tt> and <tt class="docutils literal"><span class="pre">ConfigStorage.valid</span></tt>):</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">Mount.mount</span></tt>: mount the volume.</li>
<li><tt class="docutils literal"><span class="pre">ConfigStorage.valid</span></tt>: return TRUE if the volume contains a
</div>
</div>
<div class="section">
-<h1><a id="implementations" name="implementations">4. Implementations</a></h1>
+<h1><a id="implementations" name="implementations">5. Implementations</a></h1>
<p>An AT45DB implementation can be found in tinyos-2.x/tos/chips/at45db.</p>
<p>An ST M25P implementation can be found in tinyos-2.x/tos/chips/stm25p.</p>
</div>
<div class="section">
-<h1><a id="authors-addresses" name="authors-addresses">5. Authors' Addresses</a></h1>
+<h1><a id="authors-addresses" name="authors-addresses">6. Authors' Addresses</a></h1>
<div class="line-block">
<div class="line">David Gay</div>
<div class="line">2150 Shattuck Ave, Suite 1300</div>
</div>
</div>
<div class="section">
-<h1><a id="citations" name="citations">6. Citations</a></h1>
-<table class="docutils footnote" frame="void" id="id1" rules="none">
+<h1><a id="citations" name="citations">7. Citations</a></h1>
+<table class="docutils footnote" frame="void" id="id5" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a name="id1">[1]</a></td><td>David Gay. "Design of Matchbox, the simple filing system for
+<tr><td class="label"><a name="id5">[1]</a></td><td>David Gay. "Design of Matchbox, the simple filing system for
motes. (version 1.0)."</td></tr>
</tbody>
</table>
-<table class="docutils footnote" frame="void" id="id2" rules="none">
+<table class="docutils footnote" frame="void" id="id6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a name="id2">[2]</a></td><td>TEP 2: Hardware Abstraction Architecture.</td></tr>
+<tr><td class="label"><a name="id6">[2]</a></td><td>TEP 2: Hardware Abstraction Architecture.</td></tr>
</tbody>
</table>
</div>
obtain the volume id of each of its clients.</p>
</div>
</div>
+<div class="section">
+<h1><a id="appendix-b-storage-interfaces" name="appendix-b-storage-interfaces">Appendix B. Storage interfaces</a></h1>
+<p>These interfaces are presented briefly here for reference; please refer
+to the TinyOS documentation for a full description of the commands,
+events and their parameters.</p>
+<div class="section">
+<h2><a id="b-1-blockstorage-interfaces" name="b-1-blockstorage-interfaces">B.1 BlockStorage interfaces</a></h2>
+<p>The BlockStorage interfaces are:</p>
+<pre class="literal-block">
+interface BlockRead {
+ command error_t read(storage_addr_t addr, void* buf, storage_len_t len);
+ event void readDone(storage_addr_t addr, void* buf, storage_len_t len,
+ error_t error);
+
+ command error_t computeCrc(storage_addr_t addr, storage_len_t len,
+ uint16_t crc);
+ event void computeCrcDone(storage_addr_t addr, storage_len_t len,
+ uint16_t crc, error_t error);
+
+ command storage_len_t getSize();
+}
+
+interface BlockWrite {
+ command error_t write(storage_addr_t addr, void* buf, storage_len_t len);
+ event void writeDone(storage_addr_t addr, void* buf, storage_len_t len,
+ error_t error);
+
+ command error_t erase();
+ event void eraseDone(error_t error);
+
+ command error_t sync();
+ event void syncDone(error_t error);
+}
+</pre>
+</div>
+<div class="section">
+<h2><a id="b-2-configstorage-interfaces" name="b-2-configstorage-interfaces">B.2 ConfigStorage interfaces</a></h2>
+<p>The ConfigStorage interfaces are:</p>
+<pre class="literal-block">
+interface Mount {
+ command error_t mount();
+ event void mountDone(error_t error);
+}
+
+interface ConfigStorage {
+ command error_t read(storage_addr_t addr, void* buf, storage_len_t len);
+ event void readDone(storage_addr_t addr, void* buf, storage_len_t len,
+ error_t error);
+
+ command error_t write(storage_addr_t addr, void* buf, storage_len_t len);
+ event void writeDone(storage_addr_t addr, void* buf, storage_len_t len,
+ error_t error);
+
+ command error_t commit();
+ event void commitDone(error_t error);
+
+ command storage_len_t getSize();
+ command bool valid();
+}
+</pre>
+</div>
+<div class="section">
+<h2><a id="b-3-logstorage-interfaces" name="b-3-logstorage-interfaces">B.3 LogStorage interfaces</a></h2>
+<p>The LogStorage interfaces are:</p>
+<pre class="literal-block">
+interface LogRead {
+ command error_t read(void* buf, storage_len_t len);
+ event void readDone(void* buf, storage_len_t len, error_t error);
+
+ command storage_cookie_t currentOffset();
+
+ command error_t seek(storage_cookie_t offset);
+ event void seekDone(error_t error);
+
+ command storage_len_t getSize();
+}
+
+interface LogWrite {
+ command error_t append(void* buf, storage_len_t len);
+ event void appendDone(void* buf, storage_len_t len, bool recordsLost,
+ error_t error);
+
+ command storage_cookie_t currentOffset();
+
+ command error_t erase();
+ event void eraseDone(error_t error);
+
+ command error_t sync();
+ event void syncDone(error_t error);
+}
+</pre>
+</div>
+</div>
</div>
</body>
</html>
<td>Philip Levis and Cory Sharp</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">10-Dec-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.3</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.10</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-09-08</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-08-17</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<td>Philip Levis</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">10-Dec-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.11</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-06-13</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<br />Vlado Handziski</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">28-Mar-2005</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.3</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.11</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-09-08</td>
</tr>
reflect the specifc name of the sensor, and optionally provide a
component with a generic name for application authors who only care
about the general class of the sensor.</p>
-<p>This document assumes that sensors return uninterpreted values of
-arbitrary size or datatype. Conversion of sensor values to something
-with actual physical meaning is beyond the scope of this document.</p>
+<p>This document takes no position on the meaning of the values returned
+by sensor drivers. They may be raw uninterpreted values or they may
+have some physical meaning. If a driver returns uninterpreted values,
+the driver may provide additional interfaces that would allow
+higher-level clients to interpret the value properly.</p>
</div>
<div class="section">
<h1><a id="sensor-hil-components" name="sensor-hil-components">2. Sensor HIL Components</a></h1>
</pre>
</div>
<div class="section">
-<h1><a id="sensor-hpl-components" name="sensor-hpl-components">4. Sensor HPL Components</a></h1>
-<p>A sensor HPL is necessarily platform-dependent or
-sensorboard-dependent. These components should provide access to the
-physical resources needed by the sensor, in a platform-independent
-manner that can be used by the shared logic of the sensor HAL
-components. In the case of bus-based sensors, this HPL may be nothing
-more than wiring to the appropriate bus interface for use by the HAL
-component.</p>
-<p>For example:</p>
-<pre class="literal-block">
-configuration HplSensirionSht11C {
- provides interface Init;
- provides interface Resource[ uint8_t id ];
- provides interface GeneralIO as DATA;
- provides interface GeneralIO as SCK;
- provides interface GpioInterrupt as InterruptDATA;
-}
-implementation {
- // connect to platform or sensorboard-dependent resources
- // power-manage the sensor through platform-specific means
-}
-</pre>
-</div>
-<div class="section">
-<h1><a id="directory-organization-guidelines" name="directory-organization-guidelines">5. Directory Organization Guidelines</a></h1>
+<h1><a id="directory-organization-guidelines" name="directory-organization-guidelines">4. Directory Organization Guidelines</a></h1>
<p>Because the same physical sensor may be attached to TinyOS platforms
in many different ways, the organization of sensor drivers should
reflect the distinction between sensor and sensor interconnect.</p>
receives enough <cite>-I</cite> directives to locate all of the necessary pieces.</p>
</div>
<div class="section">
-<h1><a id="authors-addresses" name="authors-addresses">6. Authors' Addresses</a></h1>
+<h1><a id="authors-addresses" name="authors-addresses">5. Authors' Addresses</a></h1>
<div class="line-block">
<div class="line">David Gay</div>
<div class="line">2150 Shattuck Ave, Suite 1300</div>
</div>
</div>
<div class="section">
-<h1><a id="citations" name="citations">7. Citations</a></h1>
+<h1><a id="citations" name="citations">6. Citations</a></h1>
<table class="docutils citation" frame="void" id="tep2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
</tbody>
</table>
</div>
+<div class="section">
+<h1><a id="appendix-a-sensor-driver-examples" name="appendix-a-sensor-driver-examples">Appendix A: Sensor Driver Examples</a></h1>
+<div class="section">
+<h2><a id="analog-adc-connected-sensor" name="analog-adc-connected-sensor">1. Analog ADC-Connected Sensor</a></h2>
+<p>The Analog sensor requires two components</p>
+<ul class="simple">
+<li>a component to present the sensor itself (HamamatsuS1087ParC)</li>
+<li>a component to select the appropriate hardware resources, such as
+ADC port 4, reference voltage 1.5V, and a slow sample and hold time
+(HamamatsuS1087ParP).</li>
+</ul>
+<p>The AdcReadClientC component and underlying machinery handles all of
+the arbitration and access to the ADC.</p>
+<pre class="literal-block">
+tos/platforms/telosa/chips/s1087/HamamatsuS1087ParC.nc
+
+generic configuration HamamatsuS1087ParC() {
+ provides interface Read<uint16_t>;
+ provides interface ReadStream<uint16_t>;
+}
+implementation {
+ components new AdcReadClientC();
+ Read = AdcReadClientC;
+
+ components new AdcReadStreamClientC();
+ ReadStream = AdcReadStreamClientC;
+
+ components HamamatsuS1087ParP;
+ AdcReadClientC.Msp430Adc12Config -> HamamatsuS1087ParP;
+ AdcReadStreamClientC.Msp430Adc12Config -> HamamatsuS1087ParP;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/s1087/HamamatsuS1087ParP.nc
+
+module HamamatsuS1087ParP {
+ provides interface Msp430Adc12Config;
+}
+implementation {
+
+ async command msp430adc12_channel_config_t
+ Msp430Adc12Config.getChannelSettings() {
+
+ msp430adc12_channel_config_t config = {
+ inch: INPUT_CHANNEL_A4,
+ sref: REFERENCE_VREFplus_AVss,
+ ref2_5v: REFVOLT_LEVEL_1_5,
+ adc12ssel: SHT_SOURCE_ACLK,
+ adc12div: SHT_CLOCK_DIV_1,
+ sht: SAMPLE_HOLD_4_CYCLES,
+ sampcon_ssel: SAMPCON_SOURCE_SMCLK,
+ sampcon_id: SAMPCON_CLOCK_DIV_1
+ };
+
+ return config;
+ }
+}
+</pre>
+</div>
+<div class="section">
+<h2><a id="binary-pin-connected-sensor" name="binary-pin-connected-sensor">2. Binary Pin-Connected Sensor</a></h2>
+<p>The Binary sensor gets a bit more complex, because it has three
+components:</p>
+<ul class="simple">
+<li>one to present the sensor (UserButtonC)</li>
+<li>one to execute the driver logic (UserButtonLogicP)</li>
+<li>one to select the appropriate hardware resources, such as MSP430
+Port 27 (HplUserButtonC).</li>
+</ul>
+<p>Note that the presentation of this sensor is not arbitrated because
+none of the operations are split-phase.</p>
+<pre class="literal-block">
+tos/platforms/telosa/UserButtonC.nc
+
+configuration UserButtonC {
+ provides interface Get<bool>;
+ provides interface Notify<bool>;
+}
+implementation {
+
+ components UserButtonLogicP;
+
+ components HplUserButtonC;
+ UserButtonLogicP.GpioInterrupt -> HplUserButtonC.GpioInterrupt;
+ UserButtonLogicP.GeneralIO -> HplUserButtonC.GeneralIO;
+
+ Get = UserButtonLogicP;
+ Notify = UserButtonLogicP;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/UserButtonLogicP.nc
+
+module UserButtonLogicP {
+ provides interface Get<bool>;
+ provides interface Notify<bool>;
+
+ uses interface GeneralIO;
+ uses interface GpioInterrupt;
+}
+implementation {
+ norace bool m_pinHigh;
+
+ task void sendEvent();
+
+ command bool Get.get() { return call GeneralIO.get(); }
+
+ command error_t Notify.enable() {
+ call GeneralIO.makeInput();
+
+ if ( call GeneralIO.get() ) {
+ m_pinHigh = TRUE;
+ return call GpioInterrupt.enableFallingEdge();
+ } else {
+ m_pinHigh = FALSE;
+ return call GpioInterrupt.enableRisingEdge();
+ }
+ }
+
+ command error_t Notify.disable() {
+ return call GpioInterrupt.disable();
+ }
+
+ async event void GpioInterrupt.fired() {
+ call GpioInterrupt.disable();
+
+ m_pinHigh = !m_pinHigh;
+
+ post sendEvent();
+ }
+
+ task void sendEvent() {
+ bool pinHigh;
+ pinHigh = m_pinHigh;
+
+ signal Notify.notify( pinHigh );
+
+ if ( pinHigh ) {
+ call GpioInterrupt.enableFallingEdge();
+ } else {
+ call GpioInterrupt.enableRisingEdge();
+ }
+ }
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/HplUserButtonC.nc
+
+configuration HplUserButtonC {
+ provides interface GeneralIO;
+ provides interface GpioInterrupt;
+}
+implementation {
+
+ components HplMsp430GeneralIOC as GeneralIOC;
+
+ components new Msp430GpioC() as UserButtonC;
+ UserButtonC -> GeneralIOC.Port27;
+ GeneralIO = UserButtonC;
+
+ components HplMsp430InterruptC as InterruptC;
+
+ components new Msp430InterruptC() as InterruptUserButtonC;
+ InterruptUserButtonC.HplInterrupt -> InterruptC.Port27;
+ GpioInterrupt = InterruptUserButtonC.Interrupt;
+}
+</pre>
+</div>
+<div class="section">
+<h2><a id="digital-bus-connected-sensor" name="digital-bus-connected-sensor">3. Digital Bus-Connected Sensor</a></h2>
+<p>The Digital sensor is the most complex out of the set, and includes
+six components:</p>
+<ul class="simple">
+<li>one to present the sensor (SensirionSht11C)</li>
+<li>one to request arbitrated access and to transform the sensor HAL
+into the sensor HIL (SensirionSht11P)</li>
+<li>one to present the sensor HAL (HalSensirionSht11C)</li>
+<li>one to perform the driver logic needed to support the HAL, which
+twiddles pins according to a sensor-specific protocol
+(SensirionSht11LogicP).</li>
+<li>one to select the appropriate hardware resources, such as the clock,
+data, and power pins, and to provide an arbiter for the sensor
+(HplSensirionSht11C).</li>
+<li>one to perform the power control logic needed to support the power
+manager associated with the arbiter (HplSensirionSht11P).</li>
+</ul>
+<p>This bus-connected sensor is overly complex because it does not rely
+on a shared framework of bus manipulation components. A sensor built
+on top of the I2C or SPI bus would likely require fewer components.</p>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/SensirionSht11C.nc
+
+generic configuration SensirionSht11C() {
+ provides interface Read<uint16_t> as Temperature;
+ provides interface Read<uint16_t> as Humidity;
+}
+implementation {
+ components new SensirionSht11ReaderP();
+
+ Temperature = SensirionSht11ReaderP.Temperature;
+ Humidity = SensirionSht11ReaderP.Humidity;
+
+ components HalSensirionSht11C;
+
+ enum { TEMP_KEY = unique("Sht11.Resource") };
+ enum { HUM_KEY = unique("Sht11.Resource") };
+
+ SensirionSht11ReaderP.TempResource -> HalSensirionSht11C.Resource[ TEMP_KEY ];
+ SensirionSht11ReaderP.Sht11Temp -> HalSensirionSht11C.SensirionSht11[ TEMP_KEY ];
+ SensirionSht11ReaderP.HumResource -> HalSensirionSht11C.Resource[ HUM_KEY ];
+ SensirionSht11ReaderP.Sht11Hum -> HalSensirionSht11C.SensirionSht11[ HUM_KEY ];
+}
+</pre>
+<pre class="literal-block">
+tos/chips/sht11/SensirionSht11ReaderP.nc
+
+generic module SensirionSht11ReaderP() {
+ provides interface Read<uint16_t> as Temperature;
+ provides interface Read<uint16_t> as Humidity;
+
+ uses interface Resource as TempResource;
+ uses interface Resource as HumResource;
+ uses interface SensirionSht11 as Sht11Temp;
+ uses interface SensirionSht11 as Sht11Hum;
+}
+implementation {
+ command error_t Temperature.read() {
+ call TempResource.request();
+ return SUCCESS;
+ }
+
+ event void TempResource.granted() {
+ error_t result;
+ if ((result = call Sht11Temp.measureTemperature()) != SUCCESS) {
+ call TempResource.release();
+ signal Temperature.readDone( result, 0 );
+ }
+ }
+
+ event void Sht11Temp.measureTemperatureDone( error_t result, uint16_t val ) {
+ call TempResource.release();
+ signal Temperature.readDone( result, val );
+ }
+
+ command error_t Humidity.read() {
+ call HumResource.request();
+ return SUCCESS;
+ }
+
+ event void HumResource.granted() {
+ error_t result;
+ if ((result = call Sht11Hum.measureHumidity()) != SUCCESS) {
+ call HumResource.release();
+ signal Humidity.readDone( result, 0 );
+ }
+ }
+
+ event void Sht11Hum.measureHumidityDone( error_t result, uint16_t val ) {
+ call HumResource.release();
+ signal Humidity.readDone( result, val );
+ }
+
+ event void Sht11Temp.resetDone( error_t result ) { }
+ event void Sht11Temp.measureHumidityDone( error_t result, uint16_t val ) { }
+ event void Sht11Temp.readStatusRegDone( error_t result, uint8_t val ) { }
+ event void Sht11Temp.writeStatusRegDone( error_t result ) { }
+
+ event void Sht11Hum.resetDone( error_t result ) { }
+ event void Sht11Hum.measureTemperatureDone( error_t result, uint16_t val ) { }
+ event void Sht11Hum.readStatusRegDone( error_t result, uint8_t val ) { }
+ event void Sht11Hum.writeStatusRegDone( error_t result ) { }
+
+ default event void Temperature.readDone( error_t result, uint16_t val ) { }
+ default event void Humidity.readDone( error_t result, uint16_t val ) { }
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/HalSensirionSht11C.nc
+
+configuration HalSensirionSht11C {
+ provides interface Resource[ uint8_t client ];
+ provides interface SensirionSht11[ uint8_t client ];
+}
+implementation {
+ components new SensirionSht11LogicP();
+ SensirionSht11 = SensirionSht11LogicP;
+
+ components HplSensirionSht11C;
+ Resource = HplSensirionSht11C.Resource;
+ SensirionSht11LogicP.DATA -> HplSensirionSht11C.DATA;
+ SensirionSht11LogicP.CLOCK -> HplSensirionSht11C.SCK;
+ SensirionSht11LogicP.InterruptDATA -> HplSensirionSht11C.InterruptDATA;
+
+ components new TimerMilliC();
+ SensirionSht11LogicP.Timer -> TimerMilliC;
+
+ components LedsC;
+ SensirionSht11LogicP.Leds -> LedsC;
+}
+</pre>
+<pre class="literal-block">
+tos/chips/sht11/SensirionSht11LogicP.nc
+
+generic module SensirionSht11LogicP() {
+ provides interface SensirionSht11[ uint8_t client ];
+
+ uses interface GeneralIO as DATA;
+ uses interface GeneralIO as CLOCK;
+ uses interface GpioInterrupt as InterruptDATA;
+
+ uses interface Timer<TMilli>;
+
+ uses interface Leds;
+}
+implementation {
+
+ ... bus protocol details omitted for brevity ...
+
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/HplSensirionSht11C.nc
+
+configuration HplSensirionSht11C {
+ provides interface Resource[ uint8_t id ];
+ provides interface GeneralIO as DATA;
+ provides interface GeneralIO as SCK;
+ provides interface GpioInterrupt as InterruptDATA;
+}
+implementation {
+ components HplMsp430GeneralIOC;
+
+ components new Msp430GpioC() as DATAM;
+ DATAM -> HplMsp430GeneralIOC.Port15;
+ DATA = DATAM;
+
+ components new Msp430GpioC() as SCKM;
+ SCKM -> HplMsp430GeneralIOC.Port16;
+ SCK = SCKM;
+
+ components new Msp430GpioC() as PWRM;
+ PWRM -> HplMsp430GeneralIOC.Port17;
+
+ components HplSensirionSht11P;
+ HplSensirionSht11P.PWR -> PWRM;
+ HplSensirionSht11P.DATA -> DATAM;
+ HplSensirionSht11P.SCK -> SCKM;
+
+ components new TimerMilliC();
+ HplSensirionSht11P.Timer -> TimerMilliC;
+
+ components HplMsp430InterruptC;
+ components new Msp430InterruptC() as InterruptDATAC;
+ InterruptDATAC.HplInterrupt -> HplMsp430InterruptC.Port15;
+ InterruptDATA = InterruptDATAC.Interrupt;
+
+ components new FcfsArbiterC( "Sht11.Resource" ) as Arbiter;
+ Resource = Arbiter;
+
+ components new SplitControlPowerManagerC();
+ SplitControlPowerManagerC.SplitControl -> HplSensirionSht11P;
+ SplitControlPowerManagerC.ArbiterInit -> Arbiter.Init;
+ SplitControlPowerManagerC.ArbiterInfo -> Arbiter.ArbiterInfo;
+ SplitControlPowerManagerC.ResourceController -> Arbiter.ResourceController;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/HplSensirionSht11P.nc
+
+module HplSensirionSht11P {
+ provides interface SplitControl;
+ uses interface Timer<TMilli>;
+ uses interface GeneralIO as PWR;
+ uses interface GeneralIO as DATA;
+ uses interface GeneralIO as SCK;
+}
+implementation {
+ task void stopTask();
+
+ command error_t SplitControl.start() {
+ call PWR.makeOutput();
+ call PWR.set();
+ call Timer.startOneShot( 11 );
+ return SUCCESS;
+ }
+
+ event void Timer.fired() {
+ signal SplitControl.startDone( SUCCESS );
+ }
+
+ command error_t SplitControl.stop() {
+ call SCK.makeInput();
+ call SCK.clr();
+ call DATA.makeInput();
+ call DATA.clr();
+ call PWR.clr();
+ post stopTask();
+ return SUCCESS;
+ }
+
+ task void stopTask() {
+ signal SplitControl.stopDone( SUCCESS );
+ }
+}
+</pre>
+</div>
+</div>
</div>
</body>
</html>
<td>Philip Levis</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">20-Jun-2005</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.2</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-02-08</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<td>Philip Levis</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">11-Jul-2005</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.15</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-10-04</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
preceding it might have different lengths, and packet-level radios
often require packets to be contiguous memory regions. Overall, these
complexities make specifying the format of <tt class="docutils literal"><span class="pre">TOS_Msg</span></tt> very difficult.</p>
+<p>TinyOS has traditionally used statically sized packet buffers,
+rather than more dynamic approaches, such as scatter-gather I/O
+in UNIX sockets (see the man page for <tt class="docutils literal"><span class="pre">recv(2)</span></tt> for details).
+TinyOS 2.x continues this approach.</p>
</div>
<div class="section">
<h1><a id="id1" name="id1">2. message_t</a></h1>
passing a message buffer between two different link layers. If the
data payload were at different offsets for different link layers, then
passing a packet between two link layers would require a <tt class="docutils literal"><span class="pre">memmove(3)</span></tt>
-operation (essentially, a copy).</p>
+operation (essentially, a copy). Unlike in TinyOS 1.x, where TOS_Msg
+as explicitly an active messaging packet, message_t is a more general
+data-link buffer. In practice, most data-link layers in TinyOS 2.x
+provide active messaging, but it is possible for a non-AM stack to
+share message_t with AM stacks.</p>
<p>The header, footer, and metadata formats are all opaque. Source code
cannot access fields directly. Instead, data-link layers provide access
to fields through nesC interfaces. Section 3 discusses this in
<h2><a id="headers" name="headers">3.1 Headers</a></h2>
<p>The message_t header field is an array of bytes whose size is
the size of a platform's union of data-link headers.
-Because packets are stored contiguously, the layout of a packet
-in memory is not the same as the layout of its nesC structure.</p>
-<p>A packet header does not necessarily start at the beginning of
+Because radio stacks often prefer packets to be stored contiguously,
+the layout of a packet in memory does not necessarily reflect the
+layout of its nesC structure.</p>
+<p>A packet header MAY start somewhere besides the beginning of
the message_t. For example, consider the Telos platform:</p>
<pre class="literal-block">
typedef union message_header {
} cc2420_metadata_t;
</pre>
</div>
+<div class="section">
+<h2><a id="variable-sized-structures" name="variable-sized-structures">3.5 Variable Sized Structures</a></h2>
+<p>The message_t structure is optimized for packets with fixed-size
+headers and footers. Variable-sized footers are generally easy
+to implement. Variable-sized headers are a bit more difficult.
+There are three general approaches that can be used.</p>
+<p>If the underlying link hardware is byte-based, the header can
+just be stored at the beginning of the message_t, giving it
+a known offset. There may be padding between the header and
+the data region, but assuming a byte-based send path this merely
+requires adjusting the index.</p>
+<p>If the underlying link hardware is packet-based, then the
+protocol stack can either include metadata (e.g., in the
+metadata structure) stating where the header begins or it
+can place the header at a fixed position and use <tt class="docutils literal"><span class="pre">memmove(3)</span></tt>
+on reception and transmit. In this latter case, on
+reception the packet is continguously read into the message_t
+beginning at the offset of the header structure. Once the
+packet is completely received, the header can be decoded,
+its length calculated, and the data region of the packet
+can be moved to the <tt class="docutils literal"><span class="pre">data</span></tt> field. On transmission,
+the opposite occurs: the data region (and footer if need
+be) are moved to be contiguous with the header. Note that
+on completion of transmission, they need to be moved back.
+Alternatively, the radio stack can institute a single
+copy at the botttom layer.</p>
+</div>
</div>
<div class="section">
-<h1><a id="implementation" name="implementation">5. Implementation</a></h1>
+<h1><a id="implementation" name="implementation">4. Implementation</a></h1>
<p>The definition of message_t can be found in
-<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/types/message.h</span></tt>. The definition of the CC2420
-message format can be found in <tt class="docutils literal"><span class="pre">tinyos-2.x/tos/chips/cc2420/CC2420.h</span></tt>.
-The defintion of the CC1000 message format can be found in
-<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/chips/cc1000/CC1000Msg.h</span></tt>. The definition
+<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/types/message.h</span></tt>.</p>
+<p>The definition of the CC2420
+message format can be found in <tt class="docutils literal"><span class="pre">tinyos-2.x/tos/chips/cc2420/CC2420.h</span></tt>.</p>
+<p>The defintion of the CC1000 message format can be found in
+<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/chips/cc1000/CC1000Msg.h</span></tt>.</p>
+<p>The definition
of the standard serial stack packet format can be found in
-<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/lib/serial/Serial.h''.</span> <span class="pre">The</span> <span class="pre">definition</span> <span class="pre">of</span>
-<span class="pre">the</span> <span class="pre">telosb</span> <span class="pre">packet</span> <span class="pre">format</span> <span class="pre">can</span> <span class="pre">be</span> <span class="pre">found</span> <span class="pre">in</span>
-<span class="pre">``tinyos-2.x/tos/platform/telosa/platform_message.h</span></tt> and the micaz format can be found in
+<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/lib/serial/Serial.h</span></tt></p>
+<p>The definition of
+the telos family packet format can be found in
+<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/platform/telosa/platform_message.h</span></tt> and the micaz format can be found in
<tt class="docutils literal"><span class="pre">tinyos-2.x/tos/platforms/micaz/platform_message.h</span></tt>.</p>
</div>
<div class="section">
-<h1><a id="author-s-address" name="author-s-address">6. Author's Address</a></h1>
+<h1><a id="author-s-address" name="author-s-address">5. Author's Address</a></h1>
<div class="line-block">
<div class="line">Philip Levis</div>
<div class="line">358 Gates Hall</div>
<td>Robert Szewczyk, Philip Levis, Martin Turon, Lama Nachman, Philip Buonadonna, Vlado Handziski</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">19-Sep-2005</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.2</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2005-10-31</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<td>Ben Greenstein and Philip Levis</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">11-Jul-2005</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.5</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-11-06</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<table class="docutils citation" frame="void" id="tep2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a name="tep2">[TEP2]</a></td><td>TEP 2: Hardware Abstraction Architecture. <a class="reference" href="http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep2.txt?view=markup">http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep2.txt?view=markup</a></td></tr>
+<tr><td class="label"><a name="tep2">[TEP2]</a></td><td>TEP 2: Hardware Abstraction Architecture. tinyos-2.x/doc/txt/tep2.txt</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep111" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a name="tep111">[TEP111]</a></td><td>TEP 111: message_t. <a class="reference" href="http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep111.txt?view=markup">http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep111.txt?view=markup</a></td></tr>
+<tr><td class="label"><a name="tep111">[TEP111]</a></td><td>TEP 111: message_t. tinyos-2.x/doc/txt/tep111.txt</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep116" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
-<tr><td class="label"><a name="tep116">[TEP116]</a></td><td>TEP 116: Packet Protocols. <a class="reference" href="http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep116.txt?view=markup">http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep116.txt?view=markup</a></td></tr>
+<tr><td class="label"><a name="tep116">[TEP116]</a></td><td>TEP 116: Packet Protocols. tinyos-2.x/doc/txt/tep116.txt</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="hdlc" rules="none">
<td>Gilman Tolle, Philip Levis, and David Gay</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">30-Oct-2005</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.3</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.4</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-09-08</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-08-30</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>Power Management of Non-Virtualised Devices</title>
-<meta name="author" content="Vlado Handziski, Kevin Klues, Jan-Hinrich Hauer, Phil Levis" />
+<meta name="author" content="Kevin Klues, Vlado Handziski, Jan-Hinrich Hauer, Phil Levis" />
<style type="text/css">
/*
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
-<td>Vlado Handziski, Kevin Klues, Jan-Hinrich Hauer, Phil Levis</td></tr>
+<td>Kevin Klues, Vlado Handziski, Jan-Hinrich Hauer, Phil Levis</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">11-Jan-2006</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.4</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-09-19</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List
<tinyos-devel at mail.millennium.berkeley.edu></td>
<td>Philip Levis</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">10-Dec-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.11</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-06-27</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
-<title>Pins and Buses</title>
-<meta name="author" content="Phil Buonadonna" />
+<title>Low-Level I/O</title>
+<meta name="author" content="Phil Buonadonna, Jonathan Hui" />
<style type="text/css">
/*
</style>
</head>
<body>
-<div class="document" id="pins-and-buses">
-<h1 class="title">Pins and Buses</h1>
+<div class="document" id="low-level-i-o">
+<h1 class="title">Low-Level I/O</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
-<td>Phil Buonadonna</td></tr>
+<td>Phil Buonadonna, Jonathan Hui</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">23-Jan-2006</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.9</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-09-30</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<div class="section">
<h1><a id="abstract" name="abstract">Abstract</a></h1>
<p>The memo documents the TinyOS 2.x interfaces used for controlling
-digital IO functionality and digital interfaces other than serial
-communication covered in [tep113].</p>
+digital IO functionality and digital interfaces.</p>
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
<p>The canonical TinyOS device is likely to have a variety of digital
interfaces. These interfaces may be divided into two broad
-categories. The first are general purpose digital I/O lines (pins)
-for individual digital signals at physical pins on a chip or
-platform. The second are digital I/O interfaces that have predefined
-communication protocol formats. The two buses covered in this
-document are the Serial Peripheral Interface (SPI) and the
-Inter-Integrated Circuit (I2c) or Two-Wire interface. While there are
-likely other bus formats, we presume SPI and I2C to have the largest
-coverage. While the UART interface is also in this category, it is
-covered separately in [tep113].</p>
-<p>This memo documents the interfaces used for pins and the two buses.</p>
+categories. The first are general purpose digital I/O lines (pins) for
+individual digital signals at physical pins on a chip or platform. The
+second are digital I/O interfaces that have predefined communication
+protocol formats. The three buses covered in this document are the
+Serial Peripheral Interface (SPI), the Inter-Integrated Circuit (I2C)
+or Two-Wire interface, and the Universal Asynchronous
+Receiver/Transmitter (UART) interface. While there are likely other
+bus formats, we presume SPI, I2C, and UART to have the largest
+coverage.</p>
+<p>This memo documents the interfaces used for pins and the three buses.</p>
</div>
<div class="section">
<h1><a id="pins" name="pins">2. Pins</a></h1>
-<p>General Purpose I/O (GPIO) pins are single, versatile digital I/O signals
-individually controllable on a particular chip or platform. Each GPIO
-can be placed into either an input mode or an output mode. On
-some platforms a third 'tri-state' mode may exist, but this
-functionality is platform specific and will not be covered in this
-document.</p>
-<p>On many platforms, a physical pin may function as either a digital GPIO
-or another special function I/O such. Examples include ADC I/O or a bus
-I/O. Interfaces to configure the specific function of a pin are
+<p>General Purpose I/O (GPIO) pins are single, versatile digital I/O
+signals individually controllable on a particular chip or
+platform. Each GPIO can be placed into either an input mode or an
+output mode. On some platforms a third 'tri-state' mode may exist, but
+this functionality is platform specific and will not be covered in
+this document.</p>
+<p>On many platforms, a physical pin may function as either a digital
+GPIO or another special function I/O such. Examples include ADC I/O or
+a bus I/O. Interfaces to configure the specific function of a pin are
platform specific.</p>
<p>The objective of the interfaces described here is not to attempt to
cover all possibilities of GPIO functionality and features, but to
async command void toggle();
async command bool get();
async command void makeInput();
+ async command bool isInput();
async command void makeOutput();
+ async command bool isOutput();
}
</pre>
</div>
interface GpioInterrupt {
async command error_t enableRisingEdge();
+ async command bool isRisingEdgeEnabled();
async command error_t enableFallingEdge();
+ async command bool isFallingEdgeEnabled();
async command error_t disable();
async event void fired();
<p>Some platforms may have hardware support for such a feature. Other
platforms may emulate this capability using the SoftCaptureC
component. The interface makes not declaration of the precision or
-accuracy of the timestamp with respect to the associated GPIO event.</p>
+accuracy of the timestamp with respect to the associated GPIO
+event.</p>
<pre class="literal-block">
interface GpioCapture {
async command error_t captureRisingEdge();
+ async command bool isRisingEdgeEnabled();
async command error_t captureFallingEdge();
+ async command bool isFallingEdgeEnabled();
async event void captured(uint16_t time);
async command void disable();
asynchronous packet level interface. The byte level interface is
intended for short transactions (3-4 bytes) on the SPI bus.</p>
<pre class="literal-block">
-interface SPIByte {
- async command error_t write( uint8_t tx, uint8_t* rx );
+interface SpiByte {
+ async command uint8_t write( uint8_t tx );
}
</pre>
<p>The packet level interface is for larger bus transactions. The
-pointer/length interface permits use of hardware assist such as DMA.</p>
+pointer/length interface permits use of hardware assist such as
+DMA.</p>
<pre class="literal-block">
-interface SPIPacket {
-
+interface SpiPacket {
async command error_t send( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len );
async event void sendDone( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len,
- error_t error );
+ error_t error );
}
</pre>
</div>
<p>The Inter-Integrated Circuit (I2C) interface is another type of
digital bus that is often used for chip-to-chip communication. It is
also known as a two-wire interface.</p>
-<p>The I2CPacket interface provides for asynchronous Master mode communication on an
-I2C with application framed packets. It supports only single
-transfers with a start-stop condition around each transfer.</p>
+<p>The I2CPacket interface provides for asynchronous Master mode
+communication on an I2C with application framed packets. Individual
+I2C START-STOP events are controllable which allows the using
+component to do multiple calls within a single I2C transaction and
+permits multiple START sequences</p>
<p>Platforms providing I2C capability MUST provide this interface.</p>
<pre class="literal-block">
-interface I2CPacket {
- async command result_t readPacket(uint16_t _addr, uint8_t _length, uint8_t* _data);
- async command result_t writePacket(uint16_t _addr, uint8_t _length, uint8_t* _data);
- async event void readPacketDone(uint16_t addr, uint8_t length, uint8_t* data, result_t success);
- async event void writePacketDone(uint16_t addr, uint8_t length, uint8_t* data, result_t success);
+interface I2CPacket<addr_size> {
+ async command error_t read(i2c_flags_t flags, uint16_t addr, uint8_t length, u int8_t* data);
+ async event void readDone(error_t error, uint16_t addr, uint8_t length, uint8_t* data);
+ async command error_t write(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data);
+ async event void writeDone(error_t error, uint16_t addr, uint8_t length, uint8_t* data)
+}
+</pre>
+<p>The interface is typed according to the addressing space the
+underlying implementation supports. Valid type values are below.</p>
+<pre class="literal-block">
+TI2CExtdAddr - Interfaces uses the extended (10-bit) addressing mode.
+TI2CBasicAddr - Interfaces uses the basic (7-bit) addressing mode.
+</pre>
+<p>The i2c_flags_t values are defined below. The flags define the
+behavior of the operation for the call being made. These values may be
+ORed together.</p>
+<pre class="literal-block">
+I2C_START - Transmit an I2C STOP at the beginning of the operation.
+I2C_STOP - Transmit an I2C STOP at the end of the operation. Cannot be used
+ with the I2C_ACK_END flag.
+I2C_ACK_END - ACK the last byte sent from the buffer. This flags is only valid
+ a write operation. Cannot be used with the I2C_STOP flag.
+</pre>
+</div>
+<div class="section">
+<h2><a id="uart" name="uart">3.3 UART</a></h2>
+<p>The Universal Asynchronous Receiver/Transmitter (UART) interface is a
+type of serial interconnect. The interface is "asynchronous" since it
+recovers timing from the data stream itself, rather than a separate
+control stream. The interface is split into an asynchronous multi-byte
+level interface and a synchronous single-byte level interface.</p>
+<p>The multi-byte level interface, UartStream, provides a split-phase
+interface for sending and receiving one or more bytes at a time. When
+receiving bytes, a byte-level interrupt can be enabled or an interrupt
+can be generated after receiving one or more bytes. The latter is
+intended to support use cases where the number of bytes to receive is
+already known. If the byte-level receive interrupt is enabled, the
+receive command MUST return FAIL. If a multi-byte receive interrupt is
+enabled, the enableReceiveInterrupt command MUST return FAIL.</p>
+<pre class="literal-block">
+interface UartStream {
+ async command error_t send( uint8_t* buf, uint16_t len );
+ async event void sendDone( uint8_t* buf, uint16_t len, error_t error );
+
+ async command error_t enableReceiveInterrupt();
+ async command error_t disableReceiveInterrupt();
+ async event void receivedByte( uint8_t byte );
+
+ async command error_t receive( uint8_t* buf, uint8_t len );
+ async event void receiveDone( uint8_t* buf, uint16_t len, error_t error );
+}
+</pre>
+<p>The single-byte level interface, UartByte, provides a synchronous
+interface for sending and receiving a single byte. This interface is
+intended to support use cases with short transactions. Because UART is
+asynchronous, the receive command takes a timeout which represents
+units in byte-times, after which the command returns with an
+error. Note that use of this interface is discouraged if the UART baud
+rate is low.</p>
+<pre class="literal-block">
+interface UartByte {
+ async command error_t send( uint8_t byte );
+ async command error_t receive( uint8_t* byte, uint8_t timeout );
}
</pre>
</div>
</div>
<div class="section">
-<h1><a id="author-s-address" name="author-s-address">4. Author's Address</a></h1>
+<h1><a id="implementation" name="implementation">4. Implementation</a></h1>
+<p>Example implementations of the pin interfaces can be found in tos/chips/msp430/pins,
+tos/chips/atm128/pins, and tos/chips/pxa27x/gpio.</p>
+<p>Example implementations of the SPI interfaces can be found in tos/chips/msp430/usart,
+tos/chips/atm128/spi, and tos/chips/pxa27x/ssp.</p>
+<p>Example implementations of the I2C interfaces can be found in tos/chips/msp430/usart,
+tos/chips/atm128/i2c, and tos/chips/pxa27x/i2c.</p>
+<p>Example implementations of the UART interfaces can be found in tos/chips/msp430/usart,
+tos/chips/atm128/uart/ and tos/chips/pxa27x/uart.</p>
+</div>
+<div class="section">
+<h1><a id="author-s-address" name="author-s-address">5. Author's Address</a></h1>
<div class="line-block">
<div class="line">Phil Buonadonna</div>
-<div class="line">Arched Rock Corporation</div>
+<div class="line">Arch Rock Corporation</div>
<div class="line">657 Mission St. Ste 600</div>
<div class="line">San Francisco, CA 94105-4120</div>
<div class="line"><br /></div>
<div class="line">phone - +1 415 692-0828 x2833</div>
+<div class="line"><br /></div>
+<div class="line"><br /></div>
+<div class="line">Jonathan Hui</div>
+<div class="line">Arched Rock Corporation</div>
+<div class="line">657 Mission St. Ste 600</div>
+<div class="line">San Francisco, CA 94105-4120</div>
+<div class="line"><br /></div>
+<div class="line">phone - +1 415 692-0828 x2835</div>
</div>
</div>
<div class="section">
-<h1><a id="citations" name="citations">5. Citations</a></h1>
+<h1><a id="citations" name="citations">6. Citations</a></h1>
<table class="docutils citation" frame="void" id="tep113" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<td>Philip Levis and Gilman Tolle</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">10-Dec-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.3</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-06-20</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
provides interface DisseminationUpdate <t>;
}
</pre>
-<p>The t argument MUST be able to fit in a single message_t[<a href="#id4" name="id5"><span class="problematic" id="id5">tep111_</span></a>] after
+<p>The t argument MUST be able to fit in a single message_t[<a class="reference" href="#id2">1</a>] after
considering the headers that the dissemination protocol introduces.
A dissemination implementation SHOULD have a compile error if a larger
type than this is used.</p>
</tbody>
</table>
</div>
-<div class="system-messages section">
-<h1>Docutils System Messages</h1>
-<div class="system-message" id="id4">
-<p class="system-message-title">System Message: <a name="id4">ERROR/3</a> (<tt class="docutils">txt/tep118.txt</tt>, line 116); <em><a href="#id5">backlink</a></em></p>
-Unknown target name: "tep111".</div>
-</div>
</div>
</body>
</html>
<p>LinkEstimatorP estimates the quality of link to or from each
neighbor. Link estimation can be done in a variety of ways, and we do
not impose one here. It is decoupled from the establishment of
-routes. There is a narrow interface (LinkEstimator) between the link
-estimator and the routing engine. The one requirement is that the
-quality returned is standardized. A larger return value from
-LinkEstimator.getQuality(), LinkEstimator.getforwardQuality(),
-LinkEstimator.getreserveQuality() MUST imply that the link to the
-neighbor is estimated to be of a higher quality than the one that
-results in a smaller return value. The range of value SHOULD be
-[0,255] and the variation in link quality in that range SHOULD be
-linear. Radio provided values such as LQI or RSI, beacon based link
-estimation to compute ETX, or their combination are some possible
-approaches to estimating link qualities. LinkEstimatorP MAY have its
-own control messages to compute bi-directional link qualities:</p>
+routes. There is a narrow interface (LinkEstimator and
+NeighborTableEviction) between the link estimator and the routing
+engine. The one requirement is that the quality returned is
+standardized. A smaller return value from LinkEstimator.getQuality(),
+LinkEstimator.getforwardQuality(), LinkEstimator.getreserveQuality()
+MUST imply that the link to the neighbor is estimated to be of a
+higher quality than the one that results in a smaller return
+value. The range of value SHOULD be [0,255] and the variation in link
+quality in that range SHOULD be linear. Radio provided values such as
+LQI or RSI, beacon based link estimation to compute ETX, or their
+combination are some possible approaches to estimating link
+qualities. LinkEstimatorP MAY have its own control messages to compute
+bi-directional link qualities. LinkEstimatorP provides calls (txAck(),
+txNoAck(), and clearDLQ()) to update the link estimates based on
+successful or unsuccessful data transmission to the neighbors. The
+user of LinkEstimatorP can call insertNeighbor() to manually insert a
+node in the neighbor table, pinNeighbor() to prevent a neighbor from
+being evicted, and unpinNeighbor() to restore eviction policy:</p>
<pre class="literal-block">
-typedef uint16_t neighbor_t
+typedef uint16_t neighbor_table_entry_t
LinkEstimatorP {
provides {
+ interface StdControl;
+ interface AMSend as Send;
+ interface Receive;
interface LinkEstimator;
- interface NeighborTable;
+ interface Init;
+ interface Packet;
+ interface LinkSrcPacket;
}
}
interface LinkEstimator {
- command uint8_t getLinkQuality(neighbot_t neighbor);
- command uint8_t getReverseQuality(neighbot_t neighbor);
- command uint8_t getForwardQuality(neighbot_t neighbor);
+ command uint8_t getLinkQuality(uint16_t neighbor);
+ command uint8_t getReverseQuality(uint16_t neighbor);
+ command uint8_t getForwardQuality(uint16_t neighbor);
+ command error_t insertNeighbor(am_addr_t neighbor);
+ command error_t pinNeighbor(am_addr_t neighbor);
+ command error_t unpinNeighbor(am_addr_t neighbor);
+ command error_t txAck(am_addr_t neighbor);
+ command error_t txNoAck(am_addr_t neighbor);
+ command error_t clearDLQ(am_addr_t neighbor);
+ event void evicted(am_addr_t neighbor);
}
-interface NeighborTable {
- event void evicted(neighbot_t neighbor)
+interface NeighborTableEviction {
+ event void evicted(uint16_t neighbor)
}
</pre>
</div>
<br />Adam Wolisz</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">17-April-2006</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.5</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-10-25</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Alliance <tinyos-alliance at mail.millennium.berkeley.edu></td>
</tr>
</div>
<div class="section">
<h1><a id="funding" name="funding">9. Funding</a></h1>
-<p>As with the IETF, individuals are responsible for their own costs,
-which primarily involve meetings, travel, and generation of work
-products. Membership participation will involve attendance at
-Alliance meetings. Registration fees will be charged to cover costs
-associated with adminstration of the meetings.</p>
-<p>Companies and institutions are encouraged to contribute financial and
-in-kind support. It will be essential that companies provide initial
-funding to create the legal structure and to establish basic IT
-capabilities to host the web site and working groups.</p>
<p>Initially, we expect that there are no full time employees in the
Alliance and that funding needs are limited to such items as lawyer's
fees, web site costs, and insurance. If the Alliance eventually
requires full time support personnel, the funding structure will have
to be re-visited.</p>
+<p>As with the IETF, individuals are responsible for their own costs,
+which primarily involve meetings, travel, and generation of work
+products. The Alliance is predominantly a volunteer organization.
+Membership participation will involve attendance at
+Alliance meetings. Registration fees will be charged to cover costs
+associated with adminstration of the meetings.</p>
<p>To maintain the focus on technical excellence and meritocracy, we want
to avoid the heavy-handed quid-pro-quo seen in many industrial
consortiums where funding determines influence. The best use of funds
and the best form of influence is direct contribution to the work
-products of the Alliance. We will permit targeted contributions
-toward specific working groups or technical capabilities.</p>
-<p>We seek to keep overall structure lean, mostly volunteer.
-Focus on desired impact and recognition, rather than control.</p>
-<p>Institutional members
+products of the Alliance.
+To keep the structure of the Alliance and its operations minimalist
+and lean, membership focuses on desired impact and recognition, rather
+than control. We want the best way to influence the direction of the Alliance
+to be to contribute technical work and demonstrate leadership, rather than
+try to control what individuals can or cannot contribute.</p>
+<p>Companies and institutions are encouraged to contribute financial and
+in-kind support. It will be essential that companies provide initial
+funding to create the legal structure and to establish basic IT
+capabilities to host the web site and working groups.
+Institutional members
will pay an annual membership fee. In some cases, a
contributing corporate member may provide in-kind services
such as lawyers' time used to
become a contributing corporate member, e.g., in those cases
where such a membership may be prohibited or unwanted.
The costs of meetings, such as the TinyOS
-technology exchange, will be covered through registration fees.</p>
-<p>Individuals are responsible
-for their own costs such as
-for travel, meeting costs, or costs for contributing
-software or documentation to the Alliance. The Alliance
-is primarily a volunteer organization.</p>
+technology exchange, will be covered through registration fees and
+not by institutional membership fees.</p>
</div>
<div class="section">
<h1><a id="work-products" name="work-products">10. Work Products</a></h1>
-<p>Code base
-Stable, robust core release
-Rapidly evolving, innovative extensions
-Reference Implementations
-Tools
-Data
-Documentation
-Standard proposals
-Marketing and Promotion
-Testing and Compliance
-Assessments
-Applications and uses of technology
-Educational Materials</p>
+<p>The broad mission of the Alliance calls for a broad range of
+work products.</p>
+<p>Foremost among these are a set of TEPs documenting
+systems and protocols as well as TEPs that provide guidance
+and knowledge to the community. Technical documentation will have
+robust and open reference implementations for the community to
+use, refine, improve, and discuss. These reference implementations
+will not preclude alternative, compatibile implementations which may
+have additional features or optimizations. The Alliance Working Groups
+will periodically produce periodic releases of these reference
+implementations for the community to use and improve.</p>
+<p>The Alliance will support community contributions
+of innovative extensions and systems by providing a CVS repository
+to store them.
+In order to keep these contributions organized for users, the
+Steering Committee may nominate one or more people to caretake
+the repository by setting minimal guidelines for the use of
+the directory structure and migrating code as it joins the core
+or falls into disuse.</p>
+<p>To make these technological resources more accessible and useful
+to a broad embedded networks community, the Alliance will be
+dedicated to providing a set of educational materials. This
+includes introductory tutorials, documentation of core systems,
+simple and complex example applications, and user guides.</p>
+<p>In addition to educational sample applications, whose purpose
+is to teach new developers about the internals and workings of
+the technology, the Alliance will develop and make available
+several end-user applications and tools. The goal is to improve
+the accessibility of the technology to end-users while
+demonstrating its effectiveness. Historical examples of such applications
+include Surge and TinyDB. An important part of this effort is
+good documentation for users who are not expert programmers, as well
+as tools and graphical environments.</p>
</div>
<div class="section">
<h1><a id="conclusions" name="conclusions">11. Conclusions</a></h1>
-<p>The time has come to create an organizational structure to allow the effort to grow
-Beyond the Berkeley + Others
-It is a balancing act
-Stability vs Innovation
-Broad Participation vs Strong Requirements
-Uniform Licensing vs Institutional Differences
-Goal is to help to community to work together
-Not a forum for maneuvering and intrigue
-Focus on consensus building and technical soundness
-Minimal mechanism to resolve rare differences
-Focus on working groups and individual contributions
-with architectural and organization oversight
-Be pragmatic on participation
-Don\92t have to make deep commitments to participate
-Can\92t expect broad guarantees in return</p>
+<p>By focusing on consensus building and technical excellence, the
+Alliance seeks to avoid being a forum for political and economic
+positioning. It will achieve this by focusing on working groups
+and the contributions of individuals, while not taking strong
+positions on the benefits or drawbacks of different approaches.
+The variety of application domains sensornets are used in and
+the huge differences in requirements mean that having a suite
+of solutions, rather than a single one, is often not only
+desirable but essential.</p>
+<p>Over the past five years, low-power embedded sensor networks have
+grown from research prototypes to working systems that are being
+actively deployed. Furthermore, there is a vibrant research community
+that actively works to deploy these systems and collaborate with
+industry, making advances quickly accessible and usable. A great
+catalyst to this growth has been the presence of a large community
+around a shared, free code base.</p>
+<p>The time has come to create an organizational structure to
+allow the effort to grow further. As sensornets become more widespread,
+contributions and advancements will be from an increasingly broad
+demographic of users, and bringing them all together will speed
+progress and improve the potential benefit these systems can bring
+to society. This focus on bringing disparate groups together lies
+at the heart of the Alliance. Rather than depend on strong requirements,
+it depends on broad collaboration and participation, placing a minimalist
+set of expectations that will encourage the exchange of ideas and
+technology.</p>
</div>
<div class="section">
<h1><a id="author-s-address" name="author-s-address">12. Author's Address</a></h1>
<div class="line-block">
<div class="line">Philippe Bonnet <<a class="reference" href="mailto:bonnet.p@gmail.com">bonnet.p@gmail.com</a>></div>
<div class="line">David Culler <<a class="reference" href="mailto:culler@cs.berkeley.edu">culler@cs.berkeley.edu</a>></div>
+<div class="line">David Culler <dculler at archrock.com>,</div>
<div class="line">Deborah Estrin <<a class="reference" href="mailto:destrin@cs.ucla.edu">destrin@cs.ucla.edu</a>></div>
<div class="line">Ramesh Govindan <<a class="reference" href="mailto:ramesh@usc.edu">ramesh@usc.edu</a>></div>
<div class="line">Mike Horton <<a class="reference" href="mailto:mhorton@xbow.com">mhorton@xbow.com</a>></div>
<div class="line">Matt Welsh <<a class="reference" href="mailto:mdw@cs.harvard.edu">mdw@cs.harvard.edu</a>></div>
<div class="line">Adam Wolisz <<a class="reference" href="mailto:awo@ieee.org">awo@ieee.org</a>></div>
</div>
-<div class="line-block">
-<div class="line">David Culler <dculler at archrock.com>,</div>
-</div>
</div>
</div>
</body>
<td>Rodrigo Fonseca, Omprakash Gnawali, Kyle Jamieson, Sukun Kim, Philip Levis, and Alec Woo</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">3-Aug-2006</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.3</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-09-08</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-10-25</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<p>Field definitions are as follows:</p>
<blockquote>
<ul class="simple">
-<li>C: Congestion notification. If a node is receiving packets faster than it can forward them, it MAY set the C field to notify other nodes. If a node hears a packet from node N with the C bit set, it MUST NOT transmit CTP data frames to N until it hears a packet from N with the C bit cleared.</li>
-<li>P: Routing pull. The P bit allows nodes to request routing information from other nodes. If a node hears a packet with the P bit set, it SHOULD transmit a routing frame in the near future if it has a valid route.</li>
+<li>C: Congestion notification. If a node is receiving packets faster than it can forward them, it MAY set the C field to notify other nodes. If a node hears a packet from node <em>N</em> with the C bit set, it MUST NOT transmit CTP data frames to <em>N</em> until it hears a packet from N with the C bit cleared.</li>
+<li>P: Routing pull. The P bit allows nodes to request routing information from other nodes. If a node with a valid route hears a packet with the P bit set, it SHOULD transmit a routing frame in the near future.</li>
<li>THL: Time Has Lived. When a node generates a CTP data frame, it MUST set THL to 0. When a node receives a CTP data frame, it MUST increment the THL. If a node receives a THL of 255, it increments it to 0.</li>
<li>ETX: The ETX routing metric of the single-hop sender. When a node transmits a CTP data frame, it MUST put the ETX value of its route through the single-hop destination in the ETX field. If a node receives a packet with a lower gradient than its own, then it MUST schedule a routing frame in the near future.</li>
<li>origin: The originating address of the packet. A node forwarding a data frame MUST NOT modify the origin field.</li>
<li>seqno: Origin sequence number. The originating node sets this field, and a node forwarding a data frame MUST NOT modify it.</li>
<li>collect_id: Higher-level protocol identifier. The origin sets this field, and a node forwarding a data frame MUST NOT modify it.</li>
-<li>data: the data payload, of zero or more bytes.</li>
+<li>data: the data payload, of zero or more bytes. A node forwarding a data frame MUST NOT modify the data payload.</li>
</ul>
</blockquote>
<p>Together, the origin, seqno and collect_id fields denote a unique
distinction is important for duplicate suppression in the presence
of routing loops. If a node suppresses origin packets, then if
asked to forward the same packet twice due to a routing loop, it will
-drop the packet. However, if it suppresses packet instances, then
-unless the THL has wrapped around to the identical value it had
-on previous times around.</p>
+drop the packet. However, if it suppresses packet instances, then it
+will route succesfully in the presence of transient loops unless the
+THL happens to wrap around to a forwarded packet instance.</p>
<p>A node MUST send CTP data frames as unicast messages with link-layer
acknowledgments enabled.</p>
</div>
own, it MUST schedule a routing frame for transmission in the near
future.</p>
</div>
+<div class="section">
+<h1><a id="implementation" name="implementation">6. Implementation</a></h1>
+<p>An implementation of CTP can be found in the tos/lib/net/ctp directory
+of TinyOS 2.0. This section describes the structure of that implementation
+and is not in any way part of the specification of CTP.</p>
+<p>This implementation has three major subcomponents:</p>
+<p>1) A <strong>link estimator</strong>, which is responsible for estimating the
+single-hop ETX of communication with single-hop neighbors.</p>
+<p>2) A <strong>routing engine</strong>, which uses link estimates as well as
+network-level information to decide which neighbor is the next
+routing hop.</p>
+<p>3) A <strong>forwarding engine</strong>, which maintains a queue of packets
+to send. It decides when and if to send them. The name is a little
+misleading: the forwarding engine is responsible for forwarded traffic
+as well as traffic generated on the node.</p>
+<div class="section">
+<h2><a id="link-estimation" name="link-estimation">6.1 Link Estimation</a></h2>
+<p>The link estimator estimates the ETX to single-hop neighbors.
+The implementation uses two mechanisms to estimate the quality of a link:
+periodic broadcast packets and data packets. The estimator itself
+only generates broadcast packets. For data traffic, it depends on
+other components telling it about acknowledged and unacknowledged
+transmissions.</p>
+<p>The periodic broadcast packets have sequence numbers, which the
+estimator uses to estimate the sender-to-receiver packet reception
+rate (PRR). The data payload of periodic broadcast packets contain
+these estimates. Therefore, when node A receives a link estimation
+broadcast message from node B, it can use the packet header to
+estimate the B-to-A PRR and the packet payload to update B's
+estimate of the A-to-B PRR.</p>
+<p>Multiplying these two values gives a <em>bidirectional</em> PRR, or
+an estimate of the probability that if A transmits a packet to B,
+B will successfully hear and acknowledge the packet and A will
+hear the acknowledgment. The inverse of the bidirecitonal PRR
+is the ETX.</p>
+<p>CTP link estimation adapts its beaconing rate to be slow when
+its routing table is stable and faster when changes occur.
+It adjusts the beaconing interval using an algorithm similar
+to the trickle dissemination protocol[<a href="#id1" name="id2"><span class="problematic" id="id2">2_</span></a>]. CTP sends beacons
+more often when one of three conditions occurs:</p>
+<blockquote>
+<ol class="arabic simple">
+<li>The routing table is empty (this also sets the P bit)</li>
+<li>The node's routing ETX increases by >= 1 trasmission</li>
+<li>The node hears a packet with the P bit set</li>
+</ol>
+</blockquote>
+<p>CTP also estimates link quality using data transmissions. This
+is a direct measure of ETX. Whenever the data path transmits a
+packet, it tells the link estimator the destimation and whether
+it was successfully acknowledged. The estimator produces an ETX
+estimate every 5 such transmissions, where 0 successes has an
+ETX of 6.</p>
+<p>The estimator combines the beacon and data estimates by incorporating
+them into an exponentially weighted moving average. Beacon-based
+estimates seed the neighbor table. The expectation is that the low
+beacon rate in a stable network means that for a selected route,
+data estimates will outweigh beacon estimates. Additionally, as
+the rate at which CTP collects data estimates is proportional to
+the transmission rate, then it can quickly detect a broken link and
+switch to another candidate neighbor.</p>
+</div>
+<div class="section">
+<h2><a id="routing-engine" name="routing-engine">6.2 Routing Engine</a></h2>
+<p>The</p>
+</div>
+</div>
+<div class="system-messages section">
+<h1>Docutils System Messages</h1>
+<div class="system-message" id="id1">
+<p class="system-message-title">System Message: <a name="id1">ERROR/3</a> (<tt class="docutils">txt/tep123.txt</tt>, line 232); <em><a href="#id2">backlink</a></em></p>
+Unknown target name: "2".</div>
+</div>
</div>
</body>
</html>
<td>Ion Yannopoulos, David Gay</td></tr>
<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">31-Dec-2004</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.2</td>
+<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.3</td>
</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-07-12</td>
+<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2006-01-16</td>
</tr>
<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu></td>
</tr>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head><style type="text/css">
-<!--
+<html>
+ <head>
-BODY { font-size: 10pt; font-family: Arial, Helvetica, sans-serif; }
-TD { font-size: 10pt; font-family: Arial, Helvetica, sans-serif; }
+ <title>Installing TinyOS 2.0</title>\r
+ <link href="../stylesheets/tutorial.css" rel="stylesheet" type="text/css">\r
+</head>
+ <body>
-P { font-size: 10pt; font-family: Arial, Helvetica, sans-serif; }
-P.headline { font-size = 14pt; font-weight=bold; }
-
--->
-</style></head><body>
+ <div class="title">Upgrading from TinyOS 1.x to TinyOS 2.x</div>
+ <div class="subtitle">Last updated 5 November 2006</div>
<p>
-<table border="0" cellpadding="0" cellspacing="0" width="100%">
-<tbody><tr><td bgcolor="#eeeeee"><font face="verdana, arial, helvetica, sans-serif" size="3"><b>Upgrading from TinyOS 1.x to TinyOS 2.x</b></font></td>
-</tr></tbody></table>
-</p><p>
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
TinyOS 2.x rpm, but also that you upgrade your tools from the toolset
</li><li> <a href="#tinyos2">Install the Tinyos 2.x source tree. </a>
</li></ol>
-<hr>
-
-<a name="external-tools"><h3> 1. Upgrade your external tools. </h3></a>
+<a name="external-tools"><h1> Step 1: Upgrade your external tools. </h1></a>
The 1.2 toolset uses the same Java JDK and ATT Graphviz versions, so
those do not need to be upgraded. What does need to be upgraded are
your compiler tools. Install the appropriate version of the following
</tbody></table>
-</p><hr>
-<a name="tinyos-tools"><h3> 2. Upgrade your TInyOS-specific tools. </h3></a>
+</p>
+<a name="tinyos-tools"><h1> Step 2: Upgrade your TinyOS-specific tools. </h1></a>
The TinyOS-specific tools are the NesC compiler and a set of tools
developed in the tinyos-2.x/tools source code repository. They are
simultaneously with a tinyos-2.x tree, the tinyos-tools installed for the
1.x versions must remain installed so use <code>rpm -ivh</code>. If you are
only installing a 2.x tree, you can use <code>rpm -Uvh</code>.
-If you using the Cygwin version recommendedin these install
+If you using the Cygwin version recommended
+in these install
instructions, you should install the "Recommended" Windows/Cygwin
-nesC RPM (1.2.7b). If you install it and it does not work (e.g., you
+nesC RPM.
+Try installing it and if it does not work (e.g., you
get strange errors when you try to execute it), this may be due
-to a Cygwin version incompatibility: try the "Other" Windows/Cygwin
+to a Cygwin version incompatibility: try the "Other" Windows/Cygwin
RPM (1.2.7a).
-
<p>
<!----- tinyos-2.x/tinyos rpms -------->
<tr>
<td>NesC</td>
- <td><a href="http://csl.stanford.edu/~pal/tinyos/nesc-1.2.7b-1.cygwin.i386.rpm">nesc-1.2.7b-1.cygwin.i386.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-1.2.0/tinyos/windows/nesc-1.2.7b-1.cygwin.i386.rpm">nesc-1.2.7b-1.cygwin.i386.rpm</a></td>
<td><a href="http://www.tinyos.net/dist-1.2.0/tinyos/windows/nesc-1.2.7a-1.cygwin.i386.rpm">nesc-1.2.7a-1.cygwin.i386.rpm</a></td>
<td><a href="http://www.tinyos.net/dist-1.2.0/tinyos/linux/nesc-1.2.7a-1.i386.rpm">nesc-1.2.7a-1.i386.rpm </a></td>
- <td><a href=""></a><code>rpm -Uvh</code></td>
+ <td><a href=""></a><code>rpm -Uvh</code><br><code>rpm -Uvh --ignoreos</code> (if Cygwin complains)</td>
</tr>
<tr>
<td bgcolor="#dddddd">tinyos-tools</td>
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-tools-1.2.2-1.cygwin.i386.rpm">tinyos-tools-1.2.2-1.cygwin.i386.rpm</a></td>
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-tools-1.2.2-1.cygwin.i386.rpm">tinyos-tools-1.2.2-1.cygwin.i386.rpm</a></td>
- <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/linux/tinyos-tools-1.2.2-1.i386.rpm">tinyos-tools-1.2.2-1.i386.rpm</a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-tools-1.2.3-1.cygwin.i386.rpm">tinyos-tools-1.2.2-1.cygwin.i386.rpm</a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-tools-1.2.3-1.cygwin.i386.rpm">tinyos-tools-1.2.2-1.cygwin.i386.rpm</a></td>
+ <td bgcolor="#dddddd"><a href="http://www.tinyos.net/dist-2.0.0/tinyos/linux/tinyos-tools-1.2.3-1.i386.rpm">tinyos-tools-1.2.2-1.i386.rpm</a></td>
<td bgcolor="#dddddd"><a href=""></a><code>rpm -ivh --force</code> (1.x tree)<br><code>rpm -Uvh</code> (no 1.x tree)<br></td>
</tr>
</tbody></table>
-</p><hr>
-<a name="tinyos2"><h3> 3. Install the TinyOS 2.x source tree. </h3></a>
+</p>
+<a name="tinyos2"><h1> Step 3: Install the TinyOS 2.x source tree. </h1></a>
Now that the tools are installed, you need only install the tinyos 2.x
source tree and then set your environment variables.
<li> Install tinyos-2.x
<p>
<!----- TinyOS -------->
-To preserve your old tinyos-1.x tree, we strongly recommend that you use
+
+<p>If you have an existing 1.x tree, we strongly recommend that you use
the install (<code>-i</code>) rpm argument when installing the tinyos-2.x rpm rather
than the upgrade (<code>-U</code>) argument. The difference is that the <code>-U</code> will
first remove the tinyos-1.x tree while <code>-i</code> will not remove previously installed
-files. Said another way, we recommend using <code>rpm -ivh</code>.
+files. Said another way, we recommend using <code>rpm -ivh</code>.</p>
+
+<p>If you have an existing 2.x tree which you want to keep unchanged, then
+you will need to move it to make space for the new one. For example, if you
+have an existing tree in <tt>/opt/tinyos-2.x/</tt>, then you can move it
+to <tt>/opt/tinyos-2.x-old</tt>. Once you have moved it, we recommend
+performing a forced installation of the 2.0 tree.</p>
+
+<p>If you have an existing 2.x tree which you do not care about, then we
+recommend removing it before installing the new one with a forced install.</p>
</p><p><b><em>TinyOS 2.x</em></b>
<table border="0">
<td bgcolor="#dddddd"><b></b></td>
<td bgcolor="#dddddd"><b>Windows/Cygwin</b></td>
<td bgcolor="#dddddd"><b>Linux</b></td>
+ <td bgcolor="#dddddd"><b>Command</b></td>
</tr>
<tr>
<td>TinyOS</td>
- <td><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-2.0.0beta2-3.cygwin.noarch.rpm">tinyos-2.0.0beta2-3.cygwin.noarch.rpm</a></td>
- <td><a href="http://www.tinyos.net/dist-2.0.0/tinyos/linux/tinyos-2.0.0beta2-3.noarch.rpm">tinyos-2.0.0beta2-3.noarch.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tinyos/windows/tinyos-2.0.0-1.cygwin.noarch.rpm">tinyos-2.0.0-1.cygwin.noarch.rpm</a></td>
+ <td><a href="http://www.tinyos.net/dist-2.0.0/tinyos/linux/tinyos-2.0.0-1.noarch.rpm">tinyos-2.0.0-1.noarch.rpm</a></td>
+ <td><tt>rpm -Uvh</tt> (to upgrade)<br>
+ <tt>rpm -ivh</tt> (to install)<br>
+ <tt>rpm -ivh --force</tt> (to force install)<br>
+ </td>
</tr>
</tbody></table>
</code></code></li></ol>
</li></ul>
-<hr>
-<a name="tinyos1"><h3>Switching back to a TinyOS 1.x tree</h3></a>
+<a name="tinyos1"><h1>Switching back to a TinyOS 1.x tree</h1></a>
Since the tools are backwardly compatible, you need only change
your environment variables to point to the 1.x settings. Assuming
that your old tree was in /opt/tinyos-1.x, you would use the following
<td>
</td></tr></tbody></table>
-</p></body></html>
+</p>
+
+<p>Switching between the two should require switching only these environment
+variables.</p>
+</body></html>
<TR>
<TD CLASS="title">
TinyOS 2.0 Documentation<br>
- <DIV CLASS="subtitle">Last Modified: Oct 31 2005</DIV>
+ <DIV CLASS="subtitle">Last Modified: October 27 2006</DIV>
</TD>
</TR>
<TR>
<li><A HREF="html/overview.html">TinyOS 2.0 overview</A></li>
<li><A HREF="html/install-tinyos.html">TinyOS 2.0 install instructions </A></li>
<li><A HREF="html/upgrade-tinyos.html">TinyOS 2.0 upgrade instructions (includes instructions for how to upgrade your tools for 2.0)</A></li>
+ <li><A HREF="html/porting.html">A brief set of notes on porting code from TinyOS 1.x to 2.0.</A></li>
</ul>
</TD>
</TR>
<TR>
- <TD CLASS="subtitle">Tutorials</TD>
+ <TD CLASS="subtitle"><A HREF="html/tutorial/index.html">Tutorials</A></TD>
</TR>
<TR>
- <TD><p>TinyOS 2.0 has a few tutorials to get a new user started with programming
+ <TD><p>TinyOS 2.0 has a few <A HREF="html/tutorial/index.html">tutorials</A> to get a new user started with programming
the system. These tutorials introduce nesC programming and some major
TinyOS abstractions, such as timers and communication.</p>
- <p><A HREF="html/tutorial/index.html"><DIV class=sublink>TinyOS 2.0 Tutorials</div></a></p></TD>
+ <p>Additionally, for more advanced programming, there is a
+ <A HREF="pdf/tinyos-programming.pdf">TinyOS Programming Manual</A>.
+ The book describes nesC's features in greater detail,
+ including generic components, concurrency, and common
+ component design patterns.</p>
</TR>
<TR>
- <TD CLASS="subtitle">TEPs and Source Code Documentation</TD>
+ <TD CLASS="subtitle">TEPs</TD>
</TR>
<TR>
<TD>
different kinds of TEPs and their roles. TEPs 1-100 are
BCP (Best Current Practice) TEPs, while TEPS 101+ are
Informational, Documentary, or Experimental. Currently,
- all TEPs are still Drafts: comments and feedback to the
+ many TEPs are Drafts: comments and feedback to the
authors or the associated working group is welcome.
<BR><BR>
<li>TEP 107: Boot Sequence [<A HREF="html/tep107.html">HTML</A>] [<A HREF="txt/tep107.txt">TXT</A>]</li>
<li>TEP 108: Resource Arbitration [<A HREF="html/tep108.html">HTML</A>] [<A HREF="txt/tep108.txt">TXT</A>]</li>
<li>TEP 109: Sensorboards [<A HREF="html/tep109.html">HTML</A>] [<A HREF="txt/tep109.txt">TXT</A>]</li>
- <li>TEP 110: Service Distributions [<A HREF="html/tep110.html">HTML</A>] [<A HREF="txt/tep110.txt">TXT</A>]</li>
<li>TEP 111: message_t [<A HREF="html/tep111.html">HTML</A>] [<A HREF="txt/tep111.txt">TXT</A>]</li>
<li>TEP 112: Microcontroller Power Management [<A HREF="html/tep112.html">HTML</A>] [<A HREF="txt/tep112.txt">TXT</A>]</li>
<li>TEP 113: Serial Communication [<A HREF="html/tep113.html">HTML</A>] [<A HREF="txt/tep113.txt">TXT</A>]</li>
<li>TEP 114: SIDs: Source and Sink Independent Drivers [<A HREF="html/tep114.html">HTML</A>] [<A HREF="txt/tep114.txt">TXT</A>]</li>
<li>TEP 115: Power Management of Non-Virtualized Devices [<A HREF="html/tep115.html">HTML</A>] [<A HREF="txt/tep115.txt">TXT</A>]</li>
<li>TEP 116: Packet Protocols [<A HREF="html/tep116.html">HTML</A>] [<A HREF="txt/tep116.txt">TXT</A>]</li>
+ <li>TEP 117: Low-Level I/O [<A HREF="html/tep117.html">HTML</A>] [<A HREF="txt/tep117.txt">TXT</A>]</li>
+ <li>TEP 118: Dissemination [<A HREF="html/tep118.html">HTML</A>] [<A HREF="txt/tep118.txt">TXT</A>]</li>
+ <li>TEP 119: Collection [<A HREF="html/tep119.html">HTML</A>] [<A HREF="txt/tep119.txt">TXT</A>]</li>
</ul>
+ <BR><BR>
+ </TD>
+ </TR>
+ <TR>
+ <TD CLASS="subtitle"><A HREF="html/nesdoc/">TinyOS Source Code Documentation</A></TD>
+ </TR>
+ <TR>
+ <TD>
<p>In addition to TEPs, which document the organization and design
- behind important parts of TinyOS, there is also source code
- documentation. TinyOS (nesC) code has nesdoc annotations,
- which can be found here (note that this link is external):<br><br>
-
- <A HREF="http://www.tinyos.net/dist-2.0.0/tinyos-2.x/doc/html/nesdoc/">
- <div class=sublink>TinyOS 2.0 nesdoc documentation</div></a>
-
- </p>
+ behind important parts of TinyOS, there is also <A HREF="html/nesdoc/">source code
+ documentation</A>.<br><br>
+ </TD>
+ </TR>
+ <TR>
+ <TD CLASS="subtitle"><A HREF="html/tos-javasdk-javadoc/index.html">TinyOS Java toolchain Code Documentation</A></TD>
+ </TR>
+ <TR>
+ <TD>
- <p>There is similar javadoc documentation for the Java toolchain,
- which can be found here:<br><br>
-
- <A HREF="http://www.tinyos.net/dist-2.0.0/tinyos-2.x/doc/html/tos-javasdk-javadoc/">
- <div class=sublink>TinyOS 2.0 javadoc documentation</div></a>
+ <p>There is similar
+ <A HREF="html/tos-javasdk-javadoc/index.html">javadoc documentation</A> for the Java toolchain,
+ which describes the Java classes and their functionality. This documentation
+ is incomplete.
</p>
</p>
font-size: 14px;
}
a:link {
- color: #d3595e;
+ color: #c3494e;
text-decoration: none;
font-weight: bold;
}
a:visited {
- color: #404040;
+ color: #c3494e;
text-decoration: none;
font-weight: bold;
}
.menu {
width: 100%;
- background-color: #c00000;
+ background-color: #d0d0d0;
padding: .2em 1em .2em 1em;
border: 0;
margin: 0;
width: 100%;
margin: 0 0 0 0;
border: 0 0 0 0;
- background-color: #a0a0a0;
+ background-color: #d0d0d0;
color: #000000;
}
border: 0 0 0 0;
padding: .2em .2em .2em .2em;
text-align: left;
- background-color: #e0e0c0;
+ background-color: #d0d0d0;
}
.title {
- background-color: grey;
+ background-color: #d0d0d0;
font-family: Helvetica, sans-serif;
font-size: x-large;
font-weight: bold;
}
.subtitle {
- background-color: grey;
+ background-color: #d0d0d0;
font-family: Helvetica, sans-serif;
font-weight: normal;
font-size: medium;
============================
:Author: Philip Levis
-:Date: Feb 8 2006
+:Date: Oct 30 2006
.. Note::
The HAA is described in TEP 2: Hardware Abstraction Architecture[TEP2_].
-Currently (as of the 2.0 beta2 release in July 2006), TinyOS 2.0 supports
+Currently (as of the 2.0 release in November 2006), TinyOS 2.0 supports
the following platforms:
* eyesIFXv2
* btnode3
-The btnode3 platform is not included in the beta2 RPM.
+The btnode3 platform is not included in the RPM.
3. Scheduler
====================================================================
Further information on message_t can be found in TEP 111:
message_t[TEP111_], while further information on AM can be
-found in TEP 116: Packet Protocoks[TEP116_].
+found in TEP 116: Packet Protocols[TEP116_].
+
+The current TinyOS release has a low-power stack for the CC1000
+radio (mica2 platform) and an experimental low-power stack for
+the CC2420 radio (micaz, telosb, and intelmote2 platforms).
+
8. Sensors
====================================================================
through resource abiters. Fully virtualized services have their
own, individual power management policies.
+TinyOS 2.0 provides low-power stacks for the CC1000 (mica2)
+and CC2420 (micaz, telosb, imote2) radios. Both use a low-power
+listening apporach, where transmitters send long preambles or
+repeatedly send packets and receivers wake up periodically to
+sense the channel to hear if there is a packet being
+transmitted. The low-power stack CC1000 is standard, while
+the CC2420 stack is experimental. That is, the default CC1000
+stack (chips/cc1000) has low-power-listening, while the default
+CC2420 stack (chips/cc2420) does not. To use the low-power CC2420
+stack, you must include chips/cc2420_lpl in your application Makefile.
+
12. Network Protocols
====================================================================
than 20 byte) data items to every node in a network, while
collection builds a routing tree rooted at a sink node. Together,
these two protocols enable a wide range of data collection
-applications.
+applications. Collection has advanced significantly since the
+most recent beta release; experimental tests in multiple
+network conditions have seen very high (>98%) deliver rates
+as long as the network is not saturated.
-12. Conclusion
+13. Conclusion
====================================================================
TinyOS 2.0 represents the next step of TinyOS development. Building on
non-volatile storage, basic multihop protocols (collection routing,
dissemination), and further power management abstractions.
-13. Acknowledgments
+14. Acknowledgments
====================================================================
TinyOS 2.0 is the result of a lot of hard work from a lot of people,
Gilman Tolle, Martin Turon, Phil Buonodonna, Ben Greenstein, David Culler,
Kristin Wright, Ion Yannopoulos, Henri Dubois-Ferriere, Jan Beutel,
Robert Szewczyk, Rodrigo Fonseca, Kyle Jamieson, Omprakash Gnawali,
-and Kristin Wright.
+David Moss, and Kristin Wright.
-14. Author's Address
+15. Author's Address
====================================================================
| Philip Levis
|
| email - pal@cs.stanford.edu
-15. Citations
+16. Citations
====================================================================
.. [TEP1] TEP 1: TEP Structure and Keywords. http://tinyos.cvs.sourceforge.net/*checkout*/tinyos/tinyos-2.x/doc/html/tep1.html?pathrev=tinyos-2_0_devel-BRANCH
The fourth field is "Status," which specifies the status of the TEP.
A TEP status can either be "Draft," which means it is a work in
-progress, "Final," which means it is complete and will not change, or
-"Obsolete," which means it should no longer be considered. If a TEP is
-"Obsolete" because it has been replaced by another TEP, then the new
-TEP number should follow "Obsolete," such as "Obsolete by TEP 1231."
+progress, "Final," which means it is complete and will not change.
+Once a TEP has the status "Final," its body MUST NOT change.
+The values of its header fields MUST NOT change. The header of a
+Final TEP MAY have an "Obsoleted By" field added.
+
+The "Obsoletes" field is a backward pointer to an earlier TEP which
+the current TEP renders obsolete. An Obsoletes field MAY have multiple
+TEPs listed. For example, if TEP 191 were to replace TEPs 111 and 116, it
+would have the field "Obsoletes: 111, 116".
+
+The "Obsoleted By" field is added to a Final TEP when another TEP has
+rendered it obsolete. The field contains the number of the obsoleting
+TEP. For example, if TEP 111 were obsoleted by TEP 191, it would have
+the field "Obsoleted By: 191".
+
+"Obsoletes" and "Obsoleted By" fields MUST agree. For a TEP to list another
+TEP in its Obsoletes field, then that TEP MUST list it in the Obsoleted By
+field.
+
+The obsoletion fields are used to keep track of evolutions and modifications
+of a single abstraction. They are not intended to force a single approach or
+mechanism over alternative possibilities.
If a TEP is Best Current Practices or Documentary, then it MUST
include an additional field, "TinyOS-Version:," which states what
to all versions of TinyOS, until made obsolete by a future TEP. This
field MUST appear after the Status field and before the Author field.
-The final required field is Author, which states the names of the
+The final required field is "Author," which states the names of the
authors of the document. Full contact information should not be listed
here (see Section 3.2).
+There is an optional field, "Extends." The "Extends" field refers to
+another TEP. The purpose of this field is to denote when a TEP represents
+an addition to an existing TEP. Meeting the requirements of a TEP with an
+Extends field requires also meeting the requirements of all TEPs listed
+in the Extends field.
+
If a TEP is a Draft, then four additional fields MUST be included:
Draft-Created, Draft-Modified, Draft-Version, and Draft-Discuss.
Draft-Created states the date the document was created, Draft-Modified
Abstract
====================================================================
-This TEP proposes a hardware abstraction for TinyOS 2.x analog-to-digital
-converters (ADCs). It focuses on aligning the ADC abstraction with the
-three-layer Hardware Abstraction Architecture (HAA) described in [TEP2]_, but
-addresses only the HPL and HAL, because the highest level abstraction of an
-ADC is platform-dependent.
+This TEP proposes a hardware abstraction for analog-to-digital converters (ADCs)
+in TinyOS 2.x, which is aligned to the three-layer Hardware Abstraction
+Architecture (HAA) specified in [TEP2]. It describes some design principles and
+documents the set of hardware-independent interfaces to an ADC.
1. Introduction
====================================================================
components that had nothing to do with an ADC to still resemble one
programatically, even though the semantics and forms of operation were
completely different. To compensate for the difference non-ADC sensors
-introduced additional interfaces, such as ADCError, that were tightly bound to
-sensor acquisition but separate in wiring. The separation between the ADC and
-ADCError interface is bug prone and problematic, as is the equation of a
+introduced additional interfaces, such as ``ADCError``, that were tightly bound
+to sensor acquisition but separate in wiring. The separation between the ADC and
+``ADCError`` interface is bug prone and problematic, as is the equation of a
sensor and an ADC. TinyOS 2.x separates the structure and interfaces of an ADC
from those of sensors (which may be on top of an ADC, but this fact is hidden
-from higher level components). This TEP presents how TinyOS 2.x decomposes and
-structures ADC software. TEP 109 (Sensor Boards) shows how a platform can
-present actual named sensors [TEP109]_.
+from higher level components). This TEP presents how TinyOS 2.x structures ADC
+software. TEP 109 (Sensor Boards) shows how a platform can present actual named
+sensors [TEP109]_.
As can be seen in Appendix A the ADC hardware used on TinyOS platforms differ
in many respects, which makes it difficult to find a chip independent
producing the input signal (sensor). Neither a platform independent
application nor the ADC hardware stack itself has access to this information,
as it can only be determined on a platform or sensorboard level. For example,
-determining which ADC port a sensor is attached to and how a conversion result
-is to be interpreted is a platform-specific determination.
+determining which ADC port a sensor is attached to and how conversion results
+need to be interpreted is a platform specific determination. Although the
+actual configuration details may be different the procedure of configuring an
+ADC can be unified on all ADCs with the help of **hardware independent
+interfaces**: in a similar way as the ``Read`` interface definition does not
+predefine the type or semantics of the exchanged data (see [TEP114]_), a
+configuration interface definition can abstract from the data type and
+semantics of the involved configuration settings. For example, like a
+component can provide a ``Read<uint8_t>`` or ``Read<uint16_t>`` interface
+depending on the data it can offer, a component can also use a
+``AdcConfigure<atm128_adc_config_t>`` or
+``AdcConfigure<msp430adc12_channel_config_t>`` interface depending on what ADC
+it represents. This TEP proposes the (typed) ``AdcConfigure`` interface as the
+standard interface for configuring an ADC in TinyOS 2.x.
In spite of their hardware differences, one aspect represents a common
-denominator of all ADCs: they produce conversion results. In order to
-facilitate sensor software development this capability can be made available
-via chip-independent interfaces for every ADC. However, conversion results
-depend on and have to be interpreted with respect to the platform-specific
-configuration settings (the ADC channel, the applied reference voltage, etc.).
-Therefore the highest level of ADC abstraction consists of
-platform-independent interfaces for ADC data collection and chip-specific
-interfaces for ADC hardware configuration. The top layer of the ADC stack
-thus remains platform-dependent and consequently the ADC abstraction does not
-include an HIL, but ends with the HAL. Following the principles of the
-HAA [TEP2]_ the HAL of an ADC should also expose the chip-specific capabilities
-for ADC data collection. For example, the ADC12 on the MSP430 MCU supports a
-complex repeat conversion mode for a set of different input channels, which is
-too specific to be represented by a platform-independent data collection
-interface. Therefore the HAL of an ADC abstraction is broken into two
-sublayers: The bottom HAL layer, called HAL1, exposes the full capabilities of
-the respective ADC in a chip-specific way. It realizes the standard HAL in the
-HAA [TEP2]_ and the HPL lies below it. On top of the HAL1 sits the HAL2 which
-maps the interfaces it uses from HAL1 to a set of platform-independent
-interfaces for data collection and chip-specific configuration interfaces.
+denominator of all ADCs: they produce conversion results. To facilitate sensor
+software development conversion results are returned by the ADC hardware stack
+using the standard TinyOS interfaces ``Read``, ``ReadNow`` and ``ReadStream``
+(see `2. Interfaces`_ and [TEP114]_). Conversion results are returned as
+uninterpreted values and translating them to engineering units can only be done
+with the configuration knowledge of the respective platform, for example, the
+reference voltage or the resistance of a reference resistor in ratiometric
+measurements. Translating uninterpreted values to engineering units is
+performed by components located on top of the ADC hardware stack and out of the
+scope of this TEP.
+
+The top layer of abstraction of an ADC - the Hardware Interface Layer (HIL) -
+thus provides the standard TinyOS interfaces ``Read``, ``ReadNow`` and
+``ReadStream`` and uses the ``AdcConfigure`` interface for hardware
+configuration (why it **uses** and does not **provide** ``AdcConfigure`` is
+explained below). Since the type and semantics of the parameters passed
+through these interfaces is dependent on the actual ADC implementation, it is
+only a "weak" HIL (see [TEP2]_).
+
+Following the principles of the HAA [TEP2]_ the Hardware Adaptation Layer (HAL,
+which resides below the HIL) of an ADC should expose all the chip-specific
+capabilities of the chip. For example, the ADC12 on the MSP430 MCU supports a
+"Repeat-Sequence-of-Channels Mode" and therefore this function should be
+accessible on the HAL of the **MSP430 ADC12** hardware abstraction. Other ADCs
+might not exhibit such functionality and might therefore - on the level of HAL
+- provide only an interface to perform single conversions. Since all ADCs have
+the same HIL representation it may thus be necessary to perform some degree of
+software emulation in the HIL implementation. For example, a ``ReadStream``
+command can be emulated by multiple single conversion commands. Below the HAL
+resides the Hardware Presentation Layer (HPL), a stateless component that
+provides access to the hardware registers (see [TEP2]_). The general structure
+(without virtualization) of the ADC hardware stack is as follows ::
+
+
+ ^ |
+ | |
+ | Read,
+ AdcConfigure ReadNow (+ Resource),
+ | ReadStream
+ | |
+ | V
+ +----------------------------------+
+ | Hardware Interface Layer (HIL) |
+ | (chip-specific implementation) |
+ +----------------------------------+
+ |
+ |
+ chip-specific interface(s) + Resource
+ (e.g. Msp430Adc12SingleChannel + Resource)
+ |
+ V
+ +----------------------------------+
+ | Hardware Adaptation Layer (HAL) |
+ | (chip-specific implementation) |
+ +----------------------------------+
+ |
+ |
+ chip-specific interface(s)
+ (e.g. HplAdc12)
+ |
+ V
+ +----------------------------------+
+ | Hardware Presentation Layer (HPL)|
+ | (chip-specific implementation) |
+ +----------------------------------+
-The rest of this TEP specifies:
-* the set of platform-independent interfaces for the collection of ADC
- conversion results (`2. Interfaces`_)
-* guidelines on how an ADC's HAL should be split into HAL1 and HAL2 and
- how the HAL1 should expose chip-specific interfaces (`3. HAL1 guidelines`_)
-* what components an ADC's HAL2 MUST implement (`4. HAL2 requirements`_)
-* guidelines on how the HAL2 may be structured (`5. HAL2 implementation guidelines`_)
-* a section pointing to the current implementation (`6. Implementation`_)
+The rest of this TEP specifies:
+* the set of standard TinyOS interfaces for collecting ADC conversion
+ results and for configuring an ADC (`2. Interfaces`_)
+* guidelines on how an ADC's HAL should expose chip-specific
+ interfaces (`3. HAL guidelines`_)
+* what components an ADC's HIL MUST implement (`4. HIL requirements`_)
+* guidelines on how the HIL should be implemented
+ (`5. HIL guidelines`_)
+* a section pointing to current implementations (`6. Implementation`_)
-This TEP ends with appendices documenting, as an example, the ADC
-implementation for the TI MSP430 MCU.
+This TEP ends with appendices documenting, as an example, the ADC implementation
+for the TI MSP430 MCU.
2. Interfaces
====================================================================
-This TEP proposes to adopt the following three generic, source-independent
-data collection interfaces from [TEP114]_ for the collection of ADC conversion
-results::
+This TEP proposes the ``AdcConfigure`` interface for ADC hardware configuration
+and the ``Read``, ``ReadNow`` and ``ReadStream`` interfaces to acquire
+conversion results. A ``Read[Now|Stream]`` interface is always provided in
+conjunction with a ``AdcConfigure`` interface.
+
+Interface for configuring the ADC hardware
+--------------------------------------------------------------------
+
+The ``AdcConfigure`` interface is defined as follows::
+
+ interface AdcConfigure< config_type >
+ {
+ async command config_type getConfiguration();
+ }
+
+This interface is used by the ADC implementation to retrieve the hardware
+configuration of an ADC client. ``config_type`` is a chip-specific data type
+(simple or structured) that contains all information necessary to configure the
+respective ADC hardware. For example, on the ADC12 of the MSP430 the
+``AdcConfigure`` interface will be instantiated with the ``const
+msp430adc12_channel_config_t*`` data type. A client MUST always return the same
+configuration through a ``AdcConfigure`` interface and, if configuration data
+is passed as a pointer, the HIL component (see `4. HIL requirements`_) MUST NOT
+reference it after the return of the ``getConfiguration()`` command. If a
+client wants to use the ADC with different configurations it must provide
+multiple instances of the ``AdcConfigure`` interface.
+
+
+Interfaces for acquiring conversion results
+--------------------------------------------------------------------
+
+This TEP proposes to adopt the following three generic, source-independent data
+collection interfaces from [TEP114]_ for the collection of ADC conversion
+results on the level of HIL::
interface Read< size_type >
interface ReadNow< size_type >
interface ReadStream< size_type >
-Every data collection interface is associated with certain chip-specific
-configuration data (e.g. input channel, sample-hold-time, etc.). How this
-association can be realized is explained in Section `4. HAL2 requirements`_.
-As the resolution of conversion results is chip-specific, the 'size_type'
-parameter reflects an upper bound for the chip-specific resolution of the
-conversion results - the actual resolution may be smaller, depending on the
-ADC and/or data source (e.g. uint16_t for a 12-bit ADC). The above interfaces
-are specified in [TEP114]_, in the following their usage is explained with
-respect to ADCs.
+Every data collection interface is associated with an ``AdcConfigure``
+interface (how this association is realized is explained in Section `4. HIL
+requirements`_). As the resolution of conversion results is chip-specific, the
+``size_type`` parameter reflects an upper bound for the chip-specific
+resolution of the conversion results - the actual resolution may be smaller
+(e.g. uint16_t for a 12-bit ADC). The above interfaces are specified in
+[TEP114]_, in the following their usage is explained with respect to ADCs.
Read
---------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The Read interface can be used to sample an ADC channel and return a single
-conversion result. It provides no guarantees about when exactly the sampling
-occurs (the request may be buffered).
+The ``Read`` interface can be used to sample an ADC channel and return a single
+conversion result as an uninterpreted value. The meaning of the ``Read``
+interface is explained in [TEP114]_.
ReadNow
---------------------------------------------------------------------
-
-The ReadNow interface provides more precise control over the time of the
-sampling: If a call to ReadNow.read() succeeds, the ADC starts to sample the
-channel immediately (the request is not buffered). Due to its timing
-constraints the ReadNow interface is always provided in conjunction with an
-instance of the Resource interface. Refer to [TEP108]_ on how the 'Resource'
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``ReadNow`` interface is similar to the ``Read`` interface. The difference
+is that if a call to ``ReadNow.read()`` succeeds, the ADC starts to sample the
+channel immediately (precisely: when ``SUCCESS`` is returned the hardware has
+started the sampling process). Due to its timing constraints the ``ReadNow``
+interface is always provided in conjunction with an instance of the
+``Resource`` interface (a client must reserve the ADC before the client may
+call ``ReadNow.read()``). Please refer to [TEP108]_ on how the ``Resource``
interface should be used by a client component.
-
ReadStream
---------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ReadStream interface can be used to sample an ADC channel multiple times
-with a specified sampling period. It provides no guarantees about when exactly
-the first sampling occurs, but all subsequent samplings occur with the
-specified sampling period.
+The ``ReadStream`` interface can be used to sample an ADC channel multiple times
+with a specified sampling period. The meaning of the ``ReadStream`` interface
+is explained in [TEP114]_ .
-3. HAL1 guidelines
+3. HAL guidelines
====================================================================
-As explained in `1. Introduction`_ the HAL of an ADC abstraction consists of
-two sublayers, HAL1 and HAL2. In the ADC component stack the HAL1 resides
-below HAL2 and above the HPL. It exposes the full capabilities of the ADC in a
-chip-specific way and has the same function as the 'traditional' HAL in the
-HAA [TEP2]_. Therefore only chip- and platform-dependent clients MAY wire to
-the HAL1. Although the HAL1 is chip-specific, both, in terms of implementation
+As explained in `1. Introduction`_ the HAL exposes the full capabilities of the
+ADC hardware. Therefore only chip- and platform-dependent clients can wire to
+the HAL. Although the HAL is chip-specific, both, in terms of implementation
and representation, its design should follow the guidelines described below to
-facilitate the mapping to platform-independent interfaces on the level of
-HAL2. Appendix B shows the HAL1 specification for the TI MSP430 MCU.
+facilitate the mapping to the HIL representation. Appendix B shows the
+signature of the HAL for the MSP430.
Resource reservation
--------------------------------------------------------------------
-As the ADC hardware is a shared resource that is multiplexed between several
-clients, it requires access arbitration. Therefore the HAL1 configuration
-component should provide a parameterized 'Resource' interface, instantiate a
-generic arbiter component and connect the 'Resource' interface to the arbiter
-as described in [TEP108]_. To ensure fair and uniform arbitration on all
-platforms the standard round robin arbiter is recommended. Refer to [TEP108]_
-on how the 'Resource' interface is to be used by a client wiring to HAL1.
+As the ADC hardware is a shared resource that is usually multiplexed between
+several clients some form of access arbitration is necessary. The HAL should
+therefore provide a parameterized ``Resource`` interface, instantiate a
+standard arbiter component and connect the ``Resource`` interface to the
+arbiter as described in [TEP108]_. To ensure fair and uniform arbitration on
+all platforms the standard round robin arbiter is recommended. Resource
+arbiters and the ``Resource`` interface are the topic of [TEP108]_.
Configuration and sampling
--------------------------------------------------------------------
-As the ADC hardware is a shared resource the HAL1 should support hardware
-configuration and sampling on a per-client basis (although per-port
-configuration is possible, it is not recommended, because it forces all
-clients to use the same settings for a given port). Therefore an HAL1 should
-provide sampling interfaces parameterized by a client identifier. An HAL1
-client can use its instance of the sampling interface to configure the ADC
-hardware, start the sampling process and get conversion results. It wires to a
-sampling interface using a unique client identifier. All commands and events
-in the sampling interface should be 'async' to reflect the potential timing
-requirements of clients. An HAL1 may provide multiple different parameterized
-sampling interfaces, depending on the hardware capabilities. This allows to
+As the ADC hardware is a shared resource the HAL should support hardware
+configuration and sampling per client (although per-port configuration is
+possible, it is not recommended, because it forces all clients to use the same
+configuration for a given port). Therefore the HAL should provide sampling
+interfaces parameterized by a client identifier. A HAL client can use its
+instance of the sampling interface to configure the ADC hardware, start the
+sampling process and acquire conversion results. It wires to a sampling
+interface using a unique client identifier (this may be hidden by a
+virtualization component). All commands and events in the sampling interface
+should be 'async' to reflect the potential timing requirements of clients on
+the level of HAL. A HAL may provide multiple different parameterized sampling
+interfaces, depending on the hardware capabilities. This allows to
differentiate/group ADC functionality, for example single vs. repeated
-sampling, single channel vs. multiple channels or low-frequency vs.
+sampling, single channel vs. multiple channels or low-frequency vs.
high-frequency sampling. Every sampling interface should allow the client to
individually configure the ADC hardware, for example by including the
configuration data as parameters in the sampling commands. However, if
-configuration data is passed as a pointer, the HAL1 component MUST NOT
-reference it after the return of the respective command. Appendix B shows the
-HAL1 interfaces for the TI MSP430 MCU.
+configuration data is passed as a pointer, the HAL component MUST NOT reference
+it after the return of the respective command. Appendix B shows the HAL
+interfaces for the MSP430.
-HAL1 virtualization
+HAL virtualization
--------------------------------------------------------------------
In order to hide wiring complexities and/or export only a subset of all ADC
-functions generic ADC wrapper components may be provided on the level of HAL1
-to be instantiated by chip- and platform-dependent clients.
+functions generic ADC wrapper components may be provided on the level of HAL.
+Such components can also be used to ensure that a sampling interface is always
+provided with a ``Resource`` interface and both are instantiated with the same
+client ID if this is required by the HAL implementation.
-4. HAL2 requirements
+4. HIL requirements
====================================================================
-The following components MUST be provided on all platforms that have an ADC::
+The following generic components MUST be provided on all platforms that have an
+ADC::
- AdcReadClient
- AdcReadNowClient
- AdcReadStreamClient
+ AdcReadClientC
+ AdcReadNowClientC
+ AdcReadStreamClientC
-These generic components are instantiated and provide access to the ADC on a
-per-client basis via a platform-independent interface for data collection and
-a chip-specific ADC configuration interface. This section describes the
-representation of the HAL2. Guidelines on how the HAL2 can be implemented are
-discussed in Section `5. HAL2 implementation guidelines`_. Appendix C shows
-the AdcReadClient for the TI MSP430 MCU.
+These components provide virtualized access to the HIL of an ADC. They are
+instantiated by an ADC client and provide/use the four interfaces described in
+Section `2. Interfaces`_. An ADC client may instantiate multiple such
+components. The following paragraphs describe their signatures. Note that this
+TEP does not address the issue of how to deal with multiple ADCs on the same
+platform (the question of how to deal with multiple devices of the same class
+is a general one in TinyOS 2.x). Appendix C shows the ``AdcReadClientC`` for
+the MSP430.
-The fact that the components use chip-specific ADC configuration interfaces
-(see below) and the fact that the provided interfaces for data-collection must
-be interpreted with respect to the configuration data - for example the
-reference voltage - makes the HAL2 representation chip dependent. Therefore
-the ADC abstraction does not include an HIL.
-AdcReadClient
+AdcReadClientC
--------------------------------------------------------------------
::
- generic configuration AdcReadClient() {
+ generic configuration AdcReadClientC() {
provides {
interface Read< size_type >;
}
uses {
- // chip-dependent configuration interface
+ interface AdcConfigure< config_type >;
}
}
-The AdcReadClient provides platform-independent access for data collection via
-the 'Read' interface. The actual ADC channel (port) and further configuration
-details are determined by a chip-dependent configuration interface. It is the
-task of the client to wire this interface to a component that provides its ADC
-configuration. The HAL2 implementation will use this interface to "pull" the
-client's ADC settings when it translates the 'Read.read()' command to a
-chip-specific sampling command. The resolution of the conversion result is
-chip-specific, the 'size_type' parameter represents an upper bound for the
-resolution of the conversion results.
-
-AdcReadNowClient
+The ``AdcReadClientC`` component provides a ``Read`` interface for acquiring
+single conversion results. The associated ADC channel (port) and further
+configuration details are returned by the ``AdcConfigure.getConfiguration()``
+command. It is the task of the client to wire this interface to a component
+that provides the client's ADC configuration. The HIL implementation will use
+the ``AdcConfigure`` interface to dynamically "pull" the client's ADC settings
+when it translates the ``Read.read()`` command to a chip-specific sampling
+command. Note that both, ``size_type`` and ``config_type``, are only
+placeholders and will be instantiated by the respective HIL implementation (for
+an example, see the AdcReadClientC for the MSP430 in Appendix C).
+
+AdcReadNowClientC
--------------------------------------------------------------------
::
- generic configuration AdcReadNowClient() {
+ generic configuration AdcReadNowClientC() {
provides {
interface Resource;
interface ReadNow< size_type >;
}
uses {
- // chip-dependent configuration interface
+ interface AdcConfigure< config_type >;
}
}
-The AdcReadNowClient provides platform-independent access for data collection
-via the 'ReadNow' and 'Resource' interface. The actual ADC channel (port) and
-further configuration details are determined by a chip-dependent configuration
-interface. It is the task of the client to wire this interface to a component
-that provides its ADC configuration. The HAL2 implementation will use this
-interface to "pull" the client's ADC settings when it translates the
-'ReadNow.read()' command to a chip-specific sampling command. A client MUST
-use the 'Resource' interface to request access to the ADC as described in
-[TEP108]_ (the HAL2 implementation SHOULD return the error code 'ERESERVE' if
-the client has not reserved access). The resolution of the conversion result
-is chip-specific, the 'size_type' parameter represents an upper bound for the
-resolution of the conversion result.
-
-AdcReadStreamClient
+The ``AdcReadNowClientC`` component provides a ``ReadNow`` interface for
+acquiring single conversion results. In contrast to ``Read.read()`` when a call
+to ``ReadNow.read()`` succeeds, the ADC starts to sample the channel
+immediately (a successful ``Read.read()`` command may not have this
+implication, see [TEP114]_ and `2. Interfaces`_). A client MUST reserve the ADC
+through the ``Resource`` interface before the client may call
+``ReadNow.read()`` and it must release the ADC through the ``Resource``
+interface when it no longer needs to access it (for more details on the
+``Resource`` interface please refer to [TEP108]_). The associated ADC channel
+(port) and further configuration details are returned by the
+``AdcConfigure.getConfiguration()`` command. It is the task of the client to
+wire this interface to a component that provides the client's ADC
+configuration. The HIL implementation will use the ``AdcConfigure`` interface
+to dynamically "pull" the client's ADC settings when it translates the
+``ReadNow.read()`` command to a chip-specific sampling command. Note that both,
+``size_type`` and ``config_type``, are only placeholders and will be
+instantiated by the respective HIL implementation (for an example how this is
+done for the AdcReadClientC see Appendix C).
+
+AdcReadStreamClientC
--------------------------------------------------------------------
::
- generic configuration AdcReadStreamClient() {
+ generic configuration AdcReadStreamClientC() {
provides {
interface ReadStream< size_type >;
}
uses {
- // chip-dependent configuration interface
+ interface AdcConfigure< config_type>;
}
}
-The AdcReadStreamClient provides platform-independent access for data
-collection via the 'ReadStream' interface. The actual ADC channel (port) and
-further configuration details are determined by a chip-dependent configuration
-interface. It is the task of the client to wire this interface to a component
-that provides its ADC configuration. The HAL2 implementation will use this
-interface to "pull" the client's ADC settings when it translates the
-'ReadStream.read()' command to a chip-specific sampling command. The
-resolution of the conversion results is chip-specific, the 'size_type'
-parameter represents an upper bound for the resolution of the conversion
-results.
-
-5. HAL2 implementation guidelines
+The ``AdcReadStreamClientC`` component provides a ``ReadStream`` interface for
+acquiring multiple conversion results at once. The ``ReadStream`` interface is
+explained in [TEP114]_ and `2. Interfaces`_. The ``AdcConfigure`` interface is
+used in the same way as described in the section on the ``AdcReadClientC``.
+Note that both, ``size_type`` and ``config_type``, are only placeholders and
+will be instantiated by the respective HIL implementation (for an example how
+this is done for the AdcReadClientC see Appendix C).
+
+5. HIL guidelines
====================================================================
-The HAL2 implementation of an ADC stack has two main tasks: It translates a
-platform-independent HAL2 request (from the 'Read', 'ReadNow' or 'ReadStream'
-interface) to a chip-specific HAL1 sampling command and it abstracts from the
-'Resource' interface. The first task cannot be solved in a chip-independent
-way, because it involves chip-specific configuration data. The second task MAY
-be performed by the following library components: ArbitratedReadC, and
-ArbitratedReadStreamC (in tinyos-2.x/tos/system) - refer to the Atmel Atmega
-128 HAL2 implementation (in tinyos-2.x/tos/chips/atm128/adc), for an example.
-Note that since the 'ReadNow' interface is always provided in conjunction with
-a 'Resource' interface the HAL2 implementation does not have to perform the
-ADC resource reservation in this case, but can simply forward an instance of
-the 'Resource' interface from the HAL1 (to AdcReadNowClient).
-
-To support multiple ADC clients the HAL2 implementation should provide
-parameterized 'Read', 'ReadNow' and 'ReadStream' interfaces as well as a
-parameterized chip-specific configuration interface. It should also use an
-instance of the 'Resource' interface (provided by the HAL1) per provided
-'Read' and 'ReadStream' interface to perform automatic resource reservation.
-The HAL2 representation ('AdcReadClient', 'AdcReadNowClient' and
-'AdcReadStreamClient') should ensure the correct wiring between the HAL1 and
-HAL2.
-
-From the perspective of the HAL2 the typical sequence of events is as follows:
-After a client has requested data via the 'Read' or 'ReadStream' interface the
-HAL2 will request access to the HAL1 via the 'Resource' interface, e.g. using
-the library components mentioned above. When it is signalled the 'granted'
-event, the HAL2 will 'pull' the client's ADC settings and translate the
-client's command to a chip-specific HAL1 sampling command. Once it is
-signalled the conversion result(s) it releases the ADC via the 'Resource'
-interface and forwards the conversion result(s) to the client. When a client
-has requested data via the 'ReadNow' interface the HAL2 translates the
-client's command to the chip-specific HAL1 sampling command without using the
-'Resource' interface (it may check ownership of the client via the
-'ArbiterInfo' interface). In order to reduce state in the HAL2 and facilitate
-the mapping between used and provided interfaces the 'AdcReadClient',
-'AdcReadNowClient' and 'AdcReadStreamClient' should use the same interface
-identifier when it connects the HAL2 to HAL1 (see, for example, the MSP430
-ADC12 implementation in Appendix C).
+The HIL implementation of an ADC stack has two main tasks: it translates a
+``Read``, ``ReadNow`` or ``ReadStream`` request to a chip-specific HAL sampling
+command and it abstracts from the ``Resource`` interface (the latter only for
+the ``AdcReadClientC`` and ``AdcReadStreamClientC``). The first task is solved
+with the help of the ``AdcConfigure`` interface which is used by the HIL
+implementation to retrieve a client's ADC configuration. The second task MAY
+be performed by the following library components: ``ArbitratedReadC``, and
+``ArbitratedReadStreamC`` (in tinyos-2.x/tos/system) - please refer to the
+Atmel Atmega 128 HAL implementation (in tinyos-2.x/tos/chips/atm128/adc) for an
+example. Note that since the ``ReadNow`` interface is always provided in
+conjunction with a ``Resource`` interface the HIL implementation does not have
+to perform the ADC resource reservation for an ``AdcReadNowClientC``, but may
+simply forward an instance of the ``Resource`` interface from the HAL to the
+``AdcReadNowClientC``.
+
+The typical sequence of events is as follows: when a client requests data
+through the ``Read`` or ``ReadStream`` interface the HIL will request access to
+the HAL using the ``Resource`` interface. After the HIL has been granted
+access, it will "pull" the client's ADC configuration using the
+``AdcConfigure`` interface and translate the client's ``Read`` or
+``ReadStream`` command to a chip-specific HAL command. Once the HIL is
+signalled the conversion result(s) from the HAL it releases the ADC through the
+``Resource`` interface and signals the conversion result(s) to the client
+though the ``Read`` or ``ReadStream`` interface. When a client requests data
+through the ``ReadNow`` interface the HIL translates the client's command to
+the chip-specific HAL command without using the ``Resource`` interface (it may
+check ownership of the client through the ``ArbiterInfo`` interface - this
+check can also be done in the HAL implementation). Once the HIL is signalled
+the conversion result(s) it forwards it to the respective ``ReadNow`` client.
6. Implementation
====================================================================
``tinyos-2.x/tos/chips/msp430/adc12``:
* ``HplAdc12P.nc`` is the HPL implementation
- * ``Msp430Adc12P.nc`` is the HAL1 implementation
- * ``AdcC.nc`` is the HAL2 implementation
+ * ``Msp430Adc12P.nc`` is the HAL implementation
+ * ``AdcP.nc`` is the HIL implementation
* ``AdcReadClientC.nc``, ``AdcReadNowClientC.nc`` and
- ``AdcReadStreamClientC.nc`` provide access to the ADC on a per-client
- basis via the interfaces 'Read', 'ReadNow' and 'ReadStream',
- respectively, and the msp430-specific ADC configuration
- interface ``Msp430Adc12Config.nc``
+ ``AdcReadStreamClientC.nc`` provide virtualized access to the HIL
+ * the use of DMA or the reference voltage generator and the
+ HAL virtualization components are explained in ``README.txt``
The Atmel Atmega 128 ADC implementation can be found in
``tinyos-2.x/tos/chips/atm128/adc``:
* ``HplAtm128AdcC.nc`` is the HPL implementation
- * ``Atm128AdcP.nc`` is the HAL1 implementation
+ * ``Atm128AdcP.nc`` is the HAL implementation
* ``WireAdcP.nc`` and the library components for arbitrating 'Read',
'ReadNow' and 'ReadStream', ``ArbitratedReadC`` and
``ArbitratedReadStreamC`` (in ``tinyos-2.x/tos/system``), realize
- the HAL2
+ the HAL
* ``AdcReadClientC.nc``, ``AdcReadNowClientC.nc`` and
- ``AdcReadStreamClientC.nc`` provide access to the ADC on a per-client
- basis via the platform-independent interfaces 'Read', 'ReadNow' and
- 'ReadStream', respectively, and the atmega-specific ADC configuration
- interface ``Atm128AdcConfig.nc``
+ ``AdcReadStreamClientC.nc`` provide virtualized access to the HIL
Appendix A: Hardware differences between platforms
+----------------------+----------------------+---------------------+
-Appendix B: an HAL1 representation: MSP430 ADC12
+Appendix B: a HAL representation: MSP430 ADC12
====================================================================
-The following shows the HAL1 representation for the ADC12 of the TI MSP430
-MCU. It reflects the four MSP430 ADC12 conversion modes as it lets a client
-sample an ADC channel once ("Single-channel-single-conversion") or repeatedly
+This section shows the HAL signature for the ADC12 of the TI MSP430 MCU. It
+reflects the four MSP430 ADC12 conversion modes as it lets a client sample an
+ADC channel once ("Single-channel-single-conversion") or repeatedly
("Repeat-single-channel"), multiple times ("Sequence-of-channels") or multiple
times repeatedly ("Repeat-sequence-of-channels"). In contrast to the single
channel conversion modes the sequence conversion modes trigger a single
-interrupt after multiple samples and thus enable high-frequency sampling (a
-sequence conversion mode for multiple different channels is not (yet)
-implemented).::
+interrupt after multiple samples and thus enable high-frequency sampling. The
+``DMAExtension`` interface is used to reset the state machine when the DMA is
+responsible for data transfer (managed in an exterior component)::
- configuration Msp430Adc12C
+ configuration Msp430Adc12P
{
- provides interface Resource[uint8_t id];
- provides interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
- }
+ provides {
+ interface Resource[uint8_t id];
+ interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
+ interface AsyncStdControl as DMAExtension[uint8_t id];
+ }
+ }
interface Msp430Adc12SingleChannel
{
- async command error_t getSingleData(const msp430adc12_channel_config_t *config);
- async command error_t getSingleDataRepeat(const msp430adc12_channel_config_t *config,
- uint16_t jiffies);
- async command error_t getMultipleData( const msp430adc12_channel_config_t *config,
- uint16_t *buffer, uint16_t numSamples, uint16_t jiffies);
- async command error_t getMultipleDataRepeat(const msp430adc12_channel_config_t *config,
- uint16_t *buffer, uint8_t numSamples, uint16_t jiffies);
+ async command error_t configureSingle(const msp430adc12_channel_config_t *config);
+ async command error_t configureSingleRepeat(const msp430adc12_channel_config_t *config, uint16_t jiffies);
+ async command error_t configureMultiple( const msp430adc12_channel_config_t *config, uint16_t buffer[], uint16_t numSamples, uint16_t jiffies);
+ async command error_t configureMultipleRepeat(const msp430adc12_channel_config_t *config, uint16_t buffer[], uint8_t numSamples, uint16_t jiffies);
+ async command error_t getData();
async event error_t singleDataReady(uint16_t data);
- async event uint16_t* multipleDataReady(uint16_t *buffer, uint16_t
- numSamples);
+ async event uint16_t* multipleDataReady(uint16_t buffer[], uint16_t numSamples);
}
-There exist two wrapper components, Msp430Adc12ClientC and
-Msp430Adc12RefVoltAutoClientC, which SHOULD be used to eliminate wiring
-errors.
+ typedef struct {
+ unsigned int inch: 4; // input channel
+ unsigned int sref: 3; // reference voltage
+ unsigned int ref2_5v: 1; // reference voltage level
+ unsigned int adc12ssel: 2; // clock source sample-hold-time
+ unsigned int adc12div: 3; // clock divider sample-hold-time
+ unsigned int sht: 4; // sample-hold-time
+ unsigned int sampcon_ssel: 2; // clock source sampcon signal
+ unsigned int sampcon_id: 2; // clock divider sampcon signal
+ } msp430adc12_channel_config_t;
-Appendix C: an HAL2 representation: MSP430 ADC12
+
+Appendix C: a HIL representation: MSP430 ADC12
====================================================================
-The AdcReadClientC component for the MSP430 ADC12 is implemented as follows:
-::
+The signature of the AdcReadClientC component for the MSP430 ADC12 is as
+follows::
generic configuration AdcReadClientC() {
provides interface Read<uint16_t>;
- uses interface Msp430Adc12Config;
- } implementation {
- components AdcC;
- #ifdef REF_VOLT_AUTO_CONFIGURE
- components new Msp430Adc12RefVoltAutoClientC() as Msp430AdcClient;
- #else
- components new Msp430Adc12ClientC() as Msp430AdcClient;
- #endif
-
- enum {
- CLIENT = unique(ADCC_SERVICE),
- };
-
- Read = AdcC.Read[CLIENT];
- Msp430Adc12Config = AdcC.Config[CLIENT];
- AdcC.SingleChannel[CLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
- AdcC.Resource[CLIENT] -> Msp430AdcClient.Resource;
- #ifdef REF_VOLT_AUTO_CONFIGURE
- Msp430Adc12Config = Msp430AdcClient.Msp430Adc12Config;
- #endif
+ uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
}
-Note that the same CLIENT identifier is used for all involved interfaces to
-facilitate the mapping between the HAL2 and HAL1 interfaces. The conditional
-compile directive REF_VOLT_AUTO_CONFIGURE can be used to automatically enable
-the internal reference voltage generator during the sampling process.
-
.. [TEP1] TEP 1: TEP Structure and Keywords.
.. [TEP2] TEP 2: Hardware Abstraction Architecture.
.. [TEP108] TEP 108: Resource Arbitration.
*accuracy*.
Examples of precision are millisecond, a cycle of a 32kHz clock, and
-microseconds. All precisions are in "binary" units with respect to
-one second. That is, one second contains 1024 binary milliseconds,
-32768 32kHz ticks, or 1048576 microseconds. This TEP emphasizes
-millisecond and 32kHz tick precisions while reasonably accommodating
-other precisions.
+microseconds. All precisions presented in this TEP are in "binary"
+units with respect to one second. That is, one second contains 1024
+binary milliseconds, 32768 32kHz ticks, or 1048576 microseconds.
+This TEP emphasizes millisecond and 32kHz tick precisions while
+reasonably accommodating other precisions.
Examples of widths are 8-bit, 16-bit, 32-bit, and 64-bit. The width
for timer interfaces and components SHOULD be 32-bits. That is, for
Precision is expressed as an empty type -- TMilli, T32khz, and
TMicro -- written in the standard Timer.h header like this::
- typedef struct { } TMilli;
- typedef struct { } T32khz;
- typedef struct { } TMicro;
+ typedef struct { } TMilli; // 1024 ticks per second
+ typedef struct { } T32khz; // 32768 ticks per second
+ typedef struct { } TMicro; // 1048576 ticks per second
Note that the precision names are expressed as either frequency or
period, whichever is convenient.
return the current time.
isOverflowPending()
- return TRUE if an overflow interrupt will occur after the outermost
- atomic block is exits. FALSE otherwise.
+ return TRUE if the overflow flag is set for this counter, i.e., if and
+ only if an overflow interrupt will occur after the outermost atomic
+ block exits. Return FALSE otherwise. This command only returns the
+ state of the overflow flag and causes no side effect. It is expected
+ that the underlying hardware platform sets the overflow flag when
+ appropriate.
clearOverflow()
- cancel the pending overflow interrupt.
+ cancel the pending overflow interrupt clearing the overflow flag.
overflow()
signals that an overflow in the current time. That is, the current
--------------------------------------------------------------------
Alarm components are extensions of Counters that signal an event
-when their Compare register detects the alarm time has been hit.
+when their compare register detects the alarm time has been hit.
All commands and events of the Alarm interface are asynchronous (or
in "interrupt context"). The Alarm interface provides a set of
"basic" commands for common usage and provides a set of "extended"
or has not yet fired. FALSE is returned otherwise.
startAt(t0,dt)
+
cancel any previously running alarm and set to fire at time t1 =
- t0+dt. This form allows a delay to be anchored to some time t0
- taken before the invocation of start. This is also the form used
- internally in the timer subsystem to allow the use of the full width
- of an alarm while being able to detect if the alarm time for a short
- alarm prematurely elapsed.
+ t0+dt. This form allows a delay to be anchored to some time t0 taken
+ before the invocation of startAt. The timer subsystem uses this form
+ internally, to be able to use of the full width of an alarm while also
+ detecting when a short alarm elapses prematurely.
getNow()
return the current time in the precision and width of the alarm.
getAlarm()
return the time the currently running alarm will fire or the time
- that the previously running alarm was set to fire.
+ that the previously running alarm was set to fire. getAlarm can
+ be used with startAt to set an alarm from the previous alarm time,
+ as in startAt(getAlarm(),dt). This pattern is used within the
+ fired() event to construct periodic alarms.
BusyWait
--------------------------------------------------------------------
-The BusyWait interface replaces the TOSH_uwait macro from TinyOS
-1.x. ::
+The BusyWait interface allows for very short synchronous delays.
+BusyWait should be used sparingly and when an Alarm would not be
+reasonably efficient or accurate. The BusyWait interface replaces
+the TOSH_uwait macro from TinyOS 1.x.
+
+BusyWait blocks for no less than the specified amount of time. No
+explicit upper bound is imposed on the enacted delay, though it is
+expected the underlying implementation spins in a busy loop until
+the specified amount of time has elapsed.
+::
interface BusyWait<precision_tag,size_type>
{
}
wait(dt)
- block for no less than the specified amount of time.
+ block until at least dt time units have elapsed
LocalTime
--------------------------------------------------------------------
3. HAL guidelines
====================================================================
-Platforms typically select a clocking option for each of their
-hardware counters, based on their hardware design (e.g., the mica
-family of motes all run their hardware timer 0 at 32kHz, and the micaz
-mote runs its timer 1 at cpu frequency/256). Platforms SHOULD expose
-the timing functionality of these timers using the Alarm and Counter
-interfaces, in the fashion described below. Platforms MAY expose the
-same hardware timer with different frequencies - use of conflicting
-frequences in the same program SHOULD produce compile-time
-errors.
-
-
-A hardware timer with precision *P* and width *W* SHOULD be exposed as
-several components::
-
- configuration CounterPWC {
- provides interface Counter<TP, uintW_t>;
- } ...
- generic configuration AlarmPWC {
- provides interface Alarm<TP,uintW_t>;
- } ...
+Platforms SHOULD expose their relevant timing capabilities using
+standard Alarm and Counter interfaces. The design pattern presented
+here defines a component naming convention to allow platform
+independent access to particular Alarms and Counters if they exist
+and to cause compile errors if they do not.
-and, except if *W* is 32::
+A platform specific hardware timer with precision ${P} and width
+${W} SHOULD be exposed as these two conventional Counter and Alarm
+components::
- configuration CounterP32C {
- provides interface Counter<TP, uint32_t>;
- } ...
- generic configuration AlarmP32C {
- provides interface Alarm<TP,uint32_t>;
- } ...
+ configuration Counter${P}${W}C
+ {
+ provides interface Counter< T${P}, uint${W}_t >;
+ }
-Instantiating the Alarm... components provides a new Alarm independent
-of all prior instantiations. Instantiating such a component "consumes"
-a compare register from the corresponding hardware timer; when no more
-compare registers are available, instantiation SHOULD produce a
-compile-time error (see Appendix B for an example of how to achieve
-this).
+ generic configuration Alarm${P}${W}C()
+ {
+ provides interface Alarm< T${P}, uint${W}_t >;
+ }
+
+Instantiating an Alarm${P}${W}C component provides a new and
+independent Alarm. If the platform presents a limited number of
+Alarm resources, then allocating more Alarms in an application than
+are available for the platform SHOULD produce a compile-time error.
+See Appendix B for an example of how to make allocatable Alarms that
+are each implemented on independent hardware timers.
+
+For example, if a platform has an 8-bit 32kHz counter and three
+8-bit 32kHz alarms, then the Counter and Alarm interfaces for
+${P}=32khz and ${W}=16 are::
+
+ configuration Counter32khz8C
+ {
+ provides interface Counter< T32khz, uint8_t >;
+ }
+
+ generic configuration Alarm32khz8C()
+ {
+ provides interface Alarm< T32khz, uint8_t >;
+ }
+
+This pattern MAY be used to defined components for the platform that
+are mutually incompatible in single application. Incompatible
+components SHOULD produce compile-time errors when compiled
+together.
-For example, the micaz platform includes an AlarmMilli8C and
-AlarmMilli32C components for timer 0 (one instantiation allowed), and
-Alarm32kHz16C and Alarm32kHz32C for timer 1 (three instantiations
-allowed).
4. HIL requirements
====================================================================
The following component MUST be provided on all platforms::
- TimerMilliC
+ HilTimerMilliC
BusyWaitMicroC
-TimerMilliC
+HilTimerMilliC
--------------------------------------------------------------------
::
- #define TIMERMILLIC_SERVICE ...
- configuration TimerMilliC
+ configuration HilTimerMilliC
{
provides interface Init;
- provides interface Timer<TMilli>[uint8_t num];
- provides interface LocalTime<TMilli>;
+ provides interface Timer<TMilli> as TimerMilli[ uint8_t num ];
}
-A timer is allocated using unique(TIMERMILLIC_SERVICE) to obtain a new
-unique timer number. This timer number is used to index the TimerMilli
-parameterised interface.
+A new timer is allocated using unique(UQ_TIMER_MILLI) to obtain a
+new unique timer number. This timer number is used to index the
+TimerMilli parameterised interface. UQ_TIMER_MILLI is defined in
+Timer.h. HilTimerMilliC is used by the generic component
+TimerMilliC found in ``tos/system/``.
BusyWaitMicroC
--------------------------------------------------------------------
new TransformAlarmC( TMilli, uint32_t, T32khz, uint16_t, 5 )
+It is the exclusive responsibility of the developer using
+TransformAlarmC to ensure that all five of its arguments are self
+consistent. No compile errors are generated if the parameters
+passed to TransformAlarmC are inconsistent.
+
TransformCounterC
--------------------------------------------------------------------
uses interface Timer<precision_tag> as TimerFrom;
}
-6. Author's Address
+6. Implementation
+====================================================================
+
+The definition of the HIL interfaces are found in ``tinyos-2.x/tos/lib/timer``:
+
+ * ``Alarm.nc``
+ * ``BusyWait.nc``
+ * ``Counter.nc``
+ * ``LocalTime.nc``
+ * ``Timer.h`` defines precision tags and strings for unique()
+ * ``Timer.nc``
+
+The implementation of the utility components are also found in
+``tinyos-2.x/tos/lib/timer``:
+
+ * ``AlarmToTimerC.nc``
+ * ``BusyWaitCounterC.nc``
+ * ``CounterToLocalTimeC.nc``
+ * ``TransformAlarmC.nc``
+ * ``TransformAlarmCounterC.nc``
+ * ``TransformCounterC.nc``
+ * ``VirtualizeAlarmC.nc``
+ * ``VirtualizeTimerC.nc``
+
+The implementation of Timers for the MSP430 is in
+``tinyos-2.x/tos/chips/msp430/timer``:
+
+ * ``Alarm32khz16C.nc`` is generic and provides a new ``Alarm<T32khz,uint16_t>``
+ * ``Alarm32khz32C.nc`` is generic and provides a new ``Alarm<T32khz,uint32_t>``
+ * ``AlarmMilli16C.nc`` is generic and provides a new ``Alarm<TMilli,uint16_t>``
+ * ``AlarmMilli32C.nc`` is generic and provides a new ``Alarm<TMilli,uint32_t>``
+ * ``BusyWait32khzC.nc`` provides ``BusyWait<T32khz,uint16_t>``
+ * ``BusyWaitMicroC.nc`` provides ``BusyWait<TMicro,uint16_t>``
+ * ``Counter32khz16C.nc`` provides ``Counter<T32khz,uint16_t>``
+ * ``Counter32khz32C.nc`` provides ``Counter<T32khz,uint32_t>``
+ * ``CounterMilli16C.nc`` provides ``Counter<TMilli,uint16_t>``
+ * ``CounterMilli32C.nc`` provides ``Counter<TMilli,uint32_t>``
+ * ``GpioCaptureC.nc``
+ * ``HilTimerMilliC.nc`` provides ``Timer<TMilli> as TimerMilli[uint8_t num]``
+ * ``Msp430AlarmC.nc`` is generic and converts an MSP430 timer to a 16-bit Alarm
+ * ``Msp430Capture.nc`` HPL interface definition for MSP430 timer captures
+ * ``Msp430ClockC.nc`` exposes MSP430 hardware clock initialization
+ * ``Msp430ClockInit.nc`` HPL interface definition for hardware clock initialization
+ * ``Msp430ClockP.nc`` implements MSP430 hardware clock initialization and
+ calibration and startup
+ * ``Msp430Compare.nc`` HPL interface definition for MSP430 timer compares
+ * ``Msp430Counter32khzC.nc`` provides ``Counter<T32khz,uint16_t>`` based on
+ MSP430 TimerB
+ * ``Msp430CounterC.nc`` is generic and converts an Msp430Timer to a Counter
+ * ``Msp430CounterMicroC.nc`` provides ``Counter<TMicro,uint16_t>`` based on
+ MSP430 TimerA
+ * ``Msp430Timer.h`` defines additional MSP430 timer bitmasks and structs
+ * ``Msp430Timer.nc`` HPL interface definition
+ * ``Msp430Timer32khzC.nc`` is generic and allocates a new 32khz hardware timer
+ * ``Msp430Timer32khzMapC.nc`` exposes the MSP430 hardware timers as a
+ parameterized interface allocatable using Msp430Timer32khzC
+ * ``Msp430TimerC.nc`` exposes the MSP430 hardware timers
+ * ``Msp430TimerCapComP.nc`` is generic and implements the HPL for MSP430
+ capture/compare special function registers
+ * ``Msp430TimerCommonP.nc`` maps the MSP430 timer interrupts to Msp430TimerEvents
+ * ``Msp430TimerControl.nc`` HPL interface definition
+ * ``Msp430TimerEvent.nc`` HPL interface definition
+ * ``Msp430TimerP.nc`` is generic and implements the HPL for MSP430 timer
+ special function registers
+
+7. Author's Address
====================================================================
| Cory Sharp
| Moteiv Corporation
| 55 Hawthorne St, Suite 550
| San Francisco, CA 94105
|
+| phone - +1 415 692 0963
| email - cory@moteiv.com
|
|
==============================================
:TEP: 103
-:Group: Core Working Group
+:Group: Core Working Group
:Type: Documentary
-:Status: Draft
+:Status: Final
:TinyOS-Version: 2.x
:Author: David Gay, Jonathan Hui
-:Draft-Created: 27-Sep-2004
-:Draft-Version: $Revision$
-:Draft-Modified: $Date$
-:Draft-Discuss: TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu>
-
-
.. Note::
This memo documents a part of TinyOS for the TinyOS Community, and
1. Introduction
====================================================================
-Flash chips are a form of EEPROM (electrically-eraseable, programmable
+Flash chips are a form of EEPROM (electrically-erasable, programmable
read-only memory), distinguished by a fast erase capability. However,
erases can only be done in large units (from 256B to 128kB depending on the
flash chip). Erases are the only way to switch bits from 0 to 1, and
programming operations can only switch 1's to 0's. Additionally, some
chips require that programming only happen once between each erase,
-or that it be in relatively large units (e.g., 256B).
+or that it be in relatively large units (e.g., 256B).
In the table below, we summarise these differences by categorising
flash chips by their underlying technology (NOR vs NAND). We also
include a column for Atmel's AT45DB flash chip family, as it has
-significantly different tradeoffs than other flash chips: ::
-
-
- NOR AT45DB NAND
- (ex: ST M25P40, (ex: Samsung
- Intel PXA27x) K9K1G08R0B)
-
- Erase : Slow (seconds) Fast (ms) Fast (ms)
- Erase unit : Large (64KB-128KB) Small (256B) Medium (8KB-32KB)
- Writes : Slow (100s kB/s) Slow (60kB/s) Fast (MBs/s)
- Write unit : 1 bit 256B 100's of bytes
- Bit-errors : Low Low High (requires ECC,
- bad-block mapping)
- Read : Bus limited* Slow+Bus limited Bus limited
- Erase cycles : 10^4 - 10^5 10^4 ** 10^5 - 10^7
- Intended use : Code storage Data storage Data storage
- Energy/byte : 1uJ 1uJ .01uJ
-
- * M25P40 reads are limited by the use of a 25MHz SPI bus. The PXA27x flash is
- memory mapped (reads are very fast and can directly execute code).
- ** Or infinite? Data sheet just says that every page within a sector
- must be written every 10^4 writes within that sector
+significantly different tradeoffs than other flash chips:
+
+
+ ============= ================== ================= ===================
+ X NOR AT45DB NAND
+ (ex: ST M25P40, (ex: Samsung
+ Intel PXA27x) K9K1G08R0B)
+ ============= ================== ================= ===================
+ Erase Slow (seconds) Fast (ms) Fast (ms)
+ Erase unit Large (64KB-128KB) Small (256B) Medium (8KB-32KB)
+ Writes Slow (100s kB/s) Slow (60kB/s) Fast (MBs/s)
+ Write unit 1 bit 256B 100's of bytes
+ Bit-errors Low Low High (requires ECC,
+ bad-block mapping)
+ Read Bus limited [*]_ Slow+Bus limited Bus limited
+ Erase cycles 10^4 - 10^5 10^4 [*]_ 10^5 - 10^7
+ Intended use Code storage Data storage Data storage
+ Energy/byte 1uJ 1uJ .01uJ
+ ============= ================== ================= ===================
+
+.. [*] M25P40 reads are limited by the use of a 25MHz SPI bus. The PXA27x flash
+ is memory mapped (reads are very fast and can directly execute code).
+.. [*] Or infinite? Data sheet just says that every page within a sector
+ must be written every 10^4 writes within that sector
The energy/byte is the per-byte cost of erasing plus programming. It is
derived from the timing and power consumption of erase and write operations
- ``ByteEEPROMC`` allows arbitrary rewrites of sections of the flash.
This is not readily implementable on a flash chip with large erase units.
- The ``Matchbox`` implementation was AT45DB-specific. It was not
- reimplemented for these other chips, in part because it does not
+ reimplemented for these other chips, in part because it does not
support some applications (e.g., network reprogramming) very well.
2. Storage in TinyOS 2.x
in a free, open-source operating system.
- To support arbitrary block writes where blocks are smaller than the
erase unit, and to deal with the limited number of erase cycles/block
- requires remapping blocks. We believe that maintaining this remapping
+ requires remapping blocks. We believe that maintaining this remapping
table is too expensive on many mote-class devices.
A second approach is to provide a generic low-level interface providing
we believe that the large differences between NAND and NOR flash (see the
table above), in particular the differences in reliability, write and
erase units, make the design of a useful generic low-level interface
-tricky at best.
+tricky at best.
We thus believe it is best, for now at least, to define high-level
storage abstractions that are useful for sensor network applications,
We prefer the use of single abstractions over fixed-size volumes over
the use of a more general filing system (like Matchbox) for several
reasons:
-
+
- TinyOS is currently targeted at running a single application, and many
applications know their storage needs in advance: for instance, a
little space for configuration data, and everything else for a log of
"wear levelling" (ensuring that each block of the flash is erased
the same number of time, to maximise flash chip lifetime).
-New abstractions (including a filing system...) can easily be added to
+New abstractions (including a filing system) can easily be added to
this framework.
The rest of this TEP covers some principles for the organisation of
The flash chip architecture follows the three-layer Hardware
Abstraction Architecture (HAA), with each chip providing a presentation
layer (HPL, Section 3.1), adaptation layer (HAL, Section 3.2) and
-platform-independent interface layer (HIL, Section 3.3) [2_].
+platform-independent interface layer (HIL, Section 3.3) [2_].
The implementation of these layers SHOULD be found in the
``tos/chips/CHIPNAME`` directory. If a flash chip is part of a larger
family with a similar interface, the HAA SHOULD support all family members
The flash HPL has a chip-dependent, platform-independent interface. The
implementation of this HPL is platform-dependent. The flash HPL SHOULD be
-stateless.
+stateless.
To remain platform independent, a flash chip's HPL SHOULD connect to
platform-specific components
providing access to the flash chip; these components
SHOULD be placed in the ``tos/platforms/PLATFORM/chips/CHIPNAME``
-directory. If the flash chip implementation supports a family of
+directory. If the flash chip implementation supports a family of
flash chips, this directory MAY also contain a file describing the
particular flash chip found on the platform.
3.3 Hardware Interface Layer (HIL)
--------------------------------------------------------------------
-Each flash chip MUST provide implementations of the storage abstractions
-described in Section 4. These abstractions MUST be presented in
+Each flash chip MUST support at least one of the storage abstractions
+described in Section 4. These abstractions SHOULD be presented in
components named ``ChipAbstractionC``, e.g., ``At45dbLogStorageC``.
+Additionally, a flash chip implementation MAY support platforms
+with multiple instances of the same storage chip. The way in which
+this is achieved is not specified further in this TEP.
-Each platform MUST have ``AbstractionC`` components (e.g., ``LogStorageC``)
-implementing the storage abstractions of Section 4. Platforms with a single
-storage chip SHOULD simply make ``AbstractionC`` be a simple configuration
-wrapping the appropriate ``ChipAbstractionC`` component. Platforms with
-multiple storage chips SHOULD redirect uses of ``AbstractionC`` to the
-appropriate storage chip, based on the requested volume.
+Each platform MUST have ``AbstractionC`` components (e.g.,
+``LogStorageC``) implementing the storage abstractions of Section 4
+supported by its flash chip(s). On platforms with multiple storage chips
+SHOULD redirect uses of ``AbstractionC`` to the appropriate storage
+chip, based on the requested volume.
4. Non-Volatile Storage Abstractions
===================================================================
location for a volume. If there is any reason that the physical allocation
cannot be satisfied, an error should be given at compile time. The tool
SHOULD be named ``tos-storage-CHIPNAME`` and be distributed with the other
-tools supporting a platform.
+tools supporting a platform. The XML file SHOULD be named
+``volumes-CHIPNAME.xml``.
The compile-time tool MUST prepend 'VOLUME\_' to each volume name in
the XML file and '#define' each resulting name to map to a unique
-integer.
+integer.
The storage abstractions are accessed by instantiating generic
components that take the volume macro as argument: ::
4.2 Large objects
------------------------------------------------------------------
-The motivating example for large objects is the transmission or long-term
-storage of large pieces of data. For instance, programs in a network-reprogramming
-system, or large data-packets in a reliable data-transmission system. Such
-objects have two interesting characteristics: each byte in the object is
-written at most once, and a full object is written in a single "session"
-(i.e., without the mote rebooting).
+The motivating example for large objects is the transmission or
+long-term storage of large pieces of data. For instance, programs in a
+network-reprogramming system, or large data-packets in a reliable
+data-transmission system. Such objects have an interesting
+characteristic: each byte in the object is written at most once.
This leads to the definition of the ``BlockStorageC`` abstraction for storing
-large objects:
+large objects or other "write-once" objects:
- A large object ranges from a few kilobytes upwards.
- A large object is erased before the first write.
-- A commit ensures that a large object survives a reboot or crash
+- A sync ensures that a large object survives a reboot or crash
- Reads are unrestricted
-- Writes can only be performed between an erase and a commit
-- Each byte can only be written once between an erase and a commit
+- Each byte can only be written once between two erases
Large objects are accessed by instantiating a BlockStorageC component
which takes a volume id argument: ::
}
} ...
-The ``BlockRead`` and ``BlockWrite`` interfaces contain the following
-operations (all split-phase, except ``BlockRead.getSize``):
+The ``BlockRead`` and ``BlockWrite`` interfaces (briefly presented in
+Appendix B) contain the following operations (all split-phase, except
+``BlockRead.getSize``):
- ``BlockWrite.erase``: erase the volume. After a reboot or a commit, a
volume MUST be erased before it can be written to.
- ``BlockWrite.write``: write some bytes starting at a given
- offset. Each byte MUST NOT be written more than once between an erase
- and the subsequent commit. Writes MUST NOT be performed between a
- commit and the subsequent erase.
+ offset. Each byte MUST NOT be written more than once between two erases.
-- ``BlockWrite.commit``: commit all writes to a given volume. Writes
- MUST NOT be performed after a commit until a subsequent erase. Commit
- MUST be called to ensure written data survives a reboot or crash.
-- ``BlockRead.verify``: verify that the volume contains the results of a
- successful commit.
+- ``BlockWrite.sync``: ensure all previous writes are present on a given
+ volume. Sync MUST be called to ensure written data survives a reboot
+ or crash.
- ``BlockRead.read``: read some bytes starting at a given offset.
For full details on arguments and other considerations, see the comments in
the interface definitions.
+Note that these interfaces contain no direct support for verifying the
+integrity of the BlockStorage data, but such support can easily be built
+by using the ``computeCrc`` command and storing the result in a
+well-defined location, and checking this CRC when desired.
+
4.3 Logging
------------------------------------------------------------------
record. On failure (crash or reboot), the log MUST only lose whole
records from the end of the log. Additionally, once a circular log wraps
around, calls to ``LogWrite.append`` MUST only lose whole records from
-the beginning of the log.
+the beginning of the log.
Logs are accessed by instantiating a LogStorageC component which takes a
volume id and a boolean argument: ::
If the ``circular`` argument is TRUE, the log is circular; otherwise
it is linear.
-The ``LogRead`` and ``LogWrite`` interfaces contain the following
-operations (all split-phase except ``LogWrite.currentOffset``,
-``LogRead.currentOffset`` and ``LogRead.getSize``):
+The ``LogRead`` and ``LogWrite`` interfaces (briefly presented in
+Appendix B) contain the following operations (all split-phase except
+``LogWrite.currentOffset``, ``LogRead.currentOffset`` and
+``LogRead.getSize``):
- ``LogWrite.erase``: erase the log. A log MUST be erased (possibly in
some previous session) before any other operation can be used.
- ``LogWrite.append``: append some bytes to the log. In a circular log,
- this may overwrite the current read position. In this case, the
+ this may overwrite the current read position. In this case, the
read position MUST be advanced to the log's current beginning
(i.e., as if ``LogRead.seek`` had been called with ``SEEK_BEGINNING``).
Additionally, the ``LogWrite.appendDone`` event reports whenever, in a
- circular log, an append erases old records.
+ circular log, an append MAY have erased old records.
Each append creates a separate record. Log implementations may have a
maximum record size; all implementations MUST support records of up
- ``LogRead.seek``: set the read position to a value returned by
a prior call to ``LogWrite.currentOffset`` or ``LogRead.currentOffset``,
or to the special ``SEEK_BEGINNING`` value. In a circular log, if
- the specified position has been overwritten, behave as if
+ the specified position has been overwritten, behave as if
``SEEK_BEGINNING`` was requested.
``SEEK_BEGINNING`` positions the read position at the beginning of
}
} ...
-A small object MUST be mounted (via the ``Mount`` interface) before
+A small object MUST be mounted (via the ``Mount`` interface) before
the first use.
-The ``Mount`` and ``ConfigStorage`` interfaces contain the following
-operations (all split-phase except ``ConfigStorage.getSize`` and
-``ConfigStorage.valid``):
+The ``Mount`` and ``ConfigStorage`` interfaces (briefly presented in
+Appendix B) contain the following operations (all split-phase except
+``ConfigStorage.getSize`` and ``ConfigStorage.valid``):
- ``Mount.mount``: mount the volume.
A.1 AT45DB
------------------------------------------------------------------
-
+
The Atmel AT45DB family HPL is: ::
configuration HplAt45dbC {
The ``HplAt45db`` interface has flash->buffer, buffer->flash, compare
buffer to flash, erase page, read, compute CRC, and write operations. Most
of these operations are asynchronous, i.e., their completion is signaled
-before the flash chip has completed the operation. The HPL also includes
+before the flash chip has completed the operation. The HPL also includes
operations to wait for asynchronous operations to complete.
A generic, system-independent implementation of the HPL
Note that the AT45DB HAL resource management is independent of the
underlying HPL's power management. The motivation for this is that
individual flash operations may take a long time, so it may be desirable to
-release the flash's bus during long-running operations.
+release the flash's bus during long-running operations.
The ``At45db`` interface abstracts from the low-level HPL operations by:
A.2 ST M25P
------------------------------------------------------------------
-
+
The ST M25P family HPL is: ::
configuration Stm25pSpiC {
volume-relative addresses. Clients of the ST M25P HAL must implement the
``getVolumeId`` event of the ``Stm25pVolume`` interface so that the HAL can
obtain the volume id of each of its clients.
+
+Appendix B. Storage interfaces
+====================================================================
+
+These interfaces are presented briefly here for reference; please refer
+to the TinyOS documentation for a full description of the commands,
+events and their parameters.
+
+B.1 BlockStorage interfaces
+------------------------------------------------------------------
+
+The BlockStorage interfaces are: ::
+
+ interface BlockRead {
+ command error_t read(storage_addr_t addr, void* buf, storage_len_t len);
+ event void readDone(storage_addr_t addr, void* buf, storage_len_t len,
+ error_t error);
+
+ command error_t computeCrc(storage_addr_t addr, storage_len_t len,
+ uint16_t crc);
+ event void computeCrcDone(storage_addr_t addr, storage_len_t len,
+ uint16_t crc, error_t error);
+
+ command storage_len_t getSize();
+ }
+
+ interface BlockWrite {
+ command error_t write(storage_addr_t addr, void* buf, storage_len_t len);
+ event void writeDone(storage_addr_t addr, void* buf, storage_len_t len,
+ error_t error);
+
+ command error_t erase();
+ event void eraseDone(error_t error);
+
+ command error_t sync();
+ event void syncDone(error_t error);
+ }
+
+B.2 ConfigStorage interfaces
+------------------------------------------------------------------
+
+The ConfigStorage interfaces are: ::
+
+ interface Mount {
+ command error_t mount();
+ event void mountDone(error_t error);
+ }
+
+ interface ConfigStorage {
+ command error_t read(storage_addr_t addr, void* buf, storage_len_t len);
+ event void readDone(storage_addr_t addr, void* buf, storage_len_t len,
+ error_t error);
+
+ command error_t write(storage_addr_t addr, void* buf, storage_len_t len);
+ event void writeDone(storage_addr_t addr, void* buf, storage_len_t len,
+ error_t error);
+
+ command error_t commit();
+ event void commitDone(error_t error);
+
+ command storage_len_t getSize();
+ command bool valid();
+ }
+
+B.3 LogStorage interfaces
+------------------------------------------------------------------
+
+The LogStorage interfaces are: ::
+
+ interface LogRead {
+ command error_t read(void* buf, storage_len_t len);
+ event void readDone(void* buf, storage_len_t len, error_t error);
+
+ command storage_cookie_t currentOffset();
+
+ command error_t seek(storage_cookie_t offset);
+ event void seekDone(error_t error);
+
+ command storage_len_t getSize();
+ }
+
+ interface LogWrite {
+ command error_t append(void* buf, storage_len_t len);
+ event void appendDone(void* buf, storage_len_t len, bool recordsLost,
+ error_t error);
+
+ command storage_cookie_t currentOffset();
+
+ command error_t erase();
+ event void eraseDone(error_t error);
+
+ command error_t sync();
+ event void syncDone(error_t error);
+ }
component with a generic name for application authors who only care
about the general class of the sensor.
-This document assumes that sensors return uninterpreted values of
-arbitrary size or datatype. Conversion of sensor values to something
-with actual physical meaning is beyond the scope of this document.
+This document takes no position on the meaning of the values returned
+by sensor drivers. They may be raw uninterpreted values or they may
+have some physical meaning. If a driver returns uninterpreted values,
+the driver may provide additional interfaces that would allow
+higher-level clients to interpret the value properly.
2. Sensor HIL Components
====================================================================
// connect to the sensor's platform-dependent HPL here
}
-4. Sensor HPL Components
-====================================================================
-
-A sensor HPL is necessarily platform-dependent or
-sensorboard-dependent. These components should provide access to the
-physical resources needed by the sensor, in a platform-independent
-manner that can be used by the shared logic of the sensor HAL
-components. In the case of bus-based sensors, this HPL may be nothing
-more than wiring to the appropriate bus interface for use by the HAL
-component.
-
-For example::
-
- configuration HplSensirionSht11C {
- provides interface Init;
- provides interface Resource[ uint8_t id ];
- provides interface GeneralIO as DATA;
- provides interface GeneralIO as SCK;
- provides interface GpioInterrupt as InterruptDATA;
- }
- implementation {
- // connect to platform or sensorboard-dependent resources
- // power-manage the sensor through platform-specific means
- }
-
-5. Directory Organization Guidelines
+4. Directory Organization Guidelines
====================================================================
Because the same physical sensor may be attached to TinyOS platforms
components may be placed anywhere as long as the nesC compiler
receives enough `-I` directives to locate all of the necessary pieces.
-6. Authors' Addresses
+5. Authors' Addresses
====================================================================
| David Gay
|
| email - gtolle@archrock.com
-7. Citations
+6. Citations
====================================================================
.. [TEP2] TEP 2: Hardware Abstraction Architecture
.. [TEP114] TEP 114: SIDs: Source and Sink Indepedent Drivers
.. [TEP115] TEP 115: Power Management of Non-Virtualized Devices
+Appendix A: Sensor Driver Examples
+====================================================================
+
+1. Analog ADC-Connected Sensor
+------------------------------
+
+The Analog sensor requires two components
+
+* a component to present the sensor itself (HamamatsuS1087ParC)
+
+* a component to select the appropriate hardware resources, such as
+ ADC port 4, reference voltage 1.5V, and a slow sample and hold time
+ (HamamatsuS1087ParP).
+
+The AdcReadClientC component and underlying machinery handles all of
+the arbitration and access to the ADC.
+
+::
+
+ tos/platforms/telosa/chips/s1087/HamamatsuS1087ParC.nc
+
+ generic configuration HamamatsuS1087ParC() {
+ provides interface Read<uint16_t>;
+ provides interface ReadStream<uint16_t>;
+ }
+ implementation {
+ components new AdcReadClientC();
+ Read = AdcReadClientC;
+
+ components new AdcReadStreamClientC();
+ ReadStream = AdcReadStreamClientC;
+
+ components HamamatsuS1087ParP;
+ AdcReadClientC.Msp430Adc12Config -> HamamatsuS1087ParP;
+ AdcReadStreamClientC.Msp430Adc12Config -> HamamatsuS1087ParP;
+ }
+
+::
+
+ tos/platforms/telosa/chips/s1087/HamamatsuS1087ParP.nc
+
+ module HamamatsuS1087ParP {
+ provides interface Msp430Adc12Config;
+ }
+ implementation {
+
+ async command msp430adc12_channel_config_t
+ Msp430Adc12Config.getChannelSettings() {
+
+ msp430adc12_channel_config_t config = {
+ inch: INPUT_CHANNEL_A4,
+ sref: REFERENCE_VREFplus_AVss,
+ ref2_5v: REFVOLT_LEVEL_1_5,
+ adc12ssel: SHT_SOURCE_ACLK,
+ adc12div: SHT_CLOCK_DIV_1,
+ sht: SAMPLE_HOLD_4_CYCLES,
+ sampcon_ssel: SAMPCON_SOURCE_SMCLK,
+ sampcon_id: SAMPCON_CLOCK_DIV_1
+ };
+
+ return config;
+ }
+ }
+
+2. Binary Pin-Connected Sensor
+------------------------------
+
+The Binary sensor gets a bit more complex, because it has three
+components:
+
+* one to present the sensor (UserButtonC)
+
+* one to execute the driver logic (UserButtonLogicP)
+
+* one to select the appropriate hardware resources, such as MSP430
+ Port 27 (HplUserButtonC).
+
+Note that the presentation of this sensor is not arbitrated because
+none of the operations are split-phase.
+
+::
+
+ tos/platforms/telosa/UserButtonC.nc
+
+ configuration UserButtonC {
+ provides interface Get<bool>;
+ provides interface Notify<bool>;
+ }
+ implementation {
+
+ components UserButtonLogicP;
+
+ components HplUserButtonC;
+ UserButtonLogicP.GpioInterrupt -> HplUserButtonC.GpioInterrupt;
+ UserButtonLogicP.GeneralIO -> HplUserButtonC.GeneralIO;
+
+ Get = UserButtonLogicP;
+ Notify = UserButtonLogicP;
+ }
+
+::
+
+ tos/platforms/telosa/UserButtonLogicP.nc
+
+ module UserButtonLogicP {
+ provides interface Get<bool>;
+ provides interface Notify<bool>;
+
+ uses interface GeneralIO;
+ uses interface GpioInterrupt;
+ }
+ implementation {
+ norace bool m_pinHigh;
+
+ task void sendEvent();
+
+ command bool Get.get() { return call GeneralIO.get(); }
+
+ command error_t Notify.enable() {
+ call GeneralIO.makeInput();
+
+ if ( call GeneralIO.get() ) {
+ m_pinHigh = TRUE;
+ return call GpioInterrupt.enableFallingEdge();
+ } else {
+ m_pinHigh = FALSE;
+ return call GpioInterrupt.enableRisingEdge();
+ }
+ }
+
+ command error_t Notify.disable() {
+ return call GpioInterrupt.disable();
+ }
+
+ async event void GpioInterrupt.fired() {
+ call GpioInterrupt.disable();
+
+ m_pinHigh = !m_pinHigh;
+
+ post sendEvent();
+ }
+
+ task void sendEvent() {
+ bool pinHigh;
+ pinHigh = m_pinHigh;
+
+ signal Notify.notify( pinHigh );
+
+ if ( pinHigh ) {
+ call GpioInterrupt.enableFallingEdge();
+ } else {
+ call GpioInterrupt.enableRisingEdge();
+ }
+ }
+ }
+
+::
+
+ tos/platforms/telosa/HplUserButtonC.nc
+
+ configuration HplUserButtonC {
+ provides interface GeneralIO;
+ provides interface GpioInterrupt;
+ }
+ implementation {
+
+ components HplMsp430GeneralIOC as GeneralIOC;
+
+ components new Msp430GpioC() as UserButtonC;
+ UserButtonC -> GeneralIOC.Port27;
+ GeneralIO = UserButtonC;
+
+ components HplMsp430InterruptC as InterruptC;
+
+ components new Msp430InterruptC() as InterruptUserButtonC;
+ InterruptUserButtonC.HplInterrupt -> InterruptC.Port27;
+ GpioInterrupt = InterruptUserButtonC.Interrupt;
+ }
+
+3. Digital Bus-Connected Sensor
+-------------------------------
+
+The Digital sensor is the most complex out of the set, and includes
+six components:
+
+* one to present the sensor (SensirionSht11C)
+
+* one to request arbitrated access and to transform the sensor HAL
+ into the sensor HIL (SensirionSht11P)
+
+* one to present the sensor HAL (HalSensirionSht11C)
+
+* one to perform the driver logic needed to support the HAL, which
+ twiddles pins according to a sensor-specific protocol
+ (SensirionSht11LogicP).
+
+* one to select the appropriate hardware resources, such as the clock,
+ data, and power pins, and to provide an arbiter for the sensor
+ (HplSensirionSht11C).
+
+* one to perform the power control logic needed to support the power
+ manager associated with the arbiter (HplSensirionSht11P).
+
+This bus-connected sensor is overly complex because it does not rely
+on a shared framework of bus manipulation components. A sensor built
+on top of the I2C or SPI bus would likely require fewer components.
+
+::
+
+ tos/platforms/telosa/chips/sht11/SensirionSht11C.nc
+
+ generic configuration SensirionSht11C() {
+ provides interface Read<uint16_t> as Temperature;
+ provides interface Read<uint16_t> as Humidity;
+ }
+ implementation {
+ components new SensirionSht11ReaderP();
+
+ Temperature = SensirionSht11ReaderP.Temperature;
+ Humidity = SensirionSht11ReaderP.Humidity;
+
+ components HalSensirionSht11C;
+
+ enum { TEMP_KEY = unique("Sht11.Resource") };
+ enum { HUM_KEY = unique("Sht11.Resource") };
+
+ SensirionSht11ReaderP.TempResource -> HalSensirionSht11C.Resource[ TEMP_KEY ];
+ SensirionSht11ReaderP.Sht11Temp -> HalSensirionSht11C.SensirionSht11[ TEMP_KEY ];
+ SensirionSht11ReaderP.HumResource -> HalSensirionSht11C.Resource[ HUM_KEY ];
+ SensirionSht11ReaderP.Sht11Hum -> HalSensirionSht11C.SensirionSht11[ HUM_KEY ];
+ }
+
+::
+
+ tos/chips/sht11/SensirionSht11ReaderP.nc
+
+ generic module SensirionSht11ReaderP() {
+ provides interface Read<uint16_t> as Temperature;
+ provides interface Read<uint16_t> as Humidity;
+
+ uses interface Resource as TempResource;
+ uses interface Resource as HumResource;
+ uses interface SensirionSht11 as Sht11Temp;
+ uses interface SensirionSht11 as Sht11Hum;
+ }
+ implementation {
+ command error_t Temperature.read() {
+ call TempResource.request();
+ return SUCCESS;
+ }
+
+ event void TempResource.granted() {
+ error_t result;
+ if ((result = call Sht11Temp.measureTemperature()) != SUCCESS) {
+ call TempResource.release();
+ signal Temperature.readDone( result, 0 );
+ }
+ }
+
+ event void Sht11Temp.measureTemperatureDone( error_t result, uint16_t val ) {
+ call TempResource.release();
+ signal Temperature.readDone( result, val );
+ }
+
+ command error_t Humidity.read() {
+ call HumResource.request();
+ return SUCCESS;
+ }
+
+ event void HumResource.granted() {
+ error_t result;
+ if ((result = call Sht11Hum.measureHumidity()) != SUCCESS) {
+ call HumResource.release();
+ signal Humidity.readDone( result, 0 );
+ }
+ }
+
+ event void Sht11Hum.measureHumidityDone( error_t result, uint16_t val ) {
+ call HumResource.release();
+ signal Humidity.readDone( result, val );
+ }
+
+ event void Sht11Temp.resetDone( error_t result ) { }
+ event void Sht11Temp.measureHumidityDone( error_t result, uint16_t val ) { }
+ event void Sht11Temp.readStatusRegDone( error_t result, uint8_t val ) { }
+ event void Sht11Temp.writeStatusRegDone( error_t result ) { }
+
+ event void Sht11Hum.resetDone( error_t result ) { }
+ event void Sht11Hum.measureTemperatureDone( error_t result, uint16_t val ) { }
+ event void Sht11Hum.readStatusRegDone( error_t result, uint8_t val ) { }
+ event void Sht11Hum.writeStatusRegDone( error_t result ) { }
+
+ default event void Temperature.readDone( error_t result, uint16_t val ) { }
+ default event void Humidity.readDone( error_t result, uint16_t val ) { }
+ }
+
+::
+
+ tos/platforms/telosa/chips/sht11/HalSensirionSht11C.nc
+
+ configuration HalSensirionSht11C {
+ provides interface Resource[ uint8_t client ];
+ provides interface SensirionSht11[ uint8_t client ];
+ }
+ implementation {
+ components new SensirionSht11LogicP();
+ SensirionSht11 = SensirionSht11LogicP;
+
+ components HplSensirionSht11C;
+ Resource = HplSensirionSht11C.Resource;
+ SensirionSht11LogicP.DATA -> HplSensirionSht11C.DATA;
+ SensirionSht11LogicP.CLOCK -> HplSensirionSht11C.SCK;
+ SensirionSht11LogicP.InterruptDATA -> HplSensirionSht11C.InterruptDATA;
+
+ components new TimerMilliC();
+ SensirionSht11LogicP.Timer -> TimerMilliC;
+
+ components LedsC;
+ SensirionSht11LogicP.Leds -> LedsC;
+ }
+
+::
+
+ tos/chips/sht11/SensirionSht11LogicP.nc
+
+ generic module SensirionSht11LogicP() {
+ provides interface SensirionSht11[ uint8_t client ];
+
+ uses interface GeneralIO as DATA;
+ uses interface GeneralIO as CLOCK;
+ uses interface GpioInterrupt as InterruptDATA;
+
+ uses interface Timer<TMilli>;
+
+ uses interface Leds;
+ }
+ implementation {
+
+ ... bus protocol details omitted for brevity ...
+
+ }
+
+::
+
+ tos/platforms/telosa/chips/sht11/HplSensirionSht11C.nc
+
+ configuration HplSensirionSht11C {
+ provides interface Resource[ uint8_t id ];
+ provides interface GeneralIO as DATA;
+ provides interface GeneralIO as SCK;
+ provides interface GpioInterrupt as InterruptDATA;
+ }
+ implementation {
+ components HplMsp430GeneralIOC;
+
+ components new Msp430GpioC() as DATAM;
+ DATAM -> HplMsp430GeneralIOC.Port15;
+ DATA = DATAM;
+
+ components new Msp430GpioC() as SCKM;
+ SCKM -> HplMsp430GeneralIOC.Port16;
+ SCK = SCKM;
+
+ components new Msp430GpioC() as PWRM;
+ PWRM -> HplMsp430GeneralIOC.Port17;
+
+ components HplSensirionSht11P;
+ HplSensirionSht11P.PWR -> PWRM;
+ HplSensirionSht11P.DATA -> DATAM;
+ HplSensirionSht11P.SCK -> SCKM;
+
+ components new TimerMilliC();
+ HplSensirionSht11P.Timer -> TimerMilliC;
+
+ components HplMsp430InterruptC;
+ components new Msp430InterruptC() as InterruptDATAC;
+ InterruptDATAC.HplInterrupt -> HplMsp430InterruptC.Port15;
+ InterruptDATA = InterruptDATAC.Interrupt;
+
+ components new FcfsArbiterC( "Sht11.Resource" ) as Arbiter;
+ Resource = Arbiter;
+
+ components new SplitControlPowerManagerC();
+ SplitControlPowerManagerC.SplitControl -> HplSensirionSht11P;
+ SplitControlPowerManagerC.ArbiterInit -> Arbiter.Init;
+ SplitControlPowerManagerC.ArbiterInfo -> Arbiter.ArbiterInfo;
+ SplitControlPowerManagerC.ResourceController -> Arbiter.ResourceController;
+ }
+
+::
+
+ tos/platforms/telosa/chips/sht11/HplSensirionSht11P.nc
+
+ module HplSensirionSht11P {
+ provides interface SplitControl;
+ uses interface Timer<TMilli>;
+ uses interface GeneralIO as PWR;
+ uses interface GeneralIO as DATA;
+ uses interface GeneralIO as SCK;
+ }
+ implementation {
+ task void stopTask();
+
+ command error_t SplitControl.start() {
+ call PWR.makeOutput();
+ call PWR.set();
+ call Timer.startOneShot( 11 );
+ return SUCCESS;
+ }
+
+ event void Timer.fired() {
+ signal SplitControl.startDone( SUCCESS );
+ }
+
+ command error_t SplitControl.stop() {
+ call SCK.makeInput();
+ call SCK.clr();
+ call DATA.makeInput();
+ call DATA.clr();
+ call PWR.clr();
+ post stopTask();
+ return SUCCESS;
+ }
+
+ task void stopTask() {
+ signal SplitControl.stopDone( SUCCESS );
+ }
+ }
often require packets to be contiguous memory regions. Overall, these
complexities make specifying the format of ``TOS_Msg`` very difficult.
+TinyOS has traditionally used statically sized packet buffers,
+rather than more dynamic approaches, such as scatter-gather I/O
+in UNIX sockets (see the man page for ``recv(2)`` for details).
+TinyOS 2.x continues this approach.
+
2. message_t
====================================================================
passing a message buffer between two different link layers. If the
data payload were at different offsets for different link layers, then
passing a packet between two link layers would require a ``memmove(3)``
-operation (essentially, a copy).
+operation (essentially, a copy). Unlike in TinyOS 1.x, where TOS_Msg
+as explicitly an active messaging packet, message_t is a more general
+data-link buffer. In practice, most data-link layers in TinyOS 2.x
+provide active messaging, but it is possible for a non-AM stack to
+share message_t with AM stacks.
The header, footer, and metadata formats are all opaque. Source code
cannot access fields directly. Instead, data-link layers provide access
The message_t header field is an array of bytes whose size is
the size of a platform's union of data-link headers.
-Because packets are stored contiguously, the layout of a packet
-in memory is not the same as the layout of its nesC structure.
+Because radio stacks often prefer packets to be stored contiguously,
+the layout of a packet in memory does not necessarily reflect the
+layout of its nesC structure.
-A packet header does not necessarily start at the beginning of
+A packet header MAY start somewhere besides the beginning of
the message_t. For example, consider the Telos platform::
typedef union message_header {
nx_uint16_t time;
} cc2420_metadata_t;
-5. Implementation
+3.5 Variable Sized Structures
+----------------------------------------------------------------
+
+The message_t structure is optimized for packets with fixed-size
+headers and footers. Variable-sized footers are generally easy
+to implement. Variable-sized headers are a bit more difficult.
+There are three general approaches that can be used.
+
+If the underlying link hardware is byte-based, the header can
+just be stored at the beginning of the message_t, giving it
+a known offset. There may be padding between the header and
+the data region, but assuming a byte-based send path this merely
+requires adjusting the index.
+
+If the underlying link hardware is packet-based, then the
+protocol stack can either include metadata (e.g., in the
+metadata structure) stating where the header begins or it
+can place the header at a fixed position and use ``memmove(3)``
+on reception and transmit. In this latter case, on
+reception the packet is continguously read into the message_t
+beginning at the offset of the header structure. Once the
+packet is completely received, the header can be decoded,
+its length calculated, and the data region of the packet
+can be moved to the ``data`` field. On transmission,
+the opposite occurs: the data region (and footer if need
+be) are moved to be contiguous with the header. Note that
+on completion of transmission, they need to be moved back.
+Alternatively, the radio stack can institute a single
+copy at the botttom layer.
+
+
+
+4. Implementation
====================================================================
The definition of message_t can be found in
-``tinyos-2.x/tos/types/message.h``. The definition of the CC2420
+``tinyos-2.x/tos/types/message.h``.
+
+The definition of the CC2420
message format can be found in ``tinyos-2.x/tos/chips/cc2420/CC2420.h``.
+
The defintion of the CC1000 message format can be found in
-``tinyos-2.x/tos/chips/cc1000/CC1000Msg.h``. The definition
+``tinyos-2.x/tos/chips/cc1000/CC1000Msg.h``.
+
+The definition
of the standard serial stack packet format can be found in
-``tinyos-2.x/tos/lib/serial/Serial.h''. The definition of
-the telosb packet format can be found in
+``tinyos-2.x/tos/lib/serial/Serial.h``
+
+The definition of
+the telos family packet format can be found in
``tinyos-2.x/tos/platform/telosa/platform_message.h`` and the micaz format can be found in
``tinyos-2.x/tos/platforms/micaz/platform_message.h``.
-6. Author's Address
+5. Author's Address
====================================================================
| Philip Levis
6. Citations
====================================================================
-.. [TEP2] TEP 2: Hardware Abstraction Architecture. http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep2.txt?view=markup
+.. [TEP2] TEP 2: Hardware Abstraction Architecture. tinyos-2.x/doc/txt/tep2.txt
-.. [TEP111] TEP 111: message_t. http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep111.txt?view=markup
+.. [TEP111] TEP 111: message_t. tinyos-2.x/doc/txt/tep111.txt
-.. [TEP116] TEP 116: Packet Protocols. http://cvs.sourceforge.net/viewcvs.py/tinyos/tinyos-1.x/beta/teps/txt/tep116.txt?view=markup
+.. [TEP116] TEP 116: Packet Protocols. tinyos-2.x/doc/txt/tep116.txt
.. [HDLC] International Organization For Standardization, ISO Standard 3309-1979, "Data communication - High-level data link control procedures - Frame structure", 1979.
:Type: Documentary
:Status: Draft
:TinyOS-Version: 2.x
-:Author: Vlado Handziski, Kevin Klues, Jan-Hinrich Hauer, Phil Levis
+:Author: Kevin Klues, Vlado Handziski, Jan-Hinrich Hauer, Phil Levis
:Draft-Created: 11-Jan-2006
:Draft-Version: $Revision$
============================
-Pins and Buses
+Low-Level I/O
============================
:TEP: 117
:Type: Documentary
:Status: Draft
:TinyOS-Version: 2.x
-:Author: Phil Buonadonna
+:Author: Phil Buonadonna, Jonathan Hui
:Draft-Created: 23-Jan-2006
:Draft-Version: $Revision$
====================================================================
The memo documents the TinyOS 2.x interfaces used for controlling
-digital IO functionality and digital interfaces other than serial
-communication covered in [tep113].
+digital IO functionality and digital interfaces.
1. Introduction
The canonical TinyOS device is likely to have a variety of digital
interfaces. These interfaces may be divided into two broad
-categories. The first are general purpose digital I/O lines (pins)
-for individual digital signals at physical pins on a chip or
-platform. The second are digital I/O interfaces that have predefined
-communication protocol formats. The two buses covered in this
-document are the Serial Peripheral Interface (SPI) and the
-Inter-Integrated Circuit (I2c) or Two-Wire interface. While there are
-likely other bus formats, we presume SPI and I2C to have the largest
-coverage. While the UART interface is also in this category, it is
-covered separately in [tep113].
-
-This memo documents the interfaces used for pins and the two buses.
+categories. The first are general purpose digital I/O lines (pins) for
+individual digital signals at physical pins on a chip or platform. The
+second are digital I/O interfaces that have predefined communication
+protocol formats. The three buses covered in this document are the
+Serial Peripheral Interface (SPI), the Inter-Integrated Circuit (I2C)
+or Two-Wire interface, and the Universal Asynchronous
+Receiver/Transmitter (UART) interface. While there are likely other
+bus formats, we presume SPI, I2C, and UART to have the largest
+coverage.
+
+This memo documents the interfaces used for pins and the three buses.
2. Pins
====================================================================
-General Purpose I/O (GPIO) pins are single, versatile digital I/O signals
-individually controllable on a particular chip or platform. Each GPIO
-can be placed into either an input mode or an output mode. On
-some platforms a third 'tri-state' mode may exist, but this
-functionality is platform specific and will not be covered in this
-document.
+General Purpose I/O (GPIO) pins are single, versatile digital I/O
+signals individually controllable on a particular chip or
+platform. Each GPIO can be placed into either an input mode or an
+output mode. On some platforms a third 'tri-state' mode may exist, but
+this functionality is platform specific and will not be covered in
+this document.
-On many platforms, a physical pin may function as either a digital GPIO
-or another special function I/O such. Examples include ADC I/O or a bus
-I/O. Interfaces to configure the specific function of a pin are
-platform specific.
+On many platforms, a physical pin may function as either a digital
+GPIO or another special function I/O such. Examples include ADC I/O or
+a bus I/O. Interfaces to configure the specific function of a pin are
+platform specific.
The objective of the interfaces described here is not to attempt to
cover all possibilities of GPIO functionality and features, but to
async command void toggle();
async command bool get();
async command void makeInput();
+ async command bool isInput();
async command void makeOutput();
+ async command bool isOutput();
}
2.2 GpioInterrupt
--------------------------------------------------------------------
-The GPIO Interrupt HIL interface provides baseline event control for a
+The GPIO Interrupt HIL interface provides baseline event control for a
GPIO pin. It provides a mechanism to detect a rising edge OR a falling
edge. Note that calls to enableRisingEdge and enableFallingEdge are
NOT cumulative and only one edge may be detected at a time. There may
interface GpioInterrupt {
async command error_t enableRisingEdge();
+ async command bool isRisingEdgeEnabled();
async command error_t enableFallingEdge();
+ async command bool isFallingEdgeEnabled();
async command error_t disable();
async event void fired();
Some platforms may have hardware support for such a feature. Other
platforms may emulate this capability using the SoftCaptureC
component. The interface makes not declaration of the precision or
-accuracy of the timestamp with respect to the associated GPIO event. ::
+accuracy of the timestamp with respect to the associated GPIO
+event. ::
interface GpioCapture {
async command error_t captureRisingEdge();
+ async command bool isRisingEdgeEnabled();
async command error_t captureFallingEdge();
+ async command bool isFallingEdgeEnabled();
async event void captured(uint16_t time);
async command void disable();
asynchronous packet level interface. The byte level interface is
intended for short transactions (3-4 bytes) on the SPI bus. ::
- interface SPIByte {
- async command error_t write( uint8_t tx, uint8_t* rx );
+ interface SpiByte {
+ async command uint8_t write( uint8_t tx );
}
The packet level interface is for larger bus transactions. The
-pointer/length interface permits use of hardware assist such as DMA. ::
+pointer/length interface permits use of hardware assist such as
+DMA. ::
- interface SPIPacket {
-
+ interface SpiPacket {
async command error_t send( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len );
- async event void sendDone( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len,
- error_t error );
+ async event void sendDone( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len,
+ error_t error );
}
3.2 I2C
The Inter-Integrated Circuit (I2C) interface is another type of
digital bus that is often used for chip-to-chip communication. It is
-also known as a two-wire interface.
+also known as a two-wire interface.
-The I2CPacket interface provides for asynchronous Master mode communication on an
-I2C with application framed packets. It supports only single
-transfers with a start-stop condition around each transfer.
+The I2CPacket interface provides for asynchronous Master mode
+communication on an I2C with application framed packets. Individual
+I2C START-STOP events are controllable which allows the using
+component to do multiple calls within a single I2C transaction and
+permits multiple START sequences
Platforms providing I2C capability MUST provide this interface. ::
- interface I2CPacket {
- async command result_t readPacket(uint16_t _addr, uint8_t _length, uint8_t* _data);
- async command result_t writePacket(uint16_t _addr, uint8_t _length, uint8_t* _data);
- async event void readPacketDone(uint16_t addr, uint8_t length, uint8_t* data, result_t success);
- async event void writePacketDone(uint16_t addr, uint8_t length, uint8_t* data, result_t success);
+ interface I2CPacket<addr_size> {
+ async command error_t read(i2c_flags_t flags, uint16_t addr, uint8_t length, u int8_t* data);
+ async event void readDone(error_t error, uint16_t addr, uint8_t length, uint8_t* data);
+ async command error_t write(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data);
+ async event void writeDone(error_t error, uint16_t addr, uint8_t length, uint8_t* data)
}
+The interface is typed according to the addressing space the
+underlying implementation supports. Valid type values are below. ::
+
+ TI2CExtdAddr - Interfaces uses the extended (10-bit) addressing mode.
+ TI2CBasicAddr - Interfaces uses the basic (7-bit) addressing mode.
+
+The i2c_flags_t values are defined below. The flags define the
+behavior of the operation for the call being made. These values may be
+ORed together. ::
+
+ I2C_START - Transmit an I2C STOP at the beginning of the operation.
+ I2C_STOP - Transmit an I2C STOP at the end of the operation. Cannot be used
+ with the I2C_ACK_END flag.
+ I2C_ACK_END - ACK the last byte sent from the buffer. This flags is only valid
+ a write operation. Cannot be used with the I2C_STOP flag.
-4. Author's Address
+3.3 UART
+--------------------------------------------------------------------
+
+The Universal Asynchronous Receiver/Transmitter (UART) interface is a
+type of serial interconnect. The interface is "asynchronous" since it
+recovers timing from the data stream itself, rather than a separate
+control stream. The interface is split into an asynchronous multi-byte
+level interface and a synchronous single-byte level interface.
+
+The multi-byte level interface, UartStream, provides a split-phase
+interface for sending and receiving one or more bytes at a time. When
+receiving bytes, a byte-level interrupt can be enabled or an interrupt
+can be generated after receiving one or more bytes. The latter is
+intended to support use cases where the number of bytes to receive is
+already known. If the byte-level receive interrupt is enabled, the
+receive command MUST return FAIL. If a multi-byte receive interrupt is
+enabled, the enableReceiveInterrupt command MUST return FAIL. ::
+
+ interface UartStream {
+ async command error_t send( uint8_t* buf, uint16_t len );
+ async event void sendDone( uint8_t* buf, uint16_t len, error_t error );
+
+ async command error_t enableReceiveInterrupt();
+ async command error_t disableReceiveInterrupt();
+ async event void receivedByte( uint8_t byte );
+
+ async command error_t receive( uint8_t* buf, uint8_t len );
+ async event void receiveDone( uint8_t* buf, uint16_t len, error_t error );
+ }
+
+The single-byte level interface, UartByte, provides a synchronous
+interface for sending and receiving a single byte. This interface is
+intended to support use cases with short transactions. Because UART is
+asynchronous, the receive command takes a timeout which represents
+units in byte-times, after which the command returns with an
+error. Note that use of this interface is discouraged if the UART baud
+rate is low. ::
+
+ interface UartByte {
+ async command error_t send( uint8_t byte );
+ async command error_t receive( uint8_t* byte, uint8_t timeout );
+ }
+
+4. Implementation
+====================================================================
+
+Example implementations of the pin interfaces can be found in tos/chips/msp430/pins,
+tos/chips/atm128/pins, and tos/chips/pxa27x/gpio.
+
+Example implementations of the SPI interfaces can be found in tos/chips/msp430/usart,
+tos/chips/atm128/spi, and tos/chips/pxa27x/ssp.
+
+Example implementations of the I2C interfaces can be found in tos/chips/msp430/usart,
+tos/chips/atm128/i2c, and tos/chips/pxa27x/i2c.
+
+Example implementations of the UART interfaces can be found in tos/chips/msp430/usart,
+tos/chips/atm128/uart/ and tos/chips/pxa27x/uart.
+
+
+5. Author's Address
====================================================================
| Phil Buonadonna
-| Arched Rock Corporation
+| Arch Rock Corporation
| 657 Mission St. Ste 600
| San Francisco, CA 94105-4120
|
| phone - +1 415 692-0828 x2833
+|
+|
+| Jonathan Hui
+| Arched Rock Corporation
+| 657 Mission St. Ste 600
+| San Francisco, CA 94105-4120
+|
+| phone - +1 415 692-0828 x2835
-5. Citations
+6. Citations
====================================================================
.. [tep113] TEP 113: Serial Communication.
The memo documents the interfaces, components, and semantics used by
collection protocol in TinyOS 2.x. Collection provides a best-effort,
-multihop delivery of packets to the root of a tree.
+multihop delivery of packets to the root of *a* tree. There may be
+multiple roots in a network, and in this case the semantics implemented
+are of *anycast* delivery to at least one of the roots. A node sending
+a packet does not specify which root the packet is destined to.
+
1. Introduction
====================================================================
parent node, a collection protocol implicitly joins one of these
trees. Collection provides a best-effort,
multihop delivery of packets to one of a network's tree roots:
-it is an *anycast* protocol.
+it is an *anycast* protocol. The semantics is that the protocol
+will make a reasonable effort to deliver the message to at least
+one of the roots in the network. There are however no guarantees of
+delivery, and there can be duplicates delivered to one or more
+roots. There is also no ordering guarantees.
Given the limited state that nodes can store and a general need
for distributed tree building algorithms, simple collection protocols
A node can perform four different roles in collection: producer,
consumer, snooper, and in-network processor. Depending on their role,
the nodes use different interfaces to interact with the collection
-component.
-
-The nodes that generate data to be sent to the root are
-*producers*. The producers use the Send interface [1_] to send
-data to the root of the collection tree. The collection tree
-identifier is be specified as a parameter to Send during
-instantiation.
-
-Root nodes that receive data from the network are *consumers*. The
-consumers use the Receive interface [1_] to receive a message
-delivered by collection. The collection tree identifier is be
-specified as a parameter to Receive during instantiation.
+component.
-The nodes that overhear messages in transit are *snoopers*. The snoopers
-use the Receive interface [1_] to receive a snooped message. The
-collection tree identifier is be specified as a parameter to Receive
-during instantiation.
-
-The nodes can process a packet that are in transit. These in-network
-*processors* use the Intercept interface [1_] to receive and
-update a packet. The collection tree identifier is be specified as a
-parameter to Intercept during instantiation.
+A consumer is a root of a tree. The set of all roots and the paths that
+lead to them form the collection routing infrastructure in the network.
+For any connected set of nodes implementing the collection protocol
+there is only one collection infrastructure, *i.e.*, all roots in this
+set active at the same time are part of the same infrastructure.
A node is configured to become a root by using the RootControl
interface. RootControl.setRoot() MUST make the current node a root of
-the tree specified during instantiation. RootControl.unsetRoot() MUST
-make the current root no longer a root in the tree specified during
-instantiation. RootControl.unsetRoot() MAY be called on a node that is
+the the collection infrastructure. RootControl.unsetRoot() MUST
+make the current root no longer a root in the collection infrastructure.
+Both calls are idempotent.
+RootControl.setRoot() MAY be called on a node that is already a root, to
+no effect. RootControl.unsetRoot() MAY be called on a node that is
not a root::
interface RootControl {
command bool isRoot();
}
+The collection infrastructure can be multiplexed among independent
+applications, by means of a *collection identifier*. It is important
+to note that the *data* traffic in the protocol is multiplexed,
+while the *control* traffic is not.
+
+The nodes that generate data to be sent to the root are *producers*.
+The producers use the Send interface [1_] to send data to the root
+of the collection tree. The collection identifier is specified as a
+parameter to Send during instantiation.
+
+Root nodes that receive data from the network are *consumers*. The
+consumers use the Receive interface [1_] to receive a message
+delivered by collection. The collection identifier is specified
+as a parameter to Receive during instantiation.
+
+The nodes that overhear messages in transit are *snoopers*. The
+snoopers use the Receive interface [1_] to receive a snooped
+message. The collection identifier is specified as a parameter
+to Receive during instantiation.
+
+The nodes can process a packet that are in transit. These in-network
+*processors* use the Intercept interface [1_] to receive and update
+a packet. The collection identifier is specified as a parameter
+to Intercept during instantiation.
3 Collection Services
====================================================================
-A collection service MUST provide one component, TreeCollectionC,
+A collection service MUST provide one component, CollectionC,
which has the following signature::
- configuration TreeCollectionC {
+ configuration CollectionC {
provides {
interface StdControl;
interface Send[uint8_t client];
interface RootControl;
interface Packet;
interface CollectionPacket;
- interface TreeRoutingInspect;
}
uses {
interface CollectionId[uint8_t client];
}
-TreeCollectionC MAY have additional interfaces, but they MUST have
+CollectionC MAY have additional interfaces, but they MUST have
default functions on all outgoing invocations (commands for uses,
events for provides) of those interfaces so that it can operate
properly if they are not wired.
-Components SHOULD NOT wire to TreeCollectionC.Send. The generic
+Components SHOULD NOT wire to CollectionC.Send. The generic
component CollectionSenderC (described in section 3.1) provides
a virtualized sending interface.
snoopers, intercepters, and receivers can parse it properly.
Receive.receive MUST NOT be signaled on non-root
-nodes. TreeCollectionC MAY signal Receive.receive on a root node when
+nodes. CollectionC MAY signal Receive.receive on a root node when
a data packet successfully arrives at that node. If a root node calls
-Send, TreeCollectionC MUST treat it as it if were a received packet.
+Send, CollectionC MUST treat it as it if were a received packet.
Note that the buffer swapping semantics of Receive.receive, when
-combined with the pass semantics of Send, require that TreeCollectionC
+combined with the pass semantics of Send, require that CollectionC
make a copy of the buffer if it signals Receive.receive.
-If TreeCollectionC receives a data packet to forward and it is not a
+If CollectionC receives a data packet to forward and it is not a
root node, it MAY signal Intercept.forward.
-If TreeCollectionC receives a data packet that a different node
+If CollectionC receives a data packet that a different node
is supposed to forward, it MAY signal Snoop.receive.
RootControl allows a node to be made a collection tree root.
-TreeCollectionC SHOULD NOT configure a node as a root by default.
+CollectionC SHOULD NOT configure a node as a root by default.
Packet and CollectionPacket allow components to access collection
data packet fields [1_].
-TreeRoutingInspect provides information on the current position of
-the node in a routing tree::
-
- interface TreeRoutingInspect {
- command error_t getParent(am_addr_t* parent);
- command error_t getHopcount(uint8_t* hopcount);
- command error_t getMetric(uint16_t* metric);
- }
-
-In each of these commands, if the return value is not SUCCESS, the
-value stored in the pointer argument is undefined. The getMetric
-command provides a measure of the quality of a node's route to the
-base station. This routing metric MUST be monotonically increasing
-across hops. In a collection tree, if node A is the parent of node B,
-then node B's metric value MUST be greater than node A's.
-
3.1 CollectionSenderC
--------------------------------------------------------------------
}
}
+
+
This abstraction follows a similar virtualization approach to
AMSenderC [1_], except that it is parameterized by a collection_id_t
rather than an am_id_t. As with am_id_t, every collection_id_t SHOULD
====================================================================
An implementation of this TEP can be found in
-``tinyos-2.x/tos/lib/net/collection``. The implementation consists of
-three major components, which are wired together to form a
-CollectionC: LinkEstimatorP, TreeRoutingEngineP, and ForwardingEngineP.
-
-This decomposition tries to encourage evolution of components and ease
-of use through modularization. Neighbor management and link estimation
-are are decoupled from the routing protocol. Furthermore, the routing
-protocol and route selection are decoupled from the forwarding policies,
-such as queueing and timing.
+``tinyos-2.x/tos/lib/net/ctp`` and ``tinyos-2.x/tos/lib/net/le``, in
+the CTP protocol. It is beyond the scope of this document to fully
+describe CTP, but we outline its main components. CTP will be
+described in an upcoming TEP [2_]. This implementation is a
+reference implementation, and is not the only possibility. It
+consists of three major components, which are wired together to form
+a CollectionC: LinkEstimatorP, CtpTreeRoutingEngineP, and
+CtpForwardingEngineP.
+
+This decomposition tries to encourage evolution of components and
+ease of use through modularization. Neighbor management and link
+estimation are decoupled from the routing protocol. Furthermore, the
+routing protocol and route selection are decoupled from the
+forwarding policies, such as queueing and timing.
4.1 LinkEstimatorP
--------------------------------------------------------------------
LinkEstimatorP estimates the quality of link to or from each
-neighbor. Link estimation can be done in a variety of ways, and we do
-not impose one here. It is decoupled from the establishment of
-routes. There is a narrow interface (LinkEstimator) between the link
-estimator and the routing engine. The one requirement is that the
-quality returned is standardized. A larger return value from
+neighbor. Link estimation can be done in a variety of ways, and we
+do not impose one here. It is decoupled from the establishment of
+routes. There is a narrow interface -- LinkEstimator -- between the
+link estimator and the routing engine. The one requirement is that
+the quality returned is standardized. A smaller return value from
LinkEstimator.getQuality(), LinkEstimator.getforwardQuality(),
LinkEstimator.getreserveQuality() MUST imply that the link to the
neighbor is estimated to be of a higher quality than the one that
[0,255] and the variation in link quality in that range SHOULD be
linear. Radio provided values such as LQI or RSI, beacon based link
estimation to compute ETX, or their combination are some possible
-approaches to estimating link qualities. LinkEstimatorP MAY have its
-own control messages to compute bi-directional link qualities::
+approaches to estimating link qualities.
- typedef uint16_t neighbor_t
+LinkEstimatorP MAY have its own control messages to compute
+bi-directional link qualities. LinkEstimatorP provides calls
+(txAck(), txNoAck(), and clearDLQ()) to update the link estimates
+based on successful or unsuccessful data transmission to the
+neighbors.
+
+The user of LinkEstimatorP can call insertNeighbor() to manually
+insert a node in the neighbor table, pinNeighbor() to prevent a
+neighbor from being evicted, and unpinNeighbor() to restore eviction
+policy::
+
+ typedef uint16_t neighbor_table_entry_t
LinkEstimatorP {
provides {
+ interface StdControl;
+ interface AMSend as Send;
+ interface Receive;
interface LinkEstimator;
- interface NeighborTable;
+ interface Init;
+ interface Packet;
+ interface LinkSrcPacket;
}
}
interface LinkEstimator {
- command uint8_t getLinkQuality(neighbot_t neighbor);
- command uint8_t getReverseQuality(neighbot_t neighbor);
- command uint8_t getForwardQuality(neighbot_t neighbor);
+ command uint8_t getLinkQuality(uint16_t neighbor);
+ command uint8_t getReverseQuality(uint16_t neighbor);
+ command uint8_t getForwardQuality(uint16_t neighbor);
+ command error_t insertNeighbor(am_addr_t neighbor);
+ command error_t pinNeighbor(am_addr_t neighbor);
+ command error_t unpinNeighbor(am_addr_t neighbor);
+ command error_t txAck(am_addr_t neighbor);
+ command error_t txNoAck(am_addr_t neighbor);
+ command error_t clearDLQ(am_addr_t neighbor);
+ event void evicted(am_addr_t neighbor);
}
- interface NeighborTable {
- event void evicted(neighbot_t neighbor)
- }
-4.2 TreeRoutingEngineP
+4.2 CtpRoutingEngineP
--------------------------------------------------------------------
-TreeRoutingEngineP is responsible for computing routes to the roots of a
-tree. It uses NeighborTable and LinkEstimator interfaces to learn
+CtpRoutingEngineP is responsible for computing routes to the roots of a
+tree. In traditional networking terminology, this is part of the
+control plane of the network, and is does not directly forward any
+data packets, which is the responsibility of CtpForwardingEngine.
+The main interface between the two is UnicastNameFreeRouting.
+
+CtpRoutingEngineP uses the LinkEstimator interface to learn
about the nodes in the neighbor table maintained by LinkEstimatorP and
the quality of links to and from the neighbors. The routing protocol
on which collection is implemented MUST be a tree-based routing
-protocol with a single or multiple roots. TreeRoutingEngineP
+protocol with a single or multiple roots. CtpRoutingEngineP
allows a node to be configured as a root or a non-root node
-dynamically. TreeRoutingEngineP maintains multiple candidate next hops::
-
- generic module TreeRoutingEngineP(uint8_t routingTableSize) {
- provides {
- interface UnicastNameFreeRouting as Routing;
- interface RootControl;
- interface TreeRoutingInspect;
- interface StdControl;
- interface Init;
- }
- uses {
- interface AMSend as BeaconSend;
- interface Receive as BeaconReceive;
- interface LinkEstimator;
- interface AMPacket;
- interface LinkSrcPacket;
- interface SplitControl as RadioControl;
- interface Timer<TMilli> as BeaconTimer;
- interface Random;
- interface CollectionDebug;
- }
+dynamically. CtpRoutingEngineP maintains multiple candidate next hops::
+
+ generic module CtpRoutingEngineP(uint8_t routingTableSize,
+ uint16_t minInterval,
+ uint16_t maxInterval) {
+ provides {
+ interface UnicastNameFreeRouting as Routing;
+ interface RootControl;
+ interface CtpInfo;
+ interface StdControl;
+ interface CtpRoutingPacket;
+ interface Init;
+ }
+ uses {
+ interface AMSend as BeaconSend;
+ interface Receive as BeaconReceive;
+ interface LinkEstimator;
+ interface AMPacket;
+ interface LinkSrcPacket;
+ interface SplitControl as RadioControl;
+ interface Timer<TMilli> as BeaconTimer;
+ interface Timer<TMilli> as RouteTimer;
+ interface Random;
+ interface CollectionDebug;
+ interface CtpCongestion;
+ }
}
-4.3 ForwardingEngineP
+
+::
+
+ interface UnicastNameFreeRouting {
+ command am_addr_t nextHop();
+
+ command bool hasRoute();
+ event void routeFound();
+ event void noRoute();
+ }
+
+
+
+4.3 CtpForwardingEngineP
--------------------------------------------------------------------
-The ForwardingEngineP component provides all the top level interfaces
-(except RootControl) which TreeCollectionC provides and an application
-uses::
+The CtpForwardingEngineP component provides all the top level interfaces
+(except RootControl) which CollectionC provides and an application
+uses. It deals with retransmissions, duplicate suppression, packet
+timing, loop detection, and also informs the LinkEstimator of the
+outcome of attempted transmissions.::
- generic module ForwardingEngineP() {
+ generic module CtpForwardingEngineP() {
provides {
interface Init;
interface StdControl;
interface Intercept[collection_id_t id];
interface Packet;
interface CollectionPacket;
+ interface CtpPacket;
+ interface CtpCongestion;
}
uses {
+ interface SplitControl as RadioControl;
interface AMSend as SubSend;
interface Receive as SubReceive;
interface Receive as SubSnoop;
interface Packet as SubPacket;
interface UnicastNameFreeRouting;
- interface SplitControl as RadioControl;
interface Queue<fe_queue_entry_t*> as SendQueue;
interface Pool<fe_queue_entry_t> as QEntryPool;
interface Pool<message_t> as MessagePool;
interface Timer<TMilli> as RetxmitTimer;
- interface Cache<uint32_t> as SentCache;
- interface TreeRoutingInspect;
+ interface LinkEstimator;
+ interface Timer<TMilli> as CongestionTimer;
+ interface Cache<message_t*> as SentCache;
+ interface CtpInfo;
interface PacketAcknowledgements;
interface Random;
interface RootControl;
}
}
-ForwardingEngineP uses a large number of interfaces, which can be
+
+CtpForwardingEngineP uses a large number of interfaces, which can be
broken up into a few groups of functionality:
* Single hop communication: SubSend, SubReceive, SubSnoop,
SubPacket, PacketAcknowledgments, AMPacket
- * Routing: UnicastNameFreeRouting, TreeRoutingInspect,
- RootControl, CollectionId, SentCache
+ * Routing: UnicastNameFreeRouting, RootControl, CtpInfo,
+ CollectionId, SentCache
* Queue and buffer management: SendQueue, MessagePool,
QEntryPool
* Packet timing: Random, RetxmitTimer
====================================================================
.. [1] TEP 116: Packet Protocols
+.. [2] TEP 124: The Collection Tree Protocol (CTP) - (upcoming)
9. Funding
====================================================================
-As with the IETF, individuals are responsible for their own costs,
-which primarily involve meetings, travel, and generation of work
-products. Membership participation will involve attendance at
-Alliance meetings. Registration fees will be charged to cover costs
-associated with adminstration of the meetings.
-
-Companies and institutions are encouraged to contribute financial and
-in-kind support. It will be essential that companies provide initial
-funding to create the legal structure and to establish basic IT
-capabilities to host the web site and working groups.
-
Initially, we expect that there are no full time employees in the
Alliance and that funding needs are limited to such items as lawyer's
fees, web site costs, and insurance. If the Alliance eventually
requires full time support personnel, the funding structure will have
to be re-visited.
+As with the IETF, individuals are responsible for their own costs,
+which primarily involve meetings, travel, and generation of work
+products. The Alliance is predominantly a volunteer organization.
+Membership participation will involve attendance at
+Alliance meetings. Registration fees will be charged to cover costs
+associated with adminstration of the meetings.
+
To maintain the focus on technical excellence and meritocracy, we want
to avoid the heavy-handed quid-pro-quo seen in many industrial
consortiums where funding determines influence. The best use of funds
and the best form of influence is direct contribution to the work
-products of the Alliance. We will permit targeted contributions
-toward specific working groups or technical capabilities.
-
-We seek to keep overall structure lean, mostly volunteer.
-Focus on desired impact and recognition, rather than control.
+products of the Alliance.
+To keep the structure of the Alliance and its operations minimalist
+and lean, membership focuses on desired impact and recognition, rather
+than control. We want the best way to influence the direction of the Alliance
+to be to contribute technical work and demonstrate leadership, rather than
+try to control what individuals can or cannot contribute.
+Companies and institutions are encouraged to contribute financial and
+in-kind support. It will be essential that companies provide initial
+funding to create the legal structure and to establish basic IT
+capabilities to host the web site and working groups.
Institutional members
will pay an annual membership fee. In some cases, a
contributing corporate member may provide in-kind services
become a contributing corporate member, e.g., in those cases
where such a membership may be prohibited or unwanted.
The costs of meetings, such as the TinyOS
-technology exchange, will be covered through registration fees.
-
-Individuals are responsible
-for their own costs such as
-for travel, meeting costs, or costs for contributing
-software or documentation to the Alliance. The Alliance
-is primarily a volunteer organization.
+technology exchange, will be covered through registration fees and
+not by institutional membership fees.
10. Work Products
====================================================================
-Code base
-Stable, robust core release
-Rapidly evolving, innovative extensions
-Reference Implementations
-Tools
-Data
-Documentation
-Standard proposals
-Marketing and Promotion
-Testing and Compliance
-Assessments
-Applications and uses of technology
-Educational Materials
+The broad mission of the Alliance calls for a broad range of
+work products.
+
+Foremost among these are a set of TEPs documenting
+systems and protocols as well as TEPs that provide guidance
+and knowledge to the community. Technical documentation will have
+robust and open reference implementations for the community to
+use, refine, improve, and discuss. These reference implementations
+will not preclude alternative, compatibile implementations which may
+have additional features or optimizations. The Alliance Working Groups
+will periodically produce periodic releases of these reference
+implementations for the community to use and improve.
+
+The Alliance will support community contributions
+of innovative extensions and systems by providing a CVS repository
+to store them.
+In order to keep these contributions organized for users, the
+Steering Committee may nominate one or more people to caretake
+the repository by setting minimal guidelines for the use of
+the directory structure and migrating code as it joins the core
+or falls into disuse.
+
+To make these technological resources more accessible and useful
+to a broad embedded networks community, the Alliance will be
+dedicated to providing a set of educational materials. This
+includes introductory tutorials, documentation of core systems,
+simple and complex example applications, and user guides.
+
+In addition to educational sample applications, whose purpose
+is to teach new developers about the internals and workings of
+the technology, the Alliance will develop and make available
+several end-user applications and tools. The goal is to improve
+the accessibility of the technology to end-users while
+demonstrating its effectiveness. Historical examples of such applications
+include Surge and TinyDB. An important part of this effort is
+good documentation for users who are not expert programmers, as well
+as tools and graphical environments.
+
11. Conclusions
====================================================================
-The time has come to create an organizational structure to allow the effort to grow
-Beyond the Berkeley + Others
-It is a balancing act
-Stability vs Innovation
-Broad Participation vs Strong Requirements
-Uniform Licensing vs Institutional Differences
-Goal is to help to community to work together
-Not a forum for maneuvering and intrigue
-Focus on consensus building and technical soundness
-Minimal mechanism to resolve rare differences
-Focus on working groups and individual contributions
-with architectural and organization oversight
-Be pragmatic on participation
-Don\92t have to make deep commitments to participate
-Can\92t expect broad guarantees in return
+By focusing on consensus building and technical excellence, the
+Alliance seeks to avoid being a forum for political and economic
+positioning. It will achieve this by focusing on working groups
+and the contributions of individuals, while not taking strong
+positions on the benefits or drawbacks of different approaches.
+The variety of application domains sensornets are used in and
+the huge differences in requirements mean that having a suite
+of solutions, rather than a single one, is often not only
+desirable but essential.
+
+Over the past five years, low-power embedded sensor networks have
+grown from research prototypes to working systems that are being
+actively deployed. Furthermore, there is a vibrant research community
+that actively works to deploy these systems and collaborate with
+industry, making advances quickly accessible and usable. A great
+catalyst to this growth has been the presence of a large community
+around a shared, free code base.
+
+The time has come to create an organizational structure to
+allow the effort to grow further. As sensornets become more widespread,
+contributions and advancements will be from an increasingly broad
+demographic of users, and bringing them all together will speed
+progress and improve the potential benefit these systems can bring
+to society. This focus on bringing disparate groups together lies
+at the heart of the Alliance. Rather than depend on strong requirements,
+it depends on broad collaboration and participation, placing a minimalist
+set of expectations that will encourage the exchange of ideas and
+technology.
+
12. Author's Address
====================================================================
| Philippe Bonnet <bonnet.p@gmail.com>
| David Culler <culler@cs.berkeley.edu>
+| David Culler <dculler at archrock.com>,
| Deborah Estrin <destrin@cs.ucla.edu>
| Ramesh Govindan <ramesh@usc.edu>
| Mike Horton <mhorton@xbow.com>
| Matt Welsh <mdw@cs.harvard.edu>
| Adam Wolisz <awo@ieee.org>
-| David Culler <dculler at archrock.com>,
-
Field definitions are as follows:
- * C: Congestion notification. If a node is receiving packets faster than it can forward them, it MAY set the C field to notify other nodes. If a node hears a packet from node N with the C bit set, it MUST NOT transmit CTP data frames to N until it hears a packet from N with the C bit cleared.
- * P: Routing pull. The P bit allows nodes to request routing information from other nodes. If a node hears a packet with the P bit set, it SHOULD transmit a routing frame in the near future if it has a valid route.
+ * C: Congestion notification. If a node is receiving packets faster than it can forward them, it MAY set the C field to notify other nodes. If a node hears a packet from node *N* with the C bit set, it MUST NOT transmit CTP data frames to *N* until it hears a packet from N with the C bit cleared.
+ * P: Routing pull. The P bit allows nodes to request routing information from other nodes. If a node with a valid route hears a packet with the P bit set, it SHOULD transmit a routing frame in the near future.
* THL: Time Has Lived. When a node generates a CTP data frame, it MUST set THL to 0. When a node receives a CTP data frame, it MUST increment the THL. If a node receives a THL of 255, it increments it to 0.
* ETX: The ETX routing metric of the single-hop sender. When a node transmits a CTP data frame, it MUST put the ETX value of its route through the single-hop destination in the ETX field. If a node receives a packet with a lower gradient than its own, then it MUST schedule a routing frame in the near future.
* origin: The originating address of the packet. A node forwarding a data frame MUST NOT modify the origin field.
* seqno: Origin sequence number. The originating node sets this field, and a node forwarding a data frame MUST NOT modify it.
* collect_id: Higher-level protocol identifier. The origin sets this field, and a node forwarding a data frame MUST NOT modify it.
- * data: the data payload, of zero or more bytes.
+ * data: the data payload, of zero or more bytes. A node forwarding a data frame MUST NOT modify the data payload.
Together, the origin, seqno and collect_id fields denote a unique
***origin packet.*** Together, the origin, seqno, collect_id, and
distinction is important for duplicate suppression in the presence
of routing loops. If a node suppresses origin packets, then if
asked to forward the same packet twice due to a routing loop, it will
-drop the packet. However, if it suppresses packet instances, then
-unless the THL has wrapped around to the identical value it had
-on previous times around.
+drop the packet. However, if it suppresses packet instances, then it
+will route succesfully in the presence of transient loops unless the
+THL happens to wrap around to a forwarded packet instance.
A node MUST send CTP data frames as unicast messages with link-layer
acknowledgments enabled.
own, it MUST schedule a routing frame for transmission in the near
future.
+6. Implementation
+==============================================================================
+
+An implementation of CTP can be found in the tos/lib/net/ctp directory
+of TinyOS 2.0. This section describes the structure of that implementation
+and is not in any way part of the specification of CTP.
+
+This implementation has three major subcomponents:
+
+1) A **link estimator**, which is responsible for estimating the
+single-hop ETX of communication with single-hop neighbors.
+
+2) A **routing engine**, which uses link estimates as well as
+network-level information to decide which neighbor is the next
+routing hop.
+
+3) A **forwarding engine**, which maintains a queue of packets
+to send. It decides when and if to send them. The name is a little
+misleading: the forwarding engine is responsible for forwarded traffic
+as well as traffic generated on the node.
+
+6.1 Link Estimation
+------------------------------------------------------------------------------
+
+The link estimator estimates the ETX to single-hop neighbors.
+The implementation uses two mechanisms to estimate the quality of a link:
+periodic broadcast packets and data packets. The estimator itself
+only generates broadcast packets. For data traffic, it depends on
+other components telling it about acknowledged and unacknowledged
+transmissions.
+
+The periodic broadcast packets have sequence numbers, which the
+estimator uses to estimate the sender-to-receiver packet reception
+rate (PRR). The data payload of periodic broadcast packets contain
+these estimates. Therefore, when node A receives a link estimation
+broadcast message from node B, it can use the packet header to
+estimate the B-to-A PRR and the packet payload to update B's
+estimate of the A-to-B PRR.
+
+Multiplying these two values gives a *bidirectional* PRR, or
+an estimate of the probability that if A transmits a packet to B,
+B will successfully hear and acknowledge the packet and A will
+hear the acknowledgment. The inverse of the bidirecitonal PRR
+is the ETX.
+
+CTP link estimation adapts its beaconing rate to be slow when
+its routing table is stable and faster when changes occur.
+It adjusts the beaconing interval using an algorithm similar
+to the trickle dissemination protocol[2_]. CTP sends beacons
+more often when one of three conditions occurs:
+
+ 1) The routing table is empty (this also sets the P bit)
+ 2) The node's routing ETX increases by >= 1 trasmission
+ 3) The node hears a packet with the P bit set
+
+CTP also estimates link quality using data transmissions. This
+is a direct measure of ETX. Whenever the data path transmits a
+packet, it tells the link estimator the destimation and whether
+it was successfully acknowledged. The estimator produces an ETX
+estimate every 5 such transmissions, where 0 successes has an
+ETX of 6.
+
+The estimator combines the beacon and data estimates by incorporating
+them into an exponentially weighted moving average. Beacon-based
+estimates seed the neighbor table. The expectation is that the low
+beacon rate in a stable network means that for a selected route,
+data estimates will outweigh beacon estimates. Additionally, as
+the rate at which CTP collects data estimates is proportional to
+the transmission rate, then it can quickly detect a broken link and
+switch to another candidate neighbor.
+
+6.2 Routing Engine
+------------------------------------------------------------------------------
+
+The
+
+
+