Peek into TinyOS Programs
Vinod Kulathumani
2
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
3
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
4
Convention
• Header File abc.h
• Interface abc.nc
• Configuration abcAppC.nc
• Module [Public] abcC.nc
• Module [Private] abcP.nc
5
HelloAppC Configuration
configuration HelloAppC {
}
implementation {
}
6
HelloAppC Configuration
configuration HelloAppC {
}
implementation {
components HelloC;
}
7
HelloC Module
module HelloC {
}
implementation {
}
8
HelloC Module
module HelloC {
uses {
interface Boot;
interface Leds;
}
}
implementation {
}
9
HelloC Module
module HelloC {
uses {
interface Boot; interface Leds;
}
}
implementation {
}
10
Boot Interface
interface Boot {
event void booted();
}
11
HelloC Module
module HelloC {
uses {
interface Boot;
interface Leds;
}
}
implementation {
event void Boot.booted() {
}
}
USE an interface,
CAPTURE all of its events!
12
Leds Interface
interface Leds {
command void led0On();
command void led0Off();
command void led0Toggle();
…
command void set(uint8_t val);
}
13
HelloC Module
module HelloC {
uses {
interface Boot;
interface Leds;
}
}
implementation {
event void Boot.booted() {
call Leds.led0On();
}
}
14
HelloAppC Configuration
configuration HelloAppC {
}
implementation {
components HelloC,
MainC,
LedsC;
// USES -> PROVIDES
HelloC.Boot -> MainC.Boot;
HelloC.Leds -> LedsC;
}
15
Hello Application
16
Example 2: Blink
• Configuration – BlinkAppC.nc
• Module – BlinkC.nc
17
Configuration
configuration BlinkAppC {
}
implementation {
}
18
Implementation
module BlinkC {
}
implementation {
}
19
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; }
20
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
}
21
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() { … }}
22
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; }
23
Sensing example
configuration SenseAppC
{ }
implementation {
components SenseC, MainC, LedsC,
new TimerMilliC() as TimerSensor,
new DemoSensorC() as Sensor;
}
24
Sensing
module SenseC
{
uses {
interface Boot;
interface Leds;
interface Timer<TMilli> as TimerSensor;
interface Read<uint16_t> as SensorRead;
}
}
25
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(); }
}
}
26
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;
}
27
Radio Stacks
Radio Hardware
Transmit / Receive / Init
CSMA / Acknowledgements
ActiveMessage
Message Queue
Your Application
ReceiveSplitControlAMSend
28
Main Radio Interfaces
• SplitControl
Provided by ActiveMessageC
• AMSend
Provided by AMSenderC
• Receive
Provided by AMReceiverC
29
Main Serial Interfaces
• SplitControl
Provided by SerialActiveMessageC
• AMSend
Provided by SerialAMSenderC
• Receive
Provided by SerialAMReceiverC
30
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
}
31
Setting up the Radio: Module
module MyRadioC { uses { interface Boot; interface SplitControl; interface AMSend; interface Receive; }}implementation { }
32
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) { }
33
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;}
34
Payloads
• A message consists of:
Header Payload Optional Footer
35
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;
36
Payloads : Use Network Types
(MyPayload.h)
typedef nx_struct MyPayload { nx_uint8_t count;} MyPayload;
37
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;}
38
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;
}
39
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
}
40
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;
}
41
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
42
References
TinyOS Tutorials – www.tinyos.net
David Moss TinyOS 2 tutorial