720 likes | 838 Views
Programming in nesC (and TOSSIM). Professor Jack Stankovic Department of Computer Science University of Virginia. Questions. How do you program these wireless sensor devices? How do you debug your code on a PC? How do you download your code? How do you debug the system?. nesC.
E N D
Programming in nesC(and TOSSIM) Professor Jack Stankovic Department of Computer Science University of Virginia
Questions • How do you program these wireless sensor devices? • How do you debug your code on a PC? • How do you download your code? • How do you debug the system? nesC TOSSIM – Lab 3 Lab 0 Message Center – Lab 2
Questions • What else do you need to know? • TinyOS • Why nesC? • Most widely used • Example of systems language for embedded systems
Helpful Materials • Labs and Lab materials – see class web site • Handouts – read • Read: • The nesC Language: A Holistic Approach to Networked Embedded Systems, D. Gay, et. al., PLDI, 2003 (sections 1-4 inclusive) • Google to find TinyOS tutorial
Outline • Overview • Main Elements and Examples • Task Model and Concurrency • More Coding Details • Examples • Message Center (Lab 2; intro in class) • TOSSIM • Summary
TinyOS and nesC Paradigm • Component-based • TinyOS, libraries, applications written in nesC • Intended for embedded systems and WSN • C-like syntax (new keywords) • Call, signal, task, post, async, … • TinyOS concurrency model (tasks and events)
TinyOS and nesC Paradigm • No dynamic memory • nesC bi-directional interface is an excellent fit for event driven systems • Race conditions checked at compile time
Big Picture • Write components; use components written by others • Will need new keywords/framework for defining components • Glue components together • Called wiring • Configuration file • Bi-directional interfaces • Concurrency/Execution Model • Tasks • Event handlers • Data races checked at compile time
Big Picture • Use development environment on PC and download to target system (motes) • Simulator available before downloading • Debug on PC • Message Center tool – inject/read msgs • Debug on actual platform
Big Picture • nesC application • 1 or more components • Wire them together • Must have a MAIN component • Modules (implement your code) • Configurations (the wiring) • Interfaces
Big Picture Provides Interfaces Interface: Commands (how to use the interface) Events (user of interface must implement) Component Uses Interfaces
sensing application application Routing Layer routing Messaging Layer messaging packet UART Packet Radio Packet Radio byte UART byte Temp byte photo SW HW RFM ADC i2c bit clocks Application Example
Example (cont.) • You might only write the application component • Perhaps all other components are from a library • Applies to TinyOS • 108 code modules in TinyOS • Examples of Applications • Surge 31 modules – 27 of them OS • TinyDB 65 modules – 38 of them OS
Example (cont.) • Note: HW components • Veneer of SW exists for each HW component • Hides interrupt vector set up • Abstracts details of HW init and use (more details later)
Interfaces Interface: Declare commands (implementor of this interface must implement these commands) Declare events (User of this interface, i.e., a components that invokes commands, must implement these events – call back functions) Interfaces have global scope!
Interface Example • Interface is a type • Many instances of the interface may exist • A command or event in an interface is named i.f (Ex: Timer.start, Timer.fired) Timer.nc * filename for a bidirectional interface interface Timer { command result_t start (char type uint32_t interval); command result_t stop(); event result_t fired(); }
Split Phase • Because of the execution model, code should exist in small execution pieces • Similar to asynchronous method calls • Separate initiation of method call from the return of the call • Call to split-phase operation returns immediately • When work actually finishes the caller is notified via another method call
Specify Split-Phase • Declare Interface with both • Command • Event (e.g., Timer.nc of previous (2) slides back) • Use to avoid long delay operations • (since a non-preemptive model is used)
Components and Interfaces Provides interfaces (multiple interfaces) (bi-directional) Component Uses Interfaces (multiple interfaces) (bidirectional)
Component Example -Modules • Implements a component’s specification with C code: module MyCompM { provides interface X; provides interface Y; uses interface Z; } implementation { …// C code } module MyCompM { provides { interface X; interface Y; } uses interface Z; } implementation { …// C code } specification MyCompM.nc MyCompM.nc The implementation part implements the provides interfaces and if the uses interface has an event then this module must also implement an event handler.
interface Clock { command result_t setRate (char interval, char scale); event result_t fired (); } Clock.nc Interfaces • Used for grouping functionality, like: • split-phase operation (send, sendDone) • standard control interface (init, start, stop) • Describe bidirectional interaction: • Interface provider must implement commands • Interface user must implement events TimerM ClockC Note: This is how you declare a split-phase operation, i.e., Command and Event declared.
Interfaces • Examples of interfaces: 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 (); } StdControl.nc Timer.nc 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); } SendMsg.nc ReceiveMsg.nc
Interfaces • Not all Interfaces are split-phase • E.g., StdControl and ReceiveMsg are not interface ReceiveMsg { event TOS_MsgPtr receive (TOS_MsgPtr m); } interface StdControl { command result_t init (); command result_t start (); command result_t stop (); }
Parameterized Interfaces • Note [ …] : This is not a parameter list (can have that too). module GenericCommM { provides interface SendMsg [uint8_t id]; provides interface ReceiveMsg [uint8_t id]; … } implementation {… } GenericCommM.nc
Parameterized Interfaces ID = 1 ID = 2 ID = 3 Uses SendMsg Interface Uses SendMsg Interface Uses SendMsg Interface Send Msg 1 Send Msg 2 Send Msg 3 SendMsg Interface Provided by some Component Must know who to respond to All boxes are components
Parameterized Interfaces ID = 1 ID = 2 ID = 3 Uses Timer Interface Uses Timer Interface Uses Timer Interface Set timer for 200 ms Set timer for 150 ms Set timer for 75 ms Timer Interface Provided by some Component Must know who to respond to All boxes are components
Components/Interfaces Events Commands Interface1 command a command b event c Interface2 command d Wire all components that issue commands a, b or d to this component Provides Component
Configurations • Wire components together • Connected elements must be compatible (interface-interface, command-command, event-event) • 3 wiring statements in nesC: • endpoint1 = endpoint2 • endpoint1 -> endpoint2 • endpoint1 <- endpoint2 (equivalent: endpoint2 -> endpoint1)
Configuration - Example • Blink application • Wiring Example BlinkC Main configuration BlinkC { } implementation { components Main, BlinkM, ClockC, LedsC; Main.StdControl->BlinkM.StdControl; BlinkM.Clock->ClockC; BlinkM.Leds->LedsC; } BlinkM BlinkC.nc ClockC LedsC ClockC is really ClockC.Clock LedsC is really LedsC.Leds
Configuration Main.StdControl -> BlinkM.StdControl Component Interface Implementation Component Interface USES PROVIDES
Equals Sign A: provides I But A does not implement I but uses what is provided by B Hence A = B B: provides I Often used for hierarchical Configuration files – see Example later
Implementation • fn.nc • For all source files (interfaces, modules and configurations)
Concurrency Model • Underlying execution model (TinyOS) • Tasks and Events • Split phase operation
Tasks • Tasks • Deferred computation • Non-preemptable by other tasks • Scheduled FCFS from task queue • When no tasks – CPU goes to sleep • Returns void • Declare tasks with task keyword • Schedule tasks with post keyword
Task task void processData() { int16_t i, sum=0; atomic { for (i=0; i< size; i++) sum += (rdata[i] >> 7); } display(sum >> log2size); }
Tasks FCFS Queue alert task void abc() { . . post alert(); . . } Next task Current task TinyOS Non-preemptive
Events • Events • Execution of an interrupt handler • Runs to completion • Can preempt tasks and can be preempted by other events • Declare events with event keyword (as part of interfaces) • Notify events with signal keyword
Events FCFS Queue alert P R E E M P T Event: packet here Upcalls Event: byte Here Signal packet Can post Tasks/keep Handlers short Event: Bits Signal Byte HW interrupt/ radio Asynchronous
Commands and Events • For those commands and events that can be executed by interrupt handlers – explicitly mark as async async event result_t ADC.ready (uint16_t data) { putdata(data); post processData(); return SUCCESS; }
Events • Signify completion of a split-phase operation • Example: packet send via send command; then communication component will signal sendDone event when transmission is complete • Events from environment • Message reception • Clock firing
Race Conditions • Solutions • Access shared data exclusively within tasks • Have all accesses within atomic statements X Non-preemptive Task queue x Shared data Event Handlers
Directions of Calls Event Call – use keyword signal Component Command Call – use keyword call
Big Picture Components (modules) async command post task call commands signal events … command … Main … Task … post tasks call commands signal events … Task … Components (modules) async command … command … async event … HW Interrupts Invoke commands and events
Components - nesC X = Y Config notation • The nesC model: • Interfaces: • uses • provides • Components: • modules • configurations • Application:= graph of components Application Component D Component A Component C Component B Component F Component E configuration configuration
Modules • Call commands and Signal events module TimerM { provides interface StdControl; provides interface Timer[uint8_t id]; uses interface Clock;… } implementation { command result_t StdControl.stop() { call Clock.setRate(TOS_I1PS, TOS_S1PS); … signal xyz.fired(); } … } TimerM.nc
Modules • Task: a task is an independent locus of control defined by a function of storage class task returning void and with no arguments • Posting tasks: keyword post 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
Atomic Statements bool busy; // gobal .… bool available; …. atomic { available = !busy; busy = TRUE; } …. atomic busy = false; nesC forbids calling commands or signaling events in an atomic section
Interrupt Handling • Keep interrupt handlers short • May post tasks • Examples • Increment counter in atomic statement and then done • Call LED to set light red; done • Post task; done • Call -> Call -> Call -> Call then return, …; bad idea
Matching SW and HW • Thin veneer of code for HW devices • See next slide • Assign symbolic names for signals/pins • Photo_PWR (to turn on power to photo sensor) • Abstract away interrupt vectors HW defined Interrupt Vectors Interrupt Handler
Matching SW and HW • Example LED • Red LED on/off • Green LED on/off • Yellow LED on/off • Toggle • Turn on/off power • LED has no interrupts • User has it easy; just know interface