1 / 132

TinyOS Tutorial Dr. WenZhan Song Professor, Computer Science

TinyOS Tutorial Dr. WenZhan Song Professor, Computer Science. Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos tutorial slides. Outline. Installing TinyOS and Building Your First App Hardware Primer Basic nesC Syntax Advanced nesC Syntax

Download Presentation

TinyOS Tutorial Dr. WenZhan Song Professor, Computer Science

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. TinyOS Tutorial Dr. WenZhan Song Professor, Computer Science Acknowledgement: Thank Greg Hackmann at Washington University in St. Louis for sharing the tinyos tutorial slides.

  2. 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 2

  3. TinyOS Installation TinyOS Documentation Wiki: http://docs.tinyos.net/ Various installation options listed under “Getting started” section Pre-compiled .rpm and .deb packages for Fedora and Ubuntu Linux users Ubuntu users: be sure to remove brltty package All necessary drivers already included with Linux kernel 3

  4. TinyOS Installation (cont.) OS X unofficially supported but works well Precompiled packages available at http://www.cse.wustl.edu/~gwh2/tinyos-2.1.0.dmg.bz2 Need to install pySerial (http://pyserial.sourceforge.net) and FTDI FT232R serial drivers (http://www.ftdichip.com/Drivers/VCP.htm) separately Can also compile by hand: see TinyOS Wiki 4

  5. TinyOS Installation (cont.) Windows installation uses Cygwin to emulate Linux software layer Problematic under XP, refuses to work on some Vista machines (updating Cygwin after the installation may help) gcc is also very slow under Cygwin “Running a XubunTOS Virtual Machine Image in VMware Player” tutorial recommended instead Or pick your favorite VM software and install Ubuntu yourself 5

  6. TinyOS Directory Structure /opt/tinyos-2.1.0 ($TOSROOT) apps support make sdk tools tos 8

  7. make System $TOSROOT/support/make includes lots of Makefiles to support the build process Create a simple stub Makefile in your app directory that points to main componentCOMPONENT=[MainComponentC]SENSORBOARD=[boardtype] # if neededinclude $(MAKERULES) make [platform] in app directory Builds but does not install program platform: one of the platforms defined in $TOSROOT/tos/platforms (mica2, micaz2, telosb) 9

  8. make System make [re]install.[node ID] [platform] [programming options] node ID: 0 - 255 programming options: mica2/micaz: mib510,/dev/ttyXYZ telosb: bsl,/dev/ttyXYZ make clean make docs [platform] Generates HTML documentation in $TOSROOT/doc/nesdoc/[platform] 10

  9. Build Stages Set AM address and node ID in binary Preprocess .nc to .c, then compile .c to binary Program mote 11

  10. How to Get Help TinyOS Documentation Wiki: http://docs.tinyos.net TinyOS Programming Manual: 139-page PDF intro to nesC and TinyOS 2.x:http://www.tinyos.net/tinyos-2.x/doc/pdf/tinyos-programming.pdf TinyOS Tutorials: short HTML lessons on using parts of TinyOS (sensors, radio, TOSSIM, etc.):http://docs.tinyos.net/index.php/TinyOS_Tutorials 12

  11. How to Get Help nesdoc: annotated API for all interfaces and components in TinyOS: http://docs.tinyos.net/index.php/Source_Code_Documentation TinyOS Enhancement Protocols (TEP): formal documentation for TinyOS features: http://docs.tinyos.net/index.php/TEPs 13

  12. 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 14

  13. MicaZ CC2420 - IEEE 802.15.4 Radio 250kbps 2.4 GHz ATmega 128L microcontroller 4kB RAM, 128kB program flash, 512 kB storage flash, Need a separate programming board and debug board 15

  14. Tmote Sky (aka TelosB) CC2420 - IEEE 802.15.4 Radio 250kbps 2.4GHz TI MSP430 microcontroller 8MHz, 16 MIPS, 10kB RAM, 1MB storage flash, 48K program flash Integrated antenna & USB interface Low power utilization 1.8mA/5.1µA vs. Mica 2’s 8mA/15µA 16

  15. TelosW = Telos + Wake-on • CC1101 – wake-on radio • 1.2kbps - 500kbps • 868-915 MHz • TI MSP430 microcontroller • 16MHz, 16 MIPS, 10kB RAM • Integrated antenna & USB interface • Low power utilization • 1.8mA/5.1µA vs. Mica 2’s 8mA/15µA • Wake-on sensor/ADC design • Onboard energy meters • More details at http://sensorweb.cs.gsu.edu/sites/default/files/research/projects/TelosW/images/TELOSW.pdf

  16. 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 18

  17. TinyOS Execution Model To save energy, node stays asleep most of the time Computation is kicked off by hardware interrupts Interrupts may schedule tasks to be executed at some time in the future TinyOS scheduler continues running until all tasks are cleared, then sends mote back to sleep zZz handlePacket readSensor sendResponse 19

  18. TinyOS Execution Model

  19. TinyOS Memory Model • STATIC memory allocation! • No heap (malloc) • No function pointers • Global variables • Available on a per-frame basis • Local variables • Saved on the stack • Declared within a method

  20. TinyOS Thread Model • Tasks: • Time flexible • Longer background processing jobs • Atomic with respect to other tasks (single threaded) • Preempted by events • Events: • Time critical • Shorter duration (hand off to task if need be) • Interrupts task • Last-in first-out semantics (no priority among events) • Do not confuse an event from the NesC event keyword!! • TinyOS-1.x supports up to 7 pending tasks by default, you can add -DTOSH_MAX_TASKS_LOG2=n to makefile’s PFLAGS line to get 2^n tasks, where n=8 is maximum. TinyOS-2.x supports up to 255 tasks by default. • Task overflow is still possible – make sure to check whether task “post” was SUCCESS or not.

  21. TinyOS Programming Model • Separation of construction and composition • Programs are built out of components • Each component is specified by an interface • Provides “hooks” for wiring components together • Components are statically wired together based on their interfaces • Increases runtime efficiency

  22. TinyOS Component Model event startDone() command start() NetworkHandlerP NetworkHandlerC provides SplitControl provides Receive ActiveMessageC uses Receive provides SplitControl 24

  23. TinyOS Component Model • Components use and provide interfaces, commands, and events • Specified by a component’s interface • The word “interface” has two meanings in TinyOS • Components implement the events they use and the commands they provide:

  24. TinyOS Component Model • There are two types of components: • Modules: Implement the application behavior • Configurations: Wires components together • A component does not care if another component is a module or configuration • A component may be composed of other components

  25. Components != Objects AppLogicP NetworkHandlerP AnotherHandlerP ✓ ✗ ActiveMessageC ActiveMessageC ActiveMessageC 27

  26. Interfaces List of exposed events and commands Like ordinary C function declarations, except with event or command in front interface Receive { event message_t * Receive(message_t * msg, void * payload, uint8_t len); command void * getPayload(message_t * msg, uint8_t * len); command uint8_t payloadLength(message_t * msg); } 28

  27. Modules providethe implementation of one or more interfaces They may consume (use) other interfaces to do so “Rename” interfaces with the as keyword -- required if you are using/providing more than one of the same interface! Modules module ExampleModuleP { provides interface SplitControl; uses interface Receive; uses interface Receive as OtherReceive; } implementation { ... } 29

  28. Modules implementationblock may contain: Variable declarations Helper functions Tasks Event handlers Command implementations 30

  29. Modules: Variables and Functions Placed inside implementation block exactly like standard C declarations: ... implementation { uint8_t localVariable; void increment(uint8_t amount); ... void increment(uint8_t amount) { localVariable += amount; } } 31

  30. Modules: Tasks Look a lot like functions, except: Prefixed with task Can’t return anything or accept any parameters implementation { ... task void legalTask() { // OK } task bool illegalTask() { // Error: can’t have a return value! } task void anotherIllegalTask(bool param1) { // Error: can’t have parameters! } } 32

  31. Modules: Task Scheduling Tasks are scheduled using the post keyword TinyOS guarantees that scheduled task will eventually run Default scheduling policy: FIFO task1 task1 ✓ ✗ task1 task2 task3 ... error_t retval; retval = post handlePacket(); // retval == SUCCESS if task was scheduled, or E_FAIL if not 33

  32. Modules: Commands and Events Commands and events also look like C functions, except: they start with the keyword command or event the “function” name is in the form InterfaceName.CommandOrEventName e.g. implementation { command error_t SplitControl.start() { // Implements SplitControl’s start() command } event message_t * Receive.receive(message_t * msg, void * payload, uint8_t len) { // Handles Receive’s receive() event } } 34

  33. Modules: Commands and Events Commands are invoked using the call keyword: Event handlers are invoked using the signal keyword: call Leds.led0Toggle(); // Invoke the led0Toggle command on the Leds interface signal SplitControl.startDone(); // Invoke the startDone event handler on the SplitControl interface 35

  34. Modules: Commands and Events A command, event handler, or function can call or signal any other command or event from any interface wired into the module: module ExampleModuleP { uses interface Receive; uses interface Leds; } implementation { event message_t Receive.receive(message_t * msg, void * payload, uint8_t len) { // Just toggle the first LED call Leds.led0Toggle(); return msg; } ... } 36

  35. 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: implementation { async event void Alarm.fired() { // Handle hardware alarm interrupt } } 37

  36. Use atomic blocks to avoid race conditions Reminder: Race Conditions Interrupts are disabled here -- use sparingly and make as short as practical implementation { uint8_t sharedCounter; async event void Alarm.fired() { sharedCounter++; } event void Receive.receive(...) { ... atomic { sharedCounter++; } } } 38

  37. Reminder: Race Conditions Tasks are always synchronous If timing isn’t crucial, defer code to tasks to avoid race conditions 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. This is just an illustration of ‘post’, not efficient in this particular example! 39

  38. 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: 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; async events are mutually exclusive 40

  39. 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 41

  40. Configurations 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 = configuration NetworkHandlerC { provides interface SplitControl; } implementation { components NetworkHandlerP as NH, ActiveMessageP as AM; NH.Receive -> AM.Receive; NH.SplitControl = SplitControl; } // // NH.Receive -> AM; NH = SplitControl; 42

  41. Configuration Wires • A configuration can bind an interface user to a provider using -> or <- • User.interface -> Provider.interface • Provider.interface <- User.interface • Bounce responsibilities using = • User1.interface = User2.interface • Provider1.interface = Provider2.interface • The interface may be implicit if there is no ambiguity • e.g., User.interface -> Provider == User.interface -> Provider.interface

  42. 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 44

  43. 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 45

  44. 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); } 46

  45. 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>; } 47

  46. Fan-In: No Big Deal AppLogicP NetworkHandlerP AnotherHandlerP uses Receive uses Receive uses Receive Many-to-one calls work like you’d expect ... provides Receive RadioP 48

  47. Fan-Out: Bad Things Happen return &buffer1; return &buffer2; return &buffer3; AppLogicP NetworkHandlerP AnotherHandlerP uses Receive uses Receive uses Receive … but what about one-to-many calls? provides Receive RadioP 49

  48. 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 50

  49. 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(...); ... } ... } AppLogicP Network HandlerP Another HandlerP uses Receive uses Receive uses Receive RadioP 51

  50. 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(...); } ... } 52

More Related