TinyOS

Post date: Mar 6, 2013 9:19:27 AM

Entre los sistemas operativos para redes de sensores inalámbricos mas utilizados por investigadores e ingenieros se encuentra tinyOS que, en su versión 2.1.2, presenta una serie de características que no hacen sino ahondar en su madurez como sistema operativo para aplicaciones que involucren WSN.

TinyOS presenta unas características algo diferentes a otros sistemas operativos que podrían ser sus competidores (e.j. Contiky, ucOS-II, etc.) y que al principio pueden alargar un poco su curva de aprendizaje. El lenguaje de programación es NesC que es muy parecido a C pero que obliga a la implementación de módulos con interfaces bien definidas y que favorecen de forma extraordinaria la reutilización de componentes. Como ya he dicho al principio, si bien aprender NesC puede llevar tiempo, una vez entendida la filosofía se simplifica la reutilización y se aumenta la productividad.

Uno de los aspectos originalmente mas descuidados, su instalación, va mejorando poco a poco y en la actualidad, parece ser mas fácil su instalación que hace no mucho tiempo. Por simplicidad usaremos la versión 2.1.1 ya que es la que estamos usando en el grupo ARCO y de momento, la pila 6lowpan/RPL IPv6 no nos hace falta.

Para la instalación, en un sistema tipo debian es tan sencillo como añadir el repositorio de Stanford al apt/sources.list:

deb http://tinyos.stanford.edu/tinyos/dists/ubuntu lucid main

y luego:

apt-get install tinyos-2.1.1

Si hay algo instalado previamente, versión anterior del tinyOS o el entorno de desarrollo de la plataforma, por ejemplo, para el micro de las mica, es mejor desinstalarlo todo para evitar problemas.

Para comprobar si todo esta instalado de forma correcta:

$tos-check-env

y finalmente, comprobar compilando una de las aplicaciones con make <plataforma>. En nuestro laboratorio trabajamos con las plataformas iris por lo que make iris debería funcionar si todo ha ido bien en cualquiera de los ejemplos de la propia distribución:

$ make iris

mkdir -p build/iris

compiling BlinkAppC to a iris binary

ncc -o build/iris/main.exe -Os -fnesc-separator=__ -Wall -Wshadow -Wnesc-all -target=iris -fnesc-cfile=build/iris/app.c -board=micasb -DDEFINED_TOS_AM_GROUP=0x22 --param max-inline-insns-single=100000 -DIDENT_APPNAME=\"BlinkAppC\" -DIDENT_USERNAME=\"felix\" -DIDENT_HOSTNAME=\"homer\" -DIDENT_USERHASH=0x4fc24a01L -DIDENT_TIMESTAMP=0x50a51339L -DIDENT_UIDHASH=0x0292744eL -fnesc-dump=wiring -fnesc-dump='interfaces(!abstract())' -fnesc-dump='referenced(interfacedefs, components)' -fnesc-dumpfile=build/iris/wiring-check.xml BlinkAppC.nc -lm

compiled BlinkAppC to build/iris/main.exe

2268 bytes in ROM

51 bytes in RAM

avr-objcopy --output-target=srec build/iris/main.exe build/iris/main.srec

avr-objcopy --output-target=ihex build/iris/main.exe build/iris/main.ihex

writing TOS image

Como ya he dicho, aunque ha mejorado bastante, la instalación puede dar problemas de diversa índole.

Si no dispones de una plataforma o quieres depurar, y quieres simularla:

$make iris sim

No olvides actualizar la versión de python que tienes instalada (2.7) en el archivo /opt/tinyos-2.1.1/support/make/sim.extra o te dirá que no encuentra el archivo Python.h.

(/opt/tinyos-2.1.1/tos/lib/tossim/tossim_wrap.cxx:139:20: fatal error: Python.h: No such file or directory compilation terminated.)

Las aplicaciones en NesC son mediante componentes que son ensamblados ("cableados") mediante las interfaces. Un componente provee de interfaces y usa otras interfaces que otros componentes proveen. Las interfaces bidireccionales se componen de comandos, implementados por el proveedor de la interfaz, y de eventos, implementados por el que usa la interfaz. De esta forma, a cada comando generalmente le corresponde un

evento que debe ser implementado para poder invocarlo. Conceptualmente estos eventos son señales que se invocan desde el hardware hacia arriba en la pila de componentes mientras que los comandos van hacia

abajo desde los componentes mas altos. No obstante, existen comandos que no tienen el correspondiente evento.

Para ejecutar un comando de una interfaz, hay que declarar el uso de dicha interfaz mediante la clausula uses. En el caso de que el comando sea no-bloqueante se generará una señal cuando termine de ejecutarse. En tal caso, por cada comando a usar hay que declarar la captura de la señal correspondiente. Mediante la palabra call se

ejecuta un comando y con signal se genera un evento.

La estructura genérica de un componente sería:

module A{

provides{

interface StdControl;

}

uses {

interface StdControl;

interface Timer

}

}

A continuación se necesita especificar la implementación.

implementation{}

La gestión de tareas se realiza mediante el post (que pone una tarea en la cola de ejecución) y task que define una función a ser ejecutada como tarea en background.

Para gestionar las condiciones de carrera, TinyOS tiene la estructura:

atomic{

}

que ejecuta un bloque de código de forma atómica y con las interrupciones deshabilitadas.

Veamos con un ejemplo básico, en /opt/tinyos-2.1.1/support/sdk/c/sf existe una pequeña sdk para comunicarnos via serie con nuestras motas.

Para programar la mota:

make iris install,2 mib510,/dev/ttyUSB0

El dos siguiente al install indica el TOS_NODE_ID que se utilizará para identificar la mota en los mensajes via radio.

Enviando mensajes:

La estructura básica para mandar mensajes es message_t :

typedef nx_struct message_t {

nx_uint8_t header[sizeof(message_header_t)];

nx_uint8_t data[TOSH_DATA_LENGTH];

nx_uint8_t footer[sizeof(message_footer_t)];

nx_uint8_t metadata[sizeof(message_metadata_t)];

} message_t;

#http://www.tinyos.net/tinyos-2.x/doc/html/tep111.html

El único campo accesible es el data, el resto es para la capa de enlace que es específica de la plataforma.

Por defecto, TOSH_DATA_LENGTH son 28 bytes pero puede ser reconfigurado en tiempo de compilación con la opción -DTOSH_DATA_LENGTH=x

Recibiendo mensajes en el PC:

La forma mas básica de recibir la información en el PC es utilizar el sdk que viene con el propio sistema operativo:

Por ejemplo, dentro de /opt/tinyos-2.1.1/support/sdk/python existe una librería tos.py que nos sirve para acceder de forma muy sencilla

al puerto serie (utilizando pySerial) y con posterioridad, parsear la cabecera de los paquetes recibidos por el puerto serie:

Así, si editamos un sencillo script (#http://docs.tinyos.net/tinywiki/index.php/Tos.py):

#!/usr/bin/env python

import sys

import tos

if '-h' in sys.argv:

print "Usage:", sys.argv[0], "serial@/dev/ttyUSB0:57600"

print " ", sys.argv[0], "network@host:port"

sys.exit()

am = tos.AM()

while True:

p = am.read()

if p:

print p

Lo guardamos con el nombre tos-dump.py y donde está el archivo tos.py. Por último lo ejecutamos indicándole donde tenemos conectada la mota que realiza las funciones de gateway entre 802.15.4 y el puerto USB:

# ./tos-dump.py serial@/dev/ttyUSB1:57600

Flushing the serial port......................................................................................

destination: 65535 source: 1 length: 4 group: 34 type: 6 data: [0, 1, 0, 232]

destination: 65535 source: 1 length: 4 group: 34 type: 6 data: [0, 1, 0, 233]

destination: 65535 source: 1 length: 4 group: 34 type: 6 data: [0, 1, 0, 234]

destination: 65535 source: 1 length: 4 group: 34 type: 6 data: [0, 1, 0, 235]

destination: 65535 source: 1 length: 4 group: 34 type: 6 data: [0, 1, 0, 236]

destination: 65535 source: 1 length: 4 group: 34 type: 6 data: [0, 1, 0, 237]

destination: 65535 source: 1 length: 4 group: 34 type: 6 data: [0, 1, 0, 238]

Esos paquetes son los que se envían desde una mota de prueba a la mota que realiza las funciones de gateway.

Algunos enlaces útiles:

http://docs.tinyos.net/tinywiki/index.php/Mote-mote_radio_communication_(TOS_2.1.1)