1 / 95

An Introduction to nesC and TinyOS, or, A really complicated way to build very simple applications

An Introduction to nesC and TinyOS, or, A really complicated way to build very simple applications. CENS Summer Internship 07/08/05 Ben Greenstein – ben@cs.ucla.edu Contributors : Tom Schoellhammer, Deepak Ganesan, David Culler’s Lab (UCB) CENS Systems Lab.

clover
Télécharger la présentation

An Introduction to nesC and TinyOS, or, A really complicated way to build very simple applications

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. An Introduction to nesC and TinyOS, or,A really complicated way to build very simple applications CENS Summer Internship 07/08/05 Ben Greenstein – ben@cs.ucla.edu Contributors: Tom Schoellhammer, Deepak Ganesan, David Culler’s Lab (UCB) CENS Systems Lab

  2. Range of platforms with different constraints Highly constrained (memory, CPU, storage, power) Solutions: TinyOS,… StarGate Capabilities MK - II Ample resources Solutions: Linux, uCos, Emstar… MICA Mote Spec Size, Power Consumption, Cost

  3. Why do we use utterly constrained platforms? • No wires = batteries and radios • Resources drain batteries • Radio, Flash, ADC, RAM, MCU, etc. • Deployments are often remote • Don’t always have summer interns to change batteries • Constrained platforms are smaller • Constrained platforms are cheaper

  4. Technology for low-power, cheap nodes • CMOS miniaturization • 1 M trans/$  tiny (~mm2), inexpensive processing and storage • 1-10 mW active, 1 mW passive (at 1% use 100 mW average) • Micro-sensors (MEMS, Materials, Circuits) • acceleration, vibration, gyroscope, tilt, magnetic, heat, motion, pressure, temp, light, moisture, humidity, barometric • chemical (CO, CO2, radon), biological, micro-radar, ... • actuators too (mirrors, motors, smart surfaces, micro-robots) • Communication • short range, low bit-rate, CMOS radios (1-10 mW) • Power • batteries remain primary storage (1,000 mW/mm3), fuel cells 10x • solar (10 mW/cm2, 0.1 mW indoors) • 1 cm3 battery  1 year at 10 msgs/sec

  5. Characteristics of Network Sensors • Small physical size and low power consumption • Concurrency-intensive operation • multiple flows, not wait-command-respond => never poll, never block • Limited Physical Parallelism and Controller Hierarchy • primitive direct-to-device interface • Asynchronous and synchronous devices => interleaving flows, events, energy management • Diversity in Design and Usage • application specific, not general purpose • huge device variation => efficient modularity => migration across HW/SW boundary • Robust Operation • numerous, unattended, critical => narrow interfaces sensors actuators storage network

  6. What is a mote? • Jason Hill’s Master’s Thesis (UCB) • PhD Dissertation was supposed to be a prototype for a smart-dust system on a chip • Small physical size: 1 mm3 • Low Power Consumption: < 50 mW

  7. Anatomy of a 3rd generation mote (mica2) • Constraints • 4KB RAM • 128KB Program Flash Memory • >25mA (Tx), <15uA (sleep) at 3.3V • 8MHz Microcontroller • 19.2Kbps (at 433 or 916MHz) • Other exciting details • 512KB Measurement Flash • 4KB Configuration EEPROM • 10bit ADC • 3 LEDs • 51pin expansion connector • Transmission range ~500ft outdoor • Runs on 2 AA batteries

  8. Processing Sub-System • Functions • Application Execution • Resource Management • Peripheral Interaction • Atmel AVR ATMEGA128L • RISC Architecture • 8 bit ALU/data-path • 128 Kb FLASH - Code • 4 Kb SRAM - Data • Multiple peripherals Details are available in the ATMEGA128L Datasheet

  9. Sensing Sub-System • Functions • Sampling physical signals/phenomena • Different types of sensors • Photo-sensor • Acoustic Microphone • Magnetometer • Accelerometer • Sensor Processor Interface • 51 Pin Connector • ON-OFF switches for individual sensors • Multiple data channels Sensors consume power Turn them off after sampling ! • Useful Link/Resources • http://www.tinyos.net/ • Look under Hardware Designs tab • Crossbow website • http://www.xbow.com

  10. Total Solar Radiation Photosynthetically Active Radiation Resolution: 0.3A/W Relative Humidity Accuracy: ±2% Barometric Pressure Accuracy: ±1.5mbar Temperature Accuracy: ±0.01oC Acceleration 2 axis Resolution: ±2mg Designed by UCB w/ Crossbow and UCLA Mica Weather Board – Weather monitoring applications Revision 1.5 Revision 1.0

  11. Communication Sub-System • Functions • Transmit – Receive data packets wirelessly • Co-ordinate/Network with other nodes • Implementation • Radio • Modulation – Demodulation • Two types of radios: RFM, ChipCon CC1000 • RFM: Mica & predecessors • CC1000: Mica2 onwards • AVR • Protocol Processing

  12. Wireless Comm. Basics • RFM Radio– Simple radio, only modulates-demodulates bits • CC1000 Radio– Performs Manchester coding-decoding and synchronization also

  13. AVR Peripherals • UART • Serial communication with the PC • SPI – Serial Peripheral Interface • Synchronous serial communication • Interface to Radio in the Mote • ADC • Analog – Digital Converter • Digitizing sensor readings • I/O Ports • General Purpose Input Output pins (GPIO) • Used to light up LEDs in Mote

  14. Radio Power Management • Radio has very high power consumption • Tx power is range dependant - 49.5 mW (0 dBm) • Rx power is also very high - 28.8 mW • Power-down sleep mode - 0.6 uW • Above data for CC1000, 868 MHz (Check out CC1000 data-sheets for more numbers) • Radio power management critical • Idle state channel monitoring power = Rx Power • Put radio to sleep when not in use • But then, how do we know when somebody is trying to contact us ?

  15. AVR Power Management • Low Power operation – 15 mW @ 4 MHz • Multiple Sleep Modes • Sleep Modes: Shutdown unused components • Idle Mode – 6 mW • CPU OFF, all peripherals ON • CPU “woken up” by interrupts • Power Down Mode – 75 uW • CPU and most peripherals OFF • External Interrupts, 2 Wire Interface, Watchdog ON • Power Save Mode – 120 uW • Similar to Power Down • Timer0 continues to run “asynchronously”

  16. Typical sensor network operation • Sensing Subsystem • Keep the very low power sensors on all the time on each node in the network • Processing subsystem • Low-power sensors interrupt (trigger) processor when “events” are identified OR • Processor wakes up periodically on clock interrupt, takes a sample from sensor, processes it, and goes back to sleep. • Radio subsystem • Processor wakes up radio when event requires collaborative processing or multi-hop routing. • Tiered architectures of above subsystems can be envisaged in other platforms

  17. Traditional Systems • Well established layers of abstractions • Strict boundaries • Ample resources • Independent apps at endpoints communicate pt-pt through routers • Well attended Application Application User System Network Stack Transport Threads Network Address Space Data Link Files Physical Layer Drivers Routers

  18. by comparison ... • Highly Constrained resources • processing, storage, bandwidth, power • Applications spread over many small nodes • self-organizing Collectives • highly integrated with changing environment and network • communication is fundamental • Concurrency intensive in bursts • streams of sensor data and network traffic • Robust • inaccessible, critical operation

  19. So, how do we write programs for motes? • Write C-style programs using a language for embedded software development (e.g., nesc) • Use a cross-compiler to build a binary image for a mote MCU (e.g., avr-gcc). • Use a programmer (e.g., uisp) to load the binary onto a mote • Event driven execution: • Messages received over radio, discrete event sensors generate interrupts when they detect things, timers go off. • We write handlers (functions) that are called in response to various events. • We write tasks to do background processing

  20. What are TinyOS and nesC? • TinyOS is a collection of software modules that can be glued together to build applications. Examples: • GenericComm: send and receive radio packets • TimerC: start timers and get notified when they expire • ADC: sample light and temperature data, among others • UART: communicate over the serial interface • LedsC: make pretty lights blink • TinyOS is also a FIFO scheduler: • Interrupts are handled immediately • Background tasks are scheduled (put on a queue are are executed when there’s nothing more important to do) • NesC is the language in which TinyOS modules are written • To define modules and the interfaces that connect them • Can create configurations, which are hierarchies of glued together modules

  21. TinyOS Goals (claims) • Flexibility • new sensor network nodes keep emerging • Telos, iMote, mica2, mica2Dot, etc. • Flexible hardware/software interface • Future designs may require different HW/software interfaces and may move service (MAC, e.g.) into hardware or software • Modularity • Component model • Sensor Network Challenges • Address the specific and unusual challenges of sensor networks: • limited resources, concurrency- intensive operation, a need for robustness, and application-specific requirements.

  22. Each mote runs a single application • Properties • All memory resources are known statically • Rather than employing a general-purpose OS, applications are built from a suite of reusable system components coupled with application-specific code • The hardware/software boundary varies depending on the application and hardware platform; it is important to design software for flexible decomposition • Challenges: • Driven by interaction with the environment (interrupts) • Limited resources (motes) • Reliability • Soft real-time requirements (radio management and sensor polling) • Lacking common service • Time synchronization

  23. TinyOS • application = scheduler + graph of components • event-driven architecture • single shared stack • NO kernel, process/memory management, virtual memory

  24. Application = Graph of Components Route map router sensor appln application Active Messages Serial Packet Radio Packet packet Temp photo SW HW UART Radio byte ADC byte clocks RFM bit

  25. The nesC programming language: moving away from perl • NesC started with a perl script • Pretended to be a lexer and parser • Offered no compile-time support for error detection • Component model wasn’t there yet • Now it is a systems programming language for motes • Interrupt-driven programming model • integrates reactivity to the environment, concurrency, and communication • Provides whole-program optimizations and compile-time data race detection (does it work?) • Does it simplify application development? • reduce code size? • eliminate many sources of potential bugs?

  26. How to periodically sense light and transmit it I know how to tell someone when some time has gone by TimerC.nc And I can transmit messages over a radio! I know how to return a light value Photo.nc GenericComm.nc

  27. How to periodically sense light and transmit it I know how to tell someone when some time has gone by I’m the glue that ties these modules together TimerC.nc And I can transmit messages over a radio! I know how to return a light value SendLightM.nc Photo.nc GenericComm.nc

  28. How to periodically sense light and transmit it I am a user of the services these other modules provide TimerC.nc SendLightM.nc Photo.nc GenericComm.nc

  29. How to periodically sense light and transmit it Specifically, I use the interfaces that these modules provide TimerC.nc Timer SendLightM.nc SendMsg ADC Photo.nc GenericComm.nc

  30. How to periodically sense light and transmit it TimerC.nc module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { // . . . } Photo.nc GenericComm.nc

  31. Modules includes Foo; module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { #include “FooConstants.h” int x; // a frame variable task void work(){ // do something } command result_t StdControl.start(){ call Timer.start(TIMER_REPEAT, 1000); return SUCCESS; } event result_t Timer.fired(){ post work(); } } • A module has: • Frame (internal state) • Tasks (computation) • Interface (events, commands) • Frame : • one per component • statically allocated • fixed size • Keyword “includes” goes before module declaration • Semantic equivalent of #include, with caveats: No cpp directives allowed • Practical hack: put #include in implementation block • Commands and events are function calls • Application: linking/glueing interfaces (events, commands)

  32. How to periodically sense light and transmit it module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { // use timer to // periodically sample // light } configuration TimerC { provides { interface StdControl; interface Timer[uint8_t id]; } uses { // . . . } } Implementation { // manage one shot & periodic // timers }

  33. How to periodically sense light and transmit it configuration SenseLightC { } implementation { components Main, SendLightM, TimerC; Main.StdControl -> SendLightM.StdControl; Main.StdControl -> TimerC; SendLightM.Timer -> TimerC.Timer[unique(“Timer”)]; } module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { // use timer to // periodically sample // light } configuration TimerC { provides { interface StdControl; interface Timer[uint8_t id]; } uses { // . . . } } Implementation { // manage one shot & periodic // timers }

  34. How to periodically sense light and transmit it interface Timer { // type is: TIMER_ONE_SHOT // or TIMER_REPEAT command result_t start(char type, uint32_t period); command result_t stop(); event result_t fired(); } configuration SenseLightC { } implementation { components Main, SendLightM, TimerC; Main.StdControl -> SendLightM.StdControl; Main.StdControl -> TimerC; SendLightM.Timer -> TimerC.Timer[unique(“Timer”)]; } module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { // use timer to // periodically sample // light } configuration TimerC { provides { interface StdControl; interface Timer[uint8_t id]; } uses { // . . . } } Implementation { // manage one shot & periodic // timers }

  35. Parameterized Interfaces • Can associate a port with an interface, so that a provider can distinguish users • Used because the provider doesn’t know how many users will be connecting to it configuration SenseLightC { } implementation { components Main, SendLightM, TimerC; Main.StdControl -> SendLightM.StdControl; Main.StdControl -> TimerC; SendLightM.Timer -> TimerC.Timer[unique(“Timer”)]; } configuration TimerC { provides { interface StdControl; interface Timer[uint8_t id]; } uses { // . . . } } Implementation { // manage one shot & periodic // timers } • TimerC can provide up to 256 instances of the Timer interface.

  36. Interfaces interface Timer { // type is: TIMER_ONE_SHOT // or TIMER_REPEAT command result_t start(char type, uint32_t period); command result_t stop(); event result_t fired(); } • Define “public methods that a component can use • used for grouping functionality, like: • standard control interface (init, start, stop) • describe bidirectional interaction: • interface provider must implement commands • interface user must implement events • commands: • deposit request parameters into the frame • are non-blocking • need to return status  postpone time consuming work by posting a task • can call lower level commands • events: • can call commands, signal events, post tasks, can not be signaled by commands • preempt tasks, not vice-versa • interrupt trigger the lowest level events • deposit the information into the frame

  37. Interface Examples interface StdControl { command result_t init (); command result_t start (); command result_t stop (); } interface Timer { command result_t start (char type, uint32_t interval); command result_t stop (); event result_t fired (); } interface SendMsg { command result_t send (uint16_t addr, uint8_t len, TOS_MsgPtr p); event result_t sendDone (); } interface ReceiveMsg { event TOS_MsgPtr receive (TOS_MsgPtr m); } StdControl.nc Timer.nc SendMsg.nc ReceiveMsg.nc

  38. How to periodically sense light and transmit it interface Timer { // type is: TIMER_ONE_SHOT // or TIMER_REPEAT command result_t start(char type, uint32_t period); command result_t stop(); event result_t fired(); } module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { command result_t StdControl.init() { return SUCCESS; } command result_t StdControl.start(){ call Timer.start(TIMER_REPEAT, 1000); // 1000ms return SUCCESS; } command result_t StdControl.stop(){ call Timer.stop(); return SUCCESS; } event result_t Timer.fired(){ call ADC.getData(); } } interface ADC { async command result_t getData(); async command result_t getContinuousData(); async event result_t dataReady(uint16_t data); }

  39. How to periodically sense light and transmit it module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { command result_t StdControl.init() { return SUCCESS; } command result_t StdControl.start(){ call Timer.start(TIMER_REPEAT, 1000); // 1000ms return SUCCESS; } command result_t StdControl.stop(){ call Timer.stop(); return SUCCESS; } event result_t Timer.fired(){ call ADC.getData(); } async event result_t ADC.dataReady(uint16_t data){ // send a message with the data } } interface Timer { // type is: TIMER_ONE_SHOT // or TIMER_REPEAT command result_t start(char type, uint32_t period); command result_t stop(); event result_t fired(); } Split-phase interface interface ADC { async command result_t getData(); async command result_t getContinuousData(); async event result_t dataReady(uint16_t data); }

  40. Split-phase Interfaces • Operation request and completion are separate functions: • No blocking operations because tasks execute non-preemptively • The usual way to do this is to register a callback by passing a function pointer interface SendMsg { command result_t send (uint16_t address, uint8_t length, TOS_MsgPtr p); event result_t sendDone (TOS_MsgPtr msg, result_t success); } SendMsg.nc

  41. How to periodically sense light and transmit it module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { command result_t StdControl.init() { return SUCCESS; } command result_t StdControl.start(){ call Timer.start(TIMER_REPEAT, 1000); // 1000ms return SUCCESS; } command result_t StdControl.stop(){ call Timer.stop(); return SUCCESS; } event result_t Timer.fired(){ call ADC.getData(); } async event result_t ADC.dataReady(uint16_t data){ // send a message with the data } } • In a configuration, modules and perhaps sub-configurations are connected together by the interfaces they use and provide • Interfaces have commands and events

  42. How to periodically sense light and transmit it module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { command result_t StdControl.init() { return SUCCESS; } command result_t StdControl.start(){ call Timer.start(TIMER_REPEAT, 1000); // 1000ms return SUCCESS; } command result_t StdControl.stop(){ call Timer.stop(); return SUCCESS; } event result_t Timer.fired(){ call ADC.getData(); } async event result_t ADC.dataReady(uint16_t data){ // send a message with the data } } • So, what’s this “async” word? • Some functions, like dataReady are called directly from a hardware interrupt handler. • Async means that this function might be called straight from the IH. • Why do we care whether or not a function is called from the IH?

  43. Concurrency Model module SendLightM{ provides { interface StdControl; } uses { interface ADC; interface Timer; interface SendMsg; } } implementation { // . . . // global variables bool dataPending; uint16_t dataValue; // tasks take no parameters and return void task void sendData(){ // send a message with the data in it dataPending = FALSE; } async event result_t ADC.dataReady(uint16_t data){ if (!dataPending){ dataPending = TRUE; dataValue = data; post sendData(); } } } • There are Interrupt Handlers and Background Tasks • We can lose interrupts, so we get out of their handlers as fast as possible by saving state and posting a task • Posting a task tells the scheduler to put a task on a queue and to call it when the MCU is idle and it is its turn

  44. Concurrency Model module SendLightM{ // . . . } implementation { // . . . // global variables bool dataPending; uint16_t dataValue; // tasks take no parameters and return void task void sendData(){ // send a message with the data in it dataPending = FALSE; } async event result_t ADC.dataReady(uint16_t data){ bool doWork = FALSE; atomic { if (!dataPending){ dataPending = TRUE; doWork = TRUE; } } if (doWork) post sendData(); } } } • Since tasks (and even some interrupts) can be interrupted, we sometimes need extra support to prevent race conditions • Use the keyword atomic to prevent interruption… • Note, try to avoid calling from within an atomic block

  45. Configurations configuration CntToLeds { } implementation { components Main, Counter, IntToLeds, TimerC; Main.StdControl -> IntToLeds.StdControl; Main.StdControl -> Counter.StdControl; Main.StdControl -> TimerC.StdControl; Counter.Timer -> TimerC.Timer[unique("Timer")]; Counter.IntOutput -> IntToLeds.IntOutput; } • Configurations refer to configurations and modules • No distinction between an included configuration and an included module • Configuration can expose an underlying module’s interface • An application must connect a Main component to other components • connected elements must be compatible (interface-interface, command-command, event-event) • 3 wiring statements in nesC: • endpoint1 = endpoint2 • endpoint1 -> endpoint2 • endpoint1 <- endpoint2 configuration TimerC { provides interface Timer[uint8_t id]; provides interface StdControl; } implementation { components TimerM, ClockC, NoLeds, HPLPowerManagementM; TimerM.Leds -> NoLeds; TimerM.Clock -> ClockC; TimerM.PowerManagement -> HPLPowerManagementM; StdControl = TimerM; Timer = TimerM; }

  46. Concurrency • Tasks and interrupts (foreground and background operations) • Tasks cannot preempt other tasks • Low priority for performing computationally intensive work • Interrupts can preempt tasks • Interrupts can preempt other interrupts, but not important for this course • TOSH_INTERRUPT() – interrupt allowed • TOSH_SIGNAL() – interrupt forbidden • Scheduler • Two level scheduling - interrupts (vector) and tasks (queue) • Queue of tasks • No associated priorities • FIFO execution • No local state associated with tasks • Programmer must manage own internal state when tasks need it • Danger: task queue overflows (because no dynamic memory)

  47. What the scheduler does… Tasks Preempt POST events commands commands Interrupts Time Hardware FIFO • Operation • When no tasks pending, sleep • Wake on interrupt, lookup interrupt handler and execute • Before sleeping again, check task queue, call task in FIFO order • Practices • Statically defined maximum queue length means code should be carefully written to avoid posting too many tasks • E.g., if we have a list of thing to process (such as messages), rather than post a separate task for each message, post the next processing task at the end of the task handler while(1) { while(more_tasks) schedule_task; sleep; } Task void send(){ //get head of send queue //send message if (queue.size > 0) post send() }

  48. Posting Tasks module BlinkM {… } implementation {… task void processing () { if(state) call Leds.redOn(); else call Leds.redOff(); } event result_t Timer.fired () { state = !state; post processing(); return SUCCESS; }… } BlinkM.nc

  49. Language features for concurrency • Post • Puts a function on a task queue • Must be void foo(void) • void task do-work() { //do something } • post do-work(); • Atomic • Interrupts can preempt execution • Turn off interrupts with atomic{ } • E.g. to implement a semaphore • Async • Use async to tell compiler that this code can be called from an interrupt context – used to detect potential race conditions • Norace • Use norace to tell compiler it was wrong about a race condition existing (the compiler usually suggests a million possible race conditions)

  50. Debugging using print statements • TinyOS’s printf: • dbg(DBG_USR1, “%s [%d] – link quality is %d\n”, __FILE__, __LINE__, link_quality); • DBG_USR1, DBG_USR2, DBG_USR3, and DBG_ERROR are defined for your enjoyment

More Related