Download presentation
Presentation is loading. Please wait.
Published byAnthony Lucas Modified over 9 years ago
1
1 Software Development Infrastructure for Sensor Networks Operating systems ( TinyOS ) Resource (device) management Basic primitives Protocols (MAC, routing) {covered in many previous lectures} Programming languages and runtime environments Low level (C, nesC) Very high level abstractions ( Regiment ) Services needed Synchronization of clocks ( RBS ) Propagation of new code to all nodes ( Trickle ) Localization {not today}
2
2 Maintenance overheads Radio transmission scheduling (e.g. TDMA) + Route discovery & maintenance + Clock synchronization + Code propagation protocol + Sensor data delivery System Application Be aware of all the background message activity when designing application-level suppression.
3
Programming Platform for Sensor Networks: TinyOS Complements of Jun Yang With contents from D.-O. Kim, D. Culler, W. Xu
4
4 Challenges in programming sensors WSN usually has severe power, memory, and bandwidth limitations WSN must respond to multiple, concurrent stimuli At the speed of changes in monitored phenomena WSN are large-scale distributed systems
5
5 Traditional embedded systems Event-driven execution and real-time scheduling General-purpose layers are often bloated ! microkernel Strict layering often adds overhead ! expose hardware controls
6
6 Node-level methodology and platform Traditional design methodologies are node-centric Node-level platforms Operating system Abstracts the hardware on a sensor node Provides services for apps such as, traditionally, file management, memory allocation, task scheduling, device drivers, networking… Language platform Provides a library of components to programmers
7
7 TinyOS Started out as a research project at Berkeley Now probably the de facto platform Overarching goal: conserving resources No file system No dynamic memory allocation No memory protection Very simple task model Minimal device and networking abstractions Application and OS are coupled—composed into one image Both are written in a special language nesC
8
8 TinyOS components Components: reusable building blocks Each component is specified by a set of interfaces Provide “hooks” for wiring components together A component C can provide an interface I C must implement all commands available through I Commands are methods exposed to an upper layer An upper layer can call a command A component C can use an interface J C must implement all events that can be signaled by J These are methods available to a lower layer By signaling an event, the lower layer calls the appropriate handler Components are then wired together into an application C I J
9
9 Component specification module TimerModule { provides { interface StdControl; interface Timer01; } uses interface Clock as Clk; } … interface StdControl { command result_t init(); command result_t start(); command result_t stop(); } interface Timer01 { command result_t start(char type, uint32_t interval); command result_t stop(); event result_t timer0Fire(); event result_t timer1Fire(); } interface Clock { command result_t setRate(char interval, char scale); event result_t fire(); } TimerModule
10
10 Module vs. configurations Two types of components Module: implements the component specification (interfaces) with application code Configuration: implements the component specification by wiring existing components
11
11 Module implementation module TimerModule { provides { interface StdControl; interface Timer01; } uses interface Clock as Clk; } implementation { bool eventFlag; command result_t StdControl.init() { eventFlag = 0; return call Clk.setRate(128, 4); // 4 ticks per sec } event result_t Clk.fire() { eventFlag = !eventFlag; if (eventFlag) signal Timer01.timer0Fire(); else signal Timer01.timer1Fire(); return SUCCESS; } … } Just like method calls (unlike raising exceptions in Java, e.g.) Internal state
12
12 Configuration implementation = (equate wire) At least one must be external ! (link wire) Both internal; goes from user to provider configuration TimerConfiguration { provides { interface StdControl; interface Timer01; } } implementation { components TimerModule, HWClock; StdControl = TimerModule.StdControl; Timer01 = TimerModule.Timer01; TimerModule.Clock ! HWClock.Clock; } TimerModule HWClock TimerConfiguration
13
13 Commands vs. events { … status = call UsedInterfaceName.cmdName(args); … } event UsedInterfaceName.eventName(args) { … return status; } command cmdName(args) { … return status; } { … status = signal ProvidedInterfaceName.eventName(args); … }
14
14 FieldMonitor example
15
15 So… why wiring? C/C++/Java? Allow use of function pointers Allow binding to be resolved at runtime Flexibility Less flexibility, but now call graph can be determined at compile time! Can inline calls cross components (5-6) into a flat instruction stream with no function calls Lots of static analysis and optimization possible
16
16 Concurrency model Two types of execution contexts Tasks Longer running jobs Time flexible (Currently) simple FIFO scheduling Atomic w.r.t. other tasks, i.e., single-threaded But can be preempted by events Events (an overloaded term) More precisely, hardware interrupt handlers Time critical Shorten duration as much as possible By issuing tasks for later execution LIFO semantics; can preempt tasks and earlier events
17
17 Tasks A task is always posted for later execution; control returns to poster immediately Scheduler supports a bounded queue of pending tasks Node sleeps when the queue is empty For simplicity, tasks don’t take args and don’t return values Typical use Event necessitates further processing Wrap it up in a task Event handler simply posts the task and can return immediately implementation { task void TaskName() { … } … … { … post TaskName(); … } }
18
18 Execution example Task A Task B Task C … Task queue Task B Task C … Event 1 Event 2 Event 3 Hardware interrupts
19
19 A more complex example Timer01.Timer0Fire() triggers data acquisition (through ADC) and transmission to base station (through Send) module SenseAndSend { provides interface StdControl; uses { interface ADC; interface Timer01; interface Send; } } implementation { bool busy; norace unit16_t sensorReading; … command result_t StdControl.init() { busy = FALSE; } event result_t Timer01.Timer0Fire() { bool localBusy; atomic { localBusy = busy; busy = TRUE; } if (!localBusy) { call ADC.getData(); return SUCCESS; } else { return FAILED; } } task void sendData() { … adcPacket.data = sensorReading; … call Send.send(&adcPacket, sizeof(adcPacket.data)); return SUCCESS; } event result_t ADC.dataReady(uint16_t data) { sensorReading = data; post sendData(); atomic { busy = FALSE; } return SUCCESS; } … }
20
20 Split-phase operation Data acquisition doesn’t take place immediately ( why? ) How does a traditional OS accomplish this? OS puts thread to sleep when it blocks Why isn’t this approach good enough here? event result_t Timer01.Timer0Fire() { bool localBusy; atomic { localBusy = busy; busy = TRUE; } if (!localBusy) { call ADC.getData(); return SUCCESS; } else { return FAILED; } } event result_t ADC.dataReady(uint16_t data) { sensorReading = data; post sendData(); atomic { busy = FALSE; } return SUCCESS; }
21
21 Posting task in interrupt handler Why? Make asynchronous code as short as possible task void sendData() { … adcPacket.data = sensorReading; … call Send.send(&adcPacket, sizeof(adcPacket.data)); return SUCCESS; } event result_t ADC.dataReady(uint16_t data) { sensorReading = data; post sendData(); atomic { busy = FALSE; } return SUCCESS; }
22
22 Race conditions Because of preemption, race conditions may arise on shared data nesC compiler can detect them, but with false positives In case of false positive, declare shared variable with norace keyword In case of real race conditions, use atomic to make code blocks non- preemptible bool busy; norace unit16_t sensorReading; … event result_t Timer01.Timer0Fire() { bool localBusy; atomic { localBusy = busy; busy = TRUE; } if (!localBusy) { call ADC.getData(); return SUCCESS; } else { return FAILED; } } task void sendData() { … adcPacket.data = sensorReading; … call Send.send(&adcPacket, sizeof(adcPacket.data)); return SUCCESS; } event result_t ADC.dataReady(uint16_t data) { sensorReading = data; post sendData(); atomic { busy = FALSE; } return SUCCESS; } Ensures at most one outstanding ADC request at all times
23
23 Discussion ? What are the first low level details of programming to TinyOS that you would like to abstract away?
24
24 Discussion Provides framework for concurrency and modularity Interleaves flows, events, energy management Never poll, never block Trade off flexibility for more optimization opportunities Still a node-level platform How do we go from individual sensors to a sensor field?
25
25 Software Development Infrastructure for Sensor Networks Operating systems ( TinyOS ) Resource (device) management Basic primitives Protocols (MAC, routing) {covered in many previous lectures} Programming languages and runtime environments Low level (C, nesC) Very high level abstractions ( Regiment ) Services needed Synchronization of clocks ( RBS ) Propagation of new code to all nodes ( Trickle ) Localization {not today}
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.