Karan Mangla Lakshya Goel Ankit Gupta Nitin Jain TinyOS
Overview of TinyOS � Industrial motivations behind TinyOS � What is TinyOS? � TinyOS vs. traditional OS � TinyOS design models � TinyOS structure
Industrial Motivations behind TinyOS � Low power wireless communication devices � Particularly wireless networked sensors; � Physical limitations � Computation ability � Memory � Power supply � High-level concurrency
What is TinyOS? � An event-based operating system designed for wireless networked sensors. � Designed to support concurrency-intensive operations required by networked sensors with minimal hardware requirements. � Developed by the EECS Department of U.C. Berkeley. � C and Assembly languages � Source code size: 500KB, 16KB commented lines
TinyOS vs. Traditional OS � Special purpose (not general purpose) � Resource constraint � 4MHz ATMEL 8535 8bit MCU � 512 byte RAM and 8K Flash � No dedicated I/O controller (missed deadline means loss data) � One program at one time (no multi-programming) � Thin-threads (tasks)
TinyOS Design Models � Component-based model (modularity) � Simple functions are incorporated in components with clean interfaces; � Complex functions can be implemented by composing components. � Event-based model � Interact with outside by events (no command shell) � There are two kinds of events for TinyOS: � External events : Clock events and message events; � Internal events triggered by external events .
TinyOS Structure Main (scheduler) Application Actuating Sensing Communication Communication Hardware Abstractions ( ADC, CLOCK, I2C, LEDS, PHOTO, UART, RFM ) � Consists of a scheduler and a graph of components.
Outline � Component Structure � Concurrency Model � TinyOS schedulers � Memory Model
TinyOS Component Structure � A TinyOS Component: � Frame (storage) � Tasks (computation & concurrency) � Time consuming computations; � Have no hard real-time requirements; � Commands and events (interfaces)
Layout of an interface � Can use other interfaces � Provide events � To be coded by the interface user � Provides commands � Coded by the interface provider
Tasks � Perform longer operations � Can be preempted by hardware event handler but not by other tasks � Declaration: task void <name>() { ... } � Posting a task: post taskname(); Done from within command, event or another task
Commands � Function call across component boundary � cause action to be initiated � bounded amount of work � cannot block � always return status (0 => error) � component can refuse to perform command � share call stack and execution context � access to local frame � commands may post tasks or call commands
Events � Upcall to notify action has occured � bounded (and small) amount of work � access local frame, shares stack � Lowest-level events triggered by hardware interrupts � hardware abstraction components perform critical section and enable interrupts � May signal events or call commands � Events may call commands
Concurrency Model � Two threads of execution � Tasks � Hardware Event Handler – handles context switch for multiple level interrupts � Both preemptable by asynchronous code � Possibility of race condition � NesC warns while compiling � Method of making a block atomic allowed
Concurrency Model (cont.) � Atomicity � Disable hardware interrupt handling thread while atomic code is running
TinyOS schedulers (Cont.) � Task scheduler � Implement FIFO scheduler in sched.c � Data structure Circular queue � TOS_sched_entry_T TOS_queue[MAX_THREADS]; � Functions MAIN Component TOS_sched_init(); � TOS_empty(); � Schedule next task in queue TOS_post(); � (TOS_schedule_task) TOS_schedule_task(); � TOS_queue Post task into queue (TOS_post) Any Component (e.g. SHELL)
Memory Model � STATIC memory(except msg buffers) � No heap(malloc) � No function pointers � Global variables � Available on a per-frame basis � Local variables � Saved on the stack � Declared within a method � Msg buffers allocated statically by components,nut shared dynamically by ownership discipline
Memory Requirement � One task at a time – non preemptive kernel � No local variables in events � Buffers for active messaging � Stack copy not with each task – reduce memory requirement – hence non preemptive
Active Messages
What are active messages? � Active Messages (AM) is a simple, extensible paradigm for message-based communication. � Used in parallel and distributed computing systems . � Centered on the concept of integrating communication and computation, as well as matching communication primitives to hardware capabilities.
Why Not Standard Messaging Protocols ? � Low level networking protocols of legacy stacks typically require : � Kilobytes of memory at a minimum � And performance is dependent on a fast processing component. � Routing protocols implemented above these are : � Complex � Place bandwidth demands that become unatenable for links with kilobits per second throughput.
Cont. � Sockets - Not well suited to the constrained environment of tiny network devices. � Interfaces centered on “stop and wait” semantics do not meet the power and agility requirements of these small devices such as Motes.
Why Active Messaging ? � Fundamental fit between the event based nature of network sensor applications and the event based primitives of the Active Messages communication. � The lightweight architecture of Active Messages can be leveraged to balance the need for an extensible communication framework while maintaining efficiency and agility. � Event based handler invocation model allows application developers to avoid busy-waiting for data to arrive and allows the system to overlap communication with other activities such as interacting with sensors or executing other applications. � Event centric nature of Active Messages makes it a natural fit for these devices.
Active Messaging Fundamentals � tos/system/AMStandard.nc � Layers Involved � Specifying message data to send � Specifying receiver’s address � Determining when message’s memory can be reused � Buffering Incoming message � Processing Message � Handler ID required to be specified
A TinyOS Application Example Main (scheduler) BLINK � TimerM LedsC � HPLclock Communication Hardware Abstractions ( CLOCK and LEDS ) The above application is used to toggle a Led on the mote at fixed intervals.
Blink.nc configuration Blink { } implementation { components Main, BlinkM, SingleTimer, LedsC; Main.StdControl -> SingleTimer.StdControl; Main.StdControl -> BlinkM.StdControl; BlinkM.Timer -> SingleTimer.Timer; BlinkM.Leds -> LedsC; } This is a configuration file which provides the top-level wiring of the � application Main is a special component which is used to initialize the system. � The wiring consist of joining interfaces required by certain � components to those provided by other components that are being used.
RealMain.nc module RealMain { uses { command result_t hardwareInit(); interface StdControl; interface Pot; } } implementation { int main() __attribute__ ((C, spontaneous)) { call hardwareInit(); call Pot.init(10); TOSH_sched_init(); call StdControl.init(); call StdControl.start(); __nesc_enable_interrupt(); while(1) { TOSH_run_task(); } } }
Implementation of Main Component The above component is a module file ,which are used to define � implementations of components. It is used to initialize all application. � Its Std Control interface is mapped onto that used by Main and � hence when it utilizes this interface it communicates with all components that are connected to the Main component. Most components have a Std Control interface as this is what initializes every component. When nesC compiles the application into C the main function � involves one call to Std Contol init followed by a call to Std Control start to start the application. This is then followed by starting the task scheduler. This function also consists of calls to Initialize the hardware and � power settings of the mote. These calls are wired to lower level components which directly interface with the device controllers for the system.
BlinkM.nc module BlinkM { provides { interface StdControl; } uses { interface Timer; interface Leds; } } implementation { command result_t StdControl.init() { call Leds.init(); return SUCCESS; } command result_t StdControl.start() { // Start a repeating timer that fires every 1000ms return call Timer.start(TIMER_REPEAT, 1000); } command result_t StdControl.stop() { return call Timer.stop(); } event result_t Timer.fired() { call Leds.redToggle(); return SUCCESS; } }
Recommend
More recommend