wNesC: Extensions to nesC from the University of Warsaw

Wiki

UW Logo

University of Warsaw, Warsaw, Poland

This website is no longer maintained!

This wiki page describes how to install and use the extensions to the nesC language and compiler, which were developed by Konrad Iwanicki's group at the University of Warsaw, Warsaw, Poland. NesC is a programming language for deeply embedded systems, notably wireless sensor networks. A huge nesC code base is available from the TinyOS project. The presented extensions, in turn, comprise embedded mock modules (not yet provided for download) and embedded code coverage tools. For more information, please, refer to our publications, especially “Bringing Modern Unit Testing Techniques to Wireless Sensor Networks.” Note, however, that since the project is evolving, the publications may be outdated, and this wiki has the most up-to-date information. All code is provided under a BSD-like license, which in particular implies no warranties.

When using the software in your projects, please, consider giving us credit by citing the “Bringing Modern Unit Testing Techniques to Wireless Sensor Networks” paper and/or this website.

To report a bug, please, contact Konrad Iwanicki. Although our responsiveness may not be high, we would be grateful for any reports, remarks, and suggestions.

Core

The core of the extensions is a modified nesC compiler. This section describes how to install it. To this end, we assume that an original nesC compiler (version 1.3.3) has already been installed and is functional. The compiler can be downloaded, for instance, from SourceForge. The modified version will overwrite the existing installation.

It is also possible to install the modified compiler independently and switch between the versions by modifying environmental variables. This is more complicated, though, and thus, we omit the instructions here.

Download

Currently, the following variants of the extended compiler can be downloaded:

Installation

To install the modified nesC from a binary package in the place of an existing installation, you need to perform the following steps:

  1. Locate your nesC installation, more specifically, a file called nesc1 or nesc1.exe. The file should reside in directory SOME_PREFIX/lib/ncc, where SOME_PREFIX is by default /usr/local.
  2. Copy the contents of the binary package to directory SOME_PREFIX. In particular, the nesc1 file from the package should overwrite the existing nesc1 file. Typically, you will need to perform the copying as the super-user.
  3. Verify the installation, for instance, by executing nesccov. If everything has been installed correctly, you should receive an output that looks as follows:
    nesccov: Code coverage assessment tool for nesc
    Copyright (C) 2011-2014, University of Warsaw
    
    ERROR: No arguments given!
    
    Usage:
      nesccov (line|cond) (<path_to_module>|<module_name>) [<exec_file>]
    
          

NescCov: Embedded Code Coverage

The NescCov package provides tools for TinyOS that allow for measuring which lines and conditional branches of nesC code are executed, both in TOSSIM and on actual sensor nodes. The following instructions assume that your TinyOS installation is operational. As a sample platform for actual sensor nodes, we assume TelosB.

Download

NescCov is available for download as a single package containing source code and precompiled Java classes:

Installation

The contents of the package reflect the directories of TinyOS, more specifically, the $TOSROOT directory. To install the package, perform the following steps:

  1. Copy the contents of the package to $TOSROOT. Depending on what your $TOSROOT is, you may need to perform the copying as the super-user.
  2. Most likely not, but if your platform defines some nonstandard serial active message stack (i.e., message formats), you may be required to regenerate two message classes: net.tinyos.tools.NescCovCondInfoDumpSerialMsg and net.tinyos.tools.NescCovLineInfoDumpSerialMsg. To this end (assuming that the mig tool for TinyOS correctly supports your platform), you need to perform the following commands from $TOSROOT/support/sdk/java/net/tinyos/tools/ (possibly as the super-user):
    mig -target=<your_platform_name> java $CFLAGS \
      -java-classname=net.tinyos.tools.NescCovLineInfoDumpSerialMsg \
      $TOSDIR/lib/nesccov/NescCovLineInfoSerialDump.h \
      NescCovLineInfoDumpSerialMsg -o NescCovLineInfoDumpSerialMsg.java
    
    mig -target=<your_platform_name> java $CFLAGS \
      -java-classname=net.tinyos.tools.NescCovCondInfoDumpSerialMsg \
      $TOSDIR/lib/nesccov/NescCovCondInfoSerialDump.h \
      NescCovCondInfoDumpSerialMsg -o NescCovCondInfoDumpSerialMsg.java
    
  3. If you use a different Java version, you may also be required to recompile the classes by invoking from $TOSROOT/support/sdk/java/net/tinyos/tools/, the following commands:
    rm -f *.class
    javac *.java
    
  4. Regenerate the tinyos.jar file. The simplest, though not entirely perfect, way to do this is by entering $TOSROOT/support/sdk/java/ and invoking:
    rm -f tinyos.jar
    zip -r tinyos.jar net/
    
  5. Test if everything works by executing:
    java net.tinyos.tools.NescCovSerialClient
    
    Your output should start as follows:
    nesccov: Code coverage assessment tool for nesc
             Java client for serial active message dumpers
    Copyright (C) 2011-2014, University of Warsaw
    
    
    If it does not, you may need to ensure that your $CLASSPATH variable contains $TOSROOT/support/sdk/java/tinyos.jar.
Usage with TOSSIM

Assuming that your TOSSIM installation works, testing code coverage with nesccov in TOSSIM is straightforward. As an illustration, we will use an application that we have developed and that is located in $TOSROOT/apps/NescCovDemo.

  1. Enter the $TOSROOT/apps/NescCovDemo directory.
  2. Build an instrumented application image for TOSSIM by executing:
    make micaz sim linecov condcov
    
    The linecov option informs the modified nesC compiler to instrument the generated code such that it is possible to measure its line coverage. Likewise, the condcov option enables measuring condition coverage. You can use none, one, or both the options in your activities. If TOSSIM is installed, correctly your output should end as follows:
    *** Successfully built micaz TOSSIM library. 
    
    In addition, the following files should be created in the application directory:
    • NescCovDemoMainP.nc.bb (produced for linecov)
    • NescCovDemoMainP.nc.branch (produced for condcov)
    • VirtualizeTimerC.nc.bb (produced for linecov)
    • VirtualizeTimerC.nc.branch (produced for condcov)
  3. Start a simulation of the image by typing:
    python tossim_run.py
    
    As a result two files should be created:
    • nesccov_line.exec
    • nesccov_cond.exec
  4. Now, you are ready to inspect the coverage of the image in the simulated run.
    • To inspect the line coverage of the main application module, execute:
      nesccov line NescCovDemoMainP nesccov_line.exec
      
      Your output should match the contents of file NescCovDemoMainP.linecov-out.txt. Information on how to interpret the contents can be found in our papers.
    • To inspect the condition coverage of the main application module, execute:
      nesccov cond NescCovDemoMainP nesccov_cond.exec
      
      Your output should match the contents of file NescCovDemoMainP.condcov-out.txt. Again, information on how to interpret the contents can be found in our papers.
    • In a similar fashion, you can inspect the coverage of module VirtualizeTimerC.
  5. When you are done and want to clean the generated files, execute:
    make clean linecov condcov
    
    Here, the linecov and condcov options tell the make system to also remove the coverage-related files.

In the above tutorial, the instrumentation concerned two modules: NescCovDemoMainP and VirtualizeTimerC. If you want to instrument other modules, edit the NESCCOV_MODULES in the Makefile of the application. Afterward, repeat all the aforementioned steps, starting from rebuilding the instrumented application image.

Usage with Sensor Nodes

For the node-based tutorial, we assume the TelosB platform. Testing coverage on a node differs from testing coverage in TOSSIM essentially only in that the runtime data must at some point be transferred from the node to the PC, where they can be stored in an appropriate .exec file. To this end, it is assumed that a TelosB node is plugged to the PC via a USB cable, which can be tested by executing:

motelist

which should produce an output similar to:

Reference  Device           Description
---------- ---------------- ---------------------------------------------
XBQWF157   /dev/ttyUSB0     XBOW Crossbow Telos Rev.B

With a node plugged, the following steps need no be performed:

  1. Enter the $TOSROOT/apps/NescCovDemo directory.
  2. Build an instrumented application image for TelosB by executing:
    make telosb linecov condcov
    
    The output should resemble the following one:
        compiled NescCovDemoAppC to build/telosb/main.exe
                9240 bytes in ROM
                 455 bytes in RAM
    msp430-objcopy --output-target=ihex build/telosb/main.exe
    build/telosb/main.ihex
        writing TOS image
    
    Note that the size of the instrumented image (in both RAM and ROM) is larger than that of a noninstrumented one (i.e., one built without the condcov and linecov option). Again, the following files should be created in the application directory:
    • NescCovDemoMainP.nc.bb (produced for linecov)
    • NescCovDemoMainP.nc.branch (produced for condcov)
    • VirtualizeTimerC.nc.bb (produced for linecov)
    • VirtualizeTimerC.nc.branch (produced for condcov)
  3. Install the image on a node, for instance, by executing:
    make telosb reinstall bsl,/dev/ttyUSB0
    
    You should get an output resembling:
    cp build/telosb/main.ihex build/telosb/main.ihex.out
        installing telosb binary using bsl
    tos-bsl --telosb -c /dev/ttyUSB0 -r -e -I -p build/telosb/main.ihex.out
    MSP430 Bootstrap Loader Version: 1.39-goodfet-8
    Mass Erase...
    Transmit default password ...
    Invoking BSL...
    Transmit default password ...
    Current bootstrap loader version: 1.61 (Device ID: f16c)
    Changing baudrate to 38400 ...
    Program ...
    9272 bytes programmed.
    Reset device ...
    rm -f build/telosb/main.exe.out build/telosb/main.ihex.out 
    
    If you get errors, try changing the permissions of /dev/ttyUSB0.
  4. To get the runtime data from the node, start an appropriate client application by executing:
    java net.tinyos.tools.NescCovSerialClient \
      -comm serial@/dev/ttyUSB0:telosb
    
    The application connects to the node over USB, downloads runtime coverage information and dumps it to:
    • nesccov_line.exec and
    • nesccov_cond.exec
    In addition it may also create .bak files whenever the dumped coverage information is to be overwritten with new data. While running, the application should produce messages that look as follows:
    Received a line coverage message of size 10.
    Received a condition coverage message of size 10.
    Received a line coverage message of size 0.
    Dumping a 10-byte report to file "nesccov_line.exec"
    Received a condition coverage message of size 0.
    Dumping a 10-byte report to file "nesccov_cond.exec"
    
    You are free to terminate the application when it has dumped each of the above two files twice (the first dump may be incomplete if the application connects to the node when the node is already transferring some information).
  5. At this point, you are ready to inspect the coverage of the image in the simulated run, which is done like in TOSSIM:
    • To inspect the line coverage of the main application module, execute:
      nesccov line NescCovDemoMainP nesccov_line.exec
      
    • To inspect the condition coverage of the main application module, execute:
      nesccov cond NescCovDemoMainP nesccov_cond.exec
      

Note that by default, async code and atomic sections are not instrumented. While it is possible to turn such instrumentation on with -fnesc-coverage-atomic and -fnesc-coverage-async compile-time options, doing so in time-critical code may cause the application to break for a number of various reasons.

Have fun!

Credits

The following people have contributed to the project one-way or another:

The research that led to the development of the tools was partially supported from the following sources:

Related Publications

  1. K. Iwanicki, P. Horban, P. Glazar, and K. Strzelecki: “Bringing Modern Unit Testing Techniques to Sensornets,” ACM Transactions on Sensor Networks, vol. 11, no. 2. ACM. July 2014. pp. 24:1—25:41. DOI: 10.1145/2629422.
  2. M. Ciszewski and K. Iwanicki: “Efficient Automated Code Partitioning for Microcontrollers with Switchable Memory Banks,” ACM Transactions on Embedded Computing Systems, vol. 16, no. 4. ACM. May 2017. pp. 114:1—114:26. DOI: 10.1145/3055511.
  3. P. Glazar: “A unit-testing framework for wireless sensor networks,” Master's Thesis, University of Warsaw, Warsaw, Poland, June 2012.
  4. K. Strzelecki: “An automated code coverage analyser for wireless sensor networks,” Master's Thesis, University of Warsaw, Warsaw, Poland, December 2012.
  5. G. Kolakowski and M. Szczepaniak: “Effective support for large NesC code bases,” Master's Thesis, University of Warsaw, Warsaw, Poland, August 2014.
  6. M. Ciszewski: “Efficient Code Banking for Internet of Things Microcontrollers,” Master's Thesis, University of Warsaw, Warsaw, Poland, September 2015.