-1- georgia state universitysensorweb research laboratory acknowledgement: thank greg hackmann at...

132
-1- Georgia State University Sensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos tutorial slides. TinyOS Tutorial TinyOS Tutorial Dr. WenZhan Song Dr. WenZhan Song Professor, Computer Science Professor, Computer Science

Upload: brandon-gibbs

Post on 19-Dec-2015

216 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-1- Georgia State UniversitySensorweb Research Laboratory

Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos tutorial slides.

TinyOS TutorialTinyOS Tutorial

Dr. WenZhan SongDr. WenZhan Song

Professor, Computer ScienceProfessor, Computer Science

Page 2: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-2- Georgia State UniversitySensorweb Research Laboratory

Outline Installing TinyOS and Building Your First

App Hardware Primer Basic nesC Syntax Advanced nesC Syntax Network Communication Sensor Data Acquisition Debugging Tricks and Techniques

2

Page 3: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-3- Georgia State UniversitySensorweb Research Laboratory

TinyOS Installation TinyOS Documentation Wiki:

http://docs.tinyos.net/ Various installation options listed under “Getting

started” section

Pre-compiled .rpm and .deb packages for Fedora and Ubuntu Linux users Ubuntu users: be sure to remove brltty package

All necessary drivers already included with Linux kernel

3

Page 4: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-4- Georgia State UniversitySensorweb Research Laboratory

TinyOS Installation (cont.) OS X unofficially supported but works well

Precompiled packages available at http://www.cse.wustl.edu/~gwh2/tinyos-2.1.0.dmg.bz2 Need to install pySerial

(http://pyserial.sourceforge.net) and FTDI FT232R serial drivers (http://www.ftdichip.com/Drivers/VCP.htm) separately

Can also compile by hand: see TinyOS Wiki

4

Page 5: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-5- Georgia State UniversitySensorweb Research Laboratory

TinyOS Installation (cont.) Windows installation uses Cygwin to emulate

Linux software layer Problematic under XP, refuses to work on some Vista

machines (updating Cygwin after the installation may help)

gcc is also very slow under Cygwin “Running a XubunTOS Virtual Machine Image in

VMware Player” tutorial recommended instead Or pick your favorite VM software and install Ubuntu

yourself

5

Page 6: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-8- Georgia State UniversitySensorweb Research Laboratory

TinyOS Directory Structure /opt/tinyos-2.1.0 ($TOSROOT)

apps support

make sdk

tools tos

8

Page 7: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-9- Georgia State UniversitySensorweb Research Laboratory

make System $TOSROOT/support/make includes lots of Makefiles to

support the build process Create a simple stub Makefile in your app

directory that points to main component

COMPONENT=[MainComponentC]SENSORBOARD=[boardtype] # if neededinclude $(MAKERULES)

make [platform] in app directory Builds but does not install program platform: one of the platforms defined in

$TOSROOT/tos/platforms (mica2, micaz2, telosb)

9

Page 8: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-10- Georgia State UniversitySensorweb Research Laboratory

make System make [re]install.[node ID] [platform]

[programming options] node ID: 0 - 255 programming options:

mica2/micaz: mib510,/dev/ttyXYZ telosb: bsl,/dev/ttyXYZ

make clean make docs [platform]

Generates HTML documentation in $TOSROOT/doc/nesdoc/[platform]

10

Page 9: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-11- Georgia State UniversitySensorweb Research Laboratory

Build Stages

11

Set AM address and node ID in binary

Program mote

Preprocess .nc to .c, then compile .c to binary

Page 10: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-12- Georgia State UniversitySensorweb Research Laboratory

How to Get Help TinyOS Documentation Wiki:

http://docs.tinyos.net TinyOS Programming Manual: 139-page PDF

intro to nesC and TinyOS 2.x:http://www.tinyos.net/tinyos-2.x/doc/pdf/tinyos-programming.pdf

TinyOS Tutorials: short HTML lessons on using parts of TinyOS (sensors, radio, TOSSIM, etc.):http://docs.tinyos.net/index.php/TinyOS_Tutorials

12

Page 11: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-13- Georgia State UniversitySensorweb Research Laboratory

How to Get Help nesdoc: annotated API for all interfaces and

components in TinyOS: http://docs.tinyos.net/index.php/Source_Code_Documentation

TinyOS Enhancement Protocols (TEP): formal documentation for TinyOS features: http://docs.tinyos.net/index.php/TEPs

13

Page 12: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-14- Georgia State UniversitySensorweb Research Laboratory

Outline Installing TinyOS and Building Your First App Hardware Primer Basic nesC Syntax Advanced nesC Syntax Network Communication Sensor Data Acquisition Debugging Tricks and Techniques

14

Page 13: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-15- Georgia State UniversitySensorweb Research Laboratory

MicaZ CC2420 - IEEE 802.15.4 Radio

250kbps 2.4 GHz

ATmega 128L microcontroller 4kB RAM, 128kB program flash, 512 kB storage flash,

Need a separate programming board and debug board

15

Page 14: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-16- Georgia State UniversitySensorweb Research Laboratory

Tmote Sky (aka TelosB) CC2420 - IEEE 802.15.4 Radio

250kbps 2.4GHz

TI MSP430 microcontroller 8MHz, 16 MIPS, 10kB RAM, 1MB storage flash, 48K

program flash Integrated antenna & USB interface Low power utilization

1.8mA/5.1µA vs. Mica 2’s 8mA/15µA

16

Page 15: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-17- Georgia State UniversitySensorweb Research Laboratory

TelosW = Telos + Wake-on CC1101 – wake-on radio

1.2kbps - 500kbps 868-915 MHz

TI MSP430 microcontroller 16MHz, 16 MIPS, 10kB RAM

Integrated antenna & USB interface Low power utilization

1.8mA/5.1µA vs. Mica 2’s 8mA/15µA Wake-on sensor/ADC design Onboard energy meters More details at

http://sensorweb.cs.gsu.edu/sites/default/files/research/projects/TelosW/images/TELOSW.pdf

Page 16: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-18- Georgia State UniversitySensorweb Research Laboratory

Outline Installing TinyOS and Building Your First App Hardware Primer Basic nesC Syntax Advanced nesC Syntax Network Communication Sensor Data Acquisition Debugging Tricks and Techniques

18

Page 17: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-19- Georgia State UniversitySensorweb Research Laboratory

TinyOS Execution Model To save energy, node stays asleep most of the

time Computation is kicked off by hardware interrupts Interrupts may schedule tasks to be executed at

some time in the future TinyOS scheduler continues running until all

tasks are cleared, then sends mote back to sleep

19

handlePackethandlePacket readSensorreadSensor sendResponsesendResponse

zZz

Page 18: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-20- Georgia State UniversitySensorweb Research Laboratory

TinyOS Execution Model

Page 19: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-21- Georgia State UniversitySensorweb Research Laboratory

TinyOS Memory Model STATIC memory allocation!

No heap (malloc) No function pointers

Global variables Available on a per-frame basis

Local variables Saved on the stack Declared within a method

Page 20: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-22- Georgia State UniversitySensorweb Research Laboratory

TinyOS Thread Model Tasks:

Time flexible Longer background processing jobs Atomic with respect to other tasks (single threaded) Preempted by events

Events: Time critical Shorter duration (hand off to task if need be) Interrupts task Last-in first-out semantics (no priority among events)

Do not confuse an event from the NesC event keyword!!

TinyOS-1.x supports up to 7 pending tasks by default, you can add -DTOSH_MAX_TASKS_LOG2=n to makefile’s PFLAGS line to get 2^n tasks, where n=8 is maximum. TinyOS-2.x supports up to 255 tasks by default.

Task overflow is still possible – make sure to check whether task “post” was SUCCESS or not.

Page 21: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-23- Georgia State UniversitySensorweb Research Laboratory

TinyOS Programming Model Separation of construction and

composition Programs are built out of components Each component is specified by an

interface Provides “hooks” for wiring components

together Components are statically wired

together based on their interfaces Increases runtime efficiency

Page 22: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-24- Georgia State UniversitySensorweb Research Laboratory

TinyOS Component Model

24

prov

ides

Split

Cont

rol

NetworkHandlerCNetworkHandlerC

NetworkHandlerP

uses Receivecommandstart()

eventstartDone()

ActiveMessageC

providesReceive

providesSplitControl

Page 23: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-25- Georgia State UniversitySensorweb Research Laboratory

TinyOS Component Model Components use and provide interfaces,

commands, and events Specified by a component’s interface The word “interface” has two meanings in

TinyOS Components implement the events they

use and the commands they provide:

Page 24: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-26- Georgia State UniversitySensorweb Research Laboratory

TinyOS Component Model There are two types of components:

Modules: Implement the application behavior

Configurations: Wires components together

A component does not care if another component is a module or configuration

A component may be composed of other components

Page 25: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-27- Georgia State UniversitySensorweb Research Laboratory

Components != Objects

27

ActiveMessageC ActiveMessageC

NetworkHandlerP AnotherHandlerPAppLogicP

✓✗ActiveMessageC

Page 26: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-28- Georgia State UniversitySensorweb Research Laboratory

Interfaces List of exposed events and commands Like ordinary C function declarations, except

with event or command in front

28

interface Receive { event message_t * Receive(message_t * msg, void * payload, uint8_t len); command void * getPayload(message_t * msg, uint8_t * len); command uint8_t payloadLength(message_t * msg); }

Page 27: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-29- Georgia State UniversitySensorweb Research Laboratory

Modules provide the implementation of one or more interfaces

They may consume (use) other interfaces to do so

“Rename” interfaces with the as keyword -- required if you are using/providing more than one of the same interface!

module ExampleModuleP { provides interface SplitControl; uses interface Receive; uses interface Receive as OtherReceive;}implementation { ...}

Modules

29

Page 28: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-30- Georgia State UniversitySensorweb Research Laboratory

Modules implementation block may contain:

Variable declarations Helper functions Tasks Event handlers Command implementations

30

Page 29: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-31- Georgia State UniversitySensorweb Research Laboratory

Modules: Variables and Functions Placed inside implementation block exactly like

standard C declarations:

31

...implementation { uint8_t localVariable; void increment(uint8_t amount);

...

void increment(uint8_t amount) { localVariable += amount; }}

Page 30: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-32- Georgia State UniversitySensorweb Research Laboratory

Modules: Tasks Look a lot like functions, except:

Prefixed with task Can’t return anything or accept any parameters

32

implementation { ... task void legalTask() { // OK } task bool illegalTask() { // Error: can’t have a return value! } task void anotherIllegalTask(bool param1) { // Error: can’t have parameters! }}

Page 31: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-33- Georgia State UniversitySensorweb Research Laboratory

Modules: Task Scheduling Tasks are scheduled using the post keyword

TinyOS guarantees that scheduled task will eventually run Default scheduling policy: FIFO

33

task1 ✓task2 task3 ...✗task1 task1

error_t retval;retval = post handlePacket();// retval == SUCCESS if task was scheduled, or E_FAIL if not

Page 32: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-34- Georgia State UniversitySensorweb Research Laboratory

Modules: Commands and Events Commands and events also look like C functions,

except: they start with the keyword command or event the “function” name is in the form

InterfaceName.CommandOrEventName

e.g.

34

implementation { command error_t SplitControl.start() { // Implements SplitControl’s start() command }

event message_t * Receive.receive(message_t * msg, void * payload, uint8_t len) { // Handles Receive’s receive() event }}

Page 33: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-35- Georgia State UniversitySensorweb Research Laboratory

Modules: Commands and Events Commands are invoked using the call keyword:

Event handlers are invoked using the signal keyword:

35

call Leds.led0Toggle();// Invoke the led0Toggle command on the Leds interface

signal SplitControl.startDone();// Invoke the startDone event handler on the SplitControl interface

Page 34: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-36- Georgia State UniversitySensorweb Research Laboratory

Modules: Commands and Events A command, event handler, or function can call or signal

any other command or event from any interface wired into the module:

36

module ExampleModuleP { uses interface Receive; uses interface Leds;}implementation { event message_t Receive.receive(message_t * msg, void * payload, uint8_t len) { // Just toggle the first LED call Leds.led0Toggle(); return msg; } ...}

Page 35: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-37- Georgia State UniversitySensorweb Research Laboratory

Synchronous vs. Asynchronous Commands and event handlers normally run in

synchronous context i.e., cannot be reached by an interrupt handler

The async keyword notifies nesC that the command/event handler may run in an asynchronous context:

37

implementation { async event void Alarm.fired() { // Handle hardware alarm interrupt }}

Page 36: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-38- Georgia State UniversitySensorweb Research Laboratory

Use atomic blocks to avoid race conditions

Interrupts are disabled here -- use sparingly and make as short as practical

implementation { uint8_t sharedCounter; async event void Alarm.fired() { sharedCounter++; }

event void Receive.receive(...) { ...

atomic { sharedCounter++;

} } }

Reminder: Race Conditions

38

Page 37: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-39- Georgia State UniversitySensorweb Research Laboratory

Reminder: Race Conditions Tasks are always synchronous If timing isn’t crucial, defer code to tasks to avoid race

conditions

39

implementation { uint8_t sharedCounter; task void incrementCounter() { sharedCounter++; }

async event void Alarm.fired() { post incrementCounter(); }

event void Receive.receive(...) { ... sharedCounter++; } }

Task is scheduled immediately, but executes

later. This is just an illustration of ‘post’, not efficient in this particular example!

Task is scheduled immediately, but executes

later. This is just an illustration of ‘post’, not efficient in this particular example!

Page 38: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-40- Georgia State UniversitySensorweb Research Laboratory

nesC and Race Conditions nesC can catch some, but not all, potential race

conditions If you’re absolutely sure that there’s no race

condition (or don’t care if there is), use the norace keyword:

40

implementation { norace uint8_t sharedCounter;

async event void Alarm1.fired() { sharedCounter++; call Alarm2.start(200); }

async event void Alarm2.fired() { sharedCounter--; call Alarm1.start(200); } }

Race condition is impossible;

async events are mutually exclusive

Race condition is impossible;

async events are mutually exclusive

Page 39: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-41- Georgia State UniversitySensorweb Research Laboratory

TOSThreads New in TinyOS 2.1: the TOSThreads threading

library Threads add a third execution context to

TinyOS’s concurrency layer Lowest priority: only run when TinyOS kernel is idle Threads are preemptable by anything: sync, async, or

other threads Also adds a library of synchronization primitives

(mutex, semaphore, etc.) and blocking wrappers around non-blocking I/O

Described in TOSThreads Tutorial (http://docs.tinyos.net/index.php/TOSThreads_Tutorial) or TEP 134

41

Page 40: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-42- Georgia State UniversitySensorweb Research Laboratory

configuration NetworkHandlerC { provides interface SplitControl;}implementation { components NetworkHandlerP as NH, ActiveMessageP as AM; NH.Receive -> AM.Receive; NH.SplitControl = SplitControl;

}

Configurations

42

//// NH.Receive -> AM; NH = SplitControl;

List interfaces that the component imports &

exports

List interfaces that the component imports &

exports

Give comma-separated list(s) of constituent

components

Give comma-separated list(s) of constituent

components

Wire two components’ interfaces together using an arrow pointing from

user to provider

Wire two components’ interfaces together using an arrow pointing from

user to providerWire external

interfaces using =Wire external

interfaces using =

Page 41: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-43- Georgia State UniversitySensorweb Research Laboratory

Configuration Wires A configuration can bind an interface user

to a provider using -> or <- User.interface -> Provider.interface Provider.interface <- User.interface

Bounce responsibilities using = User1.interface = User2.interface Provider1.interface = Provider2.interface

The interface may be implicit if there is no ambiguity e.g., User.interface -> Provider ==

User.interface -> Provider.interface

Page 42: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-44- Georgia State UniversitySensorweb Research Laboratory

Outline Installing TinyOS and Building Your First App Hardware Primer Basic nesC Syntax Advanced nesC Syntax Network Communication Sensor Data Acquisition Debugging Tricks and Techniques

44

Page 43: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-45- Georgia State UniversitySensorweb Research Laboratory

High-Level Summary nesC includes a lot of complex features that try

to alleviate design problems with TinyOS 1.x The good news: you will probably never have to

write code that incorporates these features The bad news: you’re almost certain to use code

that incorporates these features

First, an abstract look at what these features are and what their syntax means

Second, a concrete example of how to use them to build components

45

Page 44: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-46- Georgia State UniversitySensorweb Research Laboratory

Interfaces with Arguments Creating new interfaces to support different data

types can get redundant fast

interface ReadUint16 { command error_t read(); event void readDone(error_t error, uint16_t value); }

interface ReadBool { command error_t read(); event void readDone(error_t error, bool value); }

46

Page 45: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-47- Georgia State UniversitySensorweb Research Laboratory

Interfaces with Arguments If you want to make an interface adapt to

different underlying types, then put a placeholder in angle brackets:

interface Read<type> { command error_t read(); event void readDone(error_t error, type value); }

module SixteenBitSensorP { provides interface Read<uint16_t>; }

module BooleanSensorP { provides interface Read<bool>; }

47

Page 46: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-48- Georgia State UniversitySensorweb Research Laboratory

Fan-In: No Big Deal

48

NetworkHandlerP AnotherHandlerPAppLogicP

RadioP

provides Receive

uses Receive uses Receive uses Receive

Many-to-one calls work like you’d expect ...

Many-to-one calls work like you’d expect ...

Page 47: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-49- Georgia State UniversitySensorweb Research Laboratory

Fan-Out: Bad Things Happen

49

NetworkHandlerP AnotherHandlerPAppLogicP

provides Receive

uses Receive uses Receive uses Receive

… but what about one-to-many calls?

… but what about one-to-many calls?

RadioP

return &buffer1; return &buffer2; return &buffer3;

Page 48: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-50- Georgia State UniversitySensorweb Research Laboratory

Fan-Out: What Bad Things Happen?

If different return values come back, nesC may not be able to make sense of the contradiction and will arbitrarily pick one

Avoid designs where this is possible If you can’t avoid it, see TinyOS Programming

Guide 5.2 for more info on combining return values

50

Page 49: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-51- Georgia State UniversitySensorweb Research Laboratory

Parameterized Wiring

Consider the following way to avoid fan-out:

module RadioP { provides interface Receive as Receive0; provides interface Receive as Receive1; provides interface Receive as Receive2; uses interface LowLevelRadio; ... } implementation { event void LowLevelRadio.packetReceived( uint8_t * rawPacket) { ... uint8_t type = decodeType(rawPacket); if(type == 0) signal Receive0.receive(...); else if(type == 1) signal Receive1.receive(...); ... } ... }

51

NetworkHandlerP

AnotherHandlerPAppLogicP

RadioP

uses Receive uses Receive uses Receive

Page 50: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-52- Georgia State UniversitySensorweb Research Laboratory

Parameterized Wiring The idea works in concept, but isn’t maintainable in practice But nesC can approximate the behavior in a much more

maintainable way:

module RadioP { provides interface Receive[uint8_t id]; ... } implementation { event void LowLevelRadio.packetReceived(uint8_t *

rawPacket) { ... uint8_t type = decodeType(rawPacket); signal Receive[type].received(...); } ... }

52

Page 51: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-53- Georgia State UniversitySensorweb Research Laboratory

Using Parameterized Wiring You can wire parameterized interfaces like so:

AppLogicP -> RadioP.Receive[0];NetworkHandlerP -> RadioP.Receive[1];AnotherHandlerP -> RadioP.Receive[2];

If each component is wired in with a unique parameter, then fan-out goes away

53

Page 52: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-54- Georgia State UniversitySensorweb Research Laboratory

Unique Parameters In most cases, it’s unreasonable to expect the user to

count the number of times (s)he is using the interface and wire accordingly

nesC can automatically generate a unique parameter for you using the unique() macro (which is a hash function):

AppLogicP -> RadioP.Receive[unique(“RadioP”)]; // unique(“RadioP”) expands to 0

NetworkHandlerP -> RadioP.Receive[unique(“RadioP”)]; // unique(“RadioP”) expands to 1

AnotherHandlerP -> RadioP.Receive[unique(“RaadioP”)]; // unique(“RaadioP”) expands to 0 (oops) ...

54

Page 53: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-55- Georgia State UniversitySensorweb Research Laboratory

uniqueCount() What if your component needs to store different

state for each unique parameter?

module RadioP { ... } implementation { int16_t state[ ];

... }

55

uniqueCount(“RadioP”)

uniqueCount(X) expands to # of times unique(X) appears in

the application

uniqueCount(X) expands to # of times unique(X) appears in

the application

Page 54: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-56- Georgia State UniversitySensorweb Research Laboratory

Defaults If you provide a parameterized interface and signal

an event on it, you must also give a default event handler:

module SharedComponentP { ... } implementation { event void LowLevelRadio.packetReceived(uint8_t *

rawPacket) { ...

signal Receive[type].received(...); }

default event void Receive.received[uint8_t id](...) { // e.g., do nothing } ... }

56

Page 55: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-57- Georgia State UniversitySensorweb Research Laboratory

Generic Components What if you have a component where different

users absolutely should not share any state? Generic components let you “instantiate” a

single component multiple times

generic module HashTableP() { provides interface HashTable; } ...

components new HashTableP() as H1, new HashTableP() as H2;

AppLogicP.HashTable -> H1; NetworkHandlerP.HashTable -> H2;

57

Page 56: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-58- Georgia State UniversitySensorweb Research Laboratory

Generic Components But wait ... didn’t I say earlier that components aren’t

objects? nesC internally creates a complete second copy of the

component

58

HashTableP$0

AppLogicP

HashTableP$1

NetworkHandlerP

Page 57: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-59- Georgia State UniversitySensorweb Research Laboratory

Generic Components with Parameters

You can give each instantiation of the component slightly different behavior by adding compile-time parameters:

generic module ListP(typedef type, uint8_t size) { provides interface List<type>; } implementation { type data[size]; command void List.clear() { for(uint8_t i = 0; i < size; i++) data[i] = 0; } }

components new ListP(bool, 16);

59

Page 58: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-60- Georgia State UniversitySensorweb Research Laboratory

Putting It All Together: Building a Timer

Consider an AlarmC component that exposes a 32 KHz hardware clock using the following interface:

interface Alarm { async event void fired(); }

We want to create a high-level timer component that: Runs outside of the asynchronous context Can be hooked into multiple components Each consumer can choose a custom firing interval

(every n ticks) Can be transformed into lower frequencies (16 KHz, 1

Hz, etc.) 60

Page 59: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-61- Georgia State UniversitySensorweb Research Laboratory

Step 1: Get Out of Asynchronous Context

interface Timer { event void fired(); }

module AlarmToTimerP { provides interface Timer; uses interface Alarm; } implementation { task void timerTask() { signal Timer.fired(); }

async event void Alarm.fired() { post timerTask(); } }

61

AlarmC

Alarm

AlarmToTimerP

Alarm

Timer

Page 60: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-62- Georgia State UniversitySensorweb Research Laboratory

Step 2: Virtualize the Timer

module VirtualizeTimerP { uses interface Timer as SubTimer; provides interface Timer[uint8_t id]; } implementation { event void SubTimer.fired() { uint8_t i; for(i = 0; i < 255; i++) { signal Timer.fired[i](); } }

default event void Timer.fired[uint8_t id]() {

// Do nothing } }

62

AlarmC

Alarm

AlarmToTimerP

Alarm

Timer

VirtualizeTimerP

Timer

SubTimer

Page 61: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-63- Georgia State UniversitySensorweb Research Laboratory

Step 3: Reprogram the Timer

interface Timer /* v. 2 */ { event void fired(); command void startPeriodic(uint16_t

interval); }

63

AlarmC

Alarm

AlarmToTimerP

Alarm

Timer

VirtualizeTimerP

Timer

SubTimer

Page 62: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-64- Georgia State UniversitySensorweb Research Laboratory

Step 3: Reprogram the Timer

module VirtualizeTimerP /* v. 2 */ { ... } implementation { uint16_t currentTime = 0; uint16_t nextTimeToFire[255]; uint16_t intervals[255];

event void SubTimer.fired() { uint8_t i; for(i = 0; i < 255; i++) { if(nextTimeToFire[i] == currentTime) { signal Timer.fired[i](); nextTimeToFire[i] += intervals[i]; } } currentTime++; }

command void Timer.startPeriodic[uint8_t id](uint16_t interval) {

nextTimeToFire[id] = currentTime + interval; intervals[id] = interval; } ... }

64

AlarmC

Alarm

AlarmToTimerP

Alarm

Timer

VirtualizeTimerP

Timer

SubTimer

Page 63: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-65- Georgia State UniversitySensorweb Research Laboratory

Step 3.5: Tidy Up the Wiring

generic configuration VirtualizedTimerC() {

provides interface Timer; } implementation { components AlarmC; components AlarmToTimerP to AtoT; components VirtualizeTimerP as Virt; AtoT.Alarm -> AlarmC; Virt.SubTimer -> AtoT; Timer = Virt.Timer[ unique(“VirtualizedTimerC”) ]; }

65

VirtualizedTimerC

AlarmC

AlarmToTimerP

Alarm

Alarm

Timer

VirtualizeTimerP

Timer

SubTimer

Page 64: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-66- Georgia State UniversitySensorweb Research Laboratory

Step 3.5: Tidy Up the Wiring

66

VirtualizedTimerC VirtualizedTimerC VirtualizedTimerC

[0] [1] [2]

AlarmC

AlarmToTimerP

Alarm

Alarm

Timer

VirtualizeTimerP

Timer

SubTimer

Page 65: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-67- Georgia State UniversitySensorweb Research Laboratory

Step 3.5: Tidy Up the Wiring

module VirtualizeTimerP /* v. 2.5 */ { ... } implementation { enum { NUM_SLOTS = uniqueCount(“VirtualizedTimerC”); } uint16_t currentTime = 0; uint16_t nextTimeToFire[NUM_SLOTS]; uint16_t intervals[NUM_SLOTS];

event void SubTimer.fired() { uint8_t i; for(i = 0; i < NUM_SLOTS; i++) { ...

67

VirtualizedTimerC

AlarmC

AlarmToTimerP

Alarm

Alarm

Timer

VirtualizeTimerP

Timer

SubTimer

Page 66: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-68- Georgia State UniversitySensorweb Research Laboratory

Step 4: Transform the Timer’s Frequency

generic module TransformTimerP(uint16_t multiplier) {

uses interface Timer as SubTimer; provides interface Timer; } implementation { event void SubTimer.fired() { signal Timer.fired(); }

command void Timer.startPeriodic(uint16_t interval) { call SubTimer.startPeriodic(interval * multiplier); } }

68

TransformTimerP(2)

Timer

SubTimer

TransformTimerP(32)

Timer

SubTimer

Virtualized

TimerC

Virtualized

TimerC

TimerVirtualize

dTimerC

Virtualized

TimerC

TimerVirtualize

dTimerC

Virtualized

TimerC

Timer

Page 67: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-69- Georgia State UniversitySensorweb Research Laboratory

Step 5: Add Type Safety

69

enum {T32Khz,T16Khz,…,TMilli,

};

typedef struct { bool unused;} T32Khz;

typedef struct { bool unused;} T16Khz;

typedef struct { bool unused;} TMilli;

Virtualized

TimerC

Virtualized

TimerC

Timer<T32Khz>Virtualize

dTimerC

Virtualized

TimerC

Virtualized

TimerC

Virtualized

TimerC

Timer<T32Khz>Timer<T32Khz>

interface Timer<frequency> /* v. 3 */ { event void fired(); command void startPeriodic(uint16_t interval); }

Page 68: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-70- Georgia State UniversitySensorweb Research Laboratory

Step 5: Add Type Safety

generic module TransformTimerP( typedef frequency, uint16_t multiplier) { uses interface Timer<T32Khz> as

SubTimer; provides interface Timer<frequency>; } implementation { event void SubTimer.fired() { signal Timer.fired(); }

command void Timer.startPeriodic(uint16_t

interval) { call SubTimer.startPeriodic(interval * multiplier); } }

70

Virtualized

TimerC

Virtualized

TimerC

Timer<T32Khz>Virtualize

dTimerC

Virtualized

TimerC

Timer<T32KHz>Virtualize

dTimerC

Virtualized

TimerC

Timer<T32Khz>

TransformTimerP(TMilli, 32)

Timer<TMilli>

SubTimer<T32Khz>

TransformTimerP(T16Khz, 2)

Timer<T16Khz>

SubTimer<T32Khz>

Page 69: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-71- Georgia State UniversitySensorweb Research Laboratory

The Good News This is just an example! It’s already been

implemented for you TimerMilliC component provides

Timer<TMilli> interface

71

Page 70: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-72- Georgia State UniversitySensorweb Research Laboratory

Outline Installing TinyOS and Building Your First App Hardware Primer Basic nesC Syntax Advanced nesC Syntax Network Communication Sensor Data Acquisition Debugging Tricks and Techniques

72

Page 71: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-73- Georgia State UniversitySensorweb Research Laboratory

Slight Diversion: App Bootstrapping

Each app has a “main” configuration which wires together the app’s constituent components

But how do these components start running? TinyOS includes a MainC component which

provides the Boot interface:

interface Boot { event void booted(); }

73

Page 72: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-74- Georgia State UniversitySensorweb Research Laboratory

Slight Diversion: App Bootstrapping

Create one module which initializes your application, then wire MainC’s Boot interface into it:

74

component MyAppC {}implementation { components MyAppP; components MainC; ... MyAppP.Boot -> MainC;}

module MyAppP { uses interface Boot;}implementation { event void Boot.booted() { // Initialize app here } ...}

Page 73: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-75- Georgia State UniversitySensorweb Research Laboratory

Slight Diversion #2: error_t Data Type

TinyOS defines a special error_t data type that describes several different error codes

Often given as return values to commands or event handlers

Commonly used values: SUCCESS (everything’s OK) FAIL (general error, deprecated) EBUSY (subsystem is busy with another request, retry

later) ERETRY (something weird happened, retry later)

Others defined in $TOSROOT/types/TinyError.h

75

Page 74: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-76- Georgia State UniversitySensorweb Research Laboratory

Message Addressing Each node has a unique 16-bit address

(am_addr_t) specified by the make commandmake install.[address] platform

Two special address constants: TOS_BCAST_ADDR (0xFFFF) is reserved for broadcast

traffic TOS_NODE_ID always refers to the node’s own address

Each message also has an 8-bit Active Message ID (am_id_t) analogous to TCP ports Determines how host should handle received packets,

not which host receives it

76

Page 75: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-77- Georgia State UniversitySensorweb Research Laboratory

TinyOS Active Messages

message_t structure defined in $TOSROOT/tos/types/message.h

Each platform defines platform-specific header, footer, and metadata fields for the message_t

Applications can store up to TOSH_DATA_LENGTH bytes payload in the data field (28 by default)

77

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;

Header Payload (TOSH_DATA_LENGTH) Footer Metadata

Page 76: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-78- Georgia State UniversitySensorweb Research Laboratory

Split-Phase Operation Many networking commands take a long time

(ms) for underlying hardware operations to complete -- blocking would be bad

TinyOS makes these long-lived operations split-phase Application issues start...() command that returns

immediately An event is signaled when it’s actually done

78

interface SplitControl { command error_t start(); event void startDone(error_t error);

command error_t stop(); event void stopDone(error_t error); }

Error code here indicates whether TinyOS could start processing request

Error code here indicates whether TinyOS could start processing request

Error code here indicates whether TinyOS could complete processing request

Error code here indicates whether TinyOS could complete processing request

Page 77: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-79- Georgia State UniversitySensorweb Research Laboratory

Active Messaging Interfaces

interface AMSend { command error_t send(am_addr_t addr, message_t *

msg, uint8_t len); command error_t cancel(message_t * msg); event void sendDone(message_t * msg, error_t error); command uint8_t maxPayloadLength(); command void* getPayload(message_t * msg, uint8_t

len);}

interface Receive { event message_t* receive(message_t * msg, void * payload, uint8_t len);}

79

Page 78: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-80- Georgia State UniversitySensorweb Research Laboratory

interface Packet { command void clear(message_t * msg);

command void* getPayload(message_t * msg, uint8_t len);

command uint8_t payloadLength(message_t * msg); command void setPayLoadLength(message_t * msg, uint8_t len);

command uint8_t maxPayloadLength();}

Other Networking Interfaces

80

Page 79: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-81- Georgia State UniversitySensorweb Research Laboratory

interface AMPacket { command am_addr_t address(); command am_group_t localGroup();

command am_addr_t destination(message_t* amsg); command am_addr_t source(message_t* amsg); command am_group_t group(message_t* amsg); command bool isForMe(message_t* amsg);

command am_id_t type(message_t* amsg);}

Other Networking Interfaces

81

Page 80: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-82- Georgia State UniversitySensorweb Research Laboratory

Active Messaging

Application

Message Buffer Ownership

Transmission: AM gains ownership of the buffer until sendDone(...) is signaled

Reception: Application’s event handler gains ownership of the buffer, but it must return a free buffer for the next message

82

msgmsg

Page 81: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-83- Georgia State UniversitySensorweb Research Laboratory

Network Types Radio standards like 802.15.4 mean that you

could have communication among different types of motes with different CPUs

nesC defines network types (nx_uint16_t, nx_int8_t, etc.) that transparently deal with endian issues for you

nesC also defines an nx_struct analogous to C structs

83

typedef struct { uint16_t field1; bool field2;} bad_message_t;// Can have endianness problems// if sent to a host with a// different architecture

typedef nx_struct { nx_uint16_t field1; nx_bool field2;} good_message_t;

// nesC will resolve endian// issues for you

Page 82: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-84- Georgia State UniversitySensorweb Research Laboratory

Sending a Message First create a .h file with an nx_struct defining

the message data format, and a unique active message ID (127–255)

84

enum { AM_SENSORREADING = 240,};

typedef nx_struct sensor_reading { nx_int16_t temperature; nx_uint8_t humidity;} sensor_reading_t;

Page 83: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-85- Georgia State UniversitySensorweb Research Laboratory

implementation { ... message_t output;

task void sendData() { sensor_reading_t * reading = (sensor_reading_t *)call Packet.getPayload(&output, sizeof(sensor_reading_t)); reading->temperature = lastTemperatureReading; reading->humidity = lastHumidityReading; ... }}

Sending a Message

Declare a message_t variable in your module to store the packet’s contents

Get the packet’s payload using the Packet interface; cast it to your message type; and store whatever you want to send

85

Page 84: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-86- Georgia State UniversitySensorweb Research Laboratory

Finally, use the AMSend interface to send the packet

task void sendData() { ...

if(call AMSend.send(AM_BROADCAST_ADDR, &output, sizeof(sensor_reading_t)) != SUCCESS) post sendData(); // Try to send the message, and reschedule the task if it // fails (e.g., the radio is busy)}

Sending a Message

86

Page 85: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-87- Georgia State UniversitySensorweb Research Laboratory

event void AMSend.sendDone(message_t * msg, error_t err) { if(err == SUCCESS) { // Prepare next packet if needed } else { post sendTask(); // Resend on failure }}

Sending a Message The AM subsystem will signal

AMSend.sendDone() when the packet has been completely processed, successfully or not

87

Page 86: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-88- Georgia State UniversitySensorweb Research Laboratory

implementation { ... event message_t * Receive.receive(message_t * msg, void * payload, uint8_t len) { am_addr_t from = call AMPacket.source(msg); sensor_reading_t data = (sensor_reading_t *)payload; ... return msg; }}

Receiving a Message When messages with the correct AM ID are

received, the Receive interface fires the receive() event

88

Page 87: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-89- Georgia State UniversitySensorweb Research Laboratory

components new AMSenderC(AM_SENSORREADING);components new AMReceiveC(AM_SENSORREADING);

MyAppP.AMSender -> AMSenderC;// AMSenderC provides AMSend interfaceMyAppP.Receive -> AMReceiveC;// AMReceiverC provides Receive interfaceMyAppP.Packet -> AMSenderC;MyAppP.AMPacket -> AMSenderC;// AMSenderC and AMReceiveC provide Packet and AMPacket// interfaces (pick one or the other)

Networking Components Note that we didn’t mention the packet’s AM ID anywhere

in the code That’s because TinyOS includes generic components to

manage the AM ID for you when you send/receive:

89

Page 88: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-90- Georgia State UniversitySensorweb Research Laboratory

Networking Components Before you can send/receive, you need to turn

the radio on ActiveMessageC component provides a

SplitControl interface to control the radio’s power state

90

components ActiveMessageC;MyAppP.RadioPowerControl -> ActiveMessageC;

Page 89: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-91- Georgia State UniversitySensorweb Research Laboratory

What About Multi-Hop? Until recently, TinyOS did not include a general-

purpose, point-to-point multi-hop routing library

Two special-purpose algorithms instead: Collection Tree Protocol (CTP) Dissemination

Experimental TYMO point-to-point routing library added to TinyOS 2.1 (http://docs.tinyos.net/index.php/Tymo)

blip: work-in-progress IPv6 stack(http://smote.cs.berkeley.edu:8000/tracenv/wiki/blip)

91

Page 90: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-92- Georgia State UniversitySensorweb Research Laboratory

Collection Tree Protocol (CTP)

92

Page 91: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-93- Georgia State UniversitySensorweb Research Laboratory

Dissemination

93

Page 92: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-94- Georgia State UniversitySensorweb Research Laboratory

For More Information CTP & Dissemination APIs are beyond the scope

of this talk

For more information, see: TinyOS Tutorial 12: Network Protocols

(http://docs.tinyos.net/index.php/Network_Protocols)

TEP 123: Collection Tree Protocol (http://www.tinyos.net/tinyos-2.x/doc/html/tep123.html)

TEP 118: Dissemination (http://www.tinyos.net/tinyos-2.x/doc/html/tep118.html)

94

Page 93: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-95- Georgia State UniversitySensorweb Research Laboratory

Sending Data to a PC TinyOS apps can also send or receive data over

the serial/USB connection to an attached PC The SerialActiveMessageC component provides

an Active Messaging interface to the serial port:

components SerialActiveMessageC;MyAppP.SerialAMSend -> SerialActiveMessageC.Send[AM_SENSORREADING];MyAppP.SerialReceive -> SerialActiveMessageC.Receive[AM_SENSORREADING];// SerialActiveMessageC provides parameterized AMSend and// Receive interfacesMyAppP.SerialPowerControl -> SerialActiveMessageC;

95

Page 94: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-96- Georgia State UniversitySensorweb Research Laboratory

Displaying Received Data Java application: net.tinyos.tools.Listen To specify which mote to read from, use the

command-line parameter-comm serial@[port]:[platform]

96

header payload

Page 95: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-97- Georgia State UniversitySensorweb Research Laboratory

Disseminating Received Data Java application:

net.tinyos.sf.SerialForwarder Other PCs on the network can connect to the

Serial Forwarder to access the sensor data

97

Page 96: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-98- Georgia State UniversitySensorweb Research Laboratory

Java PC-to-Mote Interface MIG: Message Interface Generator

Generates a Java class representing a TOS message Usage:

mig java -java-classname=[classname] [header.h][message-name] –o [classname].java

TinyOS Java SDK includes a net.tinyos.message.MoteIF class for interfacing with motes using Java See $TOSROOT/apps/tests/TestSerial/TestSerial.java

for an example

98

Page 97: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-100- Georgia State UniversitySensorweb Research Laboratory

Outline Installing TinyOS and Building Your First App Hardware Primer Basic nesC Syntax Advanced nesC Syntax Network Communication Sensor Data Acquisition Debugging Tricks and Techniques

100

Page 98: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-101- Georgia State UniversitySensorweb Research Laboratory

Obtaining Sensor Data Each sensor has components that provides one

or more split-phase Read interfaces

interface Read<val_t> { command error_t read(); event void readDone(error_t result, val_t val);}

Some sensor drivers provide additional interfaces for bulk (ReadStream) or low-latency (ReadNow) readings See TEPs 101 and 114 for details

101

Page 99: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-102- Georgia State UniversitySensorweb Research Laboratory

module MyAppP { uses interface Read<uint16_t> as AccelX; ...}implementation { ... task void readAccelX() { if(call AccelX.read() != SUCCESS) post readAccelX(); } event void AccelX.readDone(error_t err, uint16_t reading) { if(err != SUCCESS) { post readAccelX(); return; } // Handle reading here } ...}

configuration MyAppC {}implementation { components MyAppP; components new AccelXC(); // X axis accelerator component // defined by mts300 sensorboard MyAppP.AccelX -> AccelXC; …}

Sensor Reading Example

102

Page 100: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-103- Georgia State UniversitySensorweb Research Laboratory

Sensor Components Sensor components are stored in:

$TOSROOT/tos/platform/[platform] (for standard sensors) Note that telosb “extends” telosa, so look in both

directories if you’re using a TelosB or Tmote Sky mote! $TOSROOT/tos/sensorboard/[sensorboard] (for add-on

sensor boards) Additional sensor board components may be

available from TinyOS CVS in tinyos-2.x-contrib Unfortunately, some third-party sensor board drivers

have yet to be ported from TinyOS 1.x to 2.x

103

Page 101: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-104- Georgia State UniversitySensorweb Research Laboratory

External Sensors

104

interface HplMsp430GeneralIO { command void makeInput(); command void makeOutput();

command bool get();

command void clr(); command void set(); command void toggle();}

Page 102: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-105- Georgia State UniversitySensorweb Research Laboratory

External Sensors Digital I/O: wire directly into HplMsp430GeneralIOC

componentcomponent HplMsp430GeneralIOC { provides interface HplMsp430GeneralIO as ADC0; provides interface HplMsp430GeneralIO as ADC1; provides interface HplMsp430GeneralIO as ADC2; provides interface HplMsp430GeneralIO as ADC3; provides interface HplMsp430GeneralIO as ADC4; provides interface HplMsp430GeneralIO as ADC5; provides interface HplMsp430GeneralIO as ADC6; provides interface HplMsp430GeneralIO as ADC7; provides interface HplMsp430GeneralIO as DAC0; provides interface HplMsp430GeneralIO as DAC1; ...}

Analog I/O: read TEP 101 (Analog-to-Digital Converters)

105

Page 103: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-106- Georgia State UniversitySensorweb Research Laboratory

Outline Installing TinyOS and Building Your First App Hardware Primer Basic nesC Syntax Advanced nesC Syntax Network Communication Sensor Data Acquisition Debugging Tricks and Techniques

106

Page 104: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-107- Georgia State UniversitySensorweb Research Laboratory

Hard-Learned Lessons Be sure to check return values -- don’t assume

SUCCESS! At the very least, set an LED when something goes

wrong

The TinyOS toolchain doesn’t always warn about overflowing integers

Not all the Tmote Sky motes have sensors

107

uint8_t i;for(i = 0; i < 1000; i++) { ... }// This loop will never terminate

Page 105: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-108- Georgia State UniversitySensorweb Research Laboratory

msp430-gcc Alignment Bugs If you’re unlucky, msp430-gcc will crash with

internal errors like these:

It’s almost always because of alignmentbugs (msp430-gcc doesn’t always likeit when fields straddle 16-bit boundaries)

108

/opt/tinyos-2.x/tos/interfaces/TaskBasic.nc: In function `SchedulerBasicP$TaskBasic$runTask':/opt/tinyos-2.x/tos/interfaces/TaskBasic.nc:64: unable to generate reloads for:(call_insn 732 3343 733 (set (reg:SI 15 r15) (call (mem:HI (symbol_ref:HI ("AsyncQueueC$1$Queue$dequeue")) [0 S2 A8]) (const_int 0 [0x0]))) 14 {*call_value_insn} (nil) (nil) (nil))/opt/tinyos-2.x/tos/interfaces/TaskBasic.nc:64: Internal compiler error infind_reloads, at reload.c:3590

typedef nx_struct my_msg{

nx_uint8_t field1;

nx_uint16_t field2;} my_msg_t;

nx_uint8_t pad;

Page 106: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-109- Georgia State UniversitySensorweb Research Laboratory

802.15.4 Radio Channels

The CC2420 chip on the Tmote and MicaZ supports 802.15.4 channels 11 - 26

802.15.4 uses 2.4 GHz spectrum This can lead to interference between motes and with

802.11, Bluetooth, and all sorts of other things

109

Page 107: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-110- Georgia State UniversitySensorweb Research Laboratory

802.15.4 Radio Channels If you’re seeing weird network behavior, set your

CC2420 channel to something else: Command-line: CC2420_CHANNEL=xx make ... Makefile: PFLAGS = -DCC2420_DEF_CHANNEL=xx

110

Page 108: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-111- Georgia State UniversitySensorweb Research Laboratory

LEDs The easiest way to display runtime information

is to use the mote’s LEDs:interface Leds { async command void led0On(); async command void led0Off(); async command void led0Toggle(); async command void led1On(); async command void led1Off(); async command void led1Toggle(); async command void led2On(); async command void led2Off(); async command void led2Toggle(); async command uint8_t get(); async command void set(uint8_t val); }

Provided by the components LedsC and NoLedsC

111

Page 109: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-112- Georgia State UniversitySensorweb Research Laboratory

printf() You can use printf() to print debugging

messages to the serial port The messages are sent in a printf_msg structure

($TOSROOT/tos/lib/printf/printf.h) Though printf() ships with TinyOS, its

components are not automatically located by the included Makefile stubs

To force make to locate the printf()-related components, add the following line to your Makefile:CFLAGS += -I$(TOSDIR)/lib/printf

Note: adding this flag automatically turns on SerialActiveMessageC subsystem

112

Page 110: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-113- Georgia State UniversitySensorweb Research Laboratory

BaseStation The BaseStation app in

$TOSROOT/apps/BaseStation will sniff all wireless traffic and forward it to the serial port

Extremely helpful for figuring out what data is being sent!

113

Page 111: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-115- Georgia State UniversitySensorweb Research Laboratory

TOSSIM Special target: make micaz sim Compiles application to native C code for your

own machine, which can be loaded into Python or C++ simulator (“TOSSIM”)

Upshot: use your favorite Python or C++ debugger to trace through your app’s execution

Unfortunately somewhat complex and beyond the scope of this talk; see TinyOS Tutorial 11 http://docs.tinyos.net/index.php/TOSSIM

115

Page 112: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-116- Georgia State UniversitySensorweb Research Laboratory

Avrora + MSPsim Avrora: cycle-accurate Mica2 and MicaZ

emulatorhttp://compilers.cs.ucla.edu/avrora/

MSPsim: MSP430 (TelosB) emulatorhttp://www.sics.se/project/mspsim/

Profile and benchmark apps, monitor packet transmissions, or interface with gdb

Slower than TOSSIM, but highly accurate

116

Page 113: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-117- Georgia State UniversitySensorweb Research Laboratory

Safe TinyOS New in TinyOS 2.1: make [platform] safe Augments code to enforce pointer and type

safety at runtime (bad casts, out-of-bounds array accesses, NULL pointer dereferences, etc.)

When safety violations detected, LEDs blink error code

http://www.cs.utah.edu/~coop/safetinyos/

Nathan Cooprider, Will Archer, Eric Eide, David Gay, and John Regehr, “Efficient Memory Safety for TinyOS,” Proceedings of 5th ACM Conference on Embedded Networked Sensor Systems (SenSys 2007), 2007.

117

Page 114: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-118- Georgia State UniversitySensorweb Research Laboratory

Advanced Programming TipsAdvanced Programming Tips

Page 115: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-119- Georgia State UniversitySensorweb Research Laboratory

Three Most Useful Tips in TinyOS TinyOS core is a while loop of task execution, but

interrupt can interrupt it. async event comes from hardware interruption. atomic keyword presents interruption, good or bad

All *.nc files will be pre-processed to a single app.c file.

If there is any keyword or nesC mechanism that you do not understand, look into app.c! Nothing can be hidden in app.c.

If you are not sure which components or libraries you are using, or how the system architecture looks like, run “make [platform] docs” and then look at docs/[platform]/index.html. Here [platform] could be telosb, micaz, imote2, etc.

Page 116: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-120- Georgia State UniversitySensorweb Research Laboratory

Tips in TinyOS programmingTips in TinyOS programmingRefer:

http://sensorweb.cs.gsu.edu/wiki/index.php/Tips

Handle flow between layers Stack overflow traps Post task related traps

Let task self-post itself, need a taskBusy flag Atomic efficiency concerns Sanity checks

Check whether array index out of bound or not, before you use array[ind]. Check whether post task return SUCCESS or FAIL ……

Page 117: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-121- Georgia State UniversitySensorweb Research Laboratory

How to handle send flow between How to handle send flow between layerslayers

M

U1

L

time

send

send

sendDone

sendDone

U2

send sendDone

Simple way in TinyOS programming

Busy = TRUE Busy = FALSE Busy = TRUE Busy = FALSE

U – Up layer

M – Middle layer

B – Low layer

Page 118: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-122- Georgia State UniversitySensorweb Research Laboratory

M

Busy = TRUE Busy = FALSE

How to handle send flow between How to handle send flow between layerslayers

But U1 and U2 are independent, they do not know each other. The later send by U2 will fail because M is busy. This is too bad if the

data rate is high.

U1

send sendDone

U2

send

The send request from

U2 will fail

L

send sendDone

time

Page 119: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-123- Georgia State UniversitySensorweb Research Laboratory

How to handle send flow between How to handle send flow between layerslayers

M

Ltime

send

send sendDone

send sDone

Need a queue to buffer packets from up layers. However, make sure the queue size >= sum(queue size(Ui))

Busy = TRUE Busy = FALSE

U1 U2 U3 U1 U3 U1 U3 U3 U2 U1 U3

send sDone sDone sDonesend send

retry

sDone

time

Notice: sendDone order might be different than send orderU – Up layer

M – Middle layer

B – Low layer

sDone - sendDone

Page 120: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-124- Georgia State UniversitySensorweb Research Laboratory

How to handle send flow between How to handle send flow between layerslayers

M

L

send

send(U1)

sDone(U1)

send sDone

Notice: sendDone order might be different than send order, either due to prioritization at M, or there are multiple L layer component

(e.g., radio and UART) who has different speed

Busy = TRUE Busy = FALSE

U1 U2 U3 U1 U3 U1 U3 U3 U1 U2 U3

send sDone sDone sDonesend send

retry

sDone

time

U – Up layer

M – Middle layer

B – Low layer

sDone - sendDone

send(U3)

send(U2)

send(U1)

sDone(U3)

sDone(U1)

sDone(U2)

sDone(U3)

send(U3)

prioritization

U2 sent to UART which is slower

Page 121: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-125- Georgia State UniversitySensorweb Research Laboratory

How to handle receive flow between How to handle receive flow between layerslayers

M

U1

L

time

receive

receive

receive

U2

If it takes some time to process it, copy it to buffer bool, and return original pointer immediately; otherwise, process it and return original pointer after that. If not, it will slow down the radio.

U – Up layer

M – Middle layer

B – Low layer

receive

return original pointer as soon as possible

Page 122: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-126- Georgia State UniversitySensorweb Research Laboratory

Stack overflow trapsStack overflow traps Phenomenon: nodes software works at beginning,

dies after run a while The tips to avoid:

Do not define too many/big local variables inside a function. If big, define it as component variables

Module test { // interfaces}Implementation {

void func() { int array[MAX_LEN]; TOSMsg msg; ……………. }

}

Module test { // interfaces}Implementation { int array[MAX_LEN]; TOSMsg msg;

void func() { ……………. }

}// if those variables are used by other functions as well, be careful with race conditions!

Page 123: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-127- Georgia State UniversitySensorweb Research Laboratory

Stack Overflow ProblemStack Overflow Problem Do not use big data structure variables as a function parameter. Use pointer if necessary.

By the way, the following usage is wrong, not even mentioning the above subtle problems:

void func (TOSMsg msg, ……)

void func (TOSMsgPtr msg, ……)

typedef struct{int data;int index;

} FooData;

FooData* foo(int ind){ FooData element; element.data = rand(); element.index = ind; return &element; }

Page 124: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-128- Georgia State UniversitySensorweb Research Laboratory

Make atomic section and async function routines as small as possible

func(….) { atomic {

X = y; temp = X; }//End atomic if(temp > 100) {

// Assume the following does not need to be atomic …… }

}

func(….) { atomic {

X = y; if(X > 100) { // Assume the following does not need to be atomic …… }

} //End atomic}

Page 125: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-129- Georgia State UniversitySensorweb Research Laboratory

Potentially Nasty BugsPotentially Nasty Bugs

Page 126: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-130- Georgia State UniversitySensorweb Research Laboratory

Page 127: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-131- Georgia State UniversitySensorweb Research Laboratory

Page 128: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-132- Georgia State UniversitySensorweb Research Laboratory

Page 129: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-133- Georgia State UniversitySensorweb Research Laboratory

Page 130: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-134- Georgia State UniversitySensorweb Research Laboratory

Page 131: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-135- Georgia State UniversitySensorweb Research Laboratory

Page 132: -1- Georgia State UniversitySensorweb Research Laboratory Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos

-136- Georgia State UniversitySensorweb Research Laboratory

Three Most Useful Tips in TinyOS TinyOS core is a while loop of task execution, but

interrupt can interrupt it. async event comes from hardware interruption. atomic keyword presents interruption, good or bad

All *.nc files will be pre-processed to a single app.c file.

If there is any keyword or nesC mechanism that you do not understand, look into app.c! Nothing can be hidden in app.c.

If you are not sure which components or libraries you are using, or how the system architecture looks like, run “make [platform] docs” and then look at docs/[platform]/index.html. Here [platform] could be telosb, micaz, imote2, etc.