Title: nesC: A Programming Language for Motes
1nesCA Programming Languagefor Motes
- David Gay, Phil Levis, Eric Brewer, Rob von
Behren, Nikita Borisov, Mike Chen, David Culler - Intel Research, UC Berkeley
2The State of the Motes
- TinyOS programs hard to write
- No compiler
- verbose, unwieldy syntax
- many compile-time checks missing
- No support for common idioms
- state-machine-like programs
- split-phase operations
- atomicity guarantees, etc
3A Long-term Solution
- We are working on an improved language
- Component-based
- Better support for common idioms
- split-phase ops, state-machines, etc
- Clean atomicity model
- Very much in the design/investigation stage
4A Short-term Solution nesC
- A cleaned up language for TinyOS
- Goals
- Easier to use
- Allow whole-program optimisations
- Base for language experimentation
- Pronounced nestlé
5nesC Easier to Use
- Nicer syntax
- Check errors
- Missing connections
- Type errors in connections
- Cycles, incorrect directions
- Interfaces
- Group related functionality (caller, callee)
- sendMsg
- users call send(m), implement sendDone(m)
- implementer implement send(m), call sendDone(m)
- Concise wiring
6The Old Model
- Components
- .comp specification
- .C behaviour
- .desc select and wire
- specification
- accepts commands
- uses commands
- signals events
- handles events
7The Old Model, continued
- 4 kinds of components
- .desc only (ex cnt_to_leds)
- top-level components and wiring for an
application - .C and .comp (ex CLOCK)
- a component implemented in C
- .desc and .comp (ex GENERIC_COMM)
- a component implemented by connecting other
components - .C, .comp and .desc (ex INT_TO_RFM)
- a component implemented in C with predefined
wiring to other components
8The nesC Model
- Components 1 file
- specification
- implementation
- module C behaviour
- configurationselect and wire
- specification
- provides interface
- requires interface
comp3
comp1 module
comp4
9The nesC Model, continued
- 2 kinds of components
- module was .C and .comp
- configuration was .desc and .comp
- What happened to the other 2 kinds of components
? - .desc only (ex cnt_to_leds)
- use a configuration with empty specification
- .C, .comp and .desc (ex INT_TO_RFM)
- use a configuration and module (2 files)
- naming convention IntToRfm (configuration),
IntToRfmM (module) - allows module to be re-used with different wiring
10Interfaces
- Group related functionality, e.g.
- split-phase operation (send, sendDone)
- standard control interface init, power
- Specifies bi-directional calls (defines, uses)
- interface SendMsg
- defines command result_t send(uint16_t to,
TOS_MsgPtr msg) - uses event result_t sendDone(TOS_MsgPtr msg,
result_t ok) -
- if component C with interface I has function f
- if I is required and f is uses, C must define f
- if I is provided and f is defines, C must define f
11Some Interfaces
- interface Leds
- defines
- command result_t init()
- command result_t redOn()
- command result_t redOff()
- command result_t redToggle()
- ...
-
-
interface StdControl defines command
result_t init() command result_t power(char
mode)
interface Clock defines command result_t
setRate(char interval, char scale) uses event
result_t fire()
12Some More Interfaces
interface ReceiveMsg uses event TOS_MsgPtr
receive(TOS_MsgPtr m)
interface SendMsg defines command result_t
send(uint16_t to, TOS_MsgPtr msg) uses event
result_t sendDone(TOS_MsgPtr msg, result_t ok)
interface ADC defines command result_t
getData() defines command result_t
getContinuousData() uses event result_t
dataReady(uint16_t data)
- But where did the Active Message type go ?
- But where did the ADC port go ?
13Parameterised Interfaces
- Specify a numeric parameter for an interface in a
component - argument value specified in configurations
- dynamic dispatch (receive, sendDone), implicit
argument (send) - Like the current scheme for receiving active
messages - Used also for ADC ports, exclusive EEPROM access
- configuration MyApp ... implementation
- uses MyMain, GenericComm
- MyMain.Msg1 -gt GenericComm.Send12
- MyMain.Msg2 -gt GenericComm.Receive99
-
- module MyMain
- requires interface Send Msg1
- requires interface Receive Msg2
-
- implementation
- event Msg2.receive(MsgPtr m)
- call Msg1.send(myMsg)
-
interface Receive uses event receive(MsgPtr
m) interface Send defines command
send(MsgPtr m) uses event sendDone(MsgPtr
m) configuration GenericComm provides
interface Sendchar id provides interface
Receivechar id implementation ...
14Miscellaneous Features
- default events and commands (cf _NULL_FUNC)
- some commands, events not always connected
- specify default behaviour in the absence of
connection, e.g. - default event TOS_MsgPtr receive(TOS_MsgPtr
msg) return msg - includes is used to include C types/constants/etc
for use in an interface or component - these types are accessible to all components that
use the interface or component - use, e.g., to share packet format specification
across components - nesC source code is not preprocessed
15Implementation
- nesc1 takes a closed component (no interfaces)
and - Checks nesC errors
- Unknown/multiply-defined interfaces, components,
etc - Connections (missing, cyclical, type-incorrect,
wrong direction) - Checks (most) C errors
- Generates one C-file for the application
- Includes only reachable code (prunes out
unreachable functions) - Generated in reverse-topological-call-order
- Allows gccs inliner to do a much better inlining
job - avr-gcc compiles nesc1 output
- Generated code has line directives, so clean
error messages
16Status
- Compiler complete (some bugs expected)
- Basic infrastructure and components for Mica
- (old) radio stack
- ADC, Clock, Leds, EEPROM, serial port
- Apps ported
- Blink, CntToLeds,Rfm,LedsAndRfm, RfmToLeds
- SenseToLeds, Chirp, Oscilloscope, EEPROMTest
- GenericBase
17Status Code Size
Application C (TinyOS) nesC Savings
Blink 1092 796 27
CntToLeds 1170 972 17
SenseToLeds 1636 1086 34
Oscilloscope 2792 2230 20
RfmToLeds 5226 4168 20
GenericBase 4544 4632 -2
CntToRfm 5220 4678 10
CntToLedsAndRfm 5544 4850 13
Chirp 5516 4948 10
EEPROMTest 7830 6220 21
18Plans
- Goal Switch all TinyOS C code to nesC
- Stage 1 convert all standard components apps
- Who The TinyOS team
- Support Mica, Rene2, all sensor boards
- Stage 1a Phil Levis will port TOSSIM to nesC
- Stage 1b Eric Brewer will write porting guide,
nesC tutorial - Stage 2 distribute nesC in next TinyOS release
- Stage 3 discontinue support for macros/perl
scripts - Goal Improve nesC
- See Erics talk
19Open Issues
- Naming Convention (Java-inspired)
- Interface design
- Revisit some component designs
- Directory structure
20Conclusions
- nesC much nicer to use than TinyOS
- No more obscure C compiler warnings/errors
- No more obscure bugs due to typos
- No more obscure infinite loops due to wiring
restrictions - nesC produces smaller code than TinyOS
- Prunes unreachable code
- Inlining across component boundaries
- The best is yet to come!
- Short-term multiple instantiation, better
inlining selection, packet format specification - Long-term language improvements for bug
prevention
21Packet Format Specification
- Write a C file with the packet type
- // IntMsg.th The message type for
IntToRfm/RfmToInt - typedef struct
- char val
- int src
- IntMsg
- enum
- AM_INTMSG 4
-
- Use it in nesC components via includes
- Automatic generation of corresponding Java type
and marshaller/unmarshaller
22Components
- components
- module C1
- requires interface triangle
- implementation ...
- module C2
- provides interface triangle in
- requires
- interface triangle out
- interface rectangle side
- implementation ...
- configuration C3
- provides interface triangle
- provides interface rectangle
- implementation ...
23Configurations
- Connect components
- configuration app
- implementation
- uses c1, c2, c3
- c1 -gt c2 // implicit interface sel.
- c2.out -gt c3.triangle
- c3 lt- c2.side
-
- Partial configurations
- component c2c3
- provides interface triangle t1
-
- implementation
- uses c2, c3
- t1 -gt c2.in
- c2.out -gt c3.triangle
- c3 lt- c2.side
24Modules
- C implementation of components
- all top-level declarations private, except those
specified in the components interface
- module C2
- provides interface send in
- requires interface send out
- implementation
- enum ready, busy state
- command in.send(Message m)
- if (state busy) return 0
- state busy
- call out.send(m)
- return 1
-
- event out.send_done(Message m)
- state ready
- signal in.send_done(m)
-
- ...
-