420 likes | 527 Views
Peek into TinyOS Programs. Vinod Kulathumani. Basics. Application consists of one or more components assembled, or wired A component provides and uses interfaces. Interfaces are bidirectional: they specify a set of commands and a set of events
E N D
Peek into TinyOS Programs Vinod Kulathumani
Basics • Application consists of one or more components assembled, or wired • A component provides and uses interfaces. • Interfaces are bidirectional: • they specify a set of commands • and a set of events • For a component to call the commands in an interface, it must implement the events of that interface. • A single component may use or provide multiple interfaces and multiple instances of the same interface. • Signature - The set of interfaces a component provides + set of interfaces that a component uses
Components • Two types of components in nesC • modules and configurations • Modules provide the implementations of one or more interfaces • Configurations are used to assemble other components together • connect interfaces used by components to interfaces provided by others • Every nesC application described by a top-level configuration
Convention • Header File abc.h • Interface abc.nc • Configuration abcAppC.nc • Module [Public] abcC.nc • Module [Private] abcP.nc
HelloAppC Configuration configurationHelloAppC { } implementation { }
HelloAppC Configuration configuration HelloAppC { } implementation { components HelloC; }
HelloC Module moduleHelloC { } implementation { }
HelloC Module module HelloC { uses { interface Boot; interface Leds; } } implementation { }
HelloC Module module HelloC { uses { interface Boot; interface Leds; } } implementation { }
Boot Interface interface Boot { event void booted(); }
HelloC Module module HelloC { uses { interface Boot; interface Leds; } } implementation { event void Boot.booted() { } } USE an interface, CAPTURE all of its events!
Leds Interface interface Leds { command void led0On(); command void led0Off(); command void led0Toggle(); … command void set(uint8_t val); }
HelloC Module module HelloC { uses { interface Boot; interface Leds; } } implementation { event void Boot.booted() { call Leds.led0On(); } }
HelloAppC Configuration configuration HelloAppC { } implementation { components HelloC, MainC, LedsC; // USES -> PROVIDES HelloC.Boot -> MainC.Boot; HelloC.Leds -> LedsC; }
Example 2: Blink • Configuration – BlinkAppC.nc • Module – BlinkC.nc
Configuration configuration BlinkAppC { } implementation { }
Implementation module BlinkC { } implementation { }
Configuration components list configuration BlinkAppC { } implementation { components MainC, BlinkC, LedsC; components new TimerMilliC() as Timer0; components new TimerMilliC() as Timer1; components new TimerMilliC() as Timer2; }
Module provides / uses Module BlinkC{ uses interface Timer<TMilli> as Timer0; uses interface Timer<TMilli> as Timer1; uses interface Timer<TMilli> as Timer2; uses interface Leds; uses interface Boot; } implementation { // implementation code omitted }
Module provides / uses Module BlinkC{ uses interface Timer<TMilli> as Timer0; uses interface Timer<TMilli> as Timer1; uses interface Timer<TMilli> as Timer2; uses interface Leds; uses interface Boot; } implementation { event void Boot.booted() { call Timer0.start(); …. } event Timer0.fired() { … } event Timer1.fired() { … } }
Configuration wiring configuration BlinkAppC { } implementation { components MainC, BlinkC, LedsC; components new TimerMilliC() as Timer0; components new TimerMilliC() as Timer1; components new TimerMilliC() as Timer2; BlinkC.Boot -> MainC.Boot; BlinkC.Timer0 -> Timer0; BlinkC.Timer1 -> Timer1; BlinkC.Timer2 -> Timer2; BlinkC.Leds -> LedsC; }
Sensing example configuration SenseAppC { } implementation { components SenseC, MainC, LedsC, new TimerMilliC() as TimerSensor, new DemoSensorC() as Sensor; }
Sensing module SenseC { uses { interface Boot; interface Leds; interface Timer<TMilli> as TimerSensor; interface Read<uint16_t> as SensorRead; } }
Sensing implementation { event void boot.booted { call TimerSensor.startPeriodic(SAMPLING_FREQUENCY); } event void TimerTemp.fired() { call SensorRead.read(); } event void SensorRead.readDone(error_t result, uint16_t data) { if (result == SUCCESS) {Call leds.led0Toggle(); } } }
Sensing example configuration SenseAppC { } implementation { components SenseC, MainC, LedsC, new TimerMilliC() as TimerSensor, new DemoSensorC() as Sensor; SenseC.Boot -> MainC; SenseC.Leds -> LedsC; SenseC.TimerSensor-> TimerSensor; SenseC.SensorRead-> Sensor; }
Radio Stacks Your Application SplitControl AMSend Receive Message Queue ActiveMessage CSMA / Acknowledgements Transmit / Receive / Init Radio Hardware
Main Radio Interfaces • SplitControl • Provided by ActiveMessageC • AMSend • Provided by AMSenderC • Receive • Provided by AMReceiverC
Main Serial Interfaces • SplitControl • Provided by SerialActiveMessageC • AMSend • Provided by SerialAMSenderC • Receive • Provided by SerialAMReceiverC
Setting up the Radio: Configuration configuration MyRadioAppC { } implementation { components MyRadioC, MainC, ActiveMessageC, new AMSenderC(0) as Send0, // send an AM type 0 message new AMReceiverC(0) as Receive0; // receive an AM type 0 }
Setting up the Radio: Module module MyRadioC { uses { interface Boot; interface SplitControl; interface AMSend; interface Receive; } } implementation { }
Turn on the Radio event void Boot.booted() { call SplitControl.start(); } event void SplitControl.startDone(error_t error) { post sendMsg(); } event void SplitControl.stopDone(error_t error) { }
Setting up the Radio: Configuration configuration MyRadioAppC { } implementation { components MyRadioC, MainC, ActiveMessageC, new AMSenderC(0) as Send0, // send an AM type 0 message new AMReceiverC(0) as Receive0; // receive an AM type 0 MyRadioC.Boot -> MainC; MyRadioC.SplitControl -> ActiveMessageC; MyRadioC.AMSend -> Send0; MyRadioC.Receiver -> Receive0; }
Payloads • A message consists of: • Header • Payload • Optional Footer
message_t 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;
Payloads : Use Network Types (MyPayload.h) typedef nx_struct MyPayload { nx_uint8_t count; } MyPayload;
Send Messages message_t myMsg; bool sending=false; task void sendMsg() { MyPayload *payload = (MyPayload *)call ASMSend.getPayload(&myMsg); payload->count = (myCount++); if (sending==false) { error_t p; p = call AMSend.send(AM_BROADCAST_ADDR, myMsg, 0); If (p==SUCCESS) sending=true; else post sendMsg(); } } event void AMSend.sendDone(message_t *msg, error_t error) { sending=false; }
Receive a Message event message_t *Receive.receive(message_t *msg, void *payload, uint8_t length) { MyPayload* pkt = (MyPayload *)payload; uint8_t ct = pkt->count; call Leds.led0Toggle(); return msg; }
RealMainP module RealMainP { provides interface Boot; uses { interface Scheduler; interface Init as PlatformInit; interface Init as SoftwareInit; } } Implementation{ // platform initialization stuff call SoftwareInit.init() signal Boot.booted(); // call scheduler task loop }
SoftwareInit in RealMainP • Suppose user writes module RandomIntC • provides an interface Init • should be initialized before use (to generate seed) • what if application developer forgets • Instead write a configuration RandomC around RandomIntC Module RandomC { provides interface Init; } Implementation RandomC{ components MainC, RandomIntC; MainC.SoftwareInit -> RandomIntc.Init; }
SoftwareInit in RealMainP • So far we didn’t care in our examples • All our examples were applications • Did not provide interface • Interior components that provide interface may need Init • MainC.SoftwareInit may be wired to many Inits • Each will be called in sequence
References TinyOS Tutorials – www.tinyos.net David Moss TinyOS 2 tutorial