西安电子科技大学软件学院 |
TinyOS学习报告 |
第一周报告 |
姓名:
日期:2009/12/24
TinyOS的安装:
在windows系统中安装TinyOS-2.0需要以下六个步骤:
第一步是安装java jdk 1.5;
第二步是安装cygwin;
第三步是安装avr单片机工具或者MSP430工具;
第四步是安装nesc和tinyos-tool;
第五步是安装tinyos-2.0;
第六步是配置环境变量;
本周主要学习了:
TinyOS Documentation Wiki—Starting with TinyOS—Tutorials中的几个Lesson:
Lesson 1 Getting Started with TinyOS
Lesson 2 Modules and the TinyOS Execution Model
Lesson 3 Mote-mote radio communication
Lesson 4 Mote-PC serial communication and SerialForwarder
Lesson 5 Sensing
Lesson 6 Boot Sequence
Lesson 7 Storage
Lesson 1
一、TinyOS中一些主要概念:组件、模块、配置以及接口
1. 任何一个 nesC 应用程序都是有一个或多个组件链接起来。组件提供(provide)并使用(use)接口。接口声明了一组函数,称为命令(command),接口的提供者必须实现它们;还声明了另外一组函数,称为事件(event),接口的使用者必须实现它们。
2. 组件有两种类型:
模块:提供一个或多个接口的实现
配置:装配其他组件并使组件之间的接口相连
3. 每个nesC 应用程序都由一个顶级配置所描述
4. 为什么要区分模块和配置?
为使设计者构建应用程序时能从实现细节中摆脱出来
Q:一个配置可以使用和提供接口。是不是使用或提供接口的配置就不能为顶级配置,而没有使用和提供接口的配置就一定是顶级配置?
二、怎样编译一个TinyOS程序以及安装到平台上
1. 检查环境安装正确与否:tos-check-env
2. 查看ncc版本:ncc --version
3. 使用“make”编译TinyOS应用程序,如:make micaz。若需要仿真,make micaz sim。
4. 安装程序到微粒(如mica-family)
make mica2 reinstall mib510,serialport
三、简介实例应用程序:Blink
1. 功能:在三个LEDS上每两秒显示二进制0-7.
2. 程序构成:
BlinkAppC.nc:顶级配置:导通Blink.nc和其它模板
Blink.nc:提供Blink应用的实现
3. “→”表示导通:把一个接口绑定到另一个接口。箭头的左边是使用者,右边是提供者。
四、可视化一个组件图形
nesdoc显示配置的结构与组成: make platform docs
Lesson 2
一、Blink应用程序改进:BlinkSingle
1.模块可以声明状态变量,一个组件声明的任何状态变量都是私有的:其他组件不能命名或直接访问它。
2.BlinkSingle功能:与Blink功能一样。
3.BlinKSingle实现方法:与Blink相比,不是用三个timer使得三个LEDS闪烁,而是使用单个timer和一个状态变量counter去实现功能。改变如下:
二、接口,命令和事件
1. 接口:是一系列声明的有名函数集合,同时是连接不同组件的纽带。nesC中的接口是双向的,这种接口实际上市提供者和使用者组件间的一个多功能通道。一方面接口提供者实现了接口的一组功能函数,称为命令,另一方面接口的使用者需要实现一组功能函数,称为事件。
2. 一个组件使用一个接口,就可以call接口的command,但是组件必须实现这个接口中的event。
3. 调用一个接口的命令需要“call”关键字,调用一个接口的事件需要用“signal”关键字。
三、TinyOS执行模型:任务
1. 任务在应用程序中是用来执行某些一般目的的“背景”处理的。它是一个函数,组件告诉TinyOS它稍后运行,而非现在。
2. TinyOS 提供由“任务”和“硬件事件句柄”组成的两级调度层次结构。关键字async 声明了可被硬件事件句柄执行的命令或事件。这意味着它们可在任何时候执行(可能抢占其他代码的执行),因此async 命令和事件所做的工作应该尽可能地少而且应快速结束。
3. 语法:
任务在实现模块中使用如下语法声明:
task void taskname() { ... },
其中taskname()是程序员任意指定的任务名称标识。任务的返回值类型必须是void,而且不可一带参数。
分派任务的(推后)执行使用的语法形式为:
post taskname();。
4.可以从一个命令、事件、甚至是另外一个任务内部“布置(post)”任务。布置操作将任务放入一个以先进先出(FIFO)方式处理的内部任务队列。当某个任务执行时,它会一直运行直至结束,然后下一个任务开始执行。因此,任务不应该被挂起或阻塞太长时间。虽然任务之间不能够相互抢占,但任务可能被硬件事件句柄所抢占。如果要运行一系列较长的操作,应该为每个操作分配一个任务,而不是使用一个过大的任务。
5.一个任务可以安全地call命令和 signal事件,但命令不能signal事件(为了避免递归循环)
四、内部函数
1. 命令和事件是组件之间函数调用的唯一方式。
2. 内部函数:在一些情况下组件希望一个私有的函数供它内部使用。一个组件可以定义标准的C函数,其它组件不能命名这个函数也不能直接调用这个函数。
3. 调用内部函数不需要call或signal这样的关键字。
五、分相(Split-Phase)操作
1. 在TinyOS中每一个长时间运行的操作都是分相的。在阻塞系统中,当一个调用长时间运行的操作时,只有操作完成时调用才会返回;而在分相系统中,调用会立即返回,当操作完成会发出callback。
2. 分相操作相对于顺序代码有些复杂,但他可以使操作并行并且节省内存。Timer.StartOneShot就是一个分相调用的例子。
Lesson 3
本课主要介绍了TinyOS中的微粒间的无线通信。
一、message_t:TinyOS的消息缓冲
1.TinyOS提供了许多接口去抽象底层通信服务,所有的这些接口以及许多提供这些接口的组件使用共同的消息缓冲抽象:message_t(底层通信数据的结构),用nesC结构体实现。
2.message_t结构:
typedef nx_struct message_t {
nx_uint8_t header[sizeof(message_header_t)];
nx_uint8_t data[TOSH_DATA_LENGTH];
nx_uint8_t footer[sizeof(message_footer_t)];
nx_uint8_t metadata[sizeof(message_metadata_t)];
} message_t;
二、通信接口与组件
基本通信接口:
1.Packet:提供对message_t的基本访问
a.清除消息内容(命令)
b.得到有效载荷的长度(命令)
c.得到指向有效载荷地址的指针(命令)
2.Send:提供与地址无关的发送接口
a.发送消息内容(命令)
b.取消挂起消息的发送(命令)
c.消息是否发送成功(事件)
d.得到有效载荷的长度(函数)
e.得到指向有效载荷地址的指针(函数)
3.Receive:提供基本消息的接收接口
a.接收消息(事件)
b.得到有效载荷的长度(命令)
c.得到指向有效载荷地址的指针(命令)
4. PacketAcknowledgements:为每个包的请求确认提供机制
5. RadioTimeStaming:提供时间戳
活动消息接口
1.AM层次实现了对radio的多路访问。“AM tpye”涉及到多路复用的领域。(不太理解)
2.支持AM服务的接口:
a.AMPacket:提供基本的AM访问
b.AMSend:提供基本的AM发送接口
3.一个节点的AM地址可以在初始化的时候设置:
make install.n or meke reinstall.n
通信组件:
许多组件实现了基本通信接口与AM接口
1. AMReceiverC - Provides: Receive, Packet, and AMPacket.
2. AMSenderC-Provides:AMSend,Packet,AMPacket,and RacketAcknowledgements as Acks.
3. AMSnooperC - Provides Receive, Packet, and AMPacket.
4. AMSnoopingReceiverC - Provides Receive, Packet, and AMPacket.
5. ActiveMessageAddressC – 提供用来得到或设置节点AM地址的命令(少用)
三、通过无线网络发送消息:BlinkToRadio
1. 重新实现Blink:BlinkToRadio(自增counter,用LEDs显示counter值的低三位,并通过Radio将counter的值发送出去)
2. BlinkToRadio应用程序的组成:
a.BlinkToRadioC.nc:提供实现逻辑
b.BlinkToRadioC.h:定义常量
c.BlinkToRadioAppC.nc:导通
d.Makefile
COMPONENT= BlinkToRadioAppC #指明顶级配置
include $(MAKERULES) #装载TinyOS build System
3. 定义一个信息结构
发送的信息:节点ID和消息。
结构体:
typedef nx_struct BlinkToRadioMsg {
nx_uint16_t nodeid;
nx_uint16_t counter;
} BlinkToRadioMsg;
4.实现应用程序的步骤:
明确接口
更新模块
声明新变量,增加新的初始化代码
增加逻辑调用
实现事件
更新配置的实现
导通接口
四、从无线网络中接收消息
实现步骤和三相似
Lesson 4
本课主要介绍如何从一个PC到一个微粒的通信。
一、包源与TestSerial
1.包源:对于mote-pc间通信的一个基本抽象。实际上,它是一个通信媒介,一个应用可以通过它从微粒接收包,并发送包到微粒上。
2.测试串行端口的第一步就是把TestSerial应用程序安装到微粒上(使用make)。一旦安装好后,就需要通过串行接口运行相应的JAVA应用程序进行通信:
如:java TestSerial –comm serial@/dev/ttyUSB0:telos
其中-comm是用字符串的形式明确包源
3.MOTECOM
如果没有-comm参数,那么工具就会检查MOTECOM环境变量,MOTECOM没有设定包源,则缺省的为SerialForwarder。
设置MOTECOM:
export MOTECOM=serial@COM1:19200
二、基站和net.tinyos.tools.Listen
1. BaseStation是TinyOS基本的实用应用程序。它是连接串行端口和无线通信网的桥梁。因为TinyOS有工具可以产生包并且通过串行端口发送包到微粒,所以使用一个BaseStation允许PC工具直接和微粒的网络通信。
2. net.tinyos.tools.Listen 是一个包嗅探器,它以二元的形式打印侦听到包。
$ java net.tinyos.tools.Listen
三、MIG(Message Interface Gererator)
1. Litsen是与微粒交流的最基本的方法,信息比较难提取。所以TinyOS提供了一些支持:从包描述中自动产生信息对象(使用mig工具产生java,python或C接口)
2. mig有三个基本的参数:
为那种语言产生代码
从哪个文件找到结构体
结构体的名字
四、SerialForwarder
1. 如果用串行端口,只能 一个pc与mote交互,并且必须是物理连接。SerialForwarder工具则消除了这两个。
2. SerialForwarder是第二种包源,语句如下:
Sf@HOST:PORT
Lesson 5
本课主要介绍如传感器数据的获取
一、概念
1.传感(Sensing)是传感器网络应用中不可或缺的部分。它涉及到两个任务:
配置传感器:棘手的,配置会因平台的不同而不同
读传感器数据
2.在TinyOS 2.0平台上,的sensing应用程序不在使用象ADCControl这样的配置接口,取而代之地,它们使用标准的数据获取接口:Read,ReadStream或ReadNow,来收集传感器数据。
二、Sense应用程序
1. 功能:周期性地对缺省传感器采样并用LEDs显示低位
2. Sense实现过程:
Sense.nc用Boot启动周期性计时器
计时器一到时间,Sense.nc就signal一个timer事件
读数据是分相操作的
读完用LEDs显示数据
3.interface Read command error_t read(); event void readDone(error_t result , val_t val); } 4.DemoSensorC组件 DemoSensorC为Sense提供了Read Sense.nc无法知道他所连接的传感器,甚至无法知道是否从传感器得到数据,因为它能导通到任何提供Read 事实上DemoSensorC在不同的平台下是不一样的。平台依赖于DemoSensorC组件来定义应用程序从哪个传感器来采样。 DemoSensorC组件: generic configuration DemoSensorC(){ provides interface Read } 实现部分因平台不同而不同。 DemoSensorC是一种间接获取传感器数据的方式,它会根据不同的平台实例化使用不同组件来获取传感器数据。 5.运行Sense应用: make telosb install 三、Oscilloscope 应用程序 1. 功能:使传感器读来的数据在PC上可视化 2. 运行java GUI:type make->./run Lesson 6 本课主要介绍引导序列的一些细节 引导顺序 1.TinyOS引导顺序有4个步骤: 调度初始化 组件初始化 发送引导过程完成的信号 运行调度 2.应用层引导顺序的组件是:MainC。他提供了一个接口:Boot以及使用一个接口:Init as SoftwareInit。 3. 缺省的实际的引导顺序在组件RealMainP中,比MainC多使用了两接口。 module RealMainP { provides interface Booted; uses { interface Scheduler; interface Init as PlatformInit; interface Init as SoftwareInit; } } Lesson 7 本课主要介绍在TinyOS中持久数据存储 一、基础知识 1. 不同种类别的持久数据存储:小对象,日志,大对象。TinyOS 2.x提供了三个基本存储抽象:小对象,循环日志和大对象 2. 相关接口 BlockRead BlockWrite Mount ConfigStorage LogRead LogWrite Storage.h 3容器 在编译时,TinyOS用一个XML文件把闪存芯片分成一个或多个固定大小的特定容器,这些文件叫容器表。每一个容器提供一个单独类型的存储对象。 容器是针对特殊应用的,所以必须放在应用程序的文件夹中且命名为volumes-CHIPNAME.xml。(CHIPNAME是特定平台的闪存芯片名) 二、存储配置数据 1. 配置数据可能出现在以下情况:它们被了大小;它们的值不统一;值未知;值与硬件相关。 2. 为什么配置数据必须存留: 校准:传感器的校准系数是出场配置的,持久的 设备标识:设备标识一旦分配给一个节点,这些值应该持久。 位置:节点位置数据可能在编译时不知,只有在运行时可见,需要存储。 传感:传感与发出信号过程的参数 这些都需要这种类型的数据存储。 3.如何使用Mount和configuration 三、日志数据 1.事件和小数据项的自动日志记录是一种常见的应用。日志数据不应该丢失,日志可以是线性的,也可以是循环的。 2.LogStorage抽象支持上面的日志要求。日志是基于记录的,每一次调用LogWrite.append()时就会创建一个新的日志。 3.PacketParrot:展示了怎样使用LogWrite和LogRead、 四、存储大对象 本周总结 本周主要学习了tutorials中的一些课程。经过几次反复,前四个课程感觉差不多可以理解,从第五个课程开始一部分内容就有些看不懂了。可能学习的开始阶段会有一些囫囵吞枣吧,还有就是进度有点慢,希望下周可以好一点!