]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - doc/html/tutorial/lesson2.html
Update to tutorials to redirect them to the wiki now instead of directly being modifi...
[tinyos-2.x.git] / doc / html / tutorial / lesson2.html
index d47351cc984c25193a943211ef4f99368d200dea..30f18ac3c53fb6f85b9f35078e9b578daf11f31e 100644 (file)
-<html>
-    <head>
-      <title>TinyOS Tutorial Lesson 2: Modules and the TinyOS Execution Model</title>
-      <link href="../../stylesheets/tutorial.css" rel="stylesheet" type="text/css">
-  </head>
-  <body>
-    
-    <div class="title">Lesson 2: Modules and the TinyOS Execution Model</div>
-    <div class="subtitle">Last updated June 27 2006</div>
-    
-    <p>This lesson introduces nesC modules, commands, events, and
-      tasks. It explains the TinyOS execution model.</p>
-    
-    <h1>Modules and State</h1>
-    
-    <p>Compiling TinyOS applications produces a single binary image that assumes
-      it has complete control of the hardware. Therefore, a mote only
-      runs one TinyOS image at a time. An image consists of the
-      components needed for a single application. As most more platforms
-      do not have hardware-based memory protection, there is
-      no seperation between a "user" address space and a "system"
-      address space; there is only one address space that all
-      components share. This is why many TinyOS components try to keep
-      their state private and avoid passing pointers: since there is
-      no hardware protection, the best way to keep memory uncorrupted
-      is to share it as little as possible.</p>
-    
-    <p>Recall from lesson 1 that the set of interfaces a component uses
-      and provides
-      define its signature. Both kinds of components -- configurations and
-      modules -- provide and use interfaces. The difference between the
-      two lies in their implementation: configurations are implemented
-      in terms of other components, which they wire, while modules
-      are executable code. After unwrapping all of the layers of abstraction
-      that configurations introduce, modules always lie within. Module
-      implementations are for the most part written in C, with
-      some extra constructions for nesC abstractions.</p>
-
-    <p>Modules can declare state variables. Any state a component declares
-      is private: no
-      other component can name it or directly access it. The only
-      way two components can directly interact is through interfaces.
-      Let's revisit the Blink application.
-      Here is the Blink module BlinkC's implementation in
-      its entirety:</p>
-
-<pre></pre>
-<prehead>apps/Blink/BlinkC.nc:</prehead>
-<pre>
-module BlinkC {
-  uses interface Timer&lt;TMilli&gt; as Timer0;
-  uses interface Timer&lt;TMilli&gt; as Timer1;
-  uses interface Timer&lt;TMilli&gt; as Timer2;
-  uses interface Leds;
-  uses interface Boot;
-}
-implementation
-{
-  event void Boot.booted()
-  {
-    call Timer0.startPeriodic( 250 );
-    call Timer1.startPeriodic( 500 );
-    call Timer2.startPeriodic( 1000 );
-  }
-
-  event void Timer0.fired()
-  {
-    call Leds.led0Toggle();
-  }
-  
-  event void Timer1.fired()
-  {
-    call Leds.led1Toggle();
-  }
-  
-  event void Timer2.fired()
-  {
-    call Leds.led2Toggle();
-  }
-}
-</pre>
-
-    <p>BlinkC does not allocate any state. Let's change it so that its
-      logic is a little different: rather than blink the LEDs from three
-      different timers, we'll blink them with a single timer and keep
-      some state to know which ones to toggle. Make a copy of the Blink
-      application, <tt>BlinkSingle</tt>, and go into its directory.</p>
-
-    <pre>
-$ cd tinyos-2.x/apps
-$ cp -R Blink BlinkSingle
-$ cd BlinkSingle
-    </pre>
-
-    <p>Open the BlinkC module in an editor.
-      The first step is to comment out the LED toggles in Timer1 and
-      Timer2:</p>
-
-    <pre>
-  event void Timer1.fired()
-  {
-    // call Leds.led1Toggle();
-  }
-  
-  event void Timer2.fired()
-  {
-    // call Leds.led2Toggle();
-  }
-    </pre>
-
-    <p>The next step is to add some state to BlinkC, a single byte. Just
-      like in C, variables and functions must be declared before they are
-      used, so put it at the beginning of the implementation:</p>
-
-    <pre>
-implementation
-{
-
-  uint8_t counter = 0;
-
-  event void Boot.booted()
-  {
-    call Timer0.startPeriodic( 250 );
-    call Timer1.startPeriodic( 500 );
-    call Timer2.startPeriodic( 1000 );
-  }
-    </pre>
-
-    <p>Rather than the standard C names of <tt>int</tt>, <tt>long</tt>,
-      or <tt>char</tt>, TinyOS code uses more explicit types, which
-      declare their size. In reality, these map to the basic C types, but
-      do so differently for different platforms. TinyOS code avoids using
-      <tt>int</tt>, for example, because it is platform-specific. For example,
-      on mica and Telos motes, <tt>int</tt> is 16 bits, while on the
-      IntelMote2, it is 32 bits. Additionally, TinyOS code often
-      uses unsigned values heavily, as wrap-arounds to negative numbers
-      can often lead to very unintended consequences. The commonly used
-      types are:</p>
-
-    <CENTER>
-      <table border=1 cellpadding=6>
-       <tr>
-         <td></td><td>8 bits</td><td>16 bits</td><td>32 bits</td><td>64 bits</td>
-       </tr>
-       <tr>
-         <td>signed</td><td><tt>int8_t</tt></td><td><tt>int16_t</tt></td><td><tt>int32_t</tt></td><td><tt>int64_t</tt></td>
-       </tr>
-       <tr>
-         <td>unsigned</td><td><tt>uint8_t</td><td><tt>uint16_t</td><td><tt>uint32_t</td><td><tt>uint64_t</tt></td>
-       </tr>
-      </table>
-    </CENTER>
-      <p>There is also a <tt>bool</tt> type. You can use the standard C
-       types, but doing so might raise cross-platform issues. Also,
-       <tt>uint32_t</tt> is often easier to write than <tt>unsigned
-         long</tt>. Most platforms support floating point numbers
-      (<tt>float</tt> almost always, <tt>double</tt> sometimes),
-       although their arithmetic is in software rather than hardware.</p>
-
-      <p>Returning to our modified BlinkC, we've allocated a single unsigned
-       byte, <tt>counter</tt>. When the mote boots, the <tt>counter</tt>
-       will be initialized to zero. The next step is to make it that
-       when Timer0 fires, it increments <tt>counter</tt> and displays the
-       result:</p>
-
-      <pre>
-  event void Timer0.fired()
-  {
-    counter++;
-    if (counter & 0x1) {
-      call Leds.led0On();
-    }
-    else {
-      call Leds.led0Off();
-    }
-    if (counter & 0x2) {
-      call Leds.led2On();
-    }
-    else {
-      call Leds.led2Off();
-    }
-    if (counter & 0x4) {
-      call Leds.led2On();
-    }
-    else {
-      call Leds.led2Off();
-    }
-  }
-      </pre>
-
-      <p>Another, more succinct way to do it is to use the <tt>set</tt>
-       command:</p>
-
-      <pre>
-  event void Timer0.fired()
-  {
-    counter++;
-    call Leds.set(counter);
-  }
-      </pre>
-
-      <p>Compile your program and install it on a mote. You'll see
-       that it behaves just as before, except that now the LEDs
-       are being driven by a single, rather than three, timers.</p>
-
-      <p>As only one timer is being used, this means that you don't need
-       Timer1 and Timer2: they waste CPU resources and memory. Open
-       BlinkC again and remove them from its signature and implementation.
-       You should have something that looks like this:</p>
-
-      <pre>
-module BlinkC {
-  uses interface Timer&lt;TMilli&gt; as Timer0;
-  uses interface Leds;
-  users interface Boot;
-}
-implementation
-{
-  uint8_t counter = 0;
-
-  event void Boot.booted()
-  {
-    call Timer0.startPeriodic( 250 );
-  }
-
-  event void Timer0.fired()
-  {
-    counter++;
-    call Leds.set(counter);
-  }
-  
-}
-      </pre>
-       
-      <p>Try to compile the application: nesC will throw an error, because
-       the configuration BlinkAppC is wiring to interfaces on BlinkC
-       that no longer exist (Timer1 and Timer2):</p>
-
-      <pre>
-dark /root/src/tinyos-2.x/apps/BlinkSingle -5-> make micaz
-mkdir -p build/micaz
-    compiling BlinkAppC to a micaz binary
-ncc -o build/micaz/main.exe -Os -finline-limit=100000 -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=micaz -fnesc-cfile=build/micaz/app.c -board=micasb  -fnesc-dump=wiring -fnesc-dump='interfaces(!abstract())' -fnesc-dump='referenced(interfacedefs, components)' -fnesc-dumpfile=build/micaz/wiring-check.xml BlinkAppC.nc -lm 
-In component `BlinkAppC':
-BlinkAppC.nc:54: cannot find `Timer1'
-BlinkAppC.nc:55: cannot find `Timer2'
-make: *** [exe0] Error 1
-      </pre>
-
-      <p>Open BlinkAppC and remove the two Timers and their wirings. Compile
-       the application:</p>
-
-      <pre>
-mkdir -p build/micaz
-    compiling BlinkAppC to a micaz binary
-ncc -o build/micaz/main.exe -Os -finline-limit=100000 -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=micaz -fnesc-cfile=build/micaz/app.c -board=micasb  -fnesc-dump=wiring -fnesc-dump='interfaces(!abstract())' -fnesc-dump='referenced(interfacedefs, components)' -fnesc-dumpfile=build/micaz/wiring-check.xml BlinkAppC.nc -lm 
-    compiled BlinkAppC to build/micaz/main.exe
-            2428 bytes in ROM
-              39 bytes in RAM
-avr-objcopy --output-target=srec build/micaz/main.exe build/micaz/main.srec
-avr-objcopy --output-target=ihex build/micaz/main.exe build/micaz/main.ihex
-    writing TOS image
-      </pre>
-
-      <p>If you compare the ROM and RAM sizes with the unmodified Blink
-       application, you should see that they are a bit smaller: TinyOS
-       is only allocating state for a single timer, and there is
-       event code for only one timer.</p>
-
-      <h1>Interfaces, Commands, and Events</h1>
-      
-      <p>Go back to <tt>tinyos-2.x/apps/Blink</tt>.
-      In lesson 1 we learned that if a component uses an interface, it can
-       call the interface's commands and must implement handlers for its
-       events.  We also saw that the BlinkC component uses the Timer, Leds,
-       and Boot interfaces. 
-       Let's take a look at those interfaces:</p>
-
-<pre></pre>
-<prehead>tos/interfaces/Boot.nc:</prehead>
-<pre>
-interface Boot {
-  event void booted();
-}
-</pre>
-
-<prehead>tos/interfaces/Leds.nc:</prehead>
-<pre>
-interface Leds {
-
-  /**
-   * Turn LED n on, off, or toggle its present state.
-   */
-  async command void led0On();
-  async command void led0Off();
-  async command void led0Toggle();
-
-  async command void led1On();
-  async command void led1Off();
-  async command void led1Toggle();
-
-  async command void led2On();
-  async command void led2Off();
-  async command void led2Toggle();
-
-  /**
-   * Get/Set the current LED settings as a bitmask. Each bit corresponds to
-   * whether an LED is on; bit 0 is LED 0, bit 1 is LED 1, etc. 
-   */
-  async command uint8_t get();
-  async command void set(uint8_t val);
-  
-}
-</pre>
-
-<prehead>tos/interfaces/Timer.nc:</prehead>
-<pre>
-interface Timer<precision_tag>
-{
-  // basic interface
-  command void startPeriodic( uint32_t dt );
-  command void startOneShot( uint32_t dt );
-  command void stop();
-  event void fired();
-
-  // extended interface omitted (all commands)
-}
-</pre>
-
-    <p>Looking over the interfaces for <code>Boot</code>,
-      <code>Leds</code>, and
-      <code>Timer</code>, we can see that since <code>BlinkC</code> uses
-      those interfaces it must implement handlers for the
-      <code>Boot.booted()</code> event, and the <code>Timer.fired()</code>
-      event. The <code>Leds</code> interface signature does not include any
-      events, so <code>BlinkC</code> need not implement any in order
-      to call the Leds commands. Here, again, is <code>BlinkC</code>'s
-      implementation of <code>Boot.booted()</code>:</p>
-    
-<pre></pre>
-<prehead>apps/Blink/BlinkC.nc:</prehead>
-<pre>
-  event void Boot.booted()
-  {
-    call Timer0.startPeriodic( 250 );
-    call Timer1.startPeriodic( 500 );
-    call Timer2.startPeriodic( 1000 );
-  }
-</pre>
-
-    <p><code>BlinkC</code> uses 3 instances of the TimerMilliC component,
-      wired to the interfaces <code>Timer0</code>, <code>Timer1</code>, and
-      <code>Timer2</code>. The <code>Boot.booted()</code> event handler
-      starts each instance. The parameter to
-      <code>startPeriodic()</code> specifies the period in milliseconds after 
-      which the timer will fire (it's millseconds because of the
-      <tt>&lt;TMilli&gt;</tt> in the interface).
-      Because the timer is started using
-      the <code>startPeriodic()</code> 
-      command, the timer will be reset after firing such that the
-      <code>fired()</code> event is 
-      triggered every n milliseconds.</p>
-
-    <p>Invoking an interface command requires the <tt>call</tt> keyword,
-      and invoking an interface event requires the <tt>signal</tt> keyword.
-      BlinkC does not provide any interfaces, so its code
-      does not have any signal statements: in a later lesson,
-      we'll look at the boot sequence, which signals the Boot.booted()
-      event.</p>
-    
-    <p>Next, look at the implementation of the <code>Timer.fired()</code>:</p>
-
-<pre></pre>
-<prehead>apps/Blink/BlinkC.nc:</prehead>
-<pre>
-  event void Timer0.fired()
-  {
-    call Leds.led0Toggle();
-  }
-  
-  event void Timer1.fired()
-  {
-    call Leds.led1Toggle();
-  }
-  
-  event void Timer2.fired()
-  {
-    call Leds.led2Toggle();
-  }
-}
-</pre>
-       
-    <p>Because it uses three instances of the Timer interface,
-      <code>BlinkC</code> 
-      must implement three instances of <code>Timer.fired()</code>
-      event. When implementing or invoking an interface function, the
-      function name is always <i>interface</i>.<i>function</i>. As
-      BlinkC's three Timer instances are named <tt>Timer0</tt>,
-      <tt>Timer1</tt>, and <tt>Timer2</tt>, it implements the three
-      functions <tt>Timer0.fired</tt>, <tt>Timer1.fired</tt>, and
-      <tt>Timer2.fired</tt>.</p>
-    
-    
-    
-    <h1>TinyOS Execution Model: Tasks</h1>
-    
-    <p>All of the code we've looked at so far is <i>synchronous</i>.
-      It runs in a single execution context and does not have
-      any kind of pre-emption. That is, when synchronous (sync) code
-      starts running, it does not relinquish the CPU to other
-      sync code until it completes. This simple mechanism allows
-      the TinyOS scheduler to minimize its RAM consumption and
-      keeps sync code very simple. However, it means that if one
-      piece of sync code runs for a long time, it prevents other
-      sync code from running, which can adversely affect system
-      responsiveness. For example, a long-running piece of code
-      can increase the time it takes for a mote to respond to a
-      packet.</p>
-    
-    <p>So far, all of the examples we've looked at have been
-      direct function calls. System components, such as the
-         boot sequence or timers, signal events to a component,
-         which takes some action (perhaps calling a command) and
-         returns. In most cases, this programming approach works
-         well. Because sync code is non-preemptive, however,
-         this approach does not work well for large computations.
-         A component needs to be able to split a large computation
-         into smaller parts, which can be executed one at a time.
-         Also, there are times when a component needs to do something,
-         but it's fine to do it a little later. Giving TinyOS the
-         ability to defer the computation until later can let it
-         deal with everything else that's waiting first.</p>
-
-       <p><b>Tasks</b> enable components to perform general-purpose
-         "background" processing in an application. A task is a function
-         which a component tells TinyOS to run later, rather than now.
-         The closest analogies in traditonal operating systems are
-         <A HREF="http://www.tldp.org/LDP/tlk/kernel/kernel.html">interrupt
-           bottom halves</A> and <A HREF="http://opensource.adobe.com/twiki/bin/view/AdobeSource/DeferredProcSystem">deferred
-           procedure calls</A>.</p>
-
-       <p>Make a copy of the Blink application, and call it BlinkTask:</p>
-
-       <pre>
-$ cd tinyos-2.x/apps
-$ cp -R Blink BlinkTask
-$ cd BlinkTask
-       </pre>
-
-       <p>Open <code>BlinkC.nc</code>. Currently, the event handler
-         for <code>Timer0.fired()</code> is:</p>
-
-       <pre>
-event void Timer0.fired() {
-  dbg("BlinkC", "Timer 0 fired @ %s\n", sim_time_string());
-  call Leds.led0Toggle();
-}
-       </pre>
-
-       <p>Let's change it so that it does a bit of work, enough that
-         we'll be able to see how long it runs. In terms of a mote,
-         the rate at which we can see things (about 24 Hz, or 40 ms)
-         is <u>slow</u>: the micaZ and Telos can send about 20 packets
-         in that time. So this example is really exaggerated, but it's
-         also simple enough that you can observe it with the naked eye.
-         Change the handler to be this:</p>
-
-       <pre>
-event void Timer0.fired() {
-  uint32_t i;
-  dbg("BlinkC", "Timer 0 fired @ %s\n", sim_time_string());
-  for (i = 0; i < 400001; i++) {
-    call Leds.led0Toggle();
-  }
-}
-       </pre>
-        
-    <p>This will cause the timer to toggle 400,001 times, rather
-      than once. Because the number is odd, it will have the end
-      result of a single toggle, with a bit of flickering in-between.
-      Compile and install the program. You'll see that
-      Led 0 introduces so much latency in the Led 1 and Led 2
-      toggles that you never see a situation where only one is on.
-      On TelosB motes, this long running task can cause the Timer stack
-      to completely skip events (try setting the count to 200,001 or 100,001).
-    </p>
-
-    <p>The problem is that this computation is interfering with the timer's
-      operation. What we'd like to do is tell TinyOS to execute the computation
-      later. We can accomplish this with a <b>task</b>.</p>
-
-    <p>A task is declared in your implementation module using the syntax
-    <pre>&nbsp; task void taskname() { ... }</pre> where
-    <tt>taskname()</tt> is whatever symbolic name you want to assign to the
-    task. Tasks must return <tt>void</tt> and may not take any
-    arguments. To dispatch a task for (later) execution, use the syntax
-    <pre>&nbsp; post taskname();</pre> A component can post a task in a
-    command, an event, or a task.  Because they are the root of a call
-    graph, a tasks can safely both call commands and signal events. We will
-    see later that, by convention, commands do not signal events to avoid
-    creating recursive loops across component boundaries (e.g., if command
-    X in component 1 signals event Y in component 2, which itself calls
-    command X in component 1). These loops would be hard for the programmer to
-    detect (as they depend on how the application is wired) and would lead to
-    large stack usage.</p>
-
-
-    <p>Modify BlinkC to perform the loop in a task:</p>
-
-    <pre>
-task void computeTask() {
-  uint32_t i;
-  for (i = 0; i < 400001; i++) {}
-}
-
-event void Timer0.fired() {
-  call Leds.led0Toggle();
-  post computeTask();
-}
-    </pre>
-
-    <p>Telos platforms will still struggle, but mica platforms will
-      operate OK.</p>
-
-    
-    <p>The <tt>post</tt> operation places the task on an internal
-      <b>task queue</b> which is processed in FIFO order. When a
-      task is executed, it runs to completion
-      before the next task is run. Therefore, and as the above examples
-      showed, a task should not run for long periods of time.
-      Tasks do not preempt each
-      other, but a task can  be preempted by a hardware interrupts (which
-      we haven't seen yet).
-      If you need to run a series of long operations,
-      you should dispatch a separate task for each operation, rather
-      than using one big task. The <tt>post</tt> operation returns
-      an <tt>error_t</tt>, whose value is either <tt>SUCCESS</tt>
-      or <tt>FAIL</tt>. A post fails if and only if the task is
-      already pending to run (it has been posted successfully and has not been invoked yet).(<A HREF="#task_footnote">1</A>)</p>
-
-    <p>For example, try this:</p>
-
-    <pre>
-uint32_t i;
-
-task void computeTask() {
-  uint32_t start = i;
-  for (;i < start + 10000 && i < 400001; i++) {}
-  if (i >= 400000) {
-    i = 0;
-  }
-  else {
-    post computeTask();
-  }
-}
-    </pre>
-
-    <p>This code breaks the compute task up into many smaller tasks.
-      Each invocation of computeTask runs through 10,000 iterations of
-      the  loop. If it hasn't completed all 400,001 iterations, it reposts
-      itself. Compile this code and run it; it will run fine on both
-      Telos and mica-family motes.</p>
-
-    <p>Note that using a task in this way required including another
-      variable (<tt>i</tt>) in the component. Because computeTask()
-      returns after 10,000 iterations, it needs somewhere to store
-      its state for the next invocation. In this situation, <tt>i</tt>
-      is acting as a static function variable often does in C. However,
-      as nesC component state is completely private, using the
-      <tt>static</tt> keyword to limit naming scope is not as useful.
-      This code, for example, is equivalent:</p>
-    <pre>
-task void computeTask() {
-  static uint32_t i;
-  uint32_t start = i;
-  for (;i < start + 10000 && i < 400001; i++) {}
-  if (i >= 400000) {
-    i = 0;
-  }
-  else {
-    post computeTask();
-  }
-}
-    </pre>
-
-    <h1>Internal Functions</h1>
-
-    <p>Commands and events are the only way that a function in a component
-      can be made callable by another component. There are situations
-      when a component wants private functions for its own internal
-      use. A component can define standard C functions, which other
-      components cannot name and therefore cannot invoke directly. 
-      While these functions do not have the <tt>command</tt> or <tt>event</tt>
-      modifier, they can freely call commands or signal events. For example,
-      this is perfectly reasonable nesC code:</p>
-
-    <pre>
-module BlinkC {
-  uses interface Timer&lt;TMilli&gt; as Timer0;
-  uses interface Timer&lt;TMilli&gt; as Timer1;
-  uses interface Timer&lt;TMilli&gt; as Timer2;
-  uses interface Leds;
-  uses interface Boot;
-}
-implementation
-{
-
-  void startTimers() {
-    call Timer0.startPeriodic( 250 );
-    call Timer1.startPeriodic( 500 );
-    call Timer2.startPeriodic( 1000 );
-  }
-
-  event void Boot.booted()
-  {
-    startTimers();
-  }
-
-  event void Timer0.fired()
-  {
-    call Leds.led0Toggle();
-  }
-  
-  event void Timer1.fired()
-  {
-    call Leds.led1Toggle();
-  }
-  
-  event void Timer2.fired()
-  {
-    call Leds.led2Toggle();
-  }
-}
-    </pre>
-    
-    <p>Internal functions act just like C functions: they don't need the <tt>
-       call</tt> or <tt>signal</tt> keywords.</p>
-
-    <h1>Split-Phase Operations</h1>
-
-    <p>Because nesC interfaces are wired at compile time,
-      callbacks (events) in TinyOS are very efficient. In most
-      C-like languages, callbacks have to be registered at run-time
-      with a function pointer. This can prevent the compiler from
-      being able to optimize code across callback call paths. Since
-      they are wired statically in nesC, the compiler knows exactly
-      what functions are called where and can optimize heavily.</p>
-
-    <p>The ability to optimize across component boundaries is
-      very important in TinyOS, because it has no blocking operations.
-      Instead, every long-running operation is <b>split-phase</b>.
-      In a blocking system, when a program calls a long-running operation,
-      the call does not return until the operation is complete: the program
-      blocks. In a split-phase system, when a program calls a long-running
-      operation, the call returns immediately, and the called abstraction
-      issues a callback when it completes. This approach is called
-      split-phase because it splits invocation and completion into two
-      separate phases of execution. Here is a simple example of the
-      difference between the two:</p>
-
-<center>
-    <table>
-      <tr><td align=center>Blocking</td> <td align=center>Split-Phase</td></tr>
-      <tr>
-        <td valign=top>
-<pre>
-if (send() == SUCCESS) {
-  sendCount++;
-}
-</pre>
-</td>
-        <td valign=top>
-<pre>
-// start phase
-send(); 
-
-//completion phase
-void sendDone(error_t err) {
-  if (err == SUCCESS) {
-    sendCount++;
-  }
-}
-</pre>
-</td>
-      </tr>
-    </table>
-</center>
-
-    <p>Split-phase code is often a bit more verbose and complex than
-     sequential code. But it has several advantages. First, split-phase
-     calls do not tie up stack memory while they are executing. Second,
-     they keep the system reponsive: there is never a situation when
-     an application needs to take an action but all of its threads are
-     tied up in blocking calls. Third, it tends to reduce stack
-     utilization, as creating large variables on the stack is rarely
-     necessary.</p>
-
-    <p>Split-phase interfaces enable a TinyOS component to easily start
-      several operations at once and have them execute in parallel.
-      Also, split-phase operations can save memory. This is because
-      when a program calls a blocking operation, all of the state it
-      has stored on the call stack (e.g., variables declared in functions)
-      have to be saved. As determining the exact size of the stack is
-      difficult, operating systems often choose a very conservative
-      and therefore large size.  Of course, if there is data that 
-      has to be kept across the 
-      call, split-phase operations still need to save it.</p>
-
-    <p>The command <tt>Timer.startOneShot</tt> is an example of
-     a split-phase call. The user of the Timer inteface calls the command,
-     which returns immediately. Some time later (specified by the
-     argument), the component providing Timer signals <tt>Timer.fired</tt>.
-     In a system with blocking calls, a program might use <tt>sleep()</tt>:
-
-     <center>
-       <table>
-         <tr>
-           <td align=center>Blocking</td><td align=center>Split-phase</td>
-         </tr>
-         <tr>
-           <td valign=top>
-             <pre>
-state = WAITING;
-op1();
-sleep(500);
-op2();
-state = RUNNING
-             </pre>
-           </td>
-           <td valign=top>
-             <pre>
-state = WAITING;
-op1();
-call Timer.startOneShot(500);
-
-event void Timer.fired() {
-  op2();
-  state = RUNNING;
-}
-             </pre>
-           </td>
-         </tr>
-       </table>
-     </center> 
-
-<p>In the next lesson, we'll look at one of the most basic
-split-phase operations: sending packets.</p>
-
-<a name=#related_docs>
-<h1>Related Documentation</h1>
-</a>
-<ul>
-<li> <a href="../tep102.html">TEP 102: Timers</a>
-<li> <a href="../tep106.html">TEP 106: Schedulers and Tasks</a>
-</ul>
-
-<p>
-<hr>
-
-<p><a name="task_footnote">(1)</a> The task semantics have changed
-significantly from tinyos-2.x. In 1.x, a task could be posted more
-than once and a post could fail if the task queue were full. In 2.x, a
-basic post will only fail if that task has already been posted and has
-not started execution. So a task can always run, but can only have one
-outstanding post at any time. If a component needs to post task
-several times, then the end of the task logic can repost itself as
-need be.
-
-
-<!-- Begin footer -->
-<br>
-<hr>
-<center>
-<p>&lt;&nbsp;<b><a href="lesson1.html">Previous Lesson</a></b> |&nbsp; <b><a
- href="index.html">Top</a></b> &nbsp;|&nbsp; <b><a href="lesson3.html">Next Lesson </a>&nbsp;&gt;</b>
-</center>
-
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" ^M   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>klueska.com</title>
+</head>
+<frameset>
+<frame src="http://docs.tinyos.net/index.php/Modules_and_the_TinyOS_Execution_Model" name="redir_frame" />
+<noframes>
+<body>
+<p>Sorry, your browser does not support frames. Please <a href="http://docs.tinyos.net/index.php/Modules_and_the_TinyOS_Execution_Model" target="_top">go here</a>.</p>
 </body>
-</html>
+</noframes>
+</frameset>
+</html>
\ No newline at end of file