IppatsuMan - TinyOS installation

Installation on Linux from source code

Introduction

As part of my Ph.D. research I often write software based on TinyOS that will run on sensor nodes. Although there are easy means to have TinyOS up and running (like using the Xubuntu Live CD image, the RPM packets or the Stanford repository), I prefer to install everything from scratch, using only the source code. In this how-to I describe how to install the CVS version of TinyOS 2.x on Linux. My target is Ubuntu Linux 10.04 Lucid Lynx, but I tested this method on Ubuntu 9.10 Karmic Koala and on Debian 5 too. Anyway the specific Linux distribution is relevant only for the initial installation of needed software. I'll use apt-get to install software, for any non-Debian based distribution, please use its specific package manager.

Warning
This guide is specifically for getting Crossbow TelosB (or Tmote Sky hardware from Moteiv) to work. I don't have any other motes to test this against. That said this should work for other motes. If it doesn't work for your motes (and you know how to fix it) or if you spot any error, please contact me.
Note
Several steps of the installation process must be executed as root. To became root, on many Linux distributions, you need to run su -. On Ubuntu, run sudo -s. In the following, I'll just use sudo. You can also install TinyOS without root privileges: to do so whenever you run ./configure in the following steps, add the --prefix=/path/to/your/installation/directory switch.

Software components

To install TinyOS you need to install three/four main components:

  • the TinyOS source files, i.e. the .nc files that will be compiled and uploaded on your motes;
  • the nesC compiler, that compiles the .nc files in standard C;
  • a cross compiler, i.e. a compiler that runs on your computer but has as output binary files targeting a different architecture.

The installation must be made in reverse order: first the cross compiler(s), then the nesC compiler, finally TinyOS.

Warning
This how-to does not explain how to compile and install gdb, avrdude, JTAG-related software and any other software not explicitly mentioned.

Installation

Shopping list

To install TinyOS, nesC and the cross compilers, we need to install some additional software:

  • cvs;
  • gcc and g++;
  • graphviz;
  • Java JRE and JDK;
  • libgmp3-dev, libgmp3c2, libmpfr-dev and libmpfr1ldbl;
  • make and automake;
  • tinfoil.

On Debian, enable the non-free repository and run as root

aptitude install automake cs g++ gcc graphviz libgmp3-dev libgmp3c2 libmpfr-dev libmpfr1ldbl make sun-java6-jdk texinfo

On Ubuntu, enable the multiverse repository ad run:

sudo aptitude install automake build-essential cvs graphviz libgmp3-dev libgmp3c2 libmpfr-dev libmpfr1ldbl make sun-java6-jdk texinfo

The downloading and installation may take a while, these packages sum up to several hundreds of MiB. Wait for the installation to finish before going to the next step.

On Debian and Ubuntu, to set Oracle's JDK as default Java installation, run as root:

update-java-alternatives -s java-6-sun

Installing GCC for MSP430

As first step, we'll install the GCC toolchain for the Texas Instruments MSP430 MCUs. This toolchain is needed to compile software for motes using the MSP430 microcontroller, for example the TelosB and shimmer motes. Create a directory for it and set it as current directory:

mkdir -p tinyossrc/gccmsp430
cd tinyossrc/gccmsp430

Then, download the vanilla binutils and GCC sources, that we'll patch in the following steps to make it support MSP430:

wget ftp://sources.redhat.com/pub/binutils/releases/binutils-2.19.tar.bz2
wget ftp://ftp.gnu.org/gnu/gcc/gcc-3.2.3/gcc-core-3.2.3.tar.bz2
wget ftp://ftp.gnu.org/gnu/gcc/gcc-3.2.3/gcc-g++-3.2.3.tar.bz2

Let's download the GCC MSP430 patches:

export CVSROOT=:pserver:anonymous@mspgcc.cvs.sourceforge.net:/cvsroot/mspgcc
export CVS_RSH=ssh
cvs login

When asked for password, just press enter. Then, checkout from cvs the files to patch GCC:

cvs checkout gcc
cvs checkout msp430-libc
cvs checkout packaging

We have all the files needed to compile GCC for MSP430. Let's compile binutils. The pattern is: extract the tarball, patch, compile, install. Create the directory where we'll compile binutils and then extract the tarball:

mkdir build-binutils
tar xzvf binutils-2.19.tar.bz2
cd binutils-2.19

Second step: patch the source code, using the patches checked out from CVS:

patch -p1 < ../packaging/patches/binutils-2.19-patch

Third step: configure and compile:

cd ../build-binutils
../binutils-2.19/configure --target=msp430 --prefix=/usr/local/msp430
make

Depending on how fast your system is, the compilation of binutils may take any time between five minutes and an hour. Have a break. Then, run as root make install. If you are using on Ubuntu:

sudo -s
make install
exit

Back to the user sell, we need to add the newly installed MSP430 binutils to the PATH environment variable:

export PATH=$PATH:/usr/local/msp430/bin

Now go back to the gccmsp430 directory and extract the GCC and g++ tarballs:

cd ..
tar xzvf gcc-core-3.2.3.tar.bz2
tar xzvf gcc-g++-3.2.3.tar.bz2

To patch GCC, we need to copy the files provided by the GCC MSP430 project:

cp -av gcc/gcc-3.3/* gcc-3.2.3

Now create the directory where we'll compile GCC:

mkdir build-gcc
cd build-gcc

Compile GCC:

../gcc-3.2.3/configure --target=msp430 --prefix=/usr/local/msp430
make

Install GCC:

sudo -s
export PATH=$PATH:/usr/local/msp430/bin
make install
exit

Last step: compilate and install the MSP430 libc library:

cd ../msp430-libc/src
make
sudo -s
export PATH=$PATH:/usr/local/msp430/bin
make install
exit

Installing GCC for AVR32

Many motes use Atmel's MCU, for example MICAz, MICA2 and IRIS. To download Atmel's GNU Toolchain for AVR32 go to http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4118, click on AVR32 GNU Toolchain 2.4.2 - Linux Source Code and follow the procedure to download the file named avr32_gnu_toolchain_2.4.2_source.zip. Put it into the directory tinyossrc/avr32. Then, extract all the tarballs:

for f in *.tar.gz ; do tar xzvf "$f" ; done

Again, the first step is to compile binutils. Extract the tarball (again!):

cd avr32-binutils-2.19.atmel.1.2.0
tar xvf binutils-2.19.tar.bz2

To successfully compile binutils, we need to apply a patch not provided by atmel. Using your favourite text editor, create a file called 40-binutils-2.19-avr32-opcodes-sprintf.patch into the directory avr32-binutils-2.19.atmel.1.2.0 and write in it the following data:

--- opcodes/avr-dis.c     2010-05-14 16:37:44.965947901 +0200
+++ opcodes/avr-dis.c     2010-05-14 16:40:30.705945553 +0200
@@ -109,7 +109,7 @@ avr_operand (unsigned int insn, unsigned
            case 0x100e: xyz = "-X"; break;
            default: xyz = "??"; ok = 0;
          }
-       sprintf (buf, xyz);
+       sprintf (buf, "%s", xyz);
 
        if (AVR_UNDEF_P (insn))
          sprintf (comment, _("undefined"));
@@ -149,7 +149,7 @@ avr_operand (unsigned int insn, unsigned
         value of the address only once, but this would mean recoding
         objdump_print_address() which would affect many targets.  */
       sprintf (buf, "%#lx", (unsigned long) *sym_addr);      
-      sprintf (comment, comment_start);
+      sprintf (comment, "%s", comment_start);
       break;
       
     case 'L':
@@ -158,7 +158,7 @@ avr_operand (unsigned int insn, unsigned
        sprintf (buf, ".%+-8d", rel_addr);
         *sym = 1;
         *sym_addr = pc + 2 + rel_addr;
-       sprintf (comment, comment_start);
+       sprintf (comment, "%s", comment_start);
       }
       break;
 
@@ -169,7 +169,7 @@ avr_operand (unsigned int insn, unsigned
        sprintf (buf, ".%+-8d", rel_addr);
         *sym = 1;
         *sym_addr = pc + 2 + rel_addr;
-       sprintf (comment, comment_start);
+       sprintf (comment, "%s", comment_start);
       }
       break;

Now patch the binutils source code:

cd binutils-2.19
for p in ../*.patch ; do patch -p0 < "$p" ; done

Compile binutils:

cd ../..
mkdir build-binutils
cd build-binutils
../avr32-binutils-2.19.atmel.1.2.0/binutils-2.19/configure --target=avr --prefix=/usr/local/avr
make

This may take a while. Then, install binutils:

sudo -s
make install
exit

Back to the user sell, we need to add the newly installed AVR32 binutils to the PATH environment variable:

export PATH=$PATH:/usr/local/avr/bin

Now extract the GCC tarball, apply the AVR32 patches and create a directory for GCC's binaries:

cd ..
cd avr32-gcc-4.3.2-atmel.1.2.0
tar xzvf gcc-4.3.2.tar.bz2
cd gcc-4.3.2
for p in ../*.patch ; do patch -p0 < "$p" ; done
cd ../..
mkdir build-gcc

We'll compile GCC in three steps:

  1. first we'll compile the "first stage" or "bootstrap" compiler;
  2. then the newlib library, that is a C library optimized for embedded platforms;
  3. finally we'll finish the GCC compilation.

Configure and compile the first stage of GCC:

cd build-gcc
../avr32-gcc-4.3.2-atmel.1.2.0/gcc-4.3.2/configure --target=avr --prefix=/usr/local/avr --without-headers --with-newlib --with-gnu-as --with-gnu-ld
make all-gcc

Then install it:

sudo -s
export PATH=$PATH:/usr/local/avr/bin
make install-gcc
exit

Extract the newlib tarball, apply the AVR32 patches and create a directory for newlib's binaries:

cd ..
cd avr-newlib-1.16.0.atmel.1.1.0
tar xvf newlib-1.16.0.tar.gz
cd newlib-1.16.0
for p in ../*.patch ; do patch -p0 < "$p" ; done
cd ../..
mkdir build-newlib

Configure and compile newlib:

cd build-newlib
../avr32-newlib-1.16.0.atmel.1.1.0/newlib-1.16.0/configure --target=avr --prefix=/usr/local/avr
make all

Install newlib:

sudo -s
export PATH=$PATH:/usr/local/avr/bin
make install
exit

Complete GCC's compilation:

cd ../build-gcc
../avr32-gcc-4.3.2-atmel.1.2.0/gcc-4.3.2/configure --target=avr --prefix=/usr/local/avr --with-newlib --with-gnu-as --with-gnu-ld --disable-shared --disable-libssp --enable-languages=c,c++
make all

Install GCC:

sudo -s
export PATH=$PATH:/usr/local/avr/bin
make install
exit

And that's it! After few (?) easy (?) steps, GCC for MSP430 and AVR32 is installed!

nesC compiler

Compared to build a complete toolchain for another system, building nescc it's a snap. Set tinyossrc as current directory and download the latest source code from nescc SourceForge page.

mkdir nescc
cd nescc
wget http://ignum.dl.sourceforge.net/project/nescc/nescc/v1.3.1/nesc-1.3.1.tar.gz

Extract the tarball, configure the source code and compile it:

tar xzvf nesc-1.3.1.tar.gz
cd nesc-1.3.1
./configure --prefix=/usr/local
make

Install nescc:

sudo -s
make install
exit

Easy, isn't it?

TinyOS

Now everything is in place to install TinyOS from CVS. We'll install it in /opt.

Warning
This TinyOS installation will be fully usable only by your current user, i.e. you'll be the only one able to compile the applications in the apps folder. Other users may compile applications as long as the source code is in a directory for which they have write rights (for example, their home). If you want multiple users to modify the TinyOS source code, you should add a group to the system and change the group owner of the TinyOS installation directory.

Using root rights, make the /opt directory world-writable:

sudo chmod o+w /opt

Checkout TinyOS' source files from CVS:

cvs -d:pserver:anonymous@tinyos.cvs.sourceforge.net:/cvsroot/tinyos login
cvs -z3 -d:pserver:anonymous@tinyos.cvs.sourceforge.net:/cvsroot/tinyos co -P tinyos-2.x

Make the /opt directory writable only for root:

Warning
A world-writable directory is a security hazard! Make sure that you remove the write right for others!
sudo chmod o-w /opt

TinyOS relies on environment variables to work:

export TOSROOT=/opt/tinyos-2.x
export TOSDIR=$TOSROOT/tos
export MAKERULES=$TOSROOT/support/make/Makerules
export CLASSPATH=.:$TOSROOT/support/sdk/java/tinyos.jar

Now compile and install TinyOS' tools:

cd /opt/tinyos-2.x/tools
./Bootstrap
./configure --prefix=/usr/local/tinyos
make

Install TinyOS' tools:

sudo -s
make install
exit

During the installation, you may get error messages like: "64-bit libgetenv.so NOT GENERATED - DO NOT USE THIS RUN TO BUILD AN RPM". They are safe to ignore, just press enter to skip them.

Add TinyOS' tools directory to PATH and, finally, install the JNI libraries:

sudo -s
export PATH=$PATH:/usr/local/tinyos/bin
tos-install-jni

tos-install-jni may give you an error like [: 31: =: unexpected operator. It is due to a syntax error in the tos-install-jni script, in can be safely ignored.

I had some problems with the tinyos.jar library checked out from the CVS. So, recompile it:

cd /opt/tinyos-2.x/support/sdk/java
make

Finalize installation

Finally, it's desirable to permanently export all the environment variables used in this how-to. There are basically two options: you can modify the /etc/profile file to make TinyOS easily available to all users, or you can modify the ~/.bashrc if you are the only one that needs to use TinyOS. Whatever your choice is, open your target file (/etc/profile or ~/.bashrc) and append the following instructions to the end:

export PATH=$PATH:/usr/local/msp430/bin:/usr/local/avr/bin:/usr/local/nesc/bin:/usr/local/tinyos/bin
export TOSROOT=/opt/tinyos-2.x
export TOSDIR=$TOSROOT/tos
export MAKERULES=$TOSROOT/support/make/Makerules
export CLASSPATH=.:$TOSROOT/support/sdk/java/tinyos.jar

Make sure that everything works by running tos-check-env. Its output should be similar to this:

Path:
        /usr/local/sbin
        /usr/local/bin
        /usr/sbin
        /usr/bin
        /sbin
        /bin
        /usr/games
        /usr/local/msp430/bin
        /usr/local/avr/bin
        /usr/local/nesc/bin
        /usr/local/tinyos/bin

Classpath:
        .
        /opt/tinyos-2.x/support/sdk/java/tinyos.jar



rpms:


nesc:
        /usr/local/nesc/bin/nescc
        Version: nescc: 1.3.1


perl:
        /usr/bin/perl
        Version: v5.10.0 built for x86_64-linux-gnu-thread-multi

flex:
        /usr/bin/flex

bison:
        /usr/bin/bison

java:
        /usr/bin/java

--> WARNING: The JAVA version found first by tos-check-env may not be version 1.4 or version 1.5one of which is required by TOS. Please ensure that the located Java version is 1.4 or 1.5

graphviz:
        /usr/bin/dot
        dot - Graphviz version 2.20.2 (Wed Sep 16 11:12:21 UTC 2009)

--> WARNING: The graphviz (dot) version found by tos-check-env is not 1.10. Please update your graphviz version if you'd like to use the nescdoc documentation generator.


tos-check-env completed with errors:

--> WARNING: The JAVA version found first by tos-check-env may not be version 1.4 or version 1.5one of which is required by TOS. Please ensure that the located Java version is 1.4 or 1.5
--> WARNING: The graphviz (dot) version found by tos-check-env is not 1.10. Please update your graphviz version if you'd like to use the nescdoc documentation generator.

tos-check-env reports some errors because it isn't able to recognize the recent versions of graphviz and Java. Those warnings can be safely ignored.

That's it, enjoy your fresh installed TinyOS!