![Page 1: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/1.jpg)
TinyOS Tutorial (Part II)
(courtesy of Greg Hackmann
and his notes for CSE 521S Fall 2010)
![Page 2: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/2.jpg)
Synchronous vs. Asynchronous
Commands and event handlers normally run in synchronous context i.e., cannot be reached by an interrupt handler
The async keyword notifies nesC that the command/event handler may run in an asynchronous context:
2
implementation { async event void Alarm.fired() { // Handle hardware alarm interrupt } }
![Page 3: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/3.jpg)
Reminder: Race Conditions
Use atomic blocks to avoid race conditions
3
Interrupts are disabled here -- use sparingly and make as short as practical
implementation { uint8_t sharedCounter; async event void Alarm.fired() { atomic { sharedCounter++; } } event void Receive.receive(...) { ... sharedCounter++; } }
![Page 4: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/4.jpg)
Reminder: Race Conditions
Tasks are always synchronous
If timing isn’t crucial, defer code to tasks to avoid race conditions
4
implementation { uint8_t sharedCounter; task void incrementCounter() { sharedCounter++; } async event void Alarm.fired() { post incrementCounter(); } event void Receive.receive(...) { ... sharedCounter++; } }
Task is scheduled immediately, but
executes later
![Page 5: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/5.jpg)
nesC and Race Conditions
nesC can catch some, but not all, potential race conditions
If you’re absolutely sure that there’s no race condition (or don’t care if there is), use the norace keyword:
5
implementation { norace uint8_t sharedCounter; async event void Alarm1.fired() { sharedCounter++; call Alarm2.start(200); } async event void Alarm2.fired() { sharedCounter--; call Alarm1.start(200); } }
Race condition is impossible; events
are mutually exclusive
![Page 6: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/6.jpg)
TOSThreads
New in TinyOS 2.1: the TOSThreads threading library
Threads add a third execution context to TinyOS’s concurrency layer Lowest priority: only run when TinyOS kernel is idle
Threads are preemptable by anything: sync, async, or other threads
Also adds a library of synchronization primitives (mutex, semaphore, etc.) and blocking wrappers around non-blocking I/O
Described in TOSThreads Tutorial (http://docs.tinyos.net/ index.php/TOSThreads_Tutorial) or TEP 134
6
![Page 7: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/7.jpg)
configuration NetworkHandlerC { provides interface SplitControl; } implementation { components NetworkHandlerP as NH, ActiveMessageP as AM; NH.Receive -> AM.Receive; NH.SplitControl = SplitControl; }
Configurations
7
// // NH.Receive -> AM; NH = SplitControl;
List interfaces that the component imports &
exports
Give comma-separated list(s) of constituent
components
Wire two components’ interfaces together using an arrow pointing from
user to provider Wire external
interfaces using =
![Page 8: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/8.jpg)
Outline
Installing TinyOS and Building Your First App
Hardware Primer
Basic nesC Syntax
Advanced nesC Syntax
Network Communication
Sensor Data Acquisition
Debugging Tricks and Techniques
8
![Page 9: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/9.jpg)
Recall:
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, connecting interfaces used by components to interfaces provided by others.
nesC application = top-level configuration that wires together the components inside.
9
File Name File Type
Foo.nc Interface
Foo.h Header File
FooC.nc Public Module
FooP.nc Private Module
![Page 10: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/10.jpg)
High-Level Summary
nesC includes a lot of complex features that try to alleviate design problems with TinyOS 1.x
The good news: you will probably never have to write code that incorporates these features
The bad news: you’re almost certain to use code that incorporates these features
First, an abstract look at what these features are and what their syntax means
Second, a concrete example of how to use them to build components
10
![Page 11: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/11.jpg)
Slight Diversion: App Bootstrapping
Each app has a “main” configuration which wires together the app’s constituent components
But how do these components start running?
TinyOS includes a MainC component which provides the Boot interface:
interface Boot {
event void booted();
}
11
![Page 12: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/12.jpg)
Slight Diversion: App Bootstrapping
Create one module which initializes your application, then wire MainC’s Boot interface into it:
12
configuration MyAppC { } implementation { components MyAppP; components MainC; ... MyAppP.Boot -> MainC; }
module MyAppP { uses interface Boot; } implementation { event void Boot.booted() { // Initialize app here } ... }
![Page 13: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/13.jpg)
Interfaces with Arguments
Creating new interfaces to support different data types can get redundant fast
interface ReadUint16 {
command error_t read();
event void readDone(error_t error, uint16_t value);
}
interface ReadBool {
command error_t read();
event void readDone(error_t error, bool value);
}
13
![Page 14: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/14.jpg)
Interfaces with Arguments
If you want to make an interface adapt to different underlying types, then put a placeholder in angle brackets:
interface Read<type> {
command error_t read();
event void readDone(error_t error, type value);
}
module SixteenBitSensorP {
provides interface Read<uint16_t>;
}
module BooleanSensorP {
provides interface Read<bool>;
}
14
![Page 15: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/15.jpg)
Fan-In: No Big Deal
15
NetworkHandlerP AnotherHandlerP AppLogicP
RadioP
provides Receive
uses Receive uses Receive uses Receive
Many-to-one calls work like you’d expect ...
![Page 16: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/16.jpg)
Fan-Out: Bad Things Happen
16
NetworkHandlerP AnotherHandlerP AppLogicP
provides Receive
uses Receive uses Receive uses Receive
… but what about one-to-many calls?
RadioP
return &buffer1; return &buffer2; return &buffer3;
![Page 17: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/17.jpg)
Fan-Out: What Bad Things Happen?
If different return values come back, nesC may not be able to make sense of the contradiction and will arbitrarily pick one
Avoid designs where this is possible
If you can’t avoid it, see TinyOS Programming Guide 5.2 for more info on combining return values
17
![Page 18: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/18.jpg)
Parameterized Wiring
Consider the following way to avoid fan-out: module RadioP { provides interface Receive as Receive0; provides interface Receive as Receive1; provides interface Receive as Receive2; uses interface LowLevelRadio; ... } implementation { event void LowLevelRadio.packetReceived( uint8_t * rawPacket) { ... uint8_t type = decodeType(rawPacket); if(type == 0) signal Receive0.receive(...); else if(type == 1) signal Receive1.receive(...); ... } ... }
18
Network HandlerP
Another HandlerP
AppLogicP
RadioP
uses Receive uses Receive uses Receive
![Page 19: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/19.jpg)
Parameterized Wiring
The idea works in concept, but isn’t maintainable in practice
But nesC can approximate the behavior in a much more maintainable way:
module RadioP {
provides interface Receive[uint8_t id];
...
}
implementation {
event void LowLevelRadio.packetReceived(uint8_t * rawPacket) {
...
uint8_t type = decodeType(rawPacket);
signal Receive[type].received(...);
}
...
}
19
![Page 20: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/20.jpg)
Using Parameterized Wiring
You can wire parameterized interfaces like so: AppLogicP -> RadioP.Receive[0]; NetworkHandlerP -> RadioP.Receive[1]; AnotherHandlerP -> RadioP.Receive[2];
If each component is wired in with a unique parameter, then fan-out goes away
20
![Page 21: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/21.jpg)
Unique Parameters
In most cases, it’s unreasonable to expect the user to count the number of times (s)he is using the interface and wire accordingly
nesC can automatically generate a unique parameter for you using the unique() macro:
AppLogicP -> RadioP.Receive[unique(“RadioP”)];
// unique(“RadioP”) expands to 0
NetworkHandlerP -> RadioP.Receive[unique(“RadioP”)];
// unique(“RadioP”) expands to 1
AnotherHandlerP -> RadioP.Receive[unique(“RaadioP”)];
// unique(“RaadioP”) expands to 0 (oops)
...
21
![Page 22: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/22.jpg)
uniqueCount()
What if your component needs to store different state for each unique parameter?
module RadioP {
...
}
implementation {
int16_t state[ ];
...
}
22
uniqueCount(“RadioP”)
uniqueCount(X) expands to # of times unique(X) appears in
the application
![Page 23: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/23.jpg)
Defaults
If you provide a parameterized interface and signal an event on it, you must also give a default event handler:
module SharedComponentP {
... } implementation { event void LowLevelRadio.packetReceived(uint8_t * rawPacket) {
... signal Receive[type].received(...); } default event void Receive.received[uint8_t id](...) { // e.g., do nothing } ... }
23
![Page 24: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/24.jpg)
Generic Components
What if you have a component where different users absolutely should not share any state?
Generic components let you “instantiate” a single component multiple times
generic module HashTableP() {
provides interface HashTable;
}
...
components new HashTableP() as H1, new HashTableP() as H2;
AppLogicP.HashTable -> H1;
NetworkHandlerP.HashTable -> H2;
24
![Page 25: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/25.jpg)
Generic Components
But wait ... didn’t I say earlier that components aren’t objects?
nesC internally creates a complete second copy of the component
25
HashTableP$0
AppLogicP
HashTableP$1
NetworkHandlerP
![Page 26: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/26.jpg)
Generic Components with Parameters
You can give each instantiation of the component slightly different behavior by adding compile-time parameters:
generic module ListP(typedef type, uint8_t size) { provides interface List<type>; } implementation { type data[size]; command void List.clear() { for(uint8_t i = 0; i < size; i++) data[i] = 0; } } components new ListP(bool, 16);
26
![Page 27: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/27.jpg)
Putting It All Together: Building a Timer
Consider an AlarmC component that exposes a 32 KHz hardware clock using the following interface:
interface Alarm {
async event void fired();
}
We want to create a high-level timer component that: Runs outside of the asynchronous context
Can be hooked into multiple components
Each consumer can choose a custom firing interval (every n ticks)
Can be transformed into lower frequencies (16 KHz, 1 Hz, etc.)
27
![Page 28: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/28.jpg)
Step 1: Get Out of Asynchronous Context
interface Timer { event void fired(); } module AlarmToTimerP { provides interface Timer; uses interface Alarm; } implementation { task void timerTask() { signal Timer.fired(); } async event void Alarm.fired() { post timerTask(); } }
28
AlarmC
Alarm
AlarmToTimerP
Alarm
Timer
![Page 29: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/29.jpg)
Step 2: Virtualize the Timer module VirtualizeTimerP { uses interface Timer as SubTimer; provides interface Timer[uint8_t id]; } implementation { event void SubTimer.fired() { uint8_t i; for(i = 0; i < 255; i++) { signal Timer.fired[i](); } } default event void Timer.fired[uint8_t id]() { // Do nothing } }
29
AlarmC
Alarm
AlarmToTimerP
Alarm
Timer
VirtualizeTimerP
Timer
SubTimer
![Page 30: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/30.jpg)
Step 3: Reprogram the Timer interface Timer /* v. 2 */ { event void fired(); command void startPeriodic(uint16_t interval); }
30
AlarmC
Alarm
AlarmToTimerP
Alarm
Timer
VirtualizeTimerP
Timer
SubTimer
![Page 31: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/31.jpg)
Step 3: Reprogram the Timer module VirtualizeTimerP /* v. 2 */ { ... } implementation { uint16_t currentTime = 0; uint16_t nextTimeToFire[255]; uint16_t intervals[255]; event void SubTimer.fired() { uint8_t i; for(i = 0; i < 255; i++) { if(nextTimeToFire[i] == currentTime) { signal Timer.fired[i](); nextTimeToFire[i] += intervals[i]; } } currentTime++; } command void Timer.startPeriodic[uint8_t id](uint16_t interval) { nextTimeToFire[id] = currentTime + interval; intervals[id] = interval; } ... }
31
AlarmC
Alarm
AlarmToTimerP
Alarm
Timer
VirtualizeTimerP
Timer
SubTimer
![Page 32: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/32.jpg)
Step 3.5: Tidy Up the Wiring generic configuration VirtualizedTimerC()
{ provides interface Timer; } implementation { components AlarmC; components AlarmToTimerP to AtoT; components VirtualizeTimerP as Virt; AtoT.Alarm -> AlarmC; Virt.SubTimer -> AtoT; Timer = Virt.Timer[ unique(“VirtualizedTimerC”) ]; }
32
VirtualizedTimerC
AlarmC
AlarmToTimerP
Alarm
Alarm
Timer
VirtualizeTimerP
Timer
SubTimer
![Page 33: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/33.jpg)
Step 3.5: Tidy Up the Wiring
33
VirtualizedTimerC VirtualizedTimerC VirtualizedTimerC
[0] [1] [2]
AlarmC
AlarmToTimerP
Alarm
Alarm
Timer
VirtualizeTimerP
Timer
SubTimer
![Page 34: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/34.jpg)
Step 3.5: Tidy Up the Wiring module VirtualizeTimerP /* v. 2.5 */ { ... } implementation { enum { NUM_SLOTS = uniqueCount(“VirtualizedTimerC”); } uint16_t currentTime = 0; uint16_t nextTimeToFire[NUM_SLOTS]; uint16_t intervals[NUM_SLOTS]; event void SubTimer.fired() { uint8_t i; for(i = 0; i < NUM_SLOTS; i++) { ...
34
VirtualizedTimerC
AlarmC
AlarmToTimerP
Alarm
Alarm
Timer
VirtualizeTimerP
Timer
SubTimer
![Page 35: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/35.jpg)
Step 4: Transform the Timer’s Frequency
generic module TransformTimerP(uint16_t multiplier) {
uses interface Timer as SubTimer; provides interface Timer; } implementation { event void SubTimer.fired() { signal Timer.fired(); } command void Timer.startPeriodic(uint16_t interval) { call SubTimer.startPeriodic(interval * multiplier); } }
35
Transform TimerP(2)
Timer
SubTimer
Transform TimerP(32)
Timer
SubTimer
Virtualized TimerC
Timer
Virtualized TimerC
Timer
Virtualized TimerC
Timer
![Page 36: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/36.jpg)
Step 5: Add Type Safety
36
enum { T32Khz, T16Khz, …, TMilli, };
typedef struct { bool unused; } T32Khz; typedef struct { bool unused; } T16Khz; typedef struct { bool unused; } TMilli;
Virtualized TimerC
Timer<T32Khz>
Virtualized TimerC
Virtualized TimerC
Timer<T32Khz> Timer<T32Khz>
interface Timer<frequency> /* v. 3 */ { event void fired(); command void startPeriodic(uint16_t interval); }
![Page 37: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/37.jpg)
Step 5: Add Type Safety generic module TransformTimerP( typedef frequency, uint16_t multiplier) { uses interface Timer<T32Khz> as SubTimer; provides interface Timer<frequency>; } implementation { event void SubTimer.fired() { signal Timer.fired(); } command void Timer.startPeriodic(uint16_t interval) { call SubTimer.startPeriodic(interval * multiplier); } }
37
Virtualized TimerC
Timer<T32Khz>
Virtualized TimerC
Timer<T32KHz>
Virtualized TimerC
Timer<T32Khz>
TransformTimerP(TMilli, 32)
Timer<TMilli>
SubTimer<T32Khz>
TransformTimerP(T16Khz, 2)
Timer<T16Khz>
SubTimer<T32Khz>
![Page 38: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/38.jpg)
The Good News
This is just an example! It’s already been implemented for you
TimerMilliC component provides Timer<TMilli> interface
38
![Page 39: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/39.jpg)
Outline
Installing TinyOS and Building Your First App
Hardware Primer
Basic nesC Syntax
Advanced nesC Syntax
Network Communication
Sensor Data Acquisition
Debugging Tricks and Techniques
39
![Page 40: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/40.jpg)
Slight Diversion #2: error_t Data Type
TinyOS defines a special error_t data type that describes several different error codes
Often given as return values to commands or event handlers
Commonly used values: SUCCESS (everything’s OK)
FAIL (general error, deprecated)
EBUSY (subsystem is busy with another request, retry later)
ERETRY (something weird happened, retry later)
Others defined in $TOSROOT/types/TinyError.h
40
![Page 41: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/41.jpg)
Message Addressing
Each node has a unique 16-bit address (am_addr_t) specified by the make command make install.[address] platform
Two special address constants: TOS_BCAST_ADDR (0xFFFF) is reserved for broadcast traffic
TOS_NODE_ID always refers to the node’s own address
Each message also has an 8-bit Active Message ID (am_id_t) analogous to TCP ports Determines how host should handle received packets, not which
host receives it
41
![Page 42: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/42.jpg)
TinyOS Active Messages
message_t structure defined in $TOSROOT/tos/types/message.h
Each platform defines platform-specific header, footer, and metadata fields for the message_t
Applications can store up to TOSH_DATA_LENGTH bytes payload in the data field (28 by default)
42
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;
Header Payload (TOSH_DATA_LENGTH) Footer Metadata
![Page 43: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/43.jpg)
Split-Phase Operation
Many networking commands take a long time (ms) for underlying hardware operations to complete -- blocking would be bad
TinyOS makes these long-lived operations split-phase Application issues start...() command that returns immediately
An event is signaled when it’s actually done
43
interface SplitControl { command error_t start(); event void startDone(error_t error); command error_t stop(); event void stopDone(error_t error); }
Error code here indicates whether TinyOS could start processing request
Error code here indicates whether TinyOS could complete processing request
![Page 44: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/44.jpg)
Active Messaging Interfaces
interface AMSend { command error_t send(am_addr_t addr, message_t * msg, uint8_t len); command error_t cancel(message_t * msg); event void sendDone(message_t * msg, error_t error); command uint8_t maxPayloadLength(); command void* getPayload(message_t * msg, uint8_t len); } interface Receive { event message_t* receive(message_t * msg, void * payload, uint8_t len); }
44
![Page 45: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/45.jpg)
interface Packet { command void clear(message_t * msg); command void* getPayload(message_t * msg, uint8_t len); command uint8_t payloadLength(message_t * msg); command void setPayLoadLength(message_t * msg, uint8_t len); command uint8_t maxPayloadLength(); }
Other Networking Interfaces
45
![Page 46: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/46.jpg)
interface AMPacket { command am_addr_t address(); command am_group_t localGroup(); command am_addr_t destination(message_t* amsg); command am_addr_t source(message_t* amsg); command am_group_t group(message_t* amsg); command bool isForMe(message_t* amsg); command am_id_t type(message_t* amsg); }
Other Networking Interfaces
46
![Page 47: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/47.jpg)
Demo: “Blink” Application
nesC compiler compiles a nesC application when given the file containing the top-level configuration. Typical TinyOS applications come with a standard Makefile that allows platform selection and invokes ncc with appropriate options on the application's top-level configuration. Example: the file BlinkAppC.nc
47
configuration BlinkAppC {
// NOTE: no “uses” or “provides”…
}
implementation {
components MainC, BlinkC, LedsC;
components new TimerMilliC() as Timer0;
components new TimerMilliC() as Timer1;
components new TimerMilliC() as Timer2;
BlinkC -> MainC.Boot;
BlinkC.Timer0 -> Timer0;
BlinkC.Timer1 -> Timer1;
BlinkC.Timer2 -> Timer2;
BlinkC.Leds -> LedsC; }
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 }
![Page 48: TinyOS Tutorial (Part II) - Northwestern Universityusers.eecs.northwestern.edu/~peters/courses/eecs369/docs/... · 2011-02-03 · TOSThreads New in TinyOS 2.1: the TOSThreads threading](https://reader030.vdocuments.us/reader030/viewer/2022040823/5e6e12695391023de020bf8d/html5/thumbnails/48.jpg)
Components Visualization
make platform docs NOTE: may need install graphviz
48
Single(ton) module
Configuration Generic