TinyOS学习笔记讲解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第一篇基础知识
TinyOS体系结构
(1) 组件模型module & configuration
TinyOS 是基于构件的微操作系统,采用事件驱动模型,有效的提高了系统的运行效率以及能源合理利用。TinyOS 采用nesC 语言编写,其应用程序由一个或多个组件连接而成,而组件可以提供和使用接口,组件必须实现其所提供的command 接口,并且必须实现其连接组件中申明的事件event 接口。接口是程序的实体,实现程序的各功能模块,分为command 和event ,command 接口由组件本身实现,而event 接口则由调用者实现,值得注意的是,接口是双向的,调用command 接口时必须实现其event 接口。
组件又可以细分为模块module 和配件。模块亦可分为2个部分,其一,首先申明提供以及使用的接口,如
module BlinkC { } 其二,在implementation 中模块包含各接口所提供的行为(方法),也包含仅供本模块内部使用的函数,以及申明本模块所具有的事件signal ,以及实现其连接或使用的event 。
implementation
{
uint8_t counter = 0;
void ledctl() {
call Leds.set(counter);
}
event void Boot.booted() {
} event void Timer0.fired()
{
ledctl();
}
}
配件configuration 也可以分为两个部分,和module 一样,第一部分是申明可以提供以及使用的接口。第二部分implementation 中首先列出与其相连接模块的名称,使用components 标注连接的模块,然后对本配件提供的以及与其相对应模块使用以及提供的接口进行配线,如下例:
{
}
implementation
{
BlinkC -> MainC.Boot; /////
或者写作BlinkC.Boot -> MainC.Boot;
BlinkC.Timer
BlinkC.Leds -> LedsC;
}
在TinyOS 中存在很多中间配件,这些配件的特点是没有与之相对应的模块,其作用就是根据不同的条件将上层的连接转接到不同的模块上,如下例所示
generic configuration AMSenderC(am_id_t AMId) { provides {
interface AMSend; interface Packet;
interface AMPacket;
interface PacketAcknowledgements as Acks;
}
}
implementation {
#if defined(LOW_POWER_LISTENING)
#else #endif
AMSend = SenderC;
Packet = SenderC;
AMPacket = SenderC;
Acks = SenderC;
}
接口文件相当于C 程序中头文件对函数的声明,接口文件一般放置于提供该接口的模块的同一目录下的interface 文件夹中,也可以放在TinyOS 根目录下的interface 目录中,其命名必须与模块中所提供接口名字相同,注意不是接口的实例化名称或nickname 。如下例
}
注意:带有参数的接口在interface 中申明时不需要写出其接口参数,比如,上例中CC2420Registe 接口是带有参数的,而在模块中实现是则写成CC2420Registe [uint8_t addr]。
(2)接口interface
接口是TinyOS功能实体,通过调用接口提供的方法完成某个具体任务。在TinyOS中接口可以带有参数,用[]引人参数,接口也可以带有类型标志,用<>引入。
TinyOS中可能有多个组件提供同一个接口,比如Init接口,那么这样就会带来一个问题:当一个组件有多个用户使用时,他们分别都调用了同一个接口,当这个接口事件触发fire时,那么,应该由哪个组件来响应这个信号呢?
TinyOS采用两种策略来解决这个问题:其一,多次实例化一个组件接口,这种方法在I/O上应用的最多,如下面代码
configuration PlatformLedsC {
provides {
interface GeneralIO as Led0;
interface GeneralIO as Led1;
interface GeneralIO as Led2;
}
接口GeneralIO被实例化了3次,这样就可以分别操这3个接口了。
其二,TinyOS采用带参数的接口,允许一个组件提供多个接口实例。比如
module CC2420SpiP @safe() {
provides {
interface ChipSpiResource;
interface Resource[ uint8_t id ];
interface CC2420Fifo as Fifo[ uint8_t id ];
interface CC2420Ram as Ram[ uint16_t id ];
interface CC2420Register as Reg[ uint8_t id ];
interface CC2420Strobe as Strobe[ uint8_t id ];
}
组件提供接口并实例化为带参数的接口,那么其他组件连接时,可以提供不同的id多次使用同一接口,比如
SNOP = Spi.Strobe [ CC2420_INS_SNOP ];
SIBUFEX = Spi.Strobe [ CC2420_INS_SIBUFEX ];
SSAMPLECCA =Spi.Strobe [ CC2420_INS_SSAMPLECCA ];
SXOSCON = Spi.Strobe [ CC2420_INS_SXOSCON ];
其中Spi就是连接到上例组件的。这样用起来也不是很方便,所以TinyOS由给出了可以产生唯一ID的常量函数函数。nesC 现在有二种常量函数: