Skip to content

Blink App in NesC

March 12, 2011

In this second article on TinyOS and NesC programming we will visit some of the earlier concepts that we introduced in the first article. This time we will look at them from a more technical perspective so that we can understand how the Blink application fits onto the platform that enables it. Our use case application example, Blink, is basically equivalent to the “helloWorld” application that we use to learn PC targeted languages. But in our case the mote (sensor/actuator device) does not provide a keyboard or screen! Therefore we use the LEDs to blink in a manner that we command in our program.

nesC (pronounced “NES-see”) is an extension to the C programming language designed to use the structuring concepts and execution model of TinyOS. TinyOS is an event-driven operating system designed for sensor network nodes that have very limited resources (e.g., 8K bytes of program memory, 512 bytes of RAM).

The basic concepts behind nesC are:

  • Separation of construction and composition: programs are built out of components, which are assembled (“wired”) to form whole programs. Components have internal concurrency in the form of tasks. Threads of control may pass into a component through its interfaces. These threads are rooted either in a task or a hardware interrupt.
  • Specification of component behaviour in terms of set of interfaces. Interfaces may be provided or used by components. The provided interfaces are intended to represent the functionality that the component provides to its user, the used interfaces represent the functionality the component needs to perform its job.
  • Interfaces are bidirectional: they specify a set of functions to be implemented by the interface’s provider (commands) and a set to be implemented by the interface’s user (events). This allows a single interface to represent a complex interaction between components (e.g., registration of interest in some event, followed by a callback when that event happens). This is critical because all lengthy commands in TinyOS (e.g. send packet) are non-blocking; their completion is signaled through an event (send done). By specifying interfaces, a component cannot call the send command unless it provides an implementation of the sendDone event.Typically commands call downwards, i.e., from application components to those closer to the hardware, while events call upwards. Certain primitive events are bound to hardware interrupts.
  • Components are statically linked to each other via their interfaces. This increases runtime efficiency, encourages rubust design, and allows for better static analysis of programs.
  • nesC is designed under the expectation that code will be generated by whole-program compilers. This should also allow for better code generation and analysis.

The image below shows the structure (components and their wiring) of a simple application, Blink, that blinks an LED once a second:

Following is the Blink.nc configuration:

/*
 *  Copyright (c) 2000-2002 The Regents of the University  of California.
 *  and Copyright (c) 2002 Intel Corporation
 *  All rights reserved.
 */
configuration Blink {
}
implementation {
  components Main, BlinkM, ClockC, LedsC;

  Main.StdControl -> BlinkM.StdControl;
  BlinkM.Clock -> ClockC;
  BlinkM.Leds -> LedsC;
}

Following is BlinkM.nc module:

/*
 *  Copyright (c) 2000-2002 The Regents of the University  of California.
 *  and Copyright (c) 2002 Intel Corporation
 *  All rights reserved.
 *
 * Implementation for Blink application.  Toggle the red LED when the
 * clock fires.
 */
module BlinkM {
  provides interface StdControl;
  uses interface Clock;
  uses interface Leds;
}
implementation {
  bool state; /* the state of the red LED (on or off)   */

  /* Initialize the component.
   * @return Always returns SUCCESS */
  command result_t StdControl.init() {
    state = FALSE;
    call Leds.init();
    return SUCCESS;
  }

  /* Start things up.  This just sets the rate for the clock component.
   * @return Always returns SUCCESS */
  command result_t StdControl.start() {
    return call Clock.setRate(TOS_I1PS, TOS_S1PS);
  }

  /* Halt execution of the application.
   * This just disables the clock component.
   * @return Always returns SUCCESS */
  command result_t StdControl.stop() {
    return call Clock.setRate(TOS_I0PS, TOS_S0PS);
  }

  /* Toggle the red LED in response to the Clock.fire event.
   * @return Always returns SUCCESS */
  event result_t Clock.fire() {
    state = !state;
    if (state) {
      call Leds.redOn();
    } else {
      call Leds.redOff();
    }

    return SUCCESS;
  }
}

Bibliography:

http://nescc.sourceforge.net/

http://tinyos.net

About these ads
2 Comments leave one →
  1. May 7, 2011 6:55 PM

    Very nice explanation. Hope to see more complicated/useful stuff in the future. Looks like you’re taking this sensor stuff pretty seriously :)

    • May 7, 2011 7:25 PM

      Thanks bro …. can’t find anything better at the moment. I’ll try to get to the USB device driver tutorial but it requires some device to be addressed. Can’t make up my mind for any specific device. Although I tweeted some tutorial stuff on it for you.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 48 other followers

%d bloggers like this: