]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - doc/html/tutorial/lesson10.html
Updated files.
[tinyos-2.x.git] / doc / html / tutorial / lesson10.html
diff --git a/doc/html/tutorial/lesson10.html b/doc/html/tutorial/lesson10.html
new file mode 100644 (file)
index 0000000..3c84d99
--- /dev/null
@@ -0,0 +1,556 @@
+<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+  <title>TinyOS Tutorial Lesson 10: Platforms</title>
+  <link href="../../stylesheets/tutorial.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+
+<div class="title">Lesson 10: Platforms</div>
+<div class="subtitle">Last updated October 23 2006</div>
+
+<h1>Introduction</h1>
+
+<p>Many different hardware platforms (e.g micaZ, telos, eyesIFX) can be
+  used with TinyOS. This lesson shows you what a platform port consists
+  of, and how TinyOS reuses as much code as possible between different
+  platforms.
+  The lesson will proceed by showing how to do the port for an imaginary
+  mote called "yamp", which has a MSP430 microcontroller and a CC2420 
+  radio transceiver. 
+
+<p>
+  The <b>target audience</b> of this lesson consists of those people that want
+  to better understand what the difference between e.g "make micaz" and "make
+  telosb" is, and how these differences concretely map into the underlying
+  files, definitions, etc. 
+
+<p> Note that the material covered in this tutorial is <b>not</b>
+  strictly necessary for regular tinyos developpers, and you can safely skip
+  it if you have no intention of working down to the lowest level or
+  developping new platforms.
+
+</p>
+
+<h1>Chips vs Platforms</h1>
+
+<p>
+  Two key building blocks for any mote are the microcontroller and
+  radio transceiver. 
+  Of course, both a microcontroller and a radio can be used on 
+  more than one platform. This is indeed the case for the MSP430 and CC2420
+  that our yamp mote uses (telos, eyes, and tinynode use the MSP430; telos
+  and micaz use the CC2420).
+</p>
+
+<p>
+  Given this multiplicity of platforms, it would be vasly redundant if each
+  platform developper had to rewrite the software support for each chip
+  from scratch. While a chip may be physically wired in a different way on
+  different platforms (e.g., a radio is connected to a different digital
+  pins on the microcontroller), by far the largest part of the logic to
+  deal with a chip is platform-independent.
+</p>
+
+<p>
+  Thus, platform-independent code to support a chip is placed in a
+  chip-specific directory. Writing a platform port for a platform is then 
+  (essentially) a matter of <b>pulling in the code for each of the 
+  platform's chips, and "gluing"  things together</b>.
+  For example, the modules and components that support the CC2420 are in
+  tos/chips/cc2420. This radio is used on both the telos and micaZ motes; the
+  "gluing" is done by the modules in the tos/platforms/telosa/chips/cc2420 and
+  tos/platforms/micaz/chips/cc2420/ directories.
+</p>
+
+<p>
+  Note that in general there may
+  be more to a platform port than pulling in existing code for different
+  chips, in particular when a new platform uses a chip that is not yet
+  supported. Developping drivers for a new chip can be a non-trivial
+  undertaking (especially for radios and microcontrollers); these aspects
+  are not covered here. 
+</p>
+
+<h1>Initial platform bring-up</h1>
+
+<p>
+  As a first step to bring up the platform, we will stick to the bare minimum in
+  order to compile and install the Null application on our yamp mote. 
+</p>
+
+<p>
+  All platform-specific code goes in tos/platforms/<platformname>. 
+    For example, we have tos/platforms/micaz or tos/platforms/tinynode.
+    Our first step is to create a directory for the yamp platform:
+    <pre>
+      $ cd tinyos-2.x/tos/platforms
+      $ mkdir yamp
+    </pre>
+</p>
+
+<h2>The .platform file</h2>
+
+Each platform directory (such as tos/platforms/yamp) should contain a
+file named ".platform", that contains basic compiler parameters
+information for each platform. So, create the file
+"tos/platforms/yamp/.platform" (note the <b>.</b> in  "<b>.</b>platform" !!!), that contains the following:
+
+<pre>
+  push( @includes, qw(
+
+  %T/chips/cc2420
+  %T/chips/msp430
+  %T/chips/msp430/adc12
+  %T/chips/msp430/dma
+  %T/chips/msp430/pins
+  %T/chips/msp430/timer
+  %T/chips/msp430/usart
+  %T/chips/msp430/sensors
+  %T/lib/timer
+  %T/lib/serial
+  %T/lib/power
+  ) );
+
+  @opts = qw(
+
+  -gcc=msp430-gcc
+  -mmcu=msp430x1611
+  -fnesc-target=msp430
+  -fnesc-no-debug
+  -fnesc-scheduler=TinySchedulerC,TinySchedulerC.TaskBasic,TaskBasic,TaskBasic,runTask,postTask
+
+  );
+
+</pre>
+    
+<p>
+  This file contains perl snippets that are intepreted by the ncc compiler. 
+  The first statement simply adds some directories to the include path that
+  is used when compiling an application for the yamp platform (the %T gets
+  expanded to the full location of tinyos-2.x/tos, using the TOS2DIR
+  environment variable). Note that we have included the CC2420 and MSP430
+  directories, as well as some libraries.
+</p>
+
+<p>
+  The second statement defines the @opts list, that contains various parameters
+  passed to nesc. Please consult the nesc documentation for information on the
+  meaning of these parameters.
+</p>
+
+<h2>The hardware.h file</h2>
+
+<p>
+  Each platform directory also has a file named "hardware.h" that is included by
+  default when compiling an application for that platform. This can define
+  platform-specific constants, pin names, or also include other "external"
+  header files (e.g. msp430hardware.h in our case, or atm128hardware.h for
+  platforms using the atm128 MCU).<br>
+
+  So, create the file "tos/platforms/yamp/hardware.h" with the following contents:
+</p>
+
+<pre>
+  #ifndef _H_hardware_h
+  #define _H_hardware_h
+
+  #include "msp430hardware.h"
+
+  // LEDs
+  TOSH_ASSIGN_PIN(RED_LED, 5, 4);
+  TOSH_ASSIGN_PIN(GREEN_LED, 5, 5);
+  TOSH_ASSIGN_PIN(YELLOW_LED, 5, 6);
+
+  // UART pins
+  TOSH_ASSIGN_PIN(SOMI0, 3, 2);
+  TOSH_ASSIGN_PIN(SIMO0, 3, 1);
+  TOSH_ASSIGN_PIN(UCLK0, 3, 3);
+  TOSH_ASSIGN_PIN(UTXD0, 3, 4);
+  TOSH_ASSIGN_PIN(URXD0, 3, 5);
+  TOSH_ASSIGN_PIN(UTXD1, 3, 6);
+  TOSH_ASSIGN_PIN(URXD1, 3, 7);
+  TOSH_ASSIGN_PIN(UCLK1, 5, 3);
+  TOSH_ASSIGN_PIN(SOMI1, 5, 2);
+  TOSH_ASSIGN_PIN(SIMO1, 5, 1);
+
+
+  #endif // _H_hardware_h
+</pre>
+
+<p>
+  This file simply pulls in msp430hardware.h from tos/chips/msp430 (the compiler
+  will find it because we have added this directory to our search path in the
+  .platform created previously) and defines some physical pins using macros from
+  msp430hardware.h. For example, on our yamp mote, the red led is physically
+  connected to the general purpose I/O (GPIO) pin 5.4.
+</p>
+
+<p>
+  Some other very important functions (that are defined in msp430hardware.h
+  and so pulled in indirectly via this hardware.h)
+  concern the disabling of interrupts for atomic sections (atomic blocks in nesc
+  code essentially get converted into __nesc_atomic_start() and
+  __nesc_atomic_end()). How interrupts are disabled is of course microcontroller
+  specific; the same applies to putting the microcontroller to sleep (as is done
+  by the scheduler when there are no more tasks to run, using the McuSleep
+  interface). These functions must be somehow defined for each platform, 
+  typically by means of an <tt>#include</tt>'d MCU-specific file.<br>
+<i>  As an exercise, try finding the definitions of</i> __nesc_atomic_start() <i>and
+</i>  __nesc_atomic_end()<i> for the micaZ and intelmote2 platforms.</i>
+
+</p>
+
+<h1>Setting up the build environment and building the "null" app</h1>
+Before pulling in existing chip drivers or writing any code, we must set up
+the build environment so that it is aware of and supports our platform.
+
+Once this is done, we will define the basic TinyOS module for our platform,
+and use the Null app (in tinyos-2.x/apps/null) in order to test that our
+platform is properly configured. As per it's description in its README file,
+Null is an empty skeleton application.  It is useful to test that the
+build environment is functional in its most minimal sense, i.e., you
+can correctly compile an application. So, let's go ahead and try to compile 
+Null for the yamp platform:
+
+<!-- <h2> Defining a make target</h3> -->
+
+<!-- At this point we have created all the necessary files in tos/platforms/yamp/ -->
+<!-- in order to run the Null application. But how do we compile it and install it -->
+<!-- on our yamp mote? -->
+
+<!-- We would like to enter "make yamp" in any application directory and have a -->
+<!-- yamp binary be built, just as e.g. "make micaz" builds us a micaz -->
+<!-- binary. But if we try it at this point we get an error message listing all the -->
+<!-- valid targets and telling us that yamp is not a valid target: -->
+
+<pre>
+  $ cd tinyos-2.x/apps/Null
+  $ make yamp
+/home/henridf/work/tinyos-2.x/support/make/Makerules:166: *** 
+
+Usage:  make <target> <extras>
+        make <target> help
+
+        Valid targets: all btnode3 clean eyesIFX eyesIFXv1 eyesIFXv2 intelmote2 mica2 mica2dot micaz null telos telosa telosb tinynode tmote
+        Valid extras: docs ident_flags nescDecls nowiring rpc sim sim-cygwin sim-fast tos_image verbose wiring
+
+ Welcome to the TinyOS make system!
+
+ You must specify one of the valid targets and possibly some combination of
+ the extra options.  Many targets have custom extras and extended help, so be
+ sure to try "make <target> help" to learn of all the available features.
+
+ Global extras:
+
+   docs    : compile additional nescdoc documentation
+   tinysec : compile with TinySec secure communication
+
+ERROR, "yamp tos-ident-flags tos_image" does not specify a valid target.  Stop. 
+  
+</pre>
+
+<p>
+The problem is that we need to define the platform in the <i>TinyOS build
+  system</i>, so that the make invocation above recognizes the yamp platform.
+The TinyOS build system is a Makefile-based set of rules and definitions
+that has a very rich functionality. This includes invoking
+necessary  compilation commands as with any build system, but goes much
+  further and includes support for other important aspects such as 
+device reprogramming or supporting multiple platforms and targets.
+</p>
+
+<p>
+A full description of the inner workings of the TinyOS build system is beyond
+  the scope of this tutorial. For now, we will simply see how to define the
+  yamp platform so that the "make yamp" command does what it should. (For those
+  that want to delve deeper, start with "tinyos-2.x/support/make/Makerules".)
+</p>
+
+<h2> Defining a make target</h2>
+
+The TinyOS build system resides in "tinyos-2.x/support/make". The strict
+minimum for a platform to be recognized by the build system (i.e., for the
+build system to understand that "yamp" is a legal platform when we enter "make
+yamp") is the existence of a <i>platformname</i>.target file in the
+aforementioned make directory.<br>
+So, create the file "tinyos-2.x/support/make/yamp.target" with the following
+contents:
+
+<pre>
+
+PLATFORM = yamp
+
+$(call TOSMake_include_platform,msp)
+
+yamp: $(BUILD_DEPS)
+       @:
+</pre>
+
+This sets the PLATFORM variable to yamp, includes the msp platform
+("make/msp/msp.rules") file, and provides in the last two lines a make rule
+for building a yamp application using standard Makefile syntax.
+
+Now, let's go back and try to compile the Null app as before. This time we get:
+
+<pre>
+[18:23 henridf@tinyblue: ~/work/tinyos-2.x/apps/Null] make yamp
+mkdir -p build/yamp
+    compiling NullAppC to a yamp binary
+ncc -o build/yamp/main.exe -Os -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=yamp -fnesc-cfile=build/yamp/app.c -board=   NullAppC.nc -lm 
+In file included from NullAppC.nc:42:
+In component `MainC':
+/home/henridf/work/tinyos-2.x/tos/system/MainC.nc:50: component PlatformC not found
+/home/henridf/work/tinyos-2.x/tos/system/MainC.nc:53: no match
+make: *** [exe0] Error 1
+</pre>
+
+So there's progress of sorts, since now we're getting a "real" compilation
+error as opposed to not even making it past the build system. Let's take a
+closer look at the output. The ncc compiler is unhappy about not finding a
+"PlatformC" component.
+
+The "PlatformC" component must be defined for each platform. Its role and
+placement in the system is described in more detail in TEP107. For now,
+suffice to cite from that TEP that:
+<i>A port of TinyOS to a new plaform MUST include a component PlatformC which
+  provides one and only one instance of the Init interface.</i>.
+
+
+Create the file "tos/platforms/yamp/PlatformP.nc" with the following contents:
+
+<pre>
+#include "hardware.h"
+
+module PlatformP{
+  provides interface Init;
+  uses interface Init as Msp430ClockInit;
+  uses interface Init as LedsInit;
+}
+implementation {
+  command error_t Init.init() {
+    call Msp430ClockInit.init();
+    call LedsInit.init();
+    return SUCCESS;
+  }
+
+  default command error_t LedsInit.init() { return SUCCESS; }
+
+}
+</pre>
+
+, and create the file "tos/platforms/yamp/PlatformC.nc" as:
+
+<pre>
+#include "hardware.h"
+
+configuration PlatformC
+{
+  provides interface Init;
+}
+implementation
+{
+  components PlatformP
+    , Msp430ClockC
+    ;
+
+  Init = PlatformP;
+  PlatformP.Msp430ClockInit -> Msp430ClockC.Init;
+}
+</pre>
+
+Now, compilation of the Null application finally works for the yamp platform:
+
+<pre>
+[19:47 henridf@tinyblue: ~/work/tinyos-2.x/apps/Null] make yamp
+mkdir -p build/yamp
+    compiling NullAppC to a yamp binary
+ncc -o build/yamp/main.exe -Os -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=yamp -fnesc-cfile=build/yamp/app.c -board=   NullAppC.nc -lm 
+    compiled NullAppC to build/yamp/main.exe
+            1216 bytes in ROM
+               6 bytes in RAM
+msp430-objcopy --output-target=ihex build/yamp/main.exe build/yamp/main.ihex
+    writing TOS image
+</pre>
+
+
+<h1>Getting Blink to work</h1>
+
+With the previous steps, we now have the basic foundation to start working on
+our yamp platform: the basic platform definitions are in place, and the build
+system recognizes and correctly acts upon the "make yamp" target. We haven't
+yet actually <i>programmed</i> our mote yet. 
+<p>
+The next step in the bring-up of a platform, that we will cover in this part,
+is to program a node with an application and verify that it actually
+works. We'll do this with Blink, because it is simple, and easy to verify that
+it works. As a bonus, we'll also have validated basic timer functionality once
+we see those Leds turning on and off.
+<p>
+As a first step, let's go to the Blink application directory and try to
+compile the application:
+<pre> 
+[19:06 henridf@tinyblue: ~/work/tinyos-2.x/apps/Blink] make yamp
+mkdir -p build/yamp
+    compiling BlinkAppC to a yamp binary
+ncc -o build/yamp/main.exe -Os -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=yamp -fnesc-cfile=build/yamp/app.c -board=   BlinkAppC.nc -lm 
+In file included from BlinkAppC.nc:45:
+In component `LedsC':
+/home/henridf/work/tinyos-2.x/tos/system/LedsC.nc:38: component PlatformLedsC not found
+/home/henridf/work/tinyos-2.x/tos/system/LedsC.nc:42: cannot find `Init'
+/home/henridf/work/tinyos-2.x/tos/system/LedsC.nc:43: cannot find `Led0'
+/home/henridf/work/tinyos-2.x/tos/system/LedsC.nc:44: cannot find `Led1'
+/home/henridf/work/tinyos-2.x/tos/system/LedsC.nc:45: cannot find `Led2'
+make: *** [exe0] Error 1
+</pre>
+
+The compiler cannot find the component "PlatformLedsC" that is referred to in 
+the file tos/system/LedsC.nc. As the name indicates, "PlatformLedsC" is a
+platform-specific component, and thus we will need to define this component
+for the yamp platform. 
+<p>
+Why should there be such a platform-specific component for accessing Leds?  This is because at
+the lowest level, i.e in hardware, Leds are implemented differently on
+different platforms. Typically, a Led is connected to a microcontroller I/O pin,
+and the Led is turned on/off by setting the appropriate output 0/1 on that
+pin. This is in fact the model used on all current TinyOS platforms. 
+But even in this simple and uniform model, (and disregarding
+the fact that future platforms may use different hardware implementations
+and not connect each Led directly to an I/O pin), we have that the
+lowest-level to turn on/off a Led must be defined on a per-platform basis. 
+<p> 
+Now, consider Leds from another perspective, namely that of the Leds.nc
+interface (defined in tos/interfaces/Leds.nc). In this interface, we have
+commands such as <tt>get();</tt> in principle such a command does not need to be
+platform-dependent: the code that maintains the current state of a Led and
+returns it via the get() call does not need to be re-written each time a Led
+is connected to a different pin (of course re-writing get() for each
+platform would  not be much overhead given its simplicity; this argument
+clearly becomes far stronger in more complex situations involving entire chips
+rather than individual GPIOs).
+<p> The key notion that the above example is simply that there is a boundary
+  above which software components are platform-independent, and below which
+  components are specifically written with one hardware platform in mind. 
+  This is at heart a very simple concept; its complete instantiation in TinyOS is of
+  course richer than the above example, and is the topic of TEP2 (Hardware
+  Abstraction Architecture).
+<p> Let's now return to the task at hand, which is to make Blink work on our
+  platform. If we take a closer look at the file "tos/system/LedsC.nc", we see
+  that it contains a configuration that wires the module LedsP with modules
+  Init, Leds0,  Leds1, and Leds2, all of which are to be provided by the
+  (still missing) PlatformLedsC. Taking a closer look at
+  "tos/system/LedsP.nc", we see that the Leds0,1,2 modules used by LedsP are
+  GeneralIO interfaces. The GeneralIO interface (see
+  "tos/interfaces/GeneralIO.nc" and TEP 117) simply encapsulates a digital I/O pin and
+  provides functions to control its direction and get/set its input/output
+  values. 
+<p> So, we need to create a PlatformLedsC configuration that shall provide
+  three GeneralIO interfaces and an Init. This is done by creating the file
+  "tos/platforms/yamp/PlatformLedsC.nc" with the following contents:
+
+<pre>
+#include "hardware.h"
+
+configuration PlatformLedsC {
+  provides interface GeneralIO as Led0;
+  provides interface GeneralIO as Led1;
+  provides interface GeneralIO as Led2;
+  uses interface Init;
+}
+implementation
+{
+  components 
+      HplMsp430GeneralIOC as GeneralIOC
+    , new Msp430GpioC() as Led0Impl
+    , new Msp430GpioC() as Led1Impl
+    , new Msp430GpioC() as Led2Impl
+    ;
+  components PlatformP;
+
+  Init = PlatformP.LedsInit;
+
+  Led0 = Led0Impl;
+  Led0Impl -> GeneralIOC.Port54;
+
+  Led1 = Led1Impl;
+  Led1Impl -> GeneralIOC.Port55;
+
+  Led2 = Led2Impl;
+  Led2Impl -> GeneralIOC.Port56;
+
+}
+</pre>
+
+We refer the reader to the TinyOS Programming Guide cited below for more
+explanations on how the above confiuration uses generics (ie with the "new"
+keyword). For the purpose of this lesson, the key point is that we are wiring
+to ports 5.4, 5.5, and 5.6 -- we shall suppose that these  are the MSP430 
+microcontroller pins to which the three Leds are connected on the yamp
+platform.  <p>
+
+With the above file in place, we can now compile Blink for the yamp platform. 
+How do we test that the application actually works? We have thus far presented
+yamp as an imaginary platform, but it turns out that the above application
+should work on any platform with the MSP430x1611 microcontroller and where the
+Leds are connected to microcontroller ports 5.4-5.6. 
+Not entirely coincidentally, these are exactly the Led wirings used by the
+telos/tmote platforms. So those readers that have a telos/tmote at hand can
+test this application on it. (Testing on a tinynode or eyes mote is also easy and only
+requires changing the pin wirings in PlatformLedsC to follow those of that
+platform; running this application on mica-family motes will require more
+changes since they use a different microcontroller).
+
+<p>
+Now, enter the following command (where you have suitably replaced /dev/ttyXXX by the appropriate serial port),
+<pre>
+  make yamp install bsl,/dev/ttyXXX
+</pre>
+and you will see the Leds of your impersonated (by a telos) yamp node Blinking!
+
+<h1>Conclusion</h1>
+
+<p>This lesson has introduced the notion of per-platform support in TinyOS
+  using as a guiding example the development of a platform port to an
+  imaginary "yamp" platform. We have seen how introducing support for a new
+  platform requires touching not only nesc code but also adding some rules to
+  the build system. This tutorial also touched upon the notions of Hardware
+  Abstraction Architecture (HAA) that is central to the clean and modular
+  support of different platforms and chips in TinyOS.
+<p>
+  The steps outlined here did not cover what is the hardest part of
+  a platform port: developping the components to drive a radio transceiver or
+  MCU (which are necessary if the platform uses chips that are not currently
+  supported in TinyOS). Developping such drivers is an advanced topic that is
+  beyond the scope of the tutorials; for those curious to gain some insight we
+  recommend perusing the code for a chip (e.g the CC2420 radio in
+  tos/chips/cc2420 or the xe1205 radio in tos/chips/xe1205) armed with that
+  chips datasheet and the platform schematics.
+<p>
+<a name=#related_docs>
+<h1>Related Documentation</h1>
+</a>
+<ul>
+<li> <a href="https://sourceforge.net/projects/nescc">nesc at sourceforge</a>
+<li> <a href="http://nescc.sourceforge.net/papers/nesc-ref.pdf">nesC reference manual</a>
+<li> <a href="http://csl.stanford.edu/~pal/pubs/tinyos-programming-1-0.pdf">TinyOS Programming Guide</a>
+<li> <a href="../tep102.html">TEP 2: Hardware Abstraction Architecture</a>
+<li> <a href="../tep106.html">TEP 106: Schedulers and Tasks</a>
+<li> <a href="../tep107.html">TEP 107: TinyOS 2.x Boot Sequence</a>
+<li> <a href="../tep117.html">TEP 117: Low-level I/O</a>
+</ul>
+
+<p>
+<hr>
+
+
+<!-- Begin footer -->
+<br>
+<hr>
+<center>
+<p>&lt;&nbsp;<b><a href="index.html">Top</a></b> 
+&nbsp;</b>
+</center>
+
+</body>
+</html>