资源描述
,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第九章 物联网中的常用嵌入式系统,本章主要内容,9.1 TinyOS,简介,9.2,安装,TinyOS,9.3 nesC,简介,9.4 TinyOS,内部机制简介,思考与习题,9.1 TinyOS,简介,9.1.1 TinyOS,概述,9.1.2 TinyOS,的特点,9.1.3 TinyOS,开发平台,9.1.4 TinyOS,开发案例,9.1.5 TinyOS,的基本概念,回本章目录,9.1.1 TinyOS,概述,TinyOS,操作系统采用了组件的结构。系统本身提供了一系列的组件供用户调用,其中包括主组件、应用组件、执行组件、传感组件、通信组件和硬件抽象组件,如下图,9-1,所示。组件由下到上可分为,3,类:硬件抽象组件、综合硬件组件和高层软件组件。, 硬件抽象组件将物理硬件映射到,TinyOS,的组件模型;, 综合硬件组件模拟高级的硬件行为,如感知组件、通信组件等;, 高层次的软件组件实现控制、路由以及数据传输等应用层的功能。,图,9-1 TinyOS,的组件结构,回本章目录,每个,TinyOS,程序应当具有至少一个应用组件,即用户组件。该应用组件通过接口调用下层组件提供的服务,实现针对特定应用的具体逻辑功能,如数据采集、数据处理、数据收发等。一个完整的应用系统由一个内核调度器(简称调度器)和许多功能独立且相互联系的组件构成,可以把,TinyOS,系统和在其上运行的应用程序看成是一个大的“执行程序”。现有的,TinyOS,系统提供了大多数传感网硬件平台和应用领域里都可用到的组件,例如定时器组件、传感器组件、消息收发组件、电源管理组件等,从而把用户和底层硬件隔离开来。在此基础上,用户只需开发针对特殊硬件和特殊应用需求的少量组件,大大提高了应用的开发效率。,TinyOS,设计之初的目的是制作一个专属嵌入式无线传感器网络的操作系统。但事实上,由于良好的可扩展性和足够小的代码尺寸,,TinyOS,在物联网的应用领域中也占有非常重要的地位。,由于无线传感器网络的特殊性,研究人员在设计,TinyOS,系统时就提出以下几个原则:, 能在有限的资源上运行:要求执行模式允许在单一的协议栈上运行;, 允许高度的并发性:要求执行模式能对事件作出快速的直接响应;, 适应硬件升级:要求组件和执行模式能够应对硬件,/,软件的替换;, 支持多样化的应用程序:要求能够根据实际需要,裁减操作系统的服务;, 鲁棒性强:要求通过组件间有限的交互渠道,就能应对各种复杂情况;, 支持一系列平台:要求操作系统的服务具有可移植性。,TinyOS,操作系统采用的轻量级线程技术、两层调度方式、事件驱动模式、主动消息通信技术及组件化编程等有效地提高了传感器节点,cpu,的使用率,有助于省电操作并简化了应用的开发。,TinyOS,系统、库和基于,TinyOS,的应用基本上都是用,nesC,语言开发的,在,TinyOS,中采用,nesC,语言进行应用程序开发。在,TinyOS,中,应用程序开发人员可以通过,nesC,语言表达组件以及组件之间的事件,/,命令接口。组件分为配置文件和模块,程序的流程是通过配置文件中接口的连接实现而构建起来的,而具体实现的逻辑功能是通过模块完成的。每个模块由一组命令和事件组成,这些命令和事件成为该模块的接口。一般来说,上层组件对下层组件发命令,下层组件发信号通知事件的发生,最底层的组件直接和硬件交互,从而自上到下形成一种树状结构。,TinyOS,的并行处理能力通过任务(,task,)和中断处理事件(,interrupt hander event,)来体现。任务会加入一个,FIFO,队列中,在执行过程中,任务间没有竞争;但中断处理程序可以打断任务执行。,TinyOS,采用二级调度机制来满足无线传感网络运行特点,整个程序调度过程如图,9-2,所示。组件中完成任务提交,由操作系统完成调度。一个节点上应用程序的框图如图,9-3,所示,操作系统只是在后台提供队列服务。,图,9-2 TinyOS,程序调度,图,9-3,一个节点上应用程序的框图,与,uCOS-II,相比,,,Tiny-OS,基于事件驱动的机制就决定了其实时性不高,编程复杂,但其内核占用空间极小,而,uCOS-II,是基于线程模式的,编程简单,实时性高,但相对带来的开销也大。表,9-2,比较了,Tiny-OS,与,uCOS-II,。,操作系统,TinyOS,uCOS-II,运行模式,事件,线程,抢占式内核,否,是,时间可确定性,否,是,支持动态编程,否,否,(最小)内核,RAM:47B,ROM:473B,RAM:300B,ROM:2kB,低功耗,是,否,表,9-2 Tiny-OS,与,uCOS-II,的比较,9.1.2 TinyOS,的特点,回本章目录,command void taskLoop();,interface Boot ,/opt/TinyOS-2.,形象的称为命令,即为接口提供的可供调用的命令。,系统本身提供了一系列的组件供用户调用,其中包括主组件、应用组件、执行组件、传感组件、通信组件和硬件抽象组件,如下图9-1所示。,module M2 ,一个组件使用了一个接口,它可以调用这个接口的命令,但必须实现其事件。,本章主要内容,uses interface A1;, 一个module可以同时提供一组相同的接口,又称参数化接口,表明该Module可提供多份同类资源,能够同时给多个组件分享。,配件(configuration)是一个完整的配置列表,配件可以像模块一样使用外部的接口并且对外提供接口。,event void A1.,nx_uint8_t dataTOSH_DATA_LENGTH; /有效载荷区,事件处理字阶级组件传递的解码数据,主要是通过Post一个任务进行CRC检查。,配件(configuration)是一个完整的配置列表,配件可以像模块一样使用外部的接口并且对外提供接口。,表9-3 环境变量的配置,连接的箭头是也可以对称反过来,如“BlinkC.,nesC的组件模型如图9-10。,一个nesC语言编写的程序由一个或多个组件(component)构成或连接而成。, 通过任务和事件来管理并发进程,TinyOS,的应用程序都是基于事件驱动模式的,采用事件触发去唤醒传感器工作。事件相当于不同组件之间传递状态信息的信号。当事件对应的硬件中断发生时,系统能够快速地调用相关的事件处理程序。,任务:一般用在对于时间要求不是很高的应用中,且任务之间是平等的,即在执行时是按顺序先后来得,而不能互相占先执行,一般为了减少任务的运行时间,要求每一个任务都很短小,能够使系统的负担较轻;支持网络协议的替换。,事件:一般用在对于时间的要求很严格的应用中,而且它可以占先优于任务和其他事件执行,它可以被一个操作的完成或是来自外部环境的事件触发,在,TinyOS,中一般由硬件中断处理来驱动事件。, 支持网络协议组件的替换,除了默认的协议之外,还提供其他协议供用户替换,并且支持客户自定义协议,这对于通信协议分析,非常适用于通信协议的研究工作。, 代码短小精悍,TinyOS,的程序采用的是模块化设计,所以它的程序核心往往都很小,一般来说核心代码和数据大概在,400Bytes,左右;能够突破传感器存储资源少的限制,这能够让,TinyOS,很有效的运行在无线传感器网络上并去执行相应的管理工作等。,9.1.3 TinyOS,开发平台,国内目前可以买到的,TinyOS,开发平台主要有两种,一种是,Crossbow,公司,WSN,开发套件,一种亿道电子的,XSBase-WSN,开发套件;,Crossbow,本身就是,TinyOS,联盟的成员之一,其所有产品都在,TinyOS,源码的,Platform,目录下可以找到,可以算得上是,TinyOS,技术商用化的代表;在国内有一家代理,开发平台的做工非常不错,产品覆盖面也比较广,主要的缺点就是产品太贵,而且中文的资料较少。,亿道电子的,WSN,套件使用的是较先进,CC2430,芯片,同时支持,TinyOS,和,Z-stack,两种开发方式,并且包含大量的中文教材和使用手册,硬件移植的也非常稳定,所有的,TinyOS,测试用例都能正常运行,而且还带了大量的中文教材、使用手册和实验用例,其中值得一提的是,该产品搭建了一整套的解决方案框架,实现了异构网络之间的互联互通,可以在任何一地通过,GPRS,手机上网,访问节点上的物理数据,开发者可以迅速的在这个框架下做二次开发。,回本章目录,9.1.4 TinyOS,开发案例,目前有多个采用,TinyOS,的研究项目,如,UCLA,(加州大学洛杉矶分校)的,Shahin Farshchi,在进行一项以,TinyOS,为基础的无线神经界面研究。这样的系统在,100Hz/,频道的采样频率下可传感、放大、传输神经信号,系统小巧、成本低、重量轻、功率小。系统要求一个接收器接收、解调、显示传输的神经信号。在采样精度为,8bit,时,系统的速度可达,5600,。该速度可保证,8,个,EEG,频道、或,1,个速度为每秒采样频道的可靠传输。研究者目前的奋斗目标是提高该基于,TinyOS,的传感网络的数据传输速度,设计与被测对象连接的前端神经放大电路。,路易斯安娜州立大学和位于,BatonRouge,的南方大学的,Nian-Feng Tzeng,博士正在研究应用于石油,/,气体开发和管理的,UcoMS,(,Ubiquitous Computing and Monitoring System,,泛计算和监控系统)。该系统适用于传感网络、无线通信和网格计算,主要功能包括帮助钻孔、操作数据记录和处理、在线平台信息发布和显示、设备监控,/,入侵检测、地震处理、复杂表面设备和管道的管理。也可使用,UCoMS,监控、维护淘汰的平台。,另外,,Freescale,正在其,Zigbee,开发板上测试,TinyOS,和,TinyDB,,波士顿大学的,WeiLi,将其用于传感网络的控制和优化。,回本章目录,9.1.5 TinyOS,的基本概念,TinyOS,系统、库及应用程序都是用,nesC,语言写的语言写的,这时一种新的用于编写结构化的基于组件的应用程序的语言。,nesC,语言主要用于诸如传感器网络等嵌入式系统。,nesC,具有类似于,C,语言的语法,但支持,TinyOS,的并发模型,同时具有结构化机制、命名机制,能够与其他软组件链接在一起从而形成一个鲁棒的网络嵌入式系统。其主要目标是帮助应用程序设计者建立可易于组合成完整、并发式系统的组件,并能够在编译时执行广泛的检查。,TinyOS,定义了许多在,nesC,中所表达的重要概念。首先,,nesC,应用程序要建立在定义良好、具有双向接口的组件之上。其次,,nesC,定义了并发模型,该模型是基于任务(,task,)及硬件事件句柄(,hardware event handler,)的,在编译时会检测数据争用(,data race,)。,回本章目录, 组件,任何一个,nesC,应用程序都是有一个或多个组件链接起来,从而形成一个完整的可执行程序的。组件提供(,provide,)并使用(,use,)接口。这些接口是组件的唯一访问点并且它们是双向的。接口声明了一组函数,称为命令(,command,),接口的提供者必须实现它们;还声明了另外一组函数,称为事件(,event,),接口的使用者必须实现它们。对于一个组件而言,如果它要使用某个接口中的命令,它必须实现这个接口的事件。一个组件可以使用或提供多个接口以及同一个接口的多个实例。,在,nesC,中有两种类型的组件,分别称为模块(,module,)和配件(,configuration,)。模块提供应用程序代码,实现一个或多个接口;配件则是用来将其它组件装配起来的组件,将各个组件所使用的接口与其它组件提供的接口连接在一起。这种行为称为导通(,wiring,)。每个,nesC,应用程序都由一个顶级配置所描述,其内容就是将该应用程序所用到的所有组件导通起来,形成一个有机整体。, 并发模型,TinyOS,一次仅执行一个程序。组成程序的组件来自于两个方面,一部分是系统提供的组件,另一部分是为特定应用用户自定义的组件。程序运行时,有两个执行线程:一个称为任务(,task,),另一个称为硬件事件句柄(,hardware event handler,)。任务是被延期执行的函数,它们一旦被调度,就会运行直至结束,并且在运行过程中不准相互抢占。硬件事件句柄是用来相应和处理硬件中断的,虽然也要运行完毕,但它们可能会抢占任务或其他硬件事件句柄的执行。命令和事件要作为硬件事件句柄的一部分而执行必须使用关键字,async,来声明。,因为任务和硬件事件句柄可能被其他异步代码所抢占,所以,nesC,程序易于受到特定竞争条件的影响,导致产生不一致或不正确的数据。避免竞争的办法通常是在任务内排他地访问共享数据,或访问所有数据都使用原子语句。,nesC,编译器会在编译时向程序员报告潜在的数据争用,这里面可能包含事实上并不可能发生的冲突。如果程序员确实可以担保对某个数据的访问不会导致麻烦,可以将该变量使用关键字,norace,来声明,但使用这个关键字一定要格外小心。,9.2,安装,TinyOS,回本章目录,图,9-4,设置,JAVA_HOME,环境变量, 新建系统变量,CLASSPATH,:设置类的路径,CLASSPATH=.;%JAVA_HOME%jrelibrt.jar;%JAVA_HOME%libtools.jar;%JAVA_HOME%libdt.jar,最前面加上”,.,”和”,;,”,意为首先在当前目录中查找,如图,9-5,所示。,图,9-5,设置,CLASSPATH,环境变量, 在系统变量中找到,Path,:将,%JAVA_HOME%bin;%JAVA_HOME%jrebin;,添加到最前面即可。,至此,JDK,安装过程结束,可以自行编写一个测试程序。在,D,盘根目录下新建文件夹,javatest,,然后创建文本文件,将下面的代码拷入并保存成文件,注意文件名要与类名相一致。,public class Test,public static void main(String args),System.out.println(Hello World!);,然后再使用,cmd,命令进入命令行,并进入该目录下,尝试使用如下命令编译并执行该,java,程序,如果然后屏幕上会打印出”,Hello World!”,,则表示,JDK,安装成功。,java Test,图,9-6,选择安装类型, 硬件抽象组件将物理硬件映射到TinyOS的组件模型;,interface Scheduler ,一个组件可以使用(use)或提供(provide)多个接口或者同一接口的多个实例。,回本章目录,include $(MAKERULES),该内容要放在中,SendMsg接口类型提供者必须实现send,而使用者必须实现sendDone事件。,components M2;,command bool runNextTask(bool sleep);,implementation ,TOSSIM模拟器提供运行时调试输出信息,允许用户从不同角度分析和观察程序的执行过程。,大致看来,在TinyOS的通讯经历的组件流程如图9-13所示,uses interface A1;,uses interface B1;,/opt/TinyOS-2.,TOSH run task () ;,语法结构类似于C语言,只是在最前面增加event关键字。,硬件事件句柄是用来相应和处理硬件中断的,虽然也要运行完毕,但它们可能会抢占任务或其他硬件事件句柄的执行。,接口SendMsg中包含commandssend和eventssenddone。,c -o test就可以编译该程序。,8位无符号数:uint8_t, TinyOS的程序运行机制, 选择安装目录时,在,Default Text File Type,中要选择,Unix/binary,,如图,9-7,。,图,9-7,选择安装目录, 然后在选择需要安装的工具时,全部选中,用鼠标点击“,default,”变成“,install,”。, 最后点击安装来开始安装,整个过程需要较长时间。, 安装单片机工具,可以选择,AVR,或,MSP430,等,根据自己的需要安装。如果选择,AVR,,则需要下面几个包:,avr-binutils,、,avr-gcc,、,avr-libc,、,avarice,、,insight (,avr-gdb,),、,avrdude,,这几个包的下载地址在本节开始提到的网站中可以找到,需要注意的是,在,cygwin,和,Linux,下下载的包是不一样的。, 安装,nesC,和,TinyOS_tool,这一步需要安装,NesC,、,Deputy,、,TinyOS-tools,三个包,这几个包的下载地址在本节开始提到的网站中可以找到,这里同样需要需要在,cygwin,和,Linux,下下载的包是不一样的,使用,Linux,的,rpm,命令来安装这些包。,环境变量,cygwin下的配置,Linux下的配置,TOSROOT,/opt/TinyOS-2.x,同,cygwin下的配置,TOSDIR,$TOSROOT/tos,同,cygwin下的配置,CLASSPATH,C:cygwinoptTinyOS-2.xsupportsdkjavaTinyOS.jar;.,$TOSROOT/support/sdk/java/TinyOS.jar:.,MAKERULES,$TOSROOT/support/make/Makerules,同,cygwin下的配置,PATH,/opt/msp430/bin:/opt/jflashmm:$PATH,同,cygwin下的配置,表,9-3,环境变量的配置, 安装,Graphviz,9.3 nesC,简介,9.3.1 nesC,概述,9.3.2 nesC,基本概念,9.3.3,一个简单的,nesC,编程示例,9.3.4 TOSSIM,仿真,回本章目录,9.3.1 nesC,概述,nesC,语言是一种在,C,基础上扩展的编程语言,主要用于传感器网络的编程开发,,这类系统的特点是内存有限,存在任务和中断两类操作。,nesC,语言由加州大学伯克利分校研发人员开发。,TinyOS,最初是用汇编和,C,语言编写的,后来改用支持组件化编程的,nesC,语言。该语言把组件化,/,模块化思想和基于事件驱动的执行模型结合起来。,nesC,使用,C,作为其基础语言,支持所有的,C,语言词法和语法,其独有的特色如下:, 增加了组件(,component,)和接口(,interface,)的关键字定义;, 定义了接口及如何使用接口表达组件之间关系的方法;, 目前只支持组件的静态连接,不能实现动态连接和配置。,回本章目录,图,9-8,所示是,nesC,语言的一般程序框架。该系统中的一个组件一般会提供一些接口(假定组件名为,ComA,),接口可以被认为是这个软件组件实现的一组函数的声明,是单独定义的一组命令和事件,其他组件通过引用相同接口声明来使用这个组件(,ComA,)的函数,从而实现组件间功能的相互调用,即组件的接口是实现组件间互连的通道。但若组件中实现的函数并未被它在接口中说明,就不能被其他组件所使用。,nesC,语言的定义中存在两种不同功能的组件:其中组件接口中的函数功能专门在模块的组件文件中实现,而不同组件之间的关系则是专门通过称为配件的组件文件来描述的。,图,9-8,基于,nesC,语言的一般程序框架图,为了跨平台使用,变量的类型和标准,C,语言的,int,、,long,和,char,不一样。,TinyOS,代码使用的是更清楚直接的类型,直接声明字节大小。事实上,这些能映射到基本的,C,类型,在不同的平台上是不同的映射,大多数平台支持浮点数运算,,double,可能不行。对于整形,,nesC,的定义如下:,8,位带符号数:,int8_t,8,位无符号数:,uint8_t,16,位带符号数:,int16_t,16,位无符号数:,uint16_t,32,位带符号数:,int32_t,32,位无符号数:,uint32_t,虽然可以给应用程序中的模块和配件取任意的名称,但为了简便,建议在编写代码时使用如表,9-4,所示的统一的命名格式。,表,9-4 nesC,程序的命名,最后简单介绍一下使用,nesC,编程的流程,,nesC,语言开发应用程序的一般步骤如图,9-9,所示。,图,9-9,使用,nesC,编程的流程,9.3.2 nesC,基本概念, 组件,一个,nesC,语言编写的程序由一个或多个组件(,component,)构成或连接而成。一个组件由两部分组成:第一个部分是规范说明,包含要用接口的名字;另一部分是它们的实现。一个组件可以提供接口(,provides,),也可以使用接口(,uses,),提供的接口描述了该组件提供给上一层调用者的功能,而使用的接口则表示了该组件本身工作时需要的功能。组件分两种:,Module,组件(模块)用于实现某种逻辑功能;,Configuration,组件(配件)用于将各个组件连接起来成为一个整体。组件特征的特征是组件内变量、函数可以自由访问,但组件之间不能访问和调用。,nesC,的组件模型如图,9-10,。,回本章目录, 接口,接口是一组相关函数的集合,它是双向的并且是组件间的唯一访问点。由于大多数的节点平台没有基于硬件的内存保护措施,也没有将用户地址空间和系统地址空间分离开,只有一个所有组件都能共享的地址空间。最好的办法就是保持内存尽可能少的共享。组件声明的任何状态变量都是私有的:没有任何其他组件可以对它进行命名或者直接访问它。两个组件直接交互的唯一方式是通过接口。接口声明了两种函数:,图,9-10 TinyOS,的组件模型,在中,SchedulerBasicP是主要的TinyOS调度器,提供带参数的TaskBasic接口。,$TOSROOT/support/make/Makerules,连接的箭头是也可以对称反过来,如“BlinkC.,接口SendMsg和ReceiveMsg都是参数化接口,参数id就是前面说的handlerid。,在采样精度为8bit时,系统的速度可达5600。, provides未必一定有组件使用,但uses一定要有人提供,否则编译会提示出错。, TinyOS的程序运行机制,与uCOS-II相比,Tiny-OS基于事件驱动的机制就决定了其实时性不高,编程复杂,但其内核占用空间极小,而uCOS-II是基于线程模式的,编程简单,实时性高,但相对带来的开销也大。,nesC使用箭头“-”来绑定一个接口到另一个接口,但一定要是同一类接口。,TinyOS在某些场合因实时性比较差,会出现任务过载、任务阻塞、任务队列溢出、通信吞吐量下降等一系列问题,从而导致系统崩溃,在这种情况下,需进一步改进TinyOS实时性、并发性及移植性,并通过完善其整体架构来提高其综合性能。,硬件事件句柄是用来相应和处理硬件中断的,虽然也要运行完毕,但它们可能会抢占任务或其他硬件事件句柄的执行。,消息的发送涉及组件、接口和事件三方面,当上层组件有消息发送时通过接口调用下层组件来实现。,这里需要将顶层的配置放到COMPONENT 中。,$TOSROOT/support/make/Makerules,3 一个简单的nesC编程示例,此确认消息是在主动消息层的最底层生成,其内容是一个特殊立即序列,发送方可迅速确定是否需重发消息。,若任务队列为空,CPU进入休眠状态以降低功耗。,provides interface A1;,路易斯安娜州立大学和位于BatonRouge的南方大学的Nian-Feng Tzeng博士正在研究应用于石油/气体开发和管理的UcoMS(Ubiquitous Computing and Monitoring System,泛计算和监控系统)。,cmd1(0x11);, 命令(,command,):接口的提供者必须实现它们;, 事件(,event,):接口的使用者必须实现它们 。,也就是说,提供了接口的组件必须实现该接口的命令函数;而使用了某接口的组件必须实现该接口的事件函数。函数调用时,命令用,call,,事件用,signal,,在一个组件中,,provides,的接口中的,command,函数必须被实现(在,implementation,中定义),,uses,的接口中的,event,函数必须被实现。,async,指出这个,command,或者,event,可以在有中断时使用。如果一个组件调用了(,call,)的一个接口命令,必须实现该接口的事件。一个组件可以使用(,use,)或提供(,provide,)多个接口或者同一接口的多个实例。,接口的特点是:,provides,未必一定有组件使用,但,uses,一定要有人提供,否则编译会提示出错。在动态组件配置语言中,uses,也可以动态配置。, 接口可以连接多个同样的接口,叫做多扇入,/,扇出。, 一个,module,可以同时提供一组相同的接口,又称参数化接口,表明该,Module,可提供多份同类资源,能够同时给多个组件分享。,可以按照下面的方法定义接口:, 接口放在一个单独的文件中,*.nc, 接口的名称应与文件名对应,例如,interface1,的接口必须对应于文件名。, 接口定义描述了一系列函数原型(,command,和,event,),一个简单地接口如下:,interface SendMsg ,command result_t send(uint16_t address, uint8_t length, TOS_MsgPtr msg);,event result_t sendDone(TOS_MsgPtr msg, result_t success);,该内容要放在中,,SendMsg,接口类型提供者必须实现,send,,而使用者必须实现,sendDone,事件。,nesC,使用箭头“,-,”来绑定一个接口到另一个接口,但一定要是同一类接口。例如“,A - B,”意为,A,连接到,B,,,A,是接口的使用者(,user,),而,B,是接口的提供者(,provider,)。完整的表达式应该为:,A. a - B. b,,这意味着,组件,A,的接口,a,连接到组件,B,的接口,b,。当一个组件使用或者提供同一个接口的多个不同实例时,设置别名就非常有必要了。当一个组件只含有一个接口的时候,就可以省略接口的名字了。连接的箭头是也可以对称反过来,如“,BlinkC.Timer0 - Timer0,”同“,Timer0 M2.B1;, 命令,命令是在接口中的一种函数,这种函数要求接口的提供者实现,而接口的使用者则会调用这种函数。形象的称为命令,即为接口提供的可供调用的命令。语法结构类似于,C,语言,只是在最前面增加,command,关键字。, 命令定义,下面给出一个命令的定义。,interface A1 ,command int cmd1(int arg);, 命令实现,下面给出一个命令的实现,module M1 ,provides interface A1;,implementation ,command int A1.cmd1(int arg) , 命令使用,下面给出一个命令的使用,调用命令时一定要用,call,命令,否则编译会出错。,module M2 ,uses interface A1;,implementation ,int ret = call A1.cmd1(0x11);, 事件,事件也是在接口中的一种函数,这种函数要求接口的提供者调用,而接口的使用者则会实现这种函数。形象的称为,event,,即为接口使用者所实现的事件处理函数。语法结构类似于,C,语言,只是在最前面增加,event,关键字。, 事件定义,下面给出一个事件的定义,它可以拥有参数和返回值。,interface A1 ,event void event1(int arg1, int arg2);, 事件实现,下面给出的是事件的实现,接口的提供者在发出事件时,必须使用关键字,post,,否则编译会出错。,module M1 ,provides interface A1;,implementation ,post A1.event1(0x1, 0x2);,/*,发出对应的事件,实际上类同于调用事件处理函数,*/, 事件使用,下面给出使用事件的方法,接口使用者必须实现事件的具体内容,如同事件处理函数一样。,module M2 ,uses interface A1;,implementation ,event void A1.event1(int arg1, int arg2) , 任务,任务是,TinyOS,系统提供的一种特殊的机制,类同于线程。在大多数情况下,因为同步代码是非抢占的,这种编程方式行之有效。但是,这种做法并不适合大规模计算。当一个组件需要做什么且此时还有宽裕的时间,最好给,TinyOS,延迟计算的能力,即处理完之前已在等待的事情后再执行。,任务是一个函数,组件告诉,TinyOS,稍后再运行而不是立即运行。任务一般为一个函数,无参数,无返回值。任务可以在一般的,TinyOS,程序中发出,而任务的执行是由,TinyOS,系统内核来实现的。并且任务的执行是不影响调用者的,将会在发出任务后的某一个时刻被调度运行。任务具有如下特点:, 无参数、无返回值, 系统会按特定的顺序调度这些任务, 任务执行期间不能抢占,但是可以被中断所抢占, 在任务未执行时,发出多少个任务,都将只运行一次这个任务,系统执行完一个任务后才会去执行其它任务,所以任务一般要求短小,不至于影响其它任务。,任务的定义一般也是放在,module,中的,下面给出一个任务示例:,module M1 ,implementation ,task void task1() ,void f1() ,post task1();,为了协调任务和中断的执行,,nesC,使用“,atomic,”指出该段代码“不可被打断”。另外定义了“,task,”封装一些代码来完成一个任务,系统有,FIFO,的任务队列。不同的任务之间没有优先级,但任务可以被,interrupt handler,打断。为防止全局变量等公用数据被非正常修改,,nesC,规定只在任务中进入公共的数据部分。,9.3.3,一个简单的,nesC,编程示例,下面是一个最简单的,C,程序,在,Linux,上,你只要使用命令,gcc test.c -o test,就可以编译该程序。,int main () ,return 0;,在,TinyOS,中,要完成同样的事,你需要三个文件。读者可以参考以下步骤来建立这个最简单地程序:, 创建一个文件夹,如,simple,,来保存这三文件。, 为我们的程序创建一个配置文件,内容如下:,configuration SimpleAppC ,implementation,components SimpleC, MainC;,SimpleC.Boot - MainC.Boot;,在这个程序中有两个组件:,Main,组件和,SimpleC,组件,其中,,Main,组件提供了实际上是程序入口点的信号。,回本章目录, 创建组件文件,这里包含,SimpleC,的定义(接口),内容如下:,module SimpleC,uses interface Boot;,implementation,event void Boot.booted(),/The entry point of the program, 创建,Makefile,文件,,Makefile,文件用来控制该程序的编译,,Makefile,文件内容如下:,COMPONENT=SimpleAppC,include $(MAKERULES),这里需要将顶层的配置放到,COMPONENT,中。, 使用如下命令来编译该程序,$ make micaz,如果环境变量等都已经配置好,这里就可以成功编译。,9.3.4 TOSSIM,仿真,TOSSIM,是一个支持基于,TinyOS,的应用在,PC,机上运行的模拟器,,TOSSIM,将,TinyOS,环境下的,nesC,代码直接编译为可在,PC,机环境下运行的可执行文件,提供了不用将程序下载到真实的节点上就可以对程序进行测试的一个平台。,TOSSIM,模拟器提供运行时调试输出信息,允许用户从不同角度分析和观察程序的执行过程。,TOSSIM,提供了用于显示仿真情况的用户界面,TINYVIZ,,它是一个基于,java,的,gui,应用程序,它允许用户以可视化方式控制程序的模拟过程。,TINYVIZ,提供了图形调试接口,它能可视化地和,TinyOS,应用程序交互,能使用户方便地跟踪应用的执行,可以设置断点,查看变量,同时可以模拟多个节点的执行,并能够根据一定的模拟设置网络属性。,回本章目录,command void init();,callInterrupt.,public static void main(String args),完整的表达式应该为:A.,2 TinyOS的调度机制,由于无线传感器网络的特殊性,研究人员在设计TinyOS系统时就提出以下几个原则:,5 TinyOS的基本概念,同cygwin下的配置,components SchedulerBasicP as Sched;,但是,这种做法并不适合大规模计算。,cmd1(0x11);,一个完整的应用系统由一个内核调度器(简称调度器)和许多功能独立且相互联系的组件构成,可以把TinyOS系统和在其上运行的应用程序看成是一个大的“执行程序”。,interface A1 ,系统执行完一个任务后才会去执行其它任务,所以任务一般要求短小,不至于影响其它任务。,使用了三种机制来管理和控制能量状态。,当没有中断发生时,调度器会从队列中取出一个任务执行,任务执行过程中可以被打断。, 支持网络协议组件的替换, 硬件抽象组件将物理硬件映射到TinyOS的组件模型;,现有的TinyOS系统提供了大多数传感网硬件平台和应用领域里都可用到的组件,例如定时器组件、传感器组件、消息收发组件、电源管理组件等,从而把用户和底层硬件隔离开来。,TOSSIM模拟器提供运行时调试输出信息,允许用户从不同角度分析和观察程序的执行过程。,下面介绍利用,TOSSIM,模拟,TINYVIZ,程序的具体方法。, 进入,cygwin,应用程序,进入应用程序所在目录,其中最后一级的目录为应用程序。, 运行命令:,make pc,,该命令的作用是将应用程序编译为,pc,机能执行的二进制文件;, 然后运行命令:,export dbg=usr1,,此处,dbg,模式设置为,usr1,;, 最后运行:,build/pc/main.exe -gui 20,,此处,,20,为传感器节点数目,可人为设定。,此时打开另外一个,cygwin,应用程序,注意不要关闭原来的,cygwin,应用程序。, 进入目录:, 运行命令:,make, 然后再运行命令:, 此时就可以运行仿真了,,20,个节点情形的仿真过程如图,9-11,所示,其中被箭头指向的节点为接收到信息的节点。,图,9-11 20,个节点的仿真,9.4 TinyOS,内部机制简介,9.4.1 TinyOS,程序运行机制分析,9.4.2 TinyOS,的调度机制,9.4.3 TinyOS,的通信模型,9.4.4 TinyOS,的能量管理,回本章目录,9.4.1 TinyOS,程序运行机制分析,的启动接口,的启动接口包含如下三个内容:,Init,:初始化组件和硬件状态;,interface Init ,command error_t init();,Scheduler,:初始化和运行任务;,interface Scheduler ,command void init();,command bool runNextTask(bool sleep);,command void taskLoop();,Boot,:通知系统已经成功地启动,interface Boot ,event void booted();,回本章目录,TinyOS,的启动顺序,TinyOS,的启动顺序有以下,4,步:, 调度程序初始化;, 组件初始化;, 发送启动,boot,过程完成的信号;, 运行调度程序。,TinyOS,的程序运行机制,TinyOS,程序通过并口导入到节点之上,节点一旦加电程序就会运行。实际上在,ROM,空间的零地址上是一个跳转指令,加电之后的程序首先运行这个跳转指令,将控制转向程序的真正的代码处,这之后程序才真正开始执行。,TinyOS,的所有组件都需要一个通用的主要组件即,Main,组件,在程序的配置文件中将该组件进行绑定。,Main,组件提供了一个初始化和运行,TinyOS,组件的接口,StdControl,,但是真正实现这个接口的组件应当是应用程序组件。下面看看,Main,组件究竟完成哪些功能。,Main,组件本身的实现是另外一个组件,RealMain,,它才是真正的,Main,,我们先不关心其它的代码,看看,RealMain,做了什么。,intmain() attribute (C,spontaneous),callhardwareInit () ;,callPot.init (10) ;,TOSH sched init () ;,callStdControl.init () ;,callStdControl.start () ;,callInterrupt.enable () ;,while (1) ,TOSH run task () ;,从代码上我们看到,RealMain,完成了硬件初始化、电位器的初始化、调度器的初始化,并且调用了接口,StdControl,中的函数,这些函数完成了应用程序组件的初始化任务,此外还要打开中断。从这里我们也就明白了程序执行后会先进行硬件的初始化,然后初始化组件。至于组件的初始化如何完成则取决于用户编写的组件初始化函数,因为,Main,组件使用的,StdControl,接口需要在用户编写的组件里绑定到其初始化函数中。最后,RealMain,组件开始运行队列中的任务。,TinyOS,的调度队列是个先进先出的循环队列,整个队列中至少有一个空闲位置,应用程序可以调用,Post Task,将一个新的任务加到队列中。当没有中断发生时,调度器会从队列中取出一个任务执行,任务执行过程中可以被打断。如果队列中没有了任务,处理器会进入睡眠状态,等待被其它事件激活。,9.4.2 TinyOS,的调度机制,TinyOS,调度是任务和事件的二级调度。任务是单线程运行至完毕,不可相互抢占,但事件可抢占正在运行的任务或低优先级事件。任务用于实时要求不高的应用中,所有任务只分配单个任务栈,默认是简单的,FIFO,调度。若任务队列为空,,CPU,进入休眠状态以降低功耗。其中任务数默认是,8,个,最大任务数是,255,。还采用了分段操作来减少任务的运行时间,即分为程序启动硬件操作后迅速返回和硬件完成操作后通知程序两个阶段。,事件用于实时性有要求的应用中,可分为硬件事件和软件事件。硬件事件就是由底层硬件发出的
展开阅读全文