0% found this document useful (0 votes)
57 views

Tutorial 2

This document discusses modules and the TinyOS execution model. It explains that modules can declare private state variables and interact only through interfaces. Components implement configurations through wiring other components. Tasks allow splitting long computations into smaller parts executed over time to improve responsiveness. Internal functions let a component define helper functions that are private and cannot be called by other components.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
57 views

Tutorial 2

This document discusses modules and the TinyOS execution model. It explains that modules can declare private state variables and interact only through interfaces. Components implement configurations through wiring other components. Tasks allow splitting long computations into smaller parts executed over time to improve responsiveness. Internal functions let a component define helper functions that are private and cannot be called by other components.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

Tutorial 2 Modules and TinyOS execution Model

I. Modules and states:


A mote only runs one TinyOS image at a time. An image consists of the components needed for a single application. There is no separation between a "user" address space and a "system" address space; This is why many TinyOS components try to keep their state private and avoid passing pointers Configurations are implemented in terms of other components, which they wire, while modules are executable code. Module implementations are for the most part written in C, with some extra constructions for nesC abstractions. Modules can declare state variables. Any state a component declares is private: no other component can name it or directly access it. The only way two components can directly interact is through interfaces.

Example:
In BlinkC example visited in Tutuorial 1, we will replace the three timers by only one timer that would be used for the three LEDs. If you compare the ROM and RAM sizes with the unmodified Blink application, you should see that they are a bit smaller: TinyOS is only allocating state for a single timer, and there is event code for only one timer. These are the steps to modify the application code: 1. Make a copy of the Blink application, BlinkSingle, and go into its directory.
$ cd tinyos-2.x/apps $ cp -R Blink BlinkSingle $ cd BlinkSingle

2. In the new copy, modify the code to be like that:

module BlinkC @safe(){ uses interface Timer<TMilli> as Timer0; uses interface Leds; uses interface Boot; } implementation { uint8_t counter = 0; event void Boot.booted() { call Timer0.startPeriodic( 250 ); } event void Timer0.fired() { counter++; call Leds.set(counter); } }

Using this counter, we can replace the three timers by only one timer and the leds are managed through Leds.set(counter) command. 3. Open BlinkAppC and remove the two Timers (Timer 1 and Timer 2) and their wirings. Compile the application

II. Interfaces, commands and events:


Invoking an interface command requires the call keyword, and invoking an interface event requires the signal keyword. BlinkC does not provide any interfaces, so its code does not have any signal statements When implementing or invoking an interface function, the function name is always interface function. As BlinkC's three Timer instances are named Timer0, Timer1, and Timer2, it implements the three functions Timer0.fired, Timer1.fired, and Timer2.fired.

III. Tasks
All of the code we've looked at so far is synchronous. It runs in a single execution context and does not have any kind of pre-emption. It does not relinquish the CPU to other sync code until it completes. It means that if one piece of sync code runs for a long time, it prevents other sync code from running, which can adversely affect system responsiveness.

For large computations. A component needs to be able to split a large computation into smaller parts, which can be executed one at a time. Giving TinyOS the ability to defer the computation until later can let it deal with everything else that's waiting first. Tasks enable components to perform general-purpose "background" processing in an application. A task is a function which a component tells TinyOS to run later, rather than now. A component can post a task in a command, an event, or a task. Because they are the root of a call graph, a tasks can safely both call commands and signal events. Commands do not signal events to avoid creating recursive loops across component boundaries (e.g., if command X in component 1 signals event Y in component 2, which itself calls command X in component 1). Tasks do not preempt each other, but a task can be preempted by a hardware interrupts (which we haven't seen yet). If you need to run a series of long operations, you should dispatch a separate task for each operation, rather than using one big task. A task is declared in your implementation module using the syntax: task void taskname() { ... } where taskname() is whatever symbolic name you want to assign to the task. Tasks must return void and may not take any arguments.

To dispatch a task for (later) execution, use the syntax: post taskname(); A task can be posted from within a command, an event, or even another task. The post operation places the task on an internal task queue which is processed in FIFO order. When a task is executed, it runs to completion before the next task is run; therefore, a task should not spin or block for long periods of time. Tasks do not preempt each other, but a task can be preempted by a hardware event handler. If you need to run a series of long operations, you should dispatch a separate task for each operation, rather than using one big task.

IV. Internal Functions


Commands and events are the only way that a function in a component can be made callable by another component.

A component can define standard C functions, which other components cannot name and therefore cannot invoke directly. While these functions do not have the command or event modifier, they can freely call commands or signal events. Internal functions act just like C functions: they don't need the call or signal keywords.

Example:
void startTimers() { call Timer0.startPeriodic( 250 ); call Timer1.startPeriodic( 500 ); call Timer2.startPeriodic( 1000 ); } event void Boot.booted() { startTimers(); }

You might also like