📄 lesson1.html
字号:
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en"><html><head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta name="GENERATOR" content="Mozilla/4.78 [en] (X11; U; Linux 2.4.7-10 i686) [Netscape]"> <title>TinyOS Tutorial Lesson 1: Getting Started with TinyOS and nesC</title></head><body bgcolor="#f8f8ff" link="#005bb7" vlink="#005bb7"> <table border="0" cellspacing="2" cellpadding="3" width="100%" hspace="4"> <tbody> <tr bgcolor="#e0e0ff"> <td width="100%"><b><font face="tahoma,arial,helvetica"><font size="-1">Lesson 1: Getting Started with TinyOS and nesC</font></font></b> <p><font face="tahoma,arial,helvetica">Last updated 9 September2003</font></p> </td> </tr> </tbody></table><p>This lesson introduces the basic concepts of TinyOS and the nesClanguage in which the system is written. It includes a quick overviewof the nesC language concepts and syntax to help you get started withprogramming in this environment.<table border="0" cellspacing="2" cellpadding="3" width="100%" hspace="4"> <tbody> <tr bgcolor="#e0e0ff"> <td width="100%"><b><nobr><font face="arial,helvetica">Introduction</font></nobr></b></td> </tr> </tbody></table></p><p>The TinyOS system, libraries, and applications are written in nesC,a new language for programming structured component-based applications.The nesC language is primarily intended for embedded systems such assensor networks. nesC has a C-like syntax, but supports the TinyOSconcurrency model, as well as mechanisms for structuring, naming, andlinking together software components into robust network embeddedsystems. The principal goal is to allow application designers to buildcomponents that can be easily composed into complete, concurrentsystems, and yet perform extensive checking at compile time. </p><p>TinyOS defines a number of important concepts that are expressed innesC. First, nesC applications are built out of <b>components</b> withwell-defined, bidirectional <b>interfaces</b>. Second, nesC defines aconcurrency model, based on <b>tasks</b> and <b>hardware event handlers</b>,and detects <b>data races</b> at compile time. </p><p><b>Components</b> <br><i>Specification</i> <br>A nesC application consists of one or more <i>components </i>linkedtogether to form an executable. A component <b>provides</b> and <b>uses</b> <i>interfaces</i>.These interfaces are the only point of access to the component and arebi-directional. An interface declares a set of functions called <b>commands</b>that the interface provider must implement and another set of functionscalled <b>events</b> that the interface user must implement. For acomponent to call the commands in an interface, it must implement theevents of that interface. A single component may use or providemultiple interfaces and multiple instances of the same interface. </p><p><i>Implementation</i> <br>There are two types of components in nesC: <b>modules</b> and <b>configurations</b>.Modules provide application code, implementing one or more interface.Configurations are used to assemble other components together,connecting interfaces used by components to interfaces provided byothers. This is called <b>wiring</b>. Every nesC application isdescribed by a <b>top-level configuration</b> that <i>wires</i>together the components inside. </p><p>nesC uses the filename extension "<tt>.nc</tt>" for all source files-- interfaces, modules, and configurations. Please see <a href="naming.html">TinyOS Coding and Naming Conventions</a> for moreinformation on naming conventions. </p><p><b>Concurrency Model</b> <br>TinyOS executes only one program consisting of selected systemcomponents and custom components needed for a single application. Thereare two threads of execution: <i>tasks</i> and <i>hardware eventhandlers</i>. Tasks are functions whose execution is deferred. Once scheduled, they run to completion and do not preempt one another.Hardware event handlers are executed in response to a hardwareinterrupt and also runs to completion, but may preempt the execution ofa task or other hardware event handler. Commands and events that areexecuted as part of a hardware event handler must be declared with the <b>async</b>keyword. </p><p>Because tasks and hardware event handlers may be preempted by otherasynchronous code, nesC programs are susceptible to certain raceconditions. Races are avoided either by accessing shared dataexclusively within tasks, or by having all accesses within <b>atomic</b>statements. The nesC compiler reports potential <i>data races</i> to theprogrammer at compile-time. It is possible the compiler may report afalse positive. In this case a variable can be declared with the <b>norace</b>keyword. The norace keyword should be used with extreme caution. </p><p>Please see the <a href="../../nesc/doc/ref.pdf">nesC LanguageReference Manual</a> for more information on programming in nesC. <br> <table border="0" cellspacing="2" cellpadding="3" width="100%" hspace="4"> <tbody> <tr bgcolor="#e0e0ff"> <td width="100%"><b><nobr><font face="arial,helvetica">An exampleapplication: Blink</font></nobr></b></td> </tr> </tbody></table></p><p>So far this is all fairly abstract - let's look at a concreteexample: the simple test program "Blink" found in <tt><a href="../../apps/Blink">apps/Blink</a></tt> in the TinyOS tree. Thisapplication simply causes the red LED on the mote to turn on and off at1Hz. </p><p>Blink application is composed of two <b>components</b>: a <b>module</b>,called "<tt>BlinkM.nc</tt>", and a <b>configuration</b>, called "<tt>Blink.nc</tt>".Remember that all applications require a top-level configuration file,which is typically named after the application itself. In this case <tt>Blink.nc</tt>is the configuration for the Blink application and the source file thatthe nesC compiler uses to generate an executable file. <tt>BlinkM.nc</tt>,on the other hand, actually provides the <i>implementation</i> of theBlink application. As you might guess, <tt>Blink.nc</tt> is used towire the <tt>BlinkM.nc</tt> module to other components that the Blinkapplication requires. </p><p>The reason for the distinction between modules and configurations isto allow a system designer to quickly "snap together" applications. Forexample, a designer could provide a configuration that simply wirestogether one or more modules, none of which she actually designed.Likewise, another developer can provide a new set of "library" modulesthat can be used in a range of applications. </p><p>Sometimes (as is the case with <tt>Blink</tt> and <tt>BlinkM</tt>)you will have a configuration and a module that go together. When thisis the case, the convention used in the TinyOS source tree is that <tt>Foo.nc</tt>represents a configuration and <tt>FooM.nc</tt> represents thecorresponding module. While you could name an application'simplementation module and associated top-level configuration anything,to keep things simple we suggest that you adopt this convention in yourown code. There are several other naming conventions used in TinyOScode; a <a href="naming.html">summary</a> is provided<table border="0" cellspacing="2" cellpadding="3" width="100%" hspace="4"> <tbody> <tr bgcolor="#e0e0ff"> <td width="100%"><b><nobr><font face="arial,helvetica">TheBlink.nc configuration</font></nobr></b></td> </tr> </tbody></table></p><p>The nesC compiler, <a href="../nesc/ncc.html">ncc</a>, compiles anesC application when given the file containing the top-levelconfiguration. Typical TinyOS applications come with a standard Makefilethat allows platform selection and invokes ncc with appropriate optionson the application's top-level configuration. </p><p>Let's look at <tt>Blink.nc</tt>, the configuration for thisapplication first: </p><center><table border="0" cellspacing="2" cellpadding="3" width="80%" hspace="4"> <tbody> <tr bgcolor="#e0e0e0"> <td width="100%"><b>Blink.nc</b> <pre>configuration Blink {<br>}<br>implementation {<br> components Main, BlinkM, SingleTimer, LedsC;<br><br> Main.StdControl -> BlinkM.StdControl;<br> Main.StdControl -> SingleTimer.StdControl;<br> BlinkM.Timer -> SingleTimer.Timer;<br> BlinkM.Leds -> LedsC;<br>}</pre> </td> </tr> </tbody></table></center><p>The first thing to notice is the key word <tt>configuration</tt>,which indicates that this is a configuration file. The first two lines, </p><pre> configuration Blink {<br> }</pre>simply state that this is a configuration called <tt>Blink</tt>.Within the empty braces here it is possible to specify <tt>uses</tt>and <tt>provides</tt> clauses, as with a module. This is important tokeep in mind: a configuration can use and provide interfaces!<p>The actual configuration is implemented within the pair of curlybracket following key word <tt>implementation </tt>. The <tt>components</tt>linespecifies the set of components that this configuration references, inthis case <tt>Main</tt>, <tt>BlinkM</tt>, <tt>SingleTimer</tt>, and <tt>LedsC</tt>.The remainder of the implementation consists of connecting interfacesused by components to interfaces provided by others. </p><p><tt>Main</tt> is a component that is executed first in a TinyOSapplication. To be precise, the <tt>Main.StdControl.init()</tt> commandis the first command executed in TinyOS followed byMain.StdControl.start(). Therefore, a TinyOS application must have Maincomponent in its configuration. <tt>StdControl</tt> is a commoninterface used to initialize and start TinyOS components. Let us have alook at <tt>tos/interfaces/StdControl.nc</tt>: </p><center><table border="0" cellspacing="2" cellpadding="3" width="80%" hspace="4"> <tbody> <tr bgcolor="#e0e0e0"> <td width="100%"><b>StdControl.nc</b> <pre>interface StdControl {<br> command result_t init();<br> command result_t start();<br> command result_t stop();<br>}</pre> </td> </tr> </tbody></table></center><p>We see that <tt>StdControl</tt> defines three <b>commands</b>, <tt>init()</tt>,<tt>start()</tt>,and <tt>stop()</tt>. <tt>init()</tt> is called when a component isfirst initialized, and <tt>start()</tt> when it is started, that is,actually executed for the first time. <tt>stop()</tt> is called whenthe component is stopped, for example, in order to power off the devicethat it is controlling. <tt>init()</tt> can be called multiple times,but will never be called after either <tt>start()</tt> or <tt>stop</tt>are called. Specifically, the valid call patterns of StdControl are <tt>init*(start| stop)* . </tt>All three of these commands have "deep" semantics;calling <tt>init()</tt> on a component must make it call <tt>init()</tt>on all of its subcomponents. The following 2 lines in Blinkconfiguration </p><pre> Main.StdControl -> SingleTimer.StdControl;<br> Main.StdControl -> BlinkM.StdControl;</pre>wire the <tt>StdControl</tt> interface in <tt>Main</tt> to the <tt>StdControl</tt>interface in both <tt>BlinkM</tt> and <tt>SingleTimer</tt>. <tt>SingleTimer.StdControl.init()</tt>and<tt>BlinkM.StdControl.init()</tt>will be called by <tt>Main.StdControl.init()</tt>. The same ruleapplies to the <tt>start() and <font color="#000000">stop() </font></tt>commands.<p>Concerning <i>used</i> interfaces, it is important to note thatsubcomponent initialization functions must be explicitly called by theusing component. For example, the BlinkM module uses the interfaceLeds, so Leds.init() is called explicitly in BlinkM.init(). </p><p>nesC uses arrows to determine relationships between interfaces.Think of the right arrow (<tt>-></tt>) as "binds to". The left sideof the arrow binds an interface to an implementation on the right side.In other words, the component that <b>uses</b> an interface is on theleft, and the component <b>provides </b>the interface is on the right. </p><p>The line </p><pre> BlinkM.Timer -> SingleTimer.Timer;</pre>is used to wire the <tt>Timer</tt> interface used by BlinkM to theTimer interface provided by SingleTimer. <tt>BlinkM.Timer</tt> on theleft side of the arrow is referring to the <i>interface</i> calledTimer (<tt>tos/interfaces/Timer.nc</tt>), while SingleTimer.Timer onthe right side of the arrow is referring to the <i>implementation </i>ofTimer (<tt>tos/lib/SingleTimer.nc)</tt>. Remember that the arrow alwaysbinds interfaces (on the left) to implementations (on the right).<p>nesC supports multiple implementations of the same interface. The <tt>Timer</tt>interfaceis such a example. The <tt>SingleTimer </tt>component implements asingle <tt>Timer</tt> interface while another component, <tt>TimerC, </tt>implementsmultiple timers using timer id as a parameter. Further discussions ontimers can be found in Lesson 2. </p><p>Wirings can also be implicit. For example, </p><pre> BlinkM.Leds -> LedsC;</pre>is really shorthand for<pre> BlinkM.Leds -> LedsC.Leds;</pre>If no interface name is given on the right side of the arrow, the nesCcompiler by default tries to bind to the same interface as on the leftside of the arrow. <br> <br> <table border="0" cellspacing="2" cellpadding="3" width="100%" hspace="4"> <tbody> <tr bgcolor="#e0e0ff"> <td width="100%"><b><nobr><font face="arial,helvetica">The
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -