对于TinyOS的I/O分析最好的一个分析例子就是apps/Blink。控制Led闪烁的接口Leds来自于模块LedsC。该模块(LedsC)位于Tos/System/LedsC.nc文件中定义。实际上Leds接口的实现是在同目录下的LedsP.nc文件中完成的。而从开始到这个阶段都还完全没有涉及到底层I/O的指定。其实从LedsC.nc和LedsP.nc文件所在的目录(System)看,也很容易理解:这里的接口实现也只是单纯的通过系统调用完成的,和底层的硬件I/O是完全隔离的。那么下面我们来看看,底层的I/O是在哪儿指定的呢?
在文件Leds.nc中可以看到模块PlatformLedsC的引入,该模块提供了接口les0、led1、led2(实际上均为GeneralIO接口的别名)。该模块(PlatformLedsC)位于Tos/Platforms/Telosa/PlatformLedsC.nc中(笔者的应用平台是tmote,至于为什么该文件在telosa平台目录下,这个要看makefile才能讲的清楚了)。而在模块PlatformLedsC中提供的接口les0、led1、led2(实际上均为GeneralIO接口的别名)来自于 模块Led0Impl、 Led1Impl、 Led2Impl(模块Msp430GpioC()的别名)。模块Msp430GpioC()在tos/chips/msp430/pins/Msp430GpioC.nc中定义实现。本来以为这里应该是定义了最底层的I/O指定,实际上这里也只是中间的一步而已。在该文件中很容易发现,Msp430GpioC()模块提供的接口是通过接口HplMsp430GeneralIO来实现的。那现在的问题是接口HplMsp430GeneralIO又是由谁具体来实现的呢?
要解决这个问题我们还要回到文件Tos/Platforms/Telosa/PlatformLedsC.nc中,在这里引入了模块HplMsp430GeneralIOC,同时指定接口来自这个模块。模块HplMsp430GeneralIOC实际位于tos/chips/msp430/pins/HplMsp430GeneralIOC.nc,但实际的接口提供者是同目录下的HplMsp430GeneralIOP模块。这个模块可以算是底层I/O指定的终极模块文件了。到这里我们的底层I/O挖掘之旅就算是完整的结束啦。
总结下,I/O的调用层次:apps/Blink -> Tos/System/LedsC.nc -> Tos/Platforms/Telosa/PlatformLedsC.nc -> tos/chips/msp430/pins/Msp430GpioC.nc -> tos/chips/msp430/pins/HplMsp430GeneralIOC.nc
ps:在本范例中分析的tinyOS源码版本为2.1.1