Dhanshree Nimje Smita Khartad TinyOS Dhanshree Nimje Smita Khartad
TinyOS - Design Design
What is TinyOS? TinyOS is a highly modular software environment tailored to the requirements of Network Sensors, stressing efficiency, modularity and concurrency. Capable of fine grained concurrency (event-driven architecture) Small physical size Fewer context switches: (FIFO/non-preemptable scheduling) Efficient Resource Utilization (Get done quickly and sleep) Highly Modular
TinyOS - Features Event-driven architecture Lower layer sends events to higher layer Low overhead– No busy -wait cycles Interrupt driven.Two kinds of interrupt Clock Radio Component driven programming model Size - 400 bytes Extremely flexible component graph Single Single-shared stack shared stack
Features Contd. Network management - Active Messaging No kernel, process management, virtual memory File management - Matchbox 2-level FIFO scheduler– events and tasks Complete integration with hardware
Hardware Kits Two Board Sandwich Main CPU board with Radio Communication Secondary Sensor Board Allows for expansion and customization Current sensors include: Acceleration, Magnetic Field, Temperature, Pressure, Humidity, Light, and RF Signal Strength Can control RF transmission strength & Sense Reception Strength
Hardware Abstraction: LED (pin numbering/HW wiring) CLOCK (counter interrupt) UART (baud rate control, transfer) ADC (ADC interrupt handling) RFM (abstracts bit level timing, RFM specific control logic)
Communication stack building up from the RFM bit level bit level abstracts away radio specifics byte level radio component collects individual bits into bytes packet level constructs packets from bytes messaging layer interprets packets as messages
Sensor stack photo, and temperature sensing components sits on top of ADC component typical request data, wait for data event
TinyOS component model Component interface: commands accepts (implemented) commands uses events accepts (implemented) events uses Component implementation functions that implement interface frame: internal state tasks: concurrency control
Programming Model Components .comp: specification .C: behaviour .desc: select and wire specification: accepts commands uses commands signals events handles events comp1: C code comp3 comp4 comp2: .desc application: .desc
Scheduler : Tasks: Events – 2-level scheduling (events and tasks) single shared stack, used by events and function calls Tasks: are preemptable by events may call commands may signal events not preempted by tasks Events – Time critical Shorter duration (hand off to task if need be) Interrupts task Last-in first-out semantics (no priority among events) lowest level events support by hardware interrupt
TinyOS Two-level Scheduling Tasks do intensive computations Unpreemptable FIFO scheduling Bounded number of pending tasks Events handle interrupts Interrupts trigger lowest level events Events can signal events, call commands, or post tasks Two priorities Event/command Tasks
How to handle multiple data flows? Data/interrupt are handled by interrupt/event Respond to it quickly: A sequence of non-blocking event/command (function calls) through the component graph e.g., get bit out of radio hw before it gets lost Post tasks for long computations e.g., encoding • Assumption: long computation are not urgent New events preempt tasks to handle new data
Receiving a message
What are tasks Requirement of realtime OS: bounded delays between events. Event handler should run to completion within a short duration. If a lot of computation is involved in an event handler we defer execution. How? Implementing it as a task and scheduling it for later execution. TinyOS has simple FIFO scheduler using which tasks are scheduled. On occurrence of an event a task that is executing is preempted.
Data Memory Model STATIC memory allocation! Global variables No heap (malloc) No function pointers Global variables Available on a per-frame basis Local variables Saved on the stack Declared within a method
Application Is the OS with some specific functionality. Application is interrupt driven. List of interrupts handled depend on list of hardware components included in the application (e.g. clock and receiver). Waits for interrupts. On occurrence of interrupt, calls interrupt handler. invokes Calls Hardware Interrupts ISR Interrupt Handler
A Complete Application
Example : Inter-Node Communication Sender: Receiver :
Message Buffer Ownership Transmission: AM gains ownership of the buffer until sendDone(…) is signaled Reception: Application’s event handler gains ownership of the buffer, but it must return a free buffer for the next message
Potentially Nasty Bug 1 What’s wrong with the code? Symptom: data saved in globalData is lost Reason: Race condition between two tasks Solution: Use a queue, or never rely on inter-task communication uint8_t globalData; task void processData() { call SendData.send(globalData); } command result_t Foo.bar(uint8_t data) { globalData = data; post processData();
Potentially Nasty Bug 2 What’s wrong with the code? Symptom: message is corrupt Reason: TOS_Msg is allocated in the stack, lost when function returns Solution: Declare TOS_Msg msg in component’s frame. command result_t Foo.bar(uint8_t data) { TOS_Msg msg; FooData* foo = (FooData*)msg.data; foo.data = data; call SendMsg.send(0x01, sizeof(FooData), &msg); }
Potentially Nasty Bug 3 What’s wrong with the code? Symptom: some command result_t Foo.bar(uint8_t data) { FooData* foo = (FooData*)msg.data; foo.data = data; call SendMsg.send(0x01, sizeof(FooData), &msg); } Component What’s wrong with the code? Symptom: some messages are lost Reason: Race condition between two components trying to share network stack (which is split-phase) Solution: Use a queue to store pending messages Component 2: * command result_t Goo.bar(uint8_t data) { GooData* goo = (GooData*)msg.data; goo.data = data; call SendMsg.send(0x02, sizeof(GooData), &msg); }
THANK YOU