Tutorial
Tutorial
Tutorial
Mo
Sha
Fall
2012
Outline
Installing
TinyOS
and
Building
Your
First
App
Hardware
Primer
Basic
nesC
Syntax
Advanced
nesC
Syntax
Network
CommunicaAon
Sensor
Data
AcquisiAon
Debugging
Tricks
and
Techniques
2
TinyOS
Installation
TinyOS
Community
hHp://www.Anyos.net/
Various
installaAon
opAons
listed
under
“GePng
started”
secAon
3
TinyOS
Installation
(cont.)
4
TinyOS
Installation
(cont.)
5
TinyOS
Installation
(cont.)
Pre-‐compiled
.rpm
and
.deb
packages
for
Fedora
and
Ubuntu
Linux
users
Ubuntu
users:
be
sure
to
remove
brltty
package
Automa?c
installa?on
for
debian
systems
using
the
TinyOS
debian
repository
(Manual
install
TI
MSP430
Tools)
All
necessary
drivers
already
included
with
Linux
kernel
OS
X
unofficially
supported
but
works
well
Windows
installaAon
uses
Cygwin
to
emulate
Linux
so\ware
layer
Works
well
under
XP,
refuses
to
work
on
some
Vista/7
machines
(updaAng
Cygwin
a\er
the
installaAon
may
help)
Step
5b
(op?onal):
Post-‐install
fixes
in
Windows/Cygwin
environment
“Running
a
XubunTOS
Virtual
Machine
Image
in
VMware
Player”
6
Post-‐install
+ixes
in
Windows/Cygwin
TinyOS
Installation
(cont.)
OS
X
unofficially
supported
but
works
well
8
TinyOS
Installation
Problems
If
you
run
tos-‐check-‐env
and
it
says:
-‐>
WARNING:
CLASSPATH
environment
variable
doesn't
exist.
then
add:
export
CLASSPATH=/opt/tinyos-‐2.1.1/support/sdk/java/
tinyos.jar:.
to
your
.bash_profile
or
.bash_aliases
file
9
TinyOS
Installation
Problems
If
you
try
to
run
make
micaz
sim
and
it
gives
you
a
long
error
message
starAng
with:
...:
error:
inttypes.h:
No
such
file
or
directory
then
you
need
to
install
the
C
library/header
files
for
your
own
architecture
On
Ubuntu/Debian,
run
apt-‐get
install
build-‐essential
10
TinyOS
Directory
Structure
/opt/Anyos-‐2.1.1
($TOSROOT)
apps
support
• make
• sdk
tools
tos
11
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)
13
Useful
commands
motelist
See
the
list
of
motes
connecting
with
pc
make
telosb
Compile
your
code
make
telosb
reinstall,1
Program
the
mote
make
telosb
install,1
Compile
your
code
Program
the
mote
make
docs
telosb
Generate
docs
14
Build
Stages
Program mote
15
Example
under
Windows
C:\cygwin\bin
http://students.cec.wustl.edu/~ms31/520S/
16
“Homework”
Install
TinyOS
2.1.1
and
build
Blink
(Not
graded,
but
a
good
idea
to
make
sure
you
have
everything
up
and
running)
17
How
to
Get
Help
TinyOS
DocumentaAon
Wiki:
hHp://docs.Anyos.net
TinyOS
Programming
Manual:
139-‐page
PDF
intro
to
nesC
and
TinyOS
2.x:
hHp://www.Anyos.net/Anyos-‐2.x/doc/pdf/Anyos-‐
programming.pdf
TinyOS
Tutorials:
short
HTML
lessons
on
using
parts
of
TinyOS
(sensors,
radio,
TOSSIM,
etc.):
hHp://docs.Anyos.net/Anywiki/index.php/TinyOS_Tutorials
18
How
to
Get
Help
nesdoc:
annotated
API
for
all
interfaces
and
components
in
TinyOS:
hHp://docs.Anyos.net/Anywiki/index.php/
Source_Code_DocumentaAon
TinyOS
Enhancement
Protocols
(TEP):
formal
documentaAon
for
TinyOS
features:
hHp://docs.Anyos.net/Anywiki/index.php/TEPs
20
Outline
Installing
TinyOS
and
Building
Your
First
App
Hardware
Primer
Basic
nesC
Syntax
Advanced
nesC
Syntax
Network
CommunicaAon
Sensor
Data
AcquisiAon
Debugging
Tricks
and
Techniques
21
Available
Hardware
Motes,
sensor
boards,
and
gateways
Most
up
to
date
list
here:
hHp://wsn.cse.wustl.edu/index.php/
Equipment_for_course_projects
Hardware
is
in
Mobile
CompuAng
Laboratory
(Jolley
519)
22
Tmote
Sky
(aka
TelosB)
IEEE
802.15.4
Radio
250kbps
TI
MSP430
microcontroller
16MHz,
16
MIPS,
10kB
RAM
Integrated
antenna
&
USB
interface
Low
power
uAlizaAon
1.8mA/5.1µA
vs.
Mica
2’s
8mA/15µA
QuanAty
w/o
on-‐board
sensors:
6
QuanAty
w/temperature,
light,
and
humidity
sensors:
20
QuanAty
w/SBT80
sensor
board:
4
23
MICA2
Mote
(MPR400CB)
128KB
InstrucAon
EEPROM
2
AA
4KB
Data
EEPROM
512KB
Chipcon
Atmel
External
CC1000
radio,
ATmega128L
μP
7.3827MHz
(8
MIPS)
UART
2
Flash
38K
or
19K
baud,
Manchester,
Memory
315,
433,
or
SPI
bus
900MHz
ADC
0-‐7
UART
1
I2C
Bus
3
LEDs
To
Sensors,
JTAG,
and/or
Quantity: 56 51
pin
I/O
Connector
Programming
Board
24
MPR2400
MICAz
Same
as
Mica2
except
with
IEEE
802.15.4
radio
2.4GHz
250kbps
QuanAty:
7
25
Programming
Board
(MIB510)
Mote JTAG
MICA2Dot interface
Serial interface
to laptop MICA2 interface
ISPJTAG
Block data
to laptop
5V Power
Quantity: 3 Reset
26
MTS310CA
Sensor
Board
51 pin MICA2
4.6KHz Interface
Speaker Tone Detector
Light and
2 Axis Temperature
Accelerometer
Microphone
Magnetometer
Quantity: 3
27
NSLU2
Network
Storage
Link
(“Slug”)
266MHz
Xscale
CPU,
32MB
SDRAM,
8MB
flash,
1x
Ethernet
port
Wired
power
No
built-‐in
radio,
but
2x
USB
2.0
ports
for
add-‐on
802.11/Bluetooth/mote
interface
Can
be
easily
converted
to
an
embedded
Linux
box
with
third-‐party
firmware
Our
testbed
uses
the
OpenWrt
distribuAon
(hHp://openwrt.org)
QuanAty:
15
28
MCS410
Cricket
Mote
A
Mica2
mote
with
ultrasound
Rx/Tx
Indoor
localizaAon
10.5m
range
Distance
accuracy:
1
cm
(<
3.5m
dist)
2cm
(>3.5m
dist)
Mote
finds
distance,
PC
finds
locaAon
hHp://cricket.csail.mit.edu/
QuanAty:
9
29
Outline
Installing
TinyOS
and
Building
Your
First
App
Hardware
Primer
Basic
nesC
Syntax
Advanced
nesC
Syntax
Network
CommunicaAon
Sensor
Data
AcquisiAon
Debugging
Tricks
and
Techniques
30
TinyOS
Execution
Model
To
save
energy,
node
stays
asleep
most
of
the
Ame
ComputaAon
is
kicked
off
by
hardware
interrupts
Interrupts
may
schedule
tasks
to
be
executed
at
some
Ame
in
the
future
TinyOS
scheduler
conAnues
running
unAl
all
tasks
are
cleared,
then
sends
mote
back
to
sleep
zZz
31
TinyOS
Component
Model
Upper Layer
ActiveMessageC
32
TinyOS
Component
Model
Upper Layer
ActiveMessageC
33
TinyOS
Component
Model
Upper Layer
34
Components
!=
Objects
36
Modules
Modules
provide
the
implementaAon
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
interface!
37
Modules
implementation
block
may
contain:
Variable
declaraAons
Helper
funcAons
Tasks
Event
handlers
Command
implementaAons
38
Modules:
Variables
and
Functions
Placed
inside
implementation
block
exactly
like
standard
C
declaraAons:
...
implementation
{
uint8_t
localVariable;
void
increment(uint8_t
amount);
...
void
increment(uint8_t
amount)
{
localVariable
+=
amount;
}
}
39
Modules:
Tasks
Look
a
lot
like
funcAons,
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!
}
}
40
Modules:
Task
Scheduling
Tasks
are
scheduled
using
the
post
keyword
post
handlePacket();
task1
task2
task1
task3
task1
...
✓
✗
41
Modules:
Commands
and
Events
Commands
and
events
also
look
like
C
funcAons,
except:
they
start
with
the
keyword
command
or
event
the
“funcAon”
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
}
}
42
Modules:
Commands
and
Events
Commands
are
invoked
using
the
call
keyword:
call
Leds.led0Toggle();
//
Invoke
the
led0Toggle
command
on
the
Leds
interface
signal
SplitControl.startDone();
//
Invoke
the
startDone
event
handler
on
the
SplitControl
interface
43
Modules:
Commands
and
Events
A
command,
event
handler,
or
funcAon
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;
}
...
}
44
Con]igurations
configuration
NetworkHandlerC
{
provides
interface
SplitControl;
}
implementation
{
components
NetworkHandlerP
as
NH,
ActiveMessageP
as
AM;
//
NH.Receive
-‐>
AM.Receive;
//
SplitControl
=
NH.SplitControl;
NH.Receive
-‐>
AM;
SplitControl
=
NH;
}
45
Reminder:
Race
Conditions
Use
atomic
blocks
to
avoid
race
condiAons
implementation
{
uint8_t
sharedCounter;
async
event
void
Alarm.fired()
{
...
sharedCounter++;
}
event
void
Receive.receive(...)
{
...
sharedCounter++;
}
}
46
Reminder:
Race
Conditions
Use
atomic
blocks
to
avoid
race
condiAons
implementation
{
uint8_t
sharedCounter;
async
event
void
Alarm.fired()
{
atomic
{
sharedCounter++;
Interrupts
are
disabled
here
-‐-‐
use
sparingly
and
make
as
short
as
pracAcal
}
}
event
void
Receive.receive(...)
{
...
sharedCounter++;
}
}
47
Reminder:
Race
Conditions
Tasks
are
always
synchronous
If
Aming
isn’t
crucial,
defer
code
to
tasks
to
avoid
race
condiAons
implementation
{
uint8_t
sharedCounter;
task
void
incrementCounter()
{
sharedCounter++;
}
async
event
void
Alarm.fired()
{
Task
is
scheduled
post
incrementCounter();
immediately,
but
}
executes
later
event
void
Receive.receive(...)
{
...
sharedCounter++;
}
}
48
nesC
and
Race
Conditions
nesC
can
catch
some,
but
not
all,
potenAal
race
condiAons
If
you’re
absolutely
sure
that
there’s
no
race
condiAon
(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);
Race
condiAon
is
}
impossible;
events
are
mutually
async
event
void
Alarm2.fired()
{
exclusive
sharedCounter-‐-‐;
call
Alarm1.start(200);
}
}
49
TOSThreads
New
in
TinyOS
2.1:
the
TOSThreads
threading
library
Threads
add
a
third
execuAon
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
synchronizaAon
primiAves
(mutex,
semaphore,
etc.)
and
blocking
wrappers
around
non-‐
blocking
I/O
Described
in
TOSThreads
Tutorial
(hHp://docs.Anyos.net/
index.php/TOSThreads_Tutorial)
or
TEP
134
50
Example-‐Blink
(opt\tinyos-‐2.x\apps\Blink)
Three
files:
1. Makefile
2. BlinkC.nc
(module
)
3. BlinkAppC.nc
(configuration
)
51
Make+ile
COMPONENT=BlinkAppC
include
$(MAKERULES)
52
BlinkC.nc
#include "Timer.h" implementation
{
module BlinkC { event void Boot.booted()
uses interface Timer<TMilli> as Timer0; {
uses interface Timer<TMilli> as Timer1; call Timer0.startPeriodic( 250 );
uses interface Timer<TMilli> as Timer2; call Timer1.startPeriodic( 500 );
uses interface Leds; call Timer2.startPeriodic( 1000 );
uses interface Boot; }
} event void Timer0.fired()
{
call Leds.led0Toggle();
}
event void Timer1.fired() {..}
event void Timer2.fired() {…}
}
53
BlinkAppC.nc
configuration BlinkAppC
{
}
implementation
{
components MainC, BlinkC, LedsC;
components new TimerMilliC() as Timer0;
components new TimerMilliC() as Timer1;
components new TimerMilliC() as Timer2;
55
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
56
Interfaces
with
Arguments
CreaAng
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);
}
57
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>;
}
58
Fan-‐In:
No
Big
Deal
RadioP
59
Fan-‐Out:
Bad
Things
Happen
return
&buffer1;
return
&buffer2;
return
&buffer3;
RadioP
60
Fan-‐Out:
What
Bad
Things
Happen?
If
different
return
values
come
back,
nesC
may
not
be
able
to
make
sense
of
the
contradicAon
and
will
arbitrarily
pick
one
61
Parameterized
Wiring
Consider
the
following
way
to
avoid
fan-‐out:
module
RadioP
{
provides
interface
Receive
as
Receive0;
provides
interface
Receive
as
Receive1;
Network
Another
provides
interface
Receive
as
Receive2;
AppLogicP
HandlerP
HandlerP
uses
interface
LowLevelRadio;
...
uses
Receive
uses
Receive
uses
Receive
}
implementation
{
event
void
LowLevelRadio.packetReceived(
uint8_t
*
rawPacket)
{
...
uint8_t
type
=
decodeType(rawPacket);
if(type
==
0)
signal
Receive0.receive(...);
else
if(type
==
1)
RadioP
signal
Receive1.receive(...);
...
}
...
}
62
Parameterized
Wiring
The
idea
works
in
concept,
but
isn’t
maintainable
in
pracAce
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(...);
}
...
}
63
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
64
Unique
Parameters
In
most
cases,
it’s
unreasonable
to
expect
the
user
to
count
the
number
of
Ames
(s)he
is
using
the
interface
and
wire
accordingly
nesC
can
automaAcally
generate
a
unique
parameter
for
you
using
the
unique()
macro:
AppLogicP
-‐>
RadioP.Receive[unique(“RadioP”)];
//
unique(“RadioP”)
expands
to
0
NetworkHandlerP
-‐>
RadioP.Receive[unique(“RadioP”)];
//
unique(“RadioP”)
expands
to
1
...
}
66
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(...);
}
68
Slight
Diversion:
App
Bootstrapping
Each
app
has
a
“main”
configuraAon
which
wires
together
the
app’s
consAtuent
components
But
how
do
these
components
start
running?
TinyOS
includes
a
MainC
component
which
provides
the
Boot
interface:
interface
Boot
{
event
void
booted();
}
69
Slight
Diversion:
App
Bootstrapping
Create
one
module
which
iniAalizes
your
applicaAon,
then
wire
MainC’s
Boot
interface
into
it:
module
MyAppP
{
configuration
MyAppC
{
uses
interface
Boot;
}
}
implementation
{
implementation
{
components
MyAppP;
event
void
Boot.booted()
{
components
MainC;
//
Initialize
app
here
...
}
MyAppP.Boot
-‐>
MainC;
...
}
}
70
Slight
Diversion
#2:
error_t
Data
Type
TinyOS
defines
a
special
error_t
data
type
that
describes
several
different
error
codes
O\en
given
as
return
values
to
commands
or
event
handlers
Commonly
used
values:
SUCCESS
(everything’s
OK)
FAIL
(general
error)
EBUSY
(subsystem
is
busy
with
another
request,
retry
later)
ERETRY
(something
weird
happened,
retry
later)
Others
defined
in
$TOSROOT/types/TinyError.h
71
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
AcAve
Message
ID
(am_id_t)
analogous
to
TCP
ports
Determines
how
host
should
handle
received
packets,
not
which
host
receives
it
72
TinyOS
Active
Messages
message_t
structure
defined
in
$TOSROOT/tos/types/
message.h
Each
plaiorm
defines
plaiorm-‐specific
header,
footer,
and
metadata
fields
for
the
message_t
ApplicaAons
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
73
Split-‐Phase
Operation
Many
networking
commands
take
a
long
Ame
(ms)
for
underlying
hardware
operaAons
to
complete
-‐-‐
blocking
would
be
bad
TinyOS
makes
these
long-‐lived
operaAons
split-‐phase
ApplicaAon
issues
start...()
Error
command
that
returns
immediately
ode
here
indicates
Error
code
here
indicates
An
event
is
signaled
wwhether
hen
it’s
aTctually
inyOS
could
start
done
processing
request
whether
TinyOS
could
interface
SplitControl
{
complete
processing
request
command
error_t
start();
event
void
startDone(error_t
error);
75
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();
}
76
Other
Networking
Interfaces
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);
}
77
Other
Networking
Interfaces
interface
PacketAcknowledgements
{
async
command
error_t
requestAck(message_t*
msg);
async
command
error_t
noAck(message_t*
msg);
async
command
bool
wasAcked(message_t*
msg);
}
78
Message
Buffer
Ownership
Transmission:
Radio
driver
gains
ownership
of
the
buffer
unAl
sendDone(...)
is
signaled
RecepAon:
ApplicaAon’s
event
handler
gains
ownership
of
the
buffer,
but
it
must
return
a
free
buffer
for
the
next
message
ApplicaAon
79
Network
Types
Radio
standards
like
802.15.4
mean
that
you
could
have
communicaAon
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
{
typedef
nx_struct
{
uint16_t
field1;
nx_uint16_t
field1;
bool
field2;
nx_bool
field2;
}
bad_message_t;
}
good_message_t;
//
Can
have
endianness
problems
//
if
sent
to
a
host
with
a
//
nesC
will
resolve
endian
//
different
architecture
//
issues
for
you
80
Sending
a
Message
First
create
a
.h
file
with
an
nx_struct
defining
the
message
data
format,
and
a
unique
acAve
message
ID
(127–255)
enum
{
AM_SENSORREADING
=
240,
};
typedef
nx_struct
sensor_reading
{
nx_int16_t
temperature;
nx_uint8_t
humidity;
}
sensor_reading_t;
81
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
your
data
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;
...
}
}
82
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)
}
83
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
}
}
84
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;
}
}
85
Networking
Components
Note
that
we
didn’t
menAon
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:
86
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;
87
What
About
Multi-‐Hop?
UnAl
recently,
TinyOS
did
not
include
a
general-‐purpose,
point-‐to-‐point
mulA-‐hop
rouAng
library
Two
special-‐purpose
algorithms
instead:
CollecAon
Tree
Protocol
(CTP)
DisseminaAon
88
Collection
Tree
Protocol
(CTP)
Basic
OperaAon
89
configuration
MyCtpAppC
{
module
AppLogicP
{
}
uses
interface
StdControl
as
implementation
{
RoutingControl;
components
AppLogicP;
uses
interface
RootControl;
components
CollectionC;
...
...
}
implementation
{
...
MyAppP.RoutingControl
-‐>
CollectionC;
MyAppP.RootControl
-‐>
CollectionC;
event
void
RadioControl.startDone(
...
error_t
err)
{
}
...
if(TOS_NODE_ID
==
100)
call
RootControl.setRoot();
call
RoutingControl.start();
}
...
}
90
configuration
MyCtpAppC
{
module
AppLogicP
{
}
...
implementation
{
uses
interface
Send;
components
AppLogicP;
uses
interface
Receive;
components
CollectionC;
uses
interface
Packet;
...
...
}
MyAppP.Send
-‐>
CollectionC.
implementation
{
Send[MY_MSG_ID];
...
MyAppP.Receive
-‐>
CollectionC.
Receive[MY_MSG_ID];
task
void
sendPacket()
{
MyAppP.Packet
-‐>
CollectionC;
result_t
err
=
call
Send.send(
...
&msg,
sizeof(MyMsg));
}
...
}
event
message_t
*
Receive.receive(
message_t
*
msg,
void
*
payload,
uint8_t
len)
{
//
Only
signaled
on
root
node
...
}
}
91
Collection
Tree
Protocol
(CTP)
To
link
into
your
app,
include
these
lines
in
your
Makefile:
CFLAGS
+=
-‐I$(TOSDIR)/lib/net
CFLAGS
+=
-‐I$(TOSDIR)/lib/net/4bitle
CFLAGS
+=
-‐I$(TOSDIR)/lib/net/ctp
92
Dissemination
Basic
OperaAon
93
For
More
Information
TinyOS
Tutorial
12:
Network
Protocols
(hHp://docs.Anyos.net/index.php/Network_Protocols)
TEP
123:
CollecAon
Tree
Protocol
(hHp://www.Anyos.net/
Anyos-‐2.x/doc/html/tep123.html)
TEP
118:
DisseminaAon
(hHp://www.Anyos.net/
Anyos-‐2.x/doc/html/tep118.html)
94
Sending
Data
to
a
PC
TinyOS
apps
can
also
send
or
receive
data
over
the
serial/
USB
connecAon
to
an
aHached
PC
The
SerialActiveMessageC
component
provides
an
AcAve
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
Interfacing
With
Motes
TinyOS
includes
a
Java-‐based
SerialForwarder
uAlity
that
implements
PC
side
of
TEP
113
java
net.tinyos.sf.SerialForwarder
-‐comm
serial@[port]:[speed]
[speed]
may
be
a
specific
baud
rate
or
a
plaiorm
name
(e.g.,
telosb)
Listens
on
TCP
port
and
sends/receives
TinyOS
messages
from
local
or
remote
applicaAons
96
Interfacing
With
Motes
Java
SDK
connects
to
SerialForwarder
and
converts
TinyOS
messages
to/from
naAve
Java
objects
mig
applicaAon
auto-‐generates
these
classes
from
your
app’s
header
files
mig
java
-‐java-‐classname=[classname]
[header.h]
[message-‐name]
–o
[classname].java
SomeMessage
OtherMessage
.
MoteIF
.
.
97
SDK
Support
for
Other
Languages
C/C++
C
reimplementaAon
of
SerialForwarder
(sf)
and
a
few
test
apps
found
in
$TOSROOT/support/sdk/c/sf
Building
sf
also
builds
libmote.a
for
accessing
the
motes
in
your
own
code
See
sfsource.h
and
serialsource.h
to
get
started
98
SDK
Support
for
Other
Languages
Python
Python
classes
in
$TOSROOT/support/sdk/python
closely
mirror
Java
SDK
Not
completely
stand-‐alone;
Python
MoteIF
implementaAon
talks
to
Java
or
C
SerialForwarder
See
tinyos/message/MoteIF.py
to
get
started
C#
mig
can
generate
C#
classes
to
parse/generate
raw
TinyOS
packets
But
it’s
up
to
the
user
to
actually
get
those
packets
from
the
serial
port
or
SerialForwarder
99
CC2420Config
Interface
interface
CC2420Config
{
command
uint8_t
getChannel();
command
void
setChannel(uint8_t
channel);
async
command
uint16_t
getShortAddr();
command
void
setShortAddr(uint16_t
address);
async
command
uint16_t
getPanAddr();
command
void
setPanAddr(uint16_t
address);
command
error_t
sync();
event
void
syncDone(error_t
error);
}
101
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);
}
102
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
}
MyAppP.AccelX
-‐>
AccelXC;
event
void
AccelX.readDone(error_t
err,
uint16_t
reading)
{
...
if(err
!=
SUCCESS)
{
}
post
readAccelX();
return;
}
//
Handle
reading
here
}
...
}
103
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)
104
External
Sensors
interface
HplMsp430GeneralIO
{
command
void
makeInput();
command
void
makeOutput();
command
bool
get();
command
void
clr();
command
void
set();
command
void
toggle();
}
105
External
Sensors
Digital
I/O:
wire
directly
into
HplMsp430GeneralIOC
component
component
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;
...
}
106
Outline
Installing
TinyOS
and
Building
Your
First
App
Hardware
Primer
Basic
nesC
Syntax
Advanced
nesC
Syntax
Network
CommunicaAon
Sensor
Data
AcquisiAon
Debugging
Tricks
and
Techniques
107
Hard-‐Learned
Lessons
Be
sure
to
check
return
values
-‐-‐
don’t
assume
SUCCESS!
At
the
very
least,
set
an
LED
when
something
goes
wrong
108
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
typedef
nx_struct
my_msg
It’s
almost
always
because
of
alignment
{
bugs
(msp430-‐gcc
doesn’t
always
like
nx_uint8_t
field1;
nx_uint8_t
pad;
it
when
fields
straddle
16-‐bit
boundaries)
nx_uint16_t
field2;
}
my_msg_t;
109
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
110
802.15.4
Radio
Channels
111
802.15.4
Radio
Channels
If
you’re
seeing
weird
network
behavior,
set
your
CC2420
channel
to
something
else:
Defaults
to
26
Command-‐line:
CC2420_CHANNEL=xx
make
...
Makefile:
PFLAGS
=
-‐DCC2420_DEF_CHANNEL=xx
112
Active
Message
Groups
To
avoid
address
collision
with
other
applicaAons
or
networks,
you
can
also
change
the
AM
group:
Defaults
to
0x22
Makefile:
DEFAULT_LOCAL_GROUP=xx
(any
16-‐bit
value)
On
802.15.4
compliant
chips,
maps
to
PAN
ID
113
LEDs
The
easiest
way
to
display
runAme
informaAon
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);
}
115
printf()
To
enable
the
printf
library,
add
the
following
line
to
your
Makefile:
CFLAGS
+=
-‐I$(TOSDIR)/lib/printf
Note:
this
automaAcally
turns
on
SerialActiveMessageC
subsystem
116
BaseStation
The
BaseStation
app
in
$TOSROOT/apps/
BaseStation
will
sniff
all
wireless
traffic
and
forward
it
to
the
serial
port
Listen
tool
prints
hex-‐dump
of
packets
to
console:
java
net.tinyos.tools.Listen
[-‐comm
serial@[port]:[speed]]
Extremely helpful for figuring out what data is being sent!
117
gdb
The
CPU
on
the
Tmote
Sky
motes
supports
interacAve
debugging
using
gdb
Set
breakpoints,
inspect
the
contents
of
variables,
etc.
The
catch:
it
needs
a
special
cable
and
modified
motes
-‐-‐
and
they
don’t
make
the
motes
anymore
We
have
5
motes
and
one
cable
118
TOSSIM
make
micaz
sim
compiles
applicaAon
to
naAve
C
code
for
your
own
machine,
which
can
be
loaded
into
Python
or
C++
simulator
(“TOSSIM”)
Good
way
to
rapidly
test
applicaAon
logic,
at
the
cost
of
some
realism
e.g.,
does
not
emulate
sensing
and
does
not
reproduce
Aming
of
real
microcontrollers
119
TOSSIM
Con]iguration:
Topology
List
of
links
in
the
network
and
associated
gain
(signal
strength
in
dBm)
0
1
-‐90.80
Several
sources:
1
0
-‐95.95
Real
measurements
0
2
-‐97.48
Samples
included
in
TinyOS
($TOSDIR/lib/ 2
0
-‐102.10
tossim/topologies)
0
3
-‐111.33
3
0
-‐115.49
Generate
one
based
on
various
parameters
0
4
-‐104.82
(hHp://www.Anyos.net/
4 0
-‐110.09
Anyos-‐2.x/doc/html/tutorial/usc-‐
...
topologies.html)
(from
15-‐15-‐sparse-‐mica2-‐grid.txt)
120
TOSSIM
Con]iguration:
Noise
Trace
Trace
of
ambient
noise
readings
in
dBm
Must
contain
at
least
100
entries;
more
is
beHer,
but
RAM
consumpAon
-‐39
-‐98
increases
with
larger
traces
-‐98
Two
sources:
-‐98
Real
measurements
-‐99
-‐98
Samples
included
in
TinyOS
($TOSDIR/lib/
-‐94
tossim/noise)
-‐98
...
(from
meyer-‐heavy.txt)
121
Other
TOSSIM
Features
Log
debug
messages
to
console
or
to
a
file
Inject
packets
into
network
Debugging
support
Python
TOSSIM:
read
variables’
contents
C++
TOSSIM:
use
gdb
TOSSIM
Live
fork:
TOSSIM
acts
as
SerialForwarder,
send/
receive
serial
packets
to
simulated
motes
hHp://docs.Anyos.net/index.php/TOSSIM_Live
See
TinyOS
Tutorial
11
for
more
details
122
Avrora
+
MSPsim
Avrora:
cycle-‐accurate
Mica2
and
MicaZ
emulator
hHp://compilers.cs.ucla.edu/avrora/
MSPsim:
MSP430
(TelosB)
emulator
hHp://www.sics.se/project/mspsim/
123
Safe
TinyOS
New
in
TinyOS
2.1:
make
[platform]
safe
Augments
code
to
enforce
pointer
and
type
safety
at
runAme
(bad
casts,
out-‐of-‐bounds
array
accesses,
NULL
pointer
dereferences,
etc.)
When
safety
violaAons
detected,
LEDs
blink
error
code
hHp://www.cs.utah.edu/~coop/safeAnyos/
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.
124
Demo:
Putting
it
All
Together
125
Demo
Example
Three
files:
1. Makefile
2. DemoMessage.h
3. DemoP.nc
4. DemoAppC.nc
126
Make+ile
COMPONENT=DemoAppC
include
$(MAKERULES)
127
DemoMessage.h
#ifndef __DEMOMESSAGE_H
#define __DEMOMESSAGE_H
enum
{
AM_DEMO_MSG = 231,
};
#endif
128
DemoP.nc
module DemoP
{
uses interface Boot;
129
DemoP.nc
implementation
{
message_t buf;
task void readSensor();
task void sendBuffer();
event void Boot.booted()
{
if(call RadioControl.start() != SUCCESS)
call Leds.led0On();
}
if(TOS_NODE_ID == 0)
call Timer.startPeriodic(64); 130
}
DemoP.nc
event void Timer.fired()
{
post readSensor();
}
post sendBuffer();
} 131
DemoP.nc
task void sendBuffer()
{
if(call AMSend.send(AM_BROADCAST_ADDR,
&buf, sizeof(demo_msg_t)) != SUCCESS)
post sendBuffer();
}
event void AMSend.sendDone(message_t * jkdsakljads, error_t err)
{
if(err != SUCCESS)
post sendBuffer();
}
event message_t * Receive.receive(message_t * m,void * payload,uint8_t size)
{
demo_msg_t * dpayload = (demo_msg_t *)payload;
call Leds.set(dpayload->lastReading / 200);
return m;
} 132
event void RadioControl.stopDone(error_t err) {}
DemoAppC.nc
#include "DemoMessage.h"
configuration DemoAppC{}
implementation{
components DemoP, MainC;
DemoP.Boot -> MainC.Boot;
components LedsC;
DemoP.Leds -> LedsC;
components new HamamatsuS10871TsrC() as PhotoSensor;
DemoP.Read -> PhotoSensor;
components ActiveMessageC;
DemoP.RadioControl -> ActiveMessageC;
components new AMSenderC(AM_DEMO_MSG),
new AMReceiverC(AM_DEMO_MSG);
DemoP.AMSend -> AMSenderC;
DemoP.Receive -> AMReceiverC;
DemoP.Packet -> AMSenderC;
components new TimerMilliC();
DemoP.Timer -> TimerMilliC; 133
}