通常来说,硬件是分阶段(split-phase)操作的,即软件对硬件提出请求,硬件完成操作后发送信号(比如中断)给软件系统。在硬件中断时间较长的情况下,如果软件提出请求后一直处于阻塞状态,CPU和能量都会产生较大浪费。对于这个问题,传统的解决方法是使用多个线程(thread)等待硬件信号。某应用需要使用硬件时,操作系统建立请求,将线程放入等待队列,然后调度其他线程工作。当硬件中断到达,再恢复等待线程,并将其放在就绪队列中。由于每个线程都具有自己的堆栈,嵌入式系统中使用线程会带来较大的RAM开销。对于RAM资源非常有限的无线传感器网络节点等来说,等待状态的线程造成了堆栈空间的严重浪费。而且在系统中分配合适大小的堆栈也是非常棘手的问题。
不同于传统的解决办法,TinyOS采用的方法是软件也使用分阶段操作,并使用分阶段接口来达到这个目的。分阶段接口是双向的,具有向下的函数调用(命令)来启动操作,具有向上的函数调用(事件)来通知操作完成。接口Read就是一个基本的分阶段接口,大部分传感器驱动程序都提供该接口。接口Read中包括一个命令read()和一个事件readDone()。当调用者调用命令Read.read(),接口Read的提供者直接返回成功,并在将来读取到传感器数据后,再调用Read.readDone()来通知Read接口的使用者。Read接口代码如下:
下面结合模块PeriodicReaderC来说明分阶段接口Read的应用。在模块PeriodicReaderC的实现代码中,接口函数StdControl.start()启动了计时器。计时器时间到时,Timer.fired()被通知,该事件的处理程序调用Read.read()并返回(这是分阶段操作的第一阶段)。Read.read()由负责读取传感器数据的组件定义并提供。之后的某个时刻,读取传感器数据的组件通知Read.readDone()事件,实参val为传感器数据。PeriodicReaderC对于该事件的处理操作是将采集的传感器数据存储在模块变量lastVal中(对事件进行处理,是分阶段操作的第二阶段)。(www.xing528.com)
这种同时包含命令和事件的接口也称为双向接口。双向接口使得调用者不需要使用函数指针,就能够注册回调函数。PeridoicReaderC模块代码如下:
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。