-1- georgia state universitysensorweb research laboratory acknowledgement: thank greg hackmann at...
TRANSCRIPT
-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
-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
-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
-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
-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
-8- Georgia State UniversitySensorweb Research Laboratory
TinyOS Directory Structure /opt/tinyos-2.1.0 ($TOSROOT)
apps support
make sdk
tools tos
8
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-20- Georgia State UniversitySensorweb Research Laboratory
TinyOS Execution Model
-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
-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.
-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
-24- Georgia State UniversitySensorweb Research Laboratory
TinyOS Component Model
24
prov
ides
Split
Cont
rol
NetworkHandlerCNetworkHandlerC
NetworkHandlerP
uses Receivecommandstart()
eventstartDone()
ActiveMessageC
providesReceive
providesSplitControl
-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:
-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
-27- Georgia State UniversitySensorweb Research Laboratory
Components != Objects
27
ActiveMessageC ActiveMessageC
NetworkHandlerP AnotherHandlerPAppLogicP
✓✗ActiveMessageC
-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); }
-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
-30- Georgia State UniversitySensorweb Research Laboratory
Modules implementation block may contain:
Variable declarations Helper functions Tasks Event handlers Command implementations
30
-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; }}
-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! }}
-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
-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 }}
-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
-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; } ...}
-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 }}
-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
-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!
-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
-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
-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 =
-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
-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
-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
-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
-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
-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 ...
-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;
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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); }
-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>
-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
-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
-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
-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 } ...}
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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;
-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
-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
-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
-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
-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
-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;
-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
-92- Georgia State UniversitySensorweb Research Laboratory
Collection Tree Protocol (CTP)
92
-93- Georgia State UniversitySensorweb Research Laboratory
Dissemination
93
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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();}
-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
-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
-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
-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;
-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
-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
-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
-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
-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
-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
-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
-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
-118- Georgia State UniversitySensorweb Research Laboratory
Advanced Programming TipsAdvanced Programming Tips
-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.
-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 ……
-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
-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
-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
-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
-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
-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!
-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; }
-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}
-129- Georgia State UniversitySensorweb Research Laboratory
Potentially Nasty BugsPotentially Nasty Bugs
-130- Georgia State UniversitySensorweb Research Laboratory
-131- Georgia State UniversitySensorweb Research Laboratory
-132- Georgia State UniversitySensorweb Research Laboratory
-133- Georgia State UniversitySensorweb Research Laboratory
-134- Georgia State UniversitySensorweb Research Laboratory
-135- Georgia State UniversitySensorweb Research Laboratory
-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.