TinyOS handout - Sensorweb Research Laboratory

Download Report

Transcript TinyOS handout - Sensorweb Research Laboratory

TinyOS Tutorial
Dr. WenZhan Song
Professor, Computer Science
Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos tutorial slides.
Sensorweb Research Laboratory
-1-
Georgia State University
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
Sensorweb Research Laboratory
-2-
Georgia State University
TinyOS Installation

TinyOS Documentation Wiki: http://docs.tinyos.net/


Pre-compiled .rpm and .deb packages for Fedora and
Ubuntu Linux users


Various installation options listed under “Getting started”
section
Ubuntu users: be sure to remove brltty package
All necessary drivers already included with Linux kernel
3
Sensorweb Research Laboratory
-3-
Georgia State University
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
Sensorweb Research Laboratory
-4-
Georgia State University
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
Sensorweb Research Laboratory
-5-
Georgia State University
TinyOS Directory Structure

/opt/tinyos-2.1.0 ($TOSROOT)


apps
support




make
sdk
tools
tos
8
Sensorweb Research Laboratory
-8-
Georgia State University
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 needed
include $(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
Sensorweb Research Laboratory
-9-
Georgia State University
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
Sensorweb Research Laboratory
-10-
Georgia State University
Build Stages
Preprocess .nc to .c, then compile .c
to binary
Set AM address and node ID in
binary
Program mote
11
Sensorweb Research Laboratory
-11-
Georgia State University
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/tinyosprogramming.pdf
TinyOS Tutorials: short HTML lessons on using parts of
TinyOS (sensors, radio, TOSSIM,
etc.):http://docs.tinyos.net/index.php/TinyOS_Tutorials
12
Sensorweb Research Laboratory
-12-
Georgia State University
How to Get Help


nesdoc: annotated API for all interfaces and
components in TinyOS:
http://docs.tinyos.net/index.php/Source_Code_Docume
ntation
TinyOS Enhancement Protocols (TEP): formal
documentation for TinyOS features:
http://docs.tinyos.net/index.php/TEPs
13
Sensorweb Research Laboratory
-13-
Georgia State University
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
Sensorweb Research Laboratory
-14-
Georgia State University
MicaZ

CC2420 - IEEE 802.15.4 Radio



ATmega 128L microcontroller


250kbps
2.4 GHz
4kB RAM, 128kB program flash, 512 kB storage flash,
Need a separate programming board and debug board
15
Sensorweb Research Laboratory
-15-
Georgia State University
Tmote Sky (aka TelosB)

CC2420 - IEEE 802.15.4 Radio



TI MSP430 microcontroller



250kbps
2.4GHz
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
Sensorweb Research Laboratory
-16-
Georgia State University
TelosW = Telos + Wake-on

CC1101 – wake-on radio



TI MSP430 microcontroller





16MHz, 16 MIPS, 10kB RAM
Integrated antenna & USB interface
Low power utilization


1.2kbps - 500kbps
868-915 MHz
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/Te
losW/images/TELOSW.pdf
Sensorweb Research Laboratory
-17-
Georgia State University
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
Sensorweb Research Laboratory
-18-
Georgia State University
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
zZz
handlePacket
readSensor
sendResponse
19
Sensorweb Research Laboratory
-19-
Georgia State University
TinyOS Execution Model
Sensorweb Research Laboratory
-20-
Georgia State University
TinyOS Memory Model

STATIC memory allocation!



Global variables


No heap (malloc)
No function pointers
Available on a per-frame basis
Local variables


Saved on the stack
Declared within a method
Sensorweb Research Laboratory
-21-
Georgia State University
TinyOS Thread Model

Tasks:





Events:






Time flexible
Longer background processing jobs
Atomic with respect to other tasks (single threaded)
Preempted by 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.
Sensorweb Research Laboratory
-22-
Georgia State University
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
Sensorweb Research Laboratory
-23-
Georgia State University
TinyOS Component Model
event command
startDone()
start()
provides
SplitControl
NetworkHandlerP
uses Receive
provides
Receive
provides
SplitControl
ActiveMessageC
NetworkHandlerC
24
Sensorweb Research Laboratory
-24-
Georgia State University
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:
Sensorweb Research Laboratory
-25-
Georgia State University
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
Sensorweb Research Laboratory
-26-
Georgia State University
Components != Objects
AppLogicP
NetworkHandlerP
AnotherHandlerP
ActiveMessageC
ActiveMessageC
ActiveMessageC
✗
✓
27
Sensorweb Research Laboratory
-27-
Georgia State University
Interfaces


List of exposed events and commands
Like ordinary C function declarations, except with
event or command in front
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);
}
28
Sensorweb Research Laboratory
-28-
Georgia State University
Modules


Modules provide the implementation of one or more
interfaces
They may consume (use) other interfaces to do so
module ExampleModuleP {
provides interface SplitControl;
uses interface Receive;
uses interface Receive as OtherReceive;
}
implementation {
...
}

“Rename” interfaces with the as keyword -- required if
you are using/providing more than one of the same
29
interface!
Sensorweb Research Laboratory
-29-
Georgia State University
Modules

implementation block may contain:

Variable declarations

Helper functions

Tasks

Event handlers

Command implementations
30
Sensorweb Research Laboratory
-30-
Georgia State University
Modules: Variables and Functions
Placed inside implementation block exactly like standard
C declarations:

...
implementation {
uint8_t localVariable;
void increment(uint8_t amount);
...
void increment(uint8_t amount) {
localVariable += amount;
}
}
31
Sensorweb Research Laboratory
-31-
Georgia State University
Modules: Tasks

Look a lot like functions, except:


Prefixed with task
Can’t return anything or accept any parameters
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!
}
}
32
Sensorweb Research Laboratory
-32-
Georgia State University
Modules: Task Scheduling

Tasks are scheduled using the post keyword
error_t retval;
retval = post handlePacket();
// retval == SUCCESS if task was scheduled, or E_FAIL if not

TinyOS guarantees that scheduled task will eventually run

Default scheduling policy: FIFO
task1
task2
task1
task3
task1
...
✗
✓
33
Sensorweb Research Laboratory
-33-
Georgia State University
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.
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
}
}
34
Sensorweb Research Laboratory
-34-
Georgia State University
Modules: Commands and Events

Commands are invoked using the call keyword:
call Leds.led0Toggle();
// Invoke the led0Toggle command on the Leds interface

Event handlers are invoked using the signal keyword:
signal SplitControl.startDone();
// Invoke the startDone event handler on the SplitControl interface
35
Sensorweb Research Laboratory
-35-
Georgia State University
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:
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;
}
...
}
36
Sensorweb Research Laboratory
-36-
Georgia State University
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:
implementation {
async event void Alarm.fired() {
// Handle hardware alarm interrupt
}
}
37
Sensorweb Research Laboratory
-37-
Georgia State University
Reminder: Race Conditions

Use atomic blocks to avoid race conditions
implementation {
uint8_t sharedCounter;
async event void Alarm.fired() {
sharedCounter++;
}
event void Receive.receive(...) {
...
atomic {
Interrupts are disabled here -- use sparingly
sharedCounter++;
and make as short as practical
}
}
}
38
Sensorweb Research Laboratory
-38-
Georgia State University
Reminder: Race Conditions


Tasks are always synchronous
If timing isn’t crucial, defer code to tasks to avoid race
conditions
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!
}
39
Sensorweb Research Laboratory
-39-
Georgia State University
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:


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
}
40
Sensorweb Research Laboratory
-40-
Georgia State University
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
Sensorweb Research Laboratory
-41-
Georgia State University
Configurations
List interfaces that the
component imports &
exports
configuration NetworkHandlerC {
provides interface SplitControl; Give comma-separated
list(s) of constituent
}
components
implementation {
components NetworkHandlerP as NH,
ActiveMessageP as AM;
//NH.Receive -> AM.Receive;
//NH.SplitControl = SplitControl;
Wire two components’
NH.Receive -> AM;
interfaces together using
an arrow pointing from
NH = SplitControl;
Wire external
user= to provider
interfaces using
}
42
Sensorweb Research Laboratory
-42-
Georgia State University
Configuration Wires

A configuration can bind an interface user to a
provider using -> or <


Bounce responsibilities using =



User.interface -> Provider.interface
Provider.interface <- User.interface
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
Sensorweb Research Laboratory
-43-
Georgia State University
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
Sensorweb Research Laboratory
-44-
Georgia State University
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
Sensorweb Research Laboratory
-45-
Georgia State University
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
Sensorweb Research Laboratory
-46-
Georgia State University
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
Sensorweb Research Laboratory
-47-
Georgia State University
Fan-In: No Big Deal
AppLogicP
NetworkHandlerP
AnotherHandlerP
uses Receive
uses Receive
uses Receive
Many-to-one calls work
like you’d expect ...
provides Receive
RadioP
48
Sensorweb Research Laboratory
-48-
Georgia State University
Fan-Out: Bad Things Happen
return &buffer1;
return &buffer2;
return &buffer3;
AppLogicP
NetworkHandlerP
AnotherHandlerP
uses Receive
uses Receive
uses Receive
… but what about oneto-many calls?
provides Receive
RadioP
49
Sensorweb Research Laboratory
-49-
Georgia State University
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
Sensorweb Research Laboratory
-50-
Georgia State University
Parameterized Wiring

Consider the following way to avoid fanout:
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(...);
...
}
...
}
Sensorweb Research Laboratory
-51-
AppLogicP
Network
HandlerP
Another
HandlerP
uses Receive
uses Receive
uses Receive
RadioP
51
Georgia State University
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
Sensorweb Research Laboratory
-52-
Georgia State University
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
Sensorweb Research Laboratory
-53-
Georgia State University
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
Sensorweb Research Laboratory
-54-
Georgia State University
uniqueCount()

What if your component needs to store different state
for each unique parameter?
uniqueCount(X)
module RadioP {
expands to # of times
...
unique(X) appears in
}
the application
implementation {
int16_t state[uniqueCount(“RadioP”)];
...
}
55
Sensorweb Research Laboratory
-55-
Georgia State University
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
Sensorweb Research Laboratory
-56-
Georgia State University
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
Sensorweb Research Laboratory
-57-
Georgia State University
Generic Components


But wait ... didn’t I say earlier that components aren’t objects?
nesC internally creates a complete second copy of the
component
AppLogicP
NetworkHandlerP
HashTableP$0
HashTableP$1
58
Sensorweb Research Laboratory
-58-
Georgia State University
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
Sensorweb Research Laboratory
-59-
Georgia State University
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
Sensorweb Research Laboratory
-60-
Georgia State University
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();
}
Timer
async event void Alarm.fired() {
post timerTask();
}
AlarmToTimerP
Alarm
}
Alarm
AlarmC
61
Sensorweb Research Laboratory
-61-
Georgia State University
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]();
}
}
Timer
VirtualizeTimerP
SubTimer
Timer
default event void Timer.fired[uint8_t id]() {
// Do nothing
}
}
AlarmToTimerP
Alarm
Alarm
AlarmC
62
Sensorweb Research Laboratory
-62-
Georgia State University
Step 3: Reprogram the Timer
interface Timer /* v. 2 */ {
event void fired();
command void startPeriodic(uint16_t interval);
}
Timer
VirtualizeTimerP
SubTimer
Timer
AlarmToTimerP
Alarm
Alarm
AlarmC
63
Sensorweb Research Laboratory
-63-
Georgia State University
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;
}
...
Timer
VirtualizeTimerP
SubTimer
Timer
AlarmToTimerP
Alarm
Alarm
AlarmC
}
64
Sensorweb Research Laboratory
-64-
Georgia State University
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”)
];
}
VirtualizedTimerC
Timer
VirtualizeTimerP
SubTimer
Timer
AlarmToTimerP
Alarm
Alarm
AlarmC
65
Sensorweb Research Laboratory
-65-
Georgia State University
Step 3.5: Tidy Up the Wiring
[0]
[1]
VirtualizedTimerC
[2]
VirtualizedTimerC
VirtualizedTimerC
Timer
VirtualizeTimerP
SubTimer
Timer
AlarmToTimerP
Alarm
Alarm
AlarmC
66
Sensorweb Research Laboratory
-66-
Georgia State University
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];
VirtualizedTimerC
Timer
VirtualizeTimerP
SubTimer
Timer
AlarmToTimerP
event void SubTimer.fired() {
uint8_t i;
for(i = 0; i < NUM_SLOTS; i++) {
...
Alarm
Alarm
AlarmC
67
Sensorweb Research Laboratory
-67-
Georgia State University
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);
}
Timer
Timer
Transform
TimerP(2)
Transform
TimerP(32)
SubTimer
SubTimer
}
Timer
Timer
Timer
Virtualized Virtualized Virtualized
TimerC
TimerC
TimerC
68
Sensorweb Research Laboratory
-68-
Georgia State University
Step 5: Add Type Safety
interface Timer<frequency> /* v. 3 */ {
event void fired();
command void startPeriodic(uint16_t interval);
}
typedef struct {
bool unused;
} T32Khz;
enum {
T32Khz,
T16Khz,
…,
TMilli,
};
typedef struct {
bool unused;
} T16Khz;
typedef struct {
bool unused;
} TMilli;
Timer<T32Khz>
Timer<T32Khz>
Timer<T32Khz>
Virtualized Virtualized Virtualized
TimerC
TimerC
TimerC
69
Sensorweb Research Laboratory
-69-
Georgia State University
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);
}
}
Timer<TMilli>
Timer<T16Khz>
TransformTimer
P(TMilli, 32)
TransformTimer
P(T16Khz, 2)
SubTimer<T32Khz>
SubTimer<T32Khz>
Timer<T32Khz>
Timer<T32KHz>
Timer<T32Khz>
Virtualized Virtualized Virtualized
TimerC
TimerC
TimerC
70
Sensorweb Research Laboratory
-70-
Georgia State University
The Good News


This is just an example! It’s already been implemented
for you
TimerMilliC component provides Timer<TMilli>
interface
71
Sensorweb Research Laboratory
-71-
Georgia State University
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
Sensorweb Research Laboratory
-72-
Georgia State University
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
Sensorweb Research Laboratory
-73-
Georgia State University
Slight Diversion: App Bootstrapping

Create one module which initializes your application,
then wire MainC’s Boot interface into it:
component MyAppC {
}
implementation {
components MyAppP;
components MainC;
...
MyAppP.Boot -> MainC;
}
module MyAppP {
uses interface Boot;
}
implementation {
event void Boot.booted() {
// Initialize app here
}
...
}
74
Sensorweb Research Laboratory
-74-
Georgia State University
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
Sensorweb Research Laboratory
-75-
Georgia State University
Message Addressing


Each node has a unique 16-bit address (am_addr_t)
specified by the make command
make 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
Sensorweb Research Laboratory
-76-
Georgia State University
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)
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
77
Sensorweb Research Laboratory
-77-
Georgia State University
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
Error code here indicates
whether TinyOS couldError
startcode here indicates
processing request whether TinyOS could
interface SplitControl {
complete processing request
command error_t start();
event void startDone(error_t error);
command error_t stop();
event void stopDone(error_t error);
}
78
Sensorweb Research Laboratory
-78-
Georgia State University
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
Sensorweb Research Laboratory
-79-
Georgia State University
Other Networking Interfaces
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();
}
80
Sensorweb Research Laboratory
-80-
Georgia State University
Other Networking Interfaces
interface AMPacket {
command am_addr_t address();
command am_group_t localGroup();
command
command
command
command
am_addr_t destination(message_t* amsg);
am_addr_t source(message_t* amsg);
am_group_t group(message_t* amsg);
bool isForMe(message_t* amsg);
command am_id_t type(message_t* amsg);
}
81
Sensorweb Research Laboratory
-81-
Georgia State University
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
Application
Active Messaging
msg
82
Sensorweb Research Laboratory
-82-
Georgia State University
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
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
83
Sensorweb Research Laboratory
-83-
Georgia State University
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)
enum {
AM_SENSORREADING = 240,
};
typedef nx_struct sensor_reading {
nx_int16_t temperature;
nx_uint8_t humidity;
} sensor_reading_t;
84
Sensorweb Research Laboratory
-84-
Georgia State University
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


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;
...
}
}
85
Sensorweb Research Laboratory
-85-
Georgia State University
Sending a Message

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)
}
86
Sensorweb Research Laboratory
-86-
Georgia State University
Sending a Message

The AM subsystem will signal AMSend.sendDone()
when the packet has been completely processed,
successfully or not
event void AMSend.sendDone(message_t * msg, error_t err) {
if(err == SUCCESS) {
// Prepare next packet if needed
}
else {
post sendTask();
// Resend on failure
}
}
87
Sensorweb Research Laboratory
-87-
Georgia State University
Receiving a Message

When messages with the correct AM ID are received,
the Receive interface fires the receive() event
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;
}
}
88
Sensorweb Research Laboratory
-88-
Georgia State University
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:
components new AMSenderC(AM_SENSORREADING);
components new AMReceiveC(AM_SENSORREADING);
MyAppP.AMSender -> AMSenderC;
// AMSenderC provides AMSend interface
MyAppP.Receive -> AMReceiveC;
// AMReceiverC provides Receive interface
MyAppP.Packet -> AMSenderC;
MyAppP.AMPacket -> AMSenderC;
// AMSenderC and AMReceiveC provide Packet and AMPacket
// interfaces (pick one or the other)
89
Sensorweb Research Laboratory
-89-
Georgia State University
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
components ActiveMessageC;
MyAppP.RadioPowerControl -> ActiveMessageC;
90
Sensorweb Research Laboratory
-90-
Georgia State University
What About Multi-Hop?


Until recently, TinyOS did not include a generalpurpose, 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
Sensorweb Research Laboratory
-91-
Georgia State University
Collection Tree Protocol (CTP)
92
Sensorweb Research Laboratory
-92-
Georgia State University
Dissemination
93
Sensorweb Research Laboratory
-93-
Georgia State University
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
Sensorweb Research Laboratory
-94-
Georgia State University
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 interfaces
MyAppP.SerialPowerControl -> SerialActiveMessageC;
95
Sensorweb Research Laboratory
-95-
Georgia State University
Displaying Received Data


Java application: net.tinyos.tools.Listen
To specify which mote to read from, use the commandline parameter
-comm serial@[port]:[platform]
header
payload
96
Sensorweb Research Laboratory
-96-
Georgia State University
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
Sensorweb Research Laboratory
-97-
Georgia State University
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
Sensorweb Research Laboratory
-98-
Georgia State University
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
Sensorweb Research Laboratory
-100-
Georgia State University
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
Sensorweb Research Laboratory
-101-
Georgia State University
Sensor Reading Example
module MyAppP {
uses interface Read<uint16_t> as AccelX;
...
}
configuration MyAppC {
implementation {
}
...
implementation {
task void readAccelX() {
components MyAppP;
if(call AccelX.read() != SUCCESS)
components new AccelXC();
post readAccelX();
// X axis accelerator component
}
// defined by mts300 sensorboard
event void AccelX.readDone(error_t err,
MyAppP.AccelX -> AccelXC;
uint16_t reading) {
…
if(err != SUCCESS) {
}
post readAccelX();
return;
}
// Handle reading here
}
...
}
102
Sensorweb Research Laboratory
-102-
Georgia State University
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
Sensorweb Research Laboratory
-103-
Georgia State University
External Sensors
interface HplMsp430GeneralIO {
command void makeInput();
command void makeOutput();
command bool get();
command void clr();
command void set();
command void toggle();
}
104
Sensorweb Research Laboratory
-104-
Georgia State University
External Sensors

Digital I/O: wire directly into HplMsp430GeneralIOC
component
component HplMsp430GeneralIOC {
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
provides interface HplMsp430GeneralIO
...
}

as
as
as
as
as
as
as
as
as
as
ADC0;
ADC1;
ADC2;
ADC3;
ADC4;
ADC5;
ADC6;
ADC7;
DAC0;
DAC1;
Analog I/O: read TEP 101 (Analog-to-Digital Converters)
105
Sensorweb Research Laboratory
-105-
Georgia State University
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
Sensorweb Research Laboratory
-106-
Georgia State University
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
uint8_t i;
for(i = 0; i < 1000; i++) { ... }
// This loop will never terminate

Not all the Tmote Sky motes have sensors
107
Sensorweb Research Laboratory
-107-
Georgia State University
msp430-gcc Alignment Bugs

If you’re unlucky, msp430-gcc will crash with internal
errors like these:
/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 in
find_reloads, at reload.c:3590

It’s almost always because of alignment
bugs (msp430-gcc doesn’t always like
it when fields straddle 16-bit boundaries)
typedef nx_struct my_msg
{
nx_uint8_t field1;
nx_uint8_t pad;
nx_uint16_t field2;
} my_msg_t;
108
Sensorweb Research Laboratory
-108-
Georgia State University
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
Sensorweb Research Laboratory
-109-
Georgia State University
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
Sensorweb Research Laboratory
-110-
Georgia State University
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
Sensorweb Research Laboratory
-111-
Georgia State University
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
Sensorweb Research Laboratory
-112-
Georgia State University
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
Sensorweb Research Laboratory
-113-
Georgia State University
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
Sensorweb Research Laboratory
-115-
Georgia State University
Avrora + MSPsim

Avrora: cycle-accurate Mica2 and MicaZ emulator
http://compilers.cs.ucla.edu/avrora/

MSPsim: MSP430 (TelosB) emulator
http://www.sics.se/project/mspsim/


Profile and benchmark apps, monitor packet
transmissions, or interface with gdb
Slower than TOSSIM, but highly accurate
116
Sensorweb Research Laboratory
-116-
Georgia State University
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
Sensorweb Research Laboratory
-117-
Georgia State University
Advanced Programming Tips
Sensorweb Research Laboratory
-118-
Georgia State University
Three Most Useful Tips in TinyOS

TinyOS core is a while loop of task execution, but
interrupt can interrupt it.



All *.nc files will be pre-processed to a single app.c file.


async event comes from hardware interruption.
atomic keyword presents interruption, good or bad
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.
Sensorweb Research Laboratory
-119-
Georgia State University
Tips in TinyOS programming
Refer: 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
……
Sensorweb Research Laboratory
-120-
Georgia State University
How to handle send flow between layers
U – Up layer
M – Middle layer
U2
U1
B – Low layer
sendDone
send
Busy = TRUE
send
Busy = FALSE
Busy = TRUE
sendDone
Busy = FALSE
time
M
send
sendDone
L
Simple way in TinyOS programming
Sensorweb Research Laboratory
-121-
Georgia State University
How to handle send flow between layers
The send
request
from U2
will fail
U2
U1
send
sendDone
send
Busy = TRUE
time
Busy = FALSE
M
send
sendDone
L
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.
Sensorweb Research Laboratory
-122-
Georgia State University
How to handle send flow between layers
Notice: sendDone order might
be different than send order
U – Up layer
retry
M – Middle layer
B – Low layer
U1 U2 U3 U1 U3 U1 U3
U3 U2
U1 U3
sDone - sendDone
send send send
send
sDone sDone
send
Busy = TRUE
sDone sDone sDone
time
Busy = FALSE
M
send
sendDone
L
time
Need a queue to buffer packets from up layers. However, make
sure the queue size >= sum(queue size(Ui))
Sensorweb Research Laboratory
-123-
Georgia State University
How to handle send flow between layers
U – Up layer
retry
M – Middle layer
B – Low layer
sDone - sendDone
U1 U2 U3 U1 U3 U1 U3
send send send
send
sDone sDone
send
Busy = TRUE
U3 U1
U2 U3
sDone sDone sDone
time
Busy = FALSE
M
prioritization
send
(U1)
send send
(U3) (U2)
send
(U1)
sDone sDone send
(U1)
(U3) (U3)
L
sDone sDone sDone
(U3)
(U1) (U2)
U2 sent to UART
which is slower
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
Sensorweb Research Laboratory
-124-
Georgia State University
How to handle receive flow between layers
U – Up layer
M – Middle layer
U2
U1
B – Low layer
receive
receive
time
return original pointer as soon as possible
M
receive
receive
L
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.
Sensorweb Research Laboratory
-125-
Georgia State University
Stack 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 {
Module test {
// interfaces
}
Implementation {
void func() {
int
array[MAX_LEN];
TOSMsg msg;
…………….
}
}
Sensorweb Research Laboratory
int array[MAX_LEN];
TOSMsg msg;
void func() {
…………….
}
}
// if those variables are
used by other functions as
well, be careful with race
conditions!
-126-
Georgia State University
Stack Overflow Problem

Do not use big data structure variables as a function parameter. Use pointer if
necessary.
void func (TOSMsgPtr
msg, ……)
void func (TOSMsg msg,
……)

By the way, the following usage is wrong, not even mentioning the above subtle
problems:
typedef struct{
int data;
int index;
} FooData;
FooData* foo(int ind){
FooData element;
element.data = rand();
element.index = ind;
return &element;
}
Sensorweb Research Laboratory
-127-
Georgia State University
Make atomic section and async function routines
as small as possible
func(….) {
}
func(….) {
}
atomic {
X = y;
if(X > 100) {
// Assume the following does not need to be atomic ……
}
} //End atomic
atomic {
X = y; temp = X;
}//End atomic
if(temp > 100) {
// Assume the following does not need to be atomic ……
}
Sensorweb Research Laboratory
-128-
Georgia State University
Potentially Nasty Bugs
Sensorweb Research Laboratory
-129-
Georgia State University
Sensorweb Research Laboratory
-130-
Georgia State University
Sensorweb Research Laboratory
-131-
Georgia State University
Sensorweb Research Laboratory
-132-
Georgia State University
Sensorweb Research Laboratory
-133-
Georgia State University
Sensorweb Research Laboratory
-134-
Georgia State University
Sensorweb Research Laboratory
-135-
Georgia State University
Three Most Useful Tips in TinyOS

TinyOS core is a while loop of task execution, but
interrupt can interrupt it.



All *.nc files will be pre-processed to a single app.c file.


async event comes from hardware interruption.
atomic keyword presents interruption, good or bad
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.
Sensorweb Research Laboratory
-136-
Georgia State University