Written By Neil

A. Dummy Platform Mapping

Initial platform bring-up

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 nios2 mote.

All platform-specific code goes in tos/platforms/. For example, we have tos/platforms/micaz or tos/platforms/tinynode. Our first step is to create a directory for the nios2 platform:

      $ cd tinyos-2.x/tos/platforms
      $ mkdir nios2

The .platform file

Each platform directory (such as tos/platforms/nios2) should contain a file named ".platform", that contains basic compiler parameters information for each platform. So, create the file "tos/platforms/nios2/.platform" (note the . in ".platform" !!!), that contains the following:

  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

  );

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.

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.

The hardware.h file

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).
So, create the file "tos/platforms/yamp/hardware.h" with the following contents:

  #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

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.

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 #include‘d MCU-specific file.
As an exercise, try finding the definitions of __nesc_atomic_start() and __nesc_atomic_end() for the micaZ and intelmote2 platforms.

Setting up the build environment and building the "null" app

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 nios2 platform:

  $ cd tinyos-2.x/apps/Null
  $ make nios2
/home/henridf/work/tinyos-2.x/support/make/Makerules:166: *** 

Usage:  make  
        make  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  help" to learn of all the available features.

 Global extras:

   docs    : compile additional nescdoc documentation
   tinysec : compile with TinySec secure communication

ERROR, "nios2 tos-ident-flags tos_image" does not specify a valid target.  Stop. 

The problem is that we need to define the platform in the TinyOS build system, so that the make invocation above recognizes the nios2 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.

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 nios2 platform so that the "make nios2" command does what it should. (For those that want to delve deeper, start with "tinyos-2.x/support/make/Makerules".)

Defining a make target

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 "nios2" is a legal platform when we enter "make nios2") is the existence of a platformname.target file in the aforementioned make directory.
So, create the file "tinyos-2.x/support/make/nios2.target" with the following contents:

PLATFORM = nios2

$(call TOSMake_include_platform,msp)

nios2: $(BUILD_DEPS)
	@:

This sets the PLATFORM variable to nios2, includes the msp platform ("make/msp/msp.rules") file, and provides in the last two lines a make rule for building a nios2 application using standard Makefile syntax. Now, let’s go back and try to compile the Null app as before. This time we get:

[18:23 henridf@tinyblue: ~/work/tinyos-2.x/apps/Null] make nios2
mkdir -p build/nios2
    compiling NullAppC to a nios2binary
ncc -o build/yamp/main.exe -Os -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=nios2-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

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: A port of TinyOS to a new plaform MUST include a component PlatformC which provides one and only one instance of the Init interface.. Create the file "tos/platforms/nios2/PlatformP.nc" with the following contents:

#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; }

}

, and create the file "tos/platforms/nios2/PlatformC.nc" as:

#include "hardware.h"

configuration PlatformC
{
  provides interface Init;
}
implementation
{
  components PlatformP
    , Msp430ClockC
    ;

  Init = PlatformP;
  PlatformP.Msp430ClockInit -> Msp430ClockC.Init;
}

Now, compilation of the Null application finally works for the nios2 platform:

[19:47 henridf@tinyblue: ~/work/tinyos-2.x/apps/Null] make nios2
mkdir -p build/nios2
    compiling NullAppC to a nios2 binary
ncc -o build/yamp/main.exe -Os -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=nios2 -fnesc-cfile=build/yamp/app.c -board=   NullAppC.nc -lm 
    compiled NullAppC to build/nios2/main.exe
            1216 bytes in ROM
               6 bytes in RAM
msp430-objcopy --output-target=ihex build/nios2/main.exe build/nios2/main.ihex
    writing TOS image

Advertisements