View
241
Download
0
Tags:
Embed Size (px)
Citation preview
TinyOS and NesC:programming low-resource sensor networks
OS Design: Different platforms need different solutions
Capabili
tie
s
Size, Power Consumption, Cost
MICA Mote
MK - II
StarGate
Spec
Ample resources
Solutions: Linux, uCos, Emstar…
Highly constrained (memory, CPU, storage, power)
Solutions: TinyOS,…
Hardware technology push towards miniaturization
CMOS miniaturization 1 M trans/$ tiny (~mm2), inexpensive processing and storage 1-10 mW active, 1 W passive (at 1% use 100 W average)
Micro-sensors (MEMS, Materials, Circuits) acceleration, vibration, gyroscope, tilt, magnetic, heat, motion, pressure, temp,
light, moisture, humidity, barometric chemical (CO, CO2, radon), biological, micro-radar, ... actuators too (mirrors, motors, smart surfaces, micro-robots)
Communication short range, low bit-rate, CMOS radios (1-10 mW)
Power batteries remain primary storage (1,000 mW/mm3), fuel cells 10x solar (10 mW/cm2, 0.1 mW indoors)
1 cm3 battery 1 year at 10 msgs/sec
Sensor Impact on OS Design Small physical size and low power consumption Concurrency-intensive operation
multiple flows, not wait-command-respond=> never poll, never block
Limited Physical Parallelism and Controller Hierarchy primitive direct-to-device interface Asynchronous and synchronous devices=> interleaving flows, events, energy management
Diversity in Design and Usage application specific, not general purpose huge device variation=> efficient modularity=> migration across HW/SW boundary
Robust Operation numerous, unattended, critical=> narrow interfaces
sensorsactuators
network
storage
History of the Mote Sensor Node Jason Hill’s Master’s Thesis (UCB) PhD Dissertation was a prototype for a smart-
dust system on a chip Small physical size: 1 mm3
Low Power Consumption: < 50 mW
3rd-generation mote (mica2)
Constraints 4KB RAM 128KB Program Flash Memory >25mA (Tx), <15uA (sleep) at 3.3V 8MHz Microcontroller 19.2Kbps (at 433 or 916MHz)
Other exciting details 512KB Measurement Flash 4KB Configuration EEPROM 10bit ADC 3 LEDs 51pin expansion connector Transmission range ~500ft outdoor Runs on 2 AA batteries
(backside)
Sensor Node Hardware Architecture3 subsystems:
Processing subsystem Sensing subsystem Radio communication subsystem
Processing Sub-System Functions
Application Execution Resource Management Peripheral Interaction
Atmel AVR ATMEGA128L RISC Architecture 8 bit ALU/data-path 128 Kb FLASH - Code 4 Kb SRAM - Data Multiple peripherals
Details are available in the ATMEGA128L Datasheet
Sensing Sub-System Functions
Sampling physical signals/phenomena
Different types of sensors Photo-sensor Acoustic Microphone Magnetometer Accelerometer
Sensor Processor Interface 51 Pin Connector ON-OFF switches for
individual sensors Multiple data channels
Sensors consume powerTurn them off after sampling !
Useful Link/Resources• http://www.tinyos.net/ Look under Hardware Designs tab• Crossbow website http://www.xbow.com
Example: Mica Weather Board – Weather monitoring applications Total Solar Radiation
Photosynthetically Active Radiation
Resolution: 0.3A/W Relative Humidity
Accuracy: ±2% Barometric Pressure
Accuracy: ±1.5mbar Temperature
Accuracy: ±0.01oC Acceleration
2 axis Resolution: ±2mg
Designed by UCB w/ Crossbow and UCLA
Revision 1.5
Revision 1.0
Other sensing boards
Ultrasonic transceiver – Localization Used for ranging Up to 2.5m range 6cm accuracy Dedicated microprocessor 25kHz element
Basic Sensor board Light (Photo), Temperature,
Acceleration, Magnetometer, Microphone, Tone Detector, Sounder
Communication Sub-System Functions
Transmit – Receive data packets wirelessly
Co-ordinate/Network with other nodes
Implementation Radio
Modulation – Demodulation Two types of radios: RFM,
ChipCon CC1000 RFM: Mica & predecessors CC1000: Mica2 onwards
AVR Protocol Processing
AVR Peripherals UART
Serial communication with the PC SPI – Serial Peripheral Interface
Synchronous serial communication Interface to Radio in the Mote
ADC Analog – Digital Converter Digitizing sensor readings
I/O Ports General Purpose Input Output pins (GPIO) Used to light up LEDs in Mote
Radio Power Management Radio has very high power consumption
Tx power is range dependant - 49.5 mW (0 dBm) Rx power is also very high - 28.8 mW Power-down sleep mode - 0.6 uW Above data for CC1000, 868 MHz
Radio power management critical Idle state channel monitoring power = Rx Power Put radio to sleep when not in use But then, how do we know when somebody is trying to
contact us ?
AVR Power Management Low Power operation – 15 mW @ 4 MHz Multiple Sleep Modes
Sleep Modes: Shutdown unused components Idle Mode – 6 mW
CPU OFF, all peripherals ON CPU “woken up” by interrupts
Power Down Mode – 75 uW CPU and most peripherals OFF External Interrupts, 2 Wire Interface, Watchdog ON
Power Save Mode – 120 uW Similar to Power Down Timer0 continues to run “asynchronously”
Typical sensor network operation Sensing Subsystem
Keep the very low power sensors on all the time on each node in the network
Processing subsystem Low-power sensors interrupt (trigger) processor when “events”
are identified OR Processor wakes up periodically on clock interrupt, takes a
sample from sensor, processes it, and goes back to sleep. Radio subsystem
Processor wakes up radio when event requires collaborative processing or multi-hop routing.
Tiered architectures of above subsystems can be envisaged in other platforms
Why not use Traditional Internet Systems? Well established layers
of abstractions Strict boundaries Ample resources Independent apps at
endpoints communicate pt-pt through routers
Well attended
User
System
Physical Layer
Data Link
Network
Transport
Network Stack
Threads
Address Space
Drivers
Files
Application
Application
Routers
Sensor network by comparison ...
Highly Constrained resources processing, storage, bandwidth, power
Applications spread over many small nodes self-organizing Collectives highly integrated with changing environment and
network communication is fundamental
Concurrency intensive in bursts streams of sensor data and network traffic
Robust inaccessible, critical operation
Goals for TinyOS and NesC
Flexibility new sensor network nodes keep emerging
Telos, iMote, mica2, mica2Dot, etc. Flexible hardware/software interface
Future designs may require different HW/software interfaces and may move service (MAC, e.g.) into hardware or software
Modularity Component model
Sensor Network Challenges Address the specific and unusual challenges of sensor networks:
limited resources, concurrency- intensive operation, a need for robustness, and application-specific requirements.
Do they meet these goals?
Static allocation allows for compile-time analysis, but can make programming harder
Does satisfying these goals warrant a new programming language? Why not java? The challenges (such as robustness) are often solved
in the details of implementation. While the language (nesC) offers some types of
checking, whole-system robustness is not necessarily dependent on the language used
Missing from their goals…
Heterogeneity Support for other platforms (e.g. stargate) Support for high data rate apps (e.g. acoustic
beam-forming) Interoperability with other software frameworks
and languages Visibility
Debugging Network management Intra-node fault tolerance
TinyOS: Operating System for Sensor Nodes
● application = scheduler + graph of components● event-driven architecture● single shared stack● NO kernel, process/memory management, virtual memory
Application = Graph of Components
RFM
Radio byte
Radio Packet
UART
Serial Packet
ADC
Temp photo
Active Messages
clocks
bit
by
tep
ac
ke
t
Route map router sensing application
ap
pli
ca
tio
n
HW
SWExample: ad hoc, multi-hop routing of photo sensor readings
3450 B code 226 B data
Graph of cooperatingstate machines on shared stack
Basic Concepts in Tiny OS
Scheduler + Graph of Components constrained two-level scheduling model:
threads + events Component:
Commands, Event Handlers Frame (storage) Tasks (concurrency)
Constrained Storage Model frame per component, shared stack, no
heap Very lean multithreading Efficient Layering
Messaging Component
init
Po
we
r(m
od
e)
TX
_p
ack
et(
bu
f)
TX
_p
ack
et_
do
ne
(s
ucc
ess
)
RX
_p
ack
et_
do
ne
(b
uff
er)
Internal
State
init
po
we
r(m
od
e)
sen
d_
msg
(ad
dr,
ty
pe
, d
ata
)
msg
_re
c(ty
pe
, d
ata
)m
sg_
sen
d_
do
ne
)
internal thread
Commands Events
Component A component provides and uses interfaces
The interfaces are the only point of access to the component An interface models some service, e.g., sending a message The provider of a command implements the commands, while
the user implements the events
Interface
Bidirectional interfaces support split-phase execution
TOS Execution Model Commands request action
ack/nack at every boundary call command or post task
Events notify occurrence HW interrupt at lowest level may signal events call commands post tasks
Tasks provide logical concurrency preempted by events
Migration of HW/SW boundary
RFM
Radio byte
Radio Packet
bit
by
tep
ac
ke
t
event-driven bit-pump
event-driven byte-pump
event-driven packet-pump
message-event driven
active message
application comp
encode/decode
crc
data processing
Task and Event Based Concurrency Two sources of concurrency in TinyOS: tasks and events. Tasks are deferred mechanisms of computation that run to
completion. Can’t preempt other tasks. Components post task, then the post operation returns. Task is later run by
scheduler. Components use task when time restriction is not strict. Tasks should be short. Long operations should be broken up into small tasks. Lifetime requirements of sensor networks prohibit heavy computation
(reactive). Events also run to completion. Events can preempt tasks or
another event. Events signify completion of split-phase operation or event from environment.
TinyOS execution is driven by events representing hardware interrupts
Split-Phase Operations
Because tasks execute non-preemptively, TinyOS has no blocking operations.
All long-latency ops are split-phase meaning operation requests and completions are separate functions. Non-split phase ops don’t have completion events (i.e. toggle LED).
Commands are requests to start and operation. Events signal completion of operation.
Send a packet example: one component invokes send, another communication component signals sendDone when packet is sent.
TinyOS Summary
Component-based architecture An application wires reusable components together in a
customized way Tasks and event-driven concurrency
Tasks & events run to completion, but an event can preempt the execution of a task or an event
Tasks can’t preempt another task or event Split-phase operations (for non-blocking operations)
A command will return immediately and an event signals the completion
What is nesC? Extension of C
C has direct Hardward control Many programmers already know C nesC provides safety check missing in C
Whole program analysis at compile time Detect race conditions -> Eliminate potential bugs Aggressive function inlining -> Optimization
Static language No dynamic memory allocation No function pointers Call graph and variable access are fully known at compile time
Supports and reflects TinyOS’s design Based on the component concept Directly supports event-driven concurrency model Addresses the issue of concurrent access to shared via atomic
section and norace keyword
Key Properties All resources are known statically
No general-purpose OS, but applications are built from a set of reusable system components coupled with application-specific code
HW/SW boundaries may vary depending on the application & HW platform -> Flexible decomposition is required
Challenges Event-driven: Driven by interaction with environments
1. Motes are event driven. React to changes in the environment (i.e. message arrival, sensor acquisition) rather then interactive or batch processing.
2. Event arrival and data processing are concurrent. Must now address potential bugs like race conditions.
Limited resources Reliability
Need to enable long-lived applications. Hard to reach motes, therefore must reduce run-time errors since only option is reboot.
Soft real-time requirements Although tasks like radio management/sensor polling are time critical, they do
not focus on hard real-time guarantees. Timing constraints are easily met by having complete control over OS and app. Radio link is timing critical but since radio link is unreliable, not necessary to
meet hard deadline.
nesC the nesC model:
interfaces: uses provides
components: modules configurations
application:= graph of components
Why is this a good choice for a sensor net language?
LED
Counter
ComponentD
Application
Application
configurationconfiguration Radio
ComponentF
Each mote runs a single application Properties
All memory resources are known statically Rather than employing a general-purpose OS, applications are built
from a suite of reusable system components coupled with application-specific code
The hardware/software boundary varies depending on the application and hardware platform; it is important to design software for flexible decomposition
Challenges: Driven by interaction with the environment (interrupts) Limited resources (motes) Reliability Soft real-time requirements (radio management and sensor polling) Lacking common service
Time synchronization
Applications are written by assembling components Anatomy of a component
Interfaces Implementation Default handlers
Anatomy of an application Main component for initialization, start, stop Connected graph of components
Interfaces Define “public” methods that a component can use used for grouping functionality, like:
standard control interface (init, start, stop) describe bidirectional interaction:
interface provider must implement commands interface user must implement events
TimerM
ClockC
interface IntOutput {
/* Output the given integer. */ command result_t output(uint16_t value);
/* Signal that the output operation has completed */ event result_t outputComplete(result_t success);} IntOutput.nc
Commands/Events
commands: deposit request parameters into the frame are non-blocking need to return status postpone time consuming work by posting a
task can call lower level commands
events: can call commands, signal events, post tasks, can not be signaled by
commands preempt tasks, not vice-versa interrupt trigger the lowest level events deposit the information into the frame
Interface Examples
interface StdControl { command result_t init (); command result_t start (); command result_t stop ();}
interface Timer { command result_t start (char type, uint32_t interval); command result_t stop (); event result_t fired ();}
interface SendMsg { command result_t send (uint16_t addr, uint8_t len, TOS_MsgPtr p); event result_t sendDone ();}
interface ReceiveMsg { event TOS_MsgPtr receive (TOS_MsgPtr
m);}
StdControl.nc Timer.nc
ReceiveMsg.ncSendMsg.nc
Split-phase Interfaces
Operation request and completion are separate functions:
No blocking operations because tasks execute non-preemptively
The usual way to do this is to register a callback by passing a function pointer
interface SendMsg { command result_t send (uint16_t address, uint8_t length, TOS_MsgPtr p); event result_t sendDone (TOS_MsgPtr msg, result_t success);} SendMsg.nc
Parameterized Interfaces Can associate a port with an interface, so that a provider can
distinguish users Used because the provider doesn’t know how many users will be
connecting to it
configuration CntToLeds {}implementation { components Main, Counter, IntToLeds, TimerC;
Main.StdControl -> IntToLeds.StdControl; Main.StdControl -> Counter.StdControl; Main.StdControl -> TimerC.StdControl;
Counter.Timer -> TimerC.Timer[unique("Timer")];
Counter.IntOutput -> IntToLeds.IntOutput;} CntToLeds.nc
Component Implementation
Two types of components: modules & configurations
Modules provide application code and implements one or more interfaces
Configurations wire components together Connect interfaces used by components to
interfaces provided by others
Modules A module has:
Frame (internal state) Tasks (computation) Interface (events, commands)
Frame : one per component statically allocated fixed size
Tasks
ComponentFrame
EventsCommands
● Commands and Events are function calls● Application: linking/glueing interfaces (events, commands)
A Module
module Counter { provides { interface StdControl; } uses { interface Timer; interface IntOutput; }}Implementation { int state;
command result_t StdControl.init(){ state = 0; return SUCCESS; } command result_t StdControl.start(){ return call Timer.start(TIMER_REPEAT,250); } command result_t StdControl.stop(){ return call Timer.stop(); } event result_t Timer.fired(){ state++; return call IntOutput.output(state); } event result_t IntOutput.outputComplete(result_t success){ if(success == 0) state --; return SUCCESS; }}
Implements interfaces with decorated C code
Modules Module declaration
Provides Which interfaces will be
implemented by this module Uses
Which interfaces the module will need to use
Module implementation Interface methods
implemented All command for “provides”
and events for “uses” Keyword “includes” goes
before module declaration Semantic equivalent of
#include, with caveats: No cpp directives allowed
Practical hack: Put #include in
implementation block
includes Foo; module ExampleM { provides { interface StdControl; } uses { interface Timer; }}implementation {#include “foo-constants.h” ... command result_t StdControl.start(){ return call Timer.start(TIMER_REPEAT,250); } ...event result_t Timer.fired(){
// do something }}
A Configuration
configuration CntToLeds {}implementation { components Main, Counter, IntToLeds, TimerC;
Main.StdControl -> IntToLeds.StdControl; Main.StdControl -> Counter.StdControl; Main.StdControl -> TimerC.StdControl; Counter.Timer -> TimerC.Timer[unique("Timer")]; Counter.IntOutput -> IntToLeds.IntOutput;}
Define a wiring showing how components are to be connected. I.e., a linker:
Configurations Configurations refer to
configurations and modules No distinction between an
included configuration and an included module
Configuration can expose an underlying module’s interface
An application must connect a Main component to other components
connected elements must be compatible (interface-interface, command-command, event-event)
3 wiring statements in nesC: endpoint1 = endpoint2
endpoint1 -> endpoint2
endpoint1 <- endpoint2
configuration CntToLeds {}implementation { components Main, Counter, IntToLeds, TimerC; Main.StdControl -> IntToLeds.StdControl; Main.StdControl -> Counter.StdControl; Main.StdControl -> TimerC.StdControl; Counter.Timer -> TimerC.Timer[unique("Timer")]; Counter.IntOutput -> IntToLeds.IntOutput;}
configuration TimerC { provides interface Timer[uint8_t id]; provides interface StdControl;}
implementation { components TimerM, ClockC, NoLeds, HPLPowerManagementM;
TimerM.Leds -> NoLeds; TimerM.Clock -> ClockC; TimerM.PowerManagement -> HPLPowerManagementM;
StdControl = TimerM; Timer = TimerM;}
Concurrency
Tasks and interrupts (foreground and background operations) Tasks cannot preempt other tasks
Low priority for performing computationally intensive work Interrupts can preempt tasks Interrupts can preempt other interrupts, but not important for this course
TOSH_INTERRUPT() – interrupt allowed TOSH_SIGNAL() – interrupt forbidden
Scheduler Two level scheduling - interrupts (vector) and tasks (queue) Queue of tasks
No associated priorities FIFO execution
No local state associated with tasks Programmer must manage own internal state when tasks need it
Danger: task queue overflows (because no dynamic memory)
What the scheduler does…
Operation When no tasks pending, sleep Wake on interrupt, lookup interrupt
handler and execute Before sleeping again, check task
queue, call task in FIFO order Practices
Statically defined maximum queue length means code should be carefully written to avoid posting too many tasks
E.g., if we have a list of thing to process (such as messages), rather than post a separate task for each message, post the next processing task at the end of the task handler
Task void send(){ //get head of send queue //send message if (queue.size > 0) post send()}
Hardware
Interrupts
even
ts
commands
FIFO
TasksPOST
Preempt
Time
commands
while(1) {while(more_tasks)
schedule_task;sleep;
}
Posting Tasks
module BlinkM {…}implementation {… task void processing () { if(state) call Leds.redOn(); else call Leds.redOff(); }
event result_t Timer.fired () { state = !state; post processing(); return SUCCESS; }…}
BlinkM.nc
Language features for concurrency post
Puts a function on a task queue Must be void foo(void) void task do-work() { //do something } post do-work();
atomic Interrupts can preempt execution Turn off interrupts with atomic{ } E.g. to implement a semaphore
async Use async to tell compiler that this code can be called from an
interrupt context – used to detect potential race conditions norace
Use norace to tell compiler it was wrong about a race condition existing (the compiler usually suggests several false positives)
Example “Surge”: A Sensor Application
Simple application that performs periodic sampling and using ad hoc routing over wireless network to deliver information to base station.
Each node listens to messages and chooses node with least depth to be parent. Base station will periodically broadcast beacon messages with depth 0.
Each node estimates parent’s link quality, if link quality falls below that, node selects new parent from their neighbor set based on link quality estimates and depth.
If node receives message from another node, it forwards that message to its parent.
Examples of Components
Concurrency In nesC
To handle events and concurrency, nesC provides 2 tools: atomic sections and tasks.
Atomicity is implemented by simply disabling/enabling interrupts (this only takes a few cycles). Disabling interrupts for a long
time can delay interrupt handling and make systems less responsive.
If potential race condition is present and programmer knows its not an actual race condition, can specify something as “norace”.
Evaluation Tested for three TinyOS applications
Surge, Mate, TinyDB Core TinyOS consists of 172 components
108 modules & 64 configurations Group necessary components, via nesC’s bidirectional interfaces, for a
specific application
Remaining issues in NesC
Static memory allocation Advantages
Offline analysis of memory requirements No problem?
No dynamic allocation
Short code only in atomic sections & command/event handlers
Little language support for real-time programming
nesC Summary nesC was originally designed to express concepts embodied in
TinyOS. Focus on holistic system design by making it easy to assemble
apps that include only the necessary OS parts. Component model allows alternate implementation and flexible
hardware/software boundaries. Concurrency model allows highly concurrent programs with
limited resources. Use of bidirectional interfaces and atomic statements permits
tight integration of concurrency and component oriented design. Lack of dynamic allocation and explicit specification of apps call
graph make it easier to run whole-program analysis and optimizations. Aggressive in-lining reduces memory footprint and static data-
race detection reduces bugs.
More on NesC for your programming Details and tips that are useful for you to
program in NesC and TinyOS Naming convention Compiling Directory Makefile …
Programming Environment
OS: cygwin/Win2000 or gcc/Linux Software: atmel tools, java, perl
mote
programming board
mote-PC comms Code
download
nesC details naming conventions:
nesC files suffix: .nc C stands for Configuration (Clock, ClockC) M stands for Module (Timer, TimerC, TimerM)
?
Clock.nc
?
ClockC.nc
configuration ClockC { ...}
implementation {…}
ClockC.nc
interface Clock { ...}
Clock.nc
?
Timer.nc
interface Timer { ...}
Timer.nc
?
TimerC.nc
?
TimerM.nc
configuration TimerC { ...}
implementation {…}
TimerC.nc
module TimerM { ...}
implementation {…}
TimerM.nc
● clarifications:– “C” distinguishes between
an interface and the component that provides it
– “M” when a single component has both: a configuration, a module
Compiling an application
Avr cross-compilation Specify platform, programming interface, mote ID To make and install a binary with ID of 3:
make mica2 install.3 To install a preexisting binary with ID of 12:
make mica2 reinstall.12
Pc native compilation Create a binary that runs on your pc for
debugging and simulation Make pc, make emstar
Directory structure
tos-contrib – where all contributed projects go Makecontrib –top-level build info for projects in tos-contrib project-name – a particular project that has been contributed
apps – the applications written for this project Makefile
Directives for all application in this project Makerules Foo-App
Makefile – define TOSH_DATA_LENGTH, sensorboards, etc Foo-App.nc – top-level configuration for the application Foo-AppM.nc - non-reusable application-specific code
lib - Configurations and modules defined for the project interfaces - interfaces defined to be used with the modules and
configurations in lib
tinyos-1.x has same structure (apps, lib, interfaces) as tos-contrib
Build system
An application’s Makefile…
COMPONENT=MultihopDseCONTRIB_INCLUDES += EmTos hostmote sensorIB dse#SENSORBOARD=basicsbSENSORBOARD=mda300caCFLAGS += -DCC1K_DEFAULT_FREQ=2CFLAGS += -DTOSH_DATA_LENGTH=50CFLAGS += -DLPL_MODE=0CFLAGS += -DSTATUS_DBGCFLAGS += -DHOSTMOTE_MAX_SEND_DATA_LENGTH=66#CFLAGS += -DHOSTMOTE_DEBUGinclude ../Makerules
Contrasting Emstar and TinyOS
Many similar design choices programming framework
Component-based design “Wiring together” modules into an application
Event-driven reactive to “sudden” sensor events or triggers
Robustness Nodes/system components can fail
Many differences Platform-dependent constraints
Emstar: Develop without optimization TinyOS: Develop under severe resource-constraints
Operating system and language choices Emstar: easy to use C language, tightly coupled to linux (devfs) TinyOS: an extended C-compiler (nesC), not wedded to any
particular OS.
Build system integration with Emstar Tricky to get TinyOS and Emstar to play nice Read: http://cvs.cens.ucla.edu/emstar/install.html Basically, a few symbolic links need to be
established To build in emstar:
$EMSTAR_ROOT points to your emstar distribution $TOSDIR points to your TinyOS distribution in Make.conf set BUILD_EMTOS to 1 make [ARCH=mica2]
Debugging using print statements TinyOS’s printf:
dbg(DBG_USR1, “%s [%d] – link quality is %d\n”, __FILE__, __LINE__, link_quality);
DBG_USR1, DBG_USR2, DBG_USR3, and DBG_ERROR are defined for your enjoyment