|
图3 接口示意图 在接口中声明命令和事件实现不同的功能,命令是接口具有的功能,事件是接口具有通告事件发生的能力。Asy可以命令或事件在中断处理程序中调用。
接口体现事件驱动功能和模块化。通过事件通告让使用接口者对事件进行响应;任何满足接口功能的实现者都可被其他需要这个接口功能的组件调用。
2.3.2 组件
组件是配线文件或模块文件,是逻辑功能的抽象。程序员完全可直接调用组件进行程序开发。
配线文件只是完成组件之间的接口连接,模块文件则具体实现接口中的命令和事件。在这两个文件中都可使用provides、uses语句。provides表明这个组件可以提供哪些接口,实现这些接口的命令和事件通知。uses表明这个组件使用哪些接口,组件可以接口中提供的命令和实现对接口中事件进行响应。组件结构如图4所示。
图4 组件结构图 基于组件的思想,一个组件可通过多个组件实现一定的逻辑功能,对外声明需要哪些接口和提供哪些接口。图5所示为由组件A、B和C形成的新功能组件D。
图5 组件D结构图 2.3.3 并行模型
通过任务(task)和中断处理事件(interrupt hander event)来体现TinyOS并行处理能力。任务(task)会加入一个FIFO队列中,执行过程中,任务间没有竞争;但中断处理程序可以打断任务执行。TinyOS采用二级调度机制来满足无线传感网络运行特点,整个程序调度过程如图6所示。组件中完成任务提交,由操作系统完成调度。
图6 TinyOS程序结构框图 基于以上分析,一个节点上应用程序的框图如图7所示。操作系统只是在后台提供队列服务。
图7 应用程序结构框图 3 具体实现说明
现以节点收发计数器中的数值为例,更为详细地说明网络协议是如何通过主动消息传递来实现的。
程序要求节点启动以后,开始让计数器计数,每秒向外广播自己的计数值,同时接收其他节点上计数器的值。
3.1 main组件
TinyOS应用程序从main组件开始,完成main组件的StdControl接口的3个命令init()、start()和stop()的具体实现。这个接口中命令执行次序可用init*(start|stop)*,应用程序执行前执行init()完成必要初始化工作,start是这个程序要完成的工作,stop是系统关闭前所要执行的动作。这个接口是TinyOS应用程序标准接口,与硬件操作相关的其他组件必须用到这个接口,实现接口中的命令。
3.2 使用的接口
StdControl接口完成应用程序启动及相关硬件初始化。
interface StdControl { command result_t init(); command result_t start(); command result_t stop(); } Timer接口实现计数功能。 interface Timer { command result_t start(char type, uint32_t interval); //设定触发类型和计数值 command result_t stop() //中止计数器 event result_t fired(); //计数器定时触发事件 } SendMsg接口发送消息。 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); //消息发送完成以后事件 } ReceiveMsg接口接收消息。 interface ReceiveMsg { event TOS_MsgPtr receive(TOS_MsgPtr m); //接收到消息事件 }
3.3 使用的组件
组件Main, test5M,TimerC,GenericComm as Comm实现逻辑功能。Main是系统必需的。test5M提供接口的命令并实现对调用接口事件的响应。GenericComm完成消息的发送和对接收消息的通告。其配线文件如下:
Main.StdControl -> test5M.StdControl; Main.StdControl -> TimerC.StdControl; test5M.Timer -> TimerC.Timer[unique("Timer")]; test5M.SubControl->Comm; test5M.Send -> Comm.SendMsg; test5M.Receive->Comm.ReceiveMsg;
3.4 test5M模块文件
test5M模块接口如下:
module test5M { provides { interface StdControl; } uses { interface Timer; interface SendMsg as Send[uint8_t id];//发送消息接口 interface ReceiveMsg as Receive[uint8_t id];//接收消息 interface StdControl as SubControl;//子组件:完成发送初始化 } }
provides声明这个组件所实现接口中命令和通告相关事件的产生。需要实现StdControl接口中命令init()、start()和stop()。
Uses声明这个组件调用接口中命令并对接口中事件进行响应。所需要响应的事件为Timer接口的fired()事件、SendMsg接口的sendDone事件和ReceiveMsg接口的receive事件。
3.5 通信实现
test5M发送和接收消息是通过组件GenericComm来实现的。GenericComm通过调用其他组件实现从消息包到主动消息、字节级数据传数、位级数据传送到无线电收发模块的功能。在此不再深入分析其实现过程,采用随机后退的CSMA/AD的MAC协议,只要明白组件GenericComm就可以完成消息的收发。
GenericComm提供了256个消息收发接口,也就是说系统可以使用256种消息,或者说256种状态进行转换。由于系统是非阻塞模式,一旦消息到达组件test5M中,receive事件就会立刻调用,因此在这个事件中实现不同消息的转换,从而实现通信双方的握手:
event TOS_MsgPtr Receive.receive[uint8_t id](TOS_MsgPtr m) { switch(id) { case 1: //状态转换1 case 2: //状态转换2 } return m; }
| | | | |