TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a...

24
TinyOS Programming By: R Jayampathi Sampath

Transcript of TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a...

Page 1: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

TinyOS Programming

By: R Jayampathi Sampath

Page 2: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

nesC (network embedded system C)

• necC is a component-based C dialect.• nesC application consists of one or

more components wired.• Use a purely local namespace.• There are two types of components:

– modules • provide the implementation of one or more

interfaces.

– configurations • used to wire other components together.

Page 3: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Contd.• Components define two scopes.

– Specification (signature) • names of interfaces it provides (implements) and

names of interfaces it uses (calls).

– Implementation • implementation of commands and events.

module configurationmodule

{

…..//provide and uses interfaces

…}

implementation{

…..//executable code

…}

configuration

{

…..//provide and uses interfaces

…}

implementation{

…..//wire components

…}

Page 4: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Modules and State• Modules:

– are executable codes.– must implement every command of interfaces it

provides and every event of interfaces it uses.– can declare state variables. Any state of a components

is private.– Ex: uint8_t counter = 0;

8 bits 16 bits 32 bits 64 bits

signed int8_t int16_t int32_t int64_t

unsigned

uint8_t uint16_t uint32_t uint64_t

Page 5: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

BilinkC.nc

module BilnkC

{

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.startPeriodic(250);

call Timer1.startPeriodic(500);

call Timer1.startPeriodic(1000);

}

event void Timer0.fired(){

call Leds.led0Toggle();

}

event void Timer1.fired(){

call Leds.led1Toggle();

}

event void Timer2.fired()

{

call Leds.led2Toggle();

}

}

BlinkAppC.nc

configuration BlinkC

{

}

Implementation

{

components MainC, BlinkC, LedsC;

components new TimerMillic() as Timer0;

components new TimerMillic() as Timer0;

components new TimerMillic() as Timer0;

BlinkC ->MainC.Boot;

BlinkC.Timer0 -> Timer0;

BlinkC.Timer1 -> Timer1;

BlinkC.Timer2 -> Timer2;

BlinkC.Leds -> LedsC;

}

nesC uses arrows to bind interfaces to one another. The right arrow (A->B) as "A wires to

B"

Page 6: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Interfaces, Commands and Events• if a component uses an interface, it can call the interface's

commands and must implement handlers for its events. • Invoking an interface command requires the call keyword,

and invoking an interface event requires the signal keyword.

• ExTimer.nc: interface Timer {

// basic interface command void startPeriodic( uint32_t dt ); command void startOneShot( uint32_t dt ); command void stop(); event void fired(); // extended interface omitted (all commands)

}

Page 7: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Internal Functions• Component's

private function for its own internal use.

• Similar to C function.

• Can’t invoke directly.

• Can freely call commands or signal events.

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 { void startTimers() {

call Timer0.startPeriodic( 250 ); call Timer1.startPeriodic( 500 ); call Timer2.startPeriodic( 1000 ); }

event void Boot.booted() { startTimers(); }

.

.

.}

•Ex:

Page 8: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Split-Phase Operations• Hardware is almost always split-phase (non blocking/asynchronous).• In split-phase completion of a request is a callback.

– ADC

• synchronous operation:– Magnetometer.– samples periodically.– when queried gives a cached value. (it can return the result immediately)

• make everything synchronous through threads is not possible.• Solution :

– Operations that are split-phase in hardware are split-phase in software.– Introduce interfaces that are bidirectional

ADC

S/W

Start SampleInterrupts when complete

Read the value

Page 9: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Split-Phase Operations (Contd.)

ADC

Down call

Start the operation

Up call

signals the operation is complete

• Down call - command• Up call - event

Page 10: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Split-Phase Operations (Contd.)• Split-phase interfaces enable a TinyOS component to easily start

several operations at once and have them execute in parallel. • split-phase operations can save memory.• Ex: The command Timer.startOneShot is an example of a split-

phase call. The user of the Timer inteface calls the command, which returns immediately. Some time later (specified by the argument), the component providing Timer signals Timer.fired. In a system with blocking calls, a program might use sleep():

Page 11: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Interfaces with Arguments• Interfaces can take types as arguments.

• wiring providers and users of interfaces that have type arguments, they types must match.

• used to enforce type checking.

Page 12: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Module Implementation

Page 13: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Tasks• Consider magnetometer/ADC example:

– depending on split-phase operations means that the magnetometer driver has to issue a callback.

– it could just signal the event from within the call.– signaling an event from within a command is

generally a bad idea.• might cause a very long call loop.• corrupt memory and crash the program.

– needs a way to schedule a function to be called later (like an interrupt).

– can do this is with a task.

Page 14: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Tasks (Contd.)• Task

– A module can post a task to the TinyOS scheduler.– doesn’t take any parameters.

– A component posts a task to the TinyOS scheduler with the post keyword: post

– only one task runs at any time. and TinyOS doesn’t interrupt one task to run another.

– Implies that tasks should usually be reasonably short.

Page 15: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Tasks (Contd.)• Ex:event void Timer.fired() {

call Read.read();}event void RawRead.readDone(error_t err, uint16_t val) {

if (err == SUCCESS) {lastVal = val;filterVal *= 9;filterVal /= 10;filterVal += lastVal / 10;

}}command error_t Read.read() {

post readDoneTask();return SUCCESS;

}task void readDoneTask() {

signal Read.readDone(SUCCESS, filterVal);}

• When Read.read is called, posts readDoneTask and returns immediately. At some point later, TinyOS runs the task, which signals Read.readDone.

Page 16: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Tasks (Contd.)• Why?

– Synchronous code runs in a single execution context and does not have any kind of pre-emption.

– sync code runs for a long time.– A component needs to be able to split a large

computation into smaller parts, which can be executed one at a time.

• Task– A task is function which a component tells

TinyOS to run later, rather than now.

Page 17: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Concurrency• Tasks allow software components to emulate the

split-phase behavior of hardware.• They also provide a mechanism to manage pre-

emption in the system.• In nesC and TinyOS, functions that can run

preemptively labeled with the async keyword.• async function can’t call a command or event

that isn’t async.• By default, commands and events are sync.• A task post is an async operation, while a task

running is sync.

Page 18: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Concurrency (Contd.)• Can’t make everything

async because of race condition.

• Ex: consider the command, toggle, which flips the state bit and returns the new one:

• Solutions:– Keep code synchronous

when you can.

– functionality through atomic statements.

Page 19: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Concurrency (Contd.)• The atomic block

promises that these variables can be read and written atomically

• this does not promise that the atomic block won’t be preempted– with atomic blocks, two

code segments that do not share any of the same variables can preempt one another

Page 20: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Concurrency (Contd.)• An atomic block involves some kind of

execution (e.g.. disabling an interrupt), so unnecessary atomics are a waste of CPU cycles.

• an atomic block does have a CPU cost, so you want to minimize how many you have.

• shorter atomic blocks delay interrupts less and so improve system concurrency.

Page 21: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Allocation• the only way that components can share

state is through function calls.• two basic ways that components can pass

parameters: by value and by reference (pointer).

• every pointer should have a clear owner, and only the owner can modify the corresponding memory.

• abstract data types (ADTs) in TinyOS are usually represented one of two ways:– Generic modules – Through an interface with by-reference

commands.

Page 22: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Allocation (An Example)• Generic module, Ex

– many TinyOS components needs to maintain bit vectors, and so in tos/system there’s a generic module BitVectorC that takes the number of bits as a parameter:

– This component allocates the bit vector internally and provides the BitVector interface to access it:

Page 23: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

Allocation (Contd.)– in BitVector, it’s possible that, after a bit has been

fetched for get() but before it returns, an interrupt fires whose handler calls set() on that same bit.

– you should call get() from within an atomic section.

• passing a parameter by reference,

– this is easy, as all of its commands are synchronous: no code that can preempt the call (async).

Page 24: TinyOS Programming By: R Jayampathi Sampath. nesC (network embedded system C) necC is a component-based C dialect. nesC application consists of one or.

References• TinyOS Documentation Wiki

(URL: http://docs.tinyos.net/index.php/Main_Page).

• TinyOS Programing (URL: http://www.tinyos.net/tinyos 2.x/doc/pdf/tinyos programming.pdf)