Lesson11---TOSSIM仿真_第1页
Lesson11---TOSSIM仿真_第2页
Lesson11---TOSSIM仿真_第3页
Lesson11---TOSSIM仿真_第4页
Lesson11---TOSSIM仿真_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Lesson11 TOSSIM 仿真 介绍TOSSIM仿真器。熟悉编译TOSSIM的步骤,掌握常用的仿真手段,具体有以下几个方面: 编译TOSSIM 用Python 配置仿真器 检查变量 注入包注意:本节内容针对TinyOS 2.0.1及以上版本的TOSSIM仿真。TinyOS 2.0.0版本的TOSSIM仿真会有稍微的不同,两者的主要区别在于无线射频仿真中噪声的指定方法。目 录 一、介绍 -了解 二、编译TOSSIM -了解 三、使用Python运行TOSSIM -掌握 四、调试语句 -掌握 五、配置网络 -掌握 六、变量 -掌握 七、注入数据包 -掌握 八、C+接口 -了解一、介绍 TOS

2、SIM 仿真整个TinyOS 应用程序,是通过替换组件中的实现部分(implementation)实现的。 可以灵活的选择组件来替换,可以是通信组件,也可以是芯片组件。 仿真组件的是实现部分是多平台通用的,但它缺少对真实芯片情况的捕捉。 例如,有毫秒级的定时器HilTimerMilliC 组件有针对 atmega128 平台的实现,也有intelmote2平台的实现,还有TOSSIM的仿真实现。如下图:一、介绍 TOSSIM 是离散事件仿真器。 当它运行时,把事件队列(event queue)里的事件根据时间排序抽出来执行。 仿真事件可以表现为硬件中断或者高级别的系统事件(如事信息包的接收)

3、。由仿真的级别决定。 另外,任务也是仿真事件。一、介绍 TOSSIM 是一个库(其核心代码位于tos/lib/tossim):必须编写程序来配置仿真,然后运行它。 TOSSIM 支持两种编程接口: Python 和 C+ 。 Python 允许与正在运行的仿真进行动态地交互,调试功能强大。然而,python解释器是性能瓶颈。 TOSSIM 也有C+ 接口。通常,从一种代码转换到另一种代码是非常简单的。 TOSSIM 目前不支持能耗测量。二、编译TOSSIM TOSSIM 是TinyOS 的一个库。它的核心代码位于 tos/lib/tossim文件夹中 。 每个TinyOS 源代码目录有一个可选

4、的 sim 子目录,里面包含有那个包package 的仿真实现。例如,tos/chips/atm128/timer/sim 里面就含有 Atmega 128 定时器抽象的TOSSIM 实现。 编译TOSSIM, 只需在 make 时加上可选的 sim 。如: make micaz sim 目前, micaz 是唯一被TOSSIM 支持的平台。 $ cd blink$ make micaz sim二、编译TOSSIM二、编译TOSSIM 仔细观察上图中的编译过程,我们可以得出编译TOSSIM的5个步骤如下: 1. Writing an XML Schema, 编写 XML计划; 2. Compi

5、ling the TinyOS Application, 编译 TinyOS 程序; 3. Compiling the Programming Interface, 编译编程接口; 4. Building the Shared Object, 构建共用对象; 5. Copying Python Support. 复制 Python 支持。2.1 编写XML计划 “writing XML schema to app.xml”生成的xml文件描述了这个应用程序,以及其中每个变量的名字和类型。2.2 编译 TinyOS 应用-Ia -Ib -Ic-Ia/sim -Ib/sim -Ic/sim -I%

6、T/lib/tossim -Ia -Ib -Icsim 选项会改变应用程序的include路径 这意味着 先使用特定系统的仿真实现,然后是通用的 TOSSIM 仿真实现,再接着是 标准的实现。 这一步的产物是 目标文件 sim.o ,它位于平台的 build 目录下。这个目标文件含有一组C函数,其配置了仿真,并控制执行。 2.3 编译编程接口 这一步编译支持C+ 和 Python两个编程接口。 Python 接口实际上是建立在C+接口之上的。调用的 Python 对象会调用 C+ 对象,由其通过C 接口调用TOSSIM 。 2.4 构建共享对象 2.5 复制Python 脚本三、 使用Pyth

7、on运行TOSSIM 以 RadioCountToLeds 应用程序为例,构建TOSSIM仿真。 /opt/tinyos-2.x/apps/RadioCountToLeds$ cd RadioCountToLeds$ make micaz sim 下一步就是编写python脚本,然后用Python运行脚本。也可以,交互地使用python。 Python脚本的第一行通常是:#! /usr/local/bin/python#! /usr/bin/python#! /usr/bin/env python这取决于python 二进制文件的位置。最后一条入口是最安全或最方便的,将会自动搜索你的特定环境(

8、PATH)寻找Python的位置。 第1件事是:导入 TOSSIM 并创建一个TOSSIM 对象。 运行TOSSIM仿真的方法是用runNextEevent 函数。例如: from TOSSIM import * t = Tossim() t.runNextEvent()0当告诉TOSSIM 运行 下一个 事件event,它返回 0 。这意味着:接下去没有事件可以运行。在这里,没有下一个事件是因为我们还没有让节点启动起来。 这段代码将会告诉节点32 在45654时间标记点启动(仿真时间标记 simulation tick) ,然后运行它的第1个事(booting)。 为了不使用原始的仿真时间标

9、记为单位,可以调用 ticksPerSecond() 。 m = t.getNode(32); m.bootAtTime(45654); t.runNextEvent()1 m = t.getNode(32); m.bootAtTime(4 * t.ticksPerSecond() + 242119); t.runNextEvent()1现在,runNextEvent 返回了 1 ,因为有一个事件要运行。但程序员没有办法知道这个节点到底有没有启动。接下来介绍两种办法来确认节点是否启动。 第1种方法:直接用相关函数查询 m.isOn()1 m.turnOff() m.isOn()0一个TOSSI

10、M 对象有几个有用的函数。可以用dir 函数查看。如下图:前后有两个下划线 “_”的通常是不能手动使用的内部函数。例如,_init_ 在创建对象时在内部被自动调用的。 currentNode():返回当前节点的ID。 getNode(id):返回一个节点对象。 runNextEvent():运行一个仿真事件。 time():返回当前时间,用仿真时间标记表示,是一个大型整数。 timeStr():返回当前时间的字符串。 init():初始化TOSSIM。 mac():返回介质访问层的对象。 radio():返回无线电模型的对象。 addChannel(ch, output):增加output作为

11、到ch通道的输出。 removeChannel(ch, output):移除output作为到ch通道的输出。 ticksPerSecond():返回1s仿真时间对应的仿真时间标记数。Tossim 对象的几个常见的工具函数四、调试语句 得知节点是否打开的第2种方法是让它在启动后打印出信息告诉程序员。 TOSSIM 有一个调试输出系统,称为 dbg 。有4个 dbg 命令: dbg:打印调试语句,以节点ID 开头。 dbg_clear:打印调试语句,不以节点ID 开头。 dbgerror: 打印错误信息,以节点ID 开头。 dbgerror_clear:打印错误信息,不以节点ID 开头。四、调试

12、语句 修改 RadioCountToLedsC 里的boot.booted事件,打印出当它启动时的调试信息。例如:event void Boot.booted() call Leds.led0On(); dbg(Boot, Application booted.n); call AMControl.start(); dbg() 语句带有两个或更多的参数。 第1个参数(上述例子中的”Boot” )定义了输出通道。一个输出通道是一个string 字符串。 紧接的参数是输出的消息内容和变量格式。 event message_t* Receive.receive(message_t* bufPtr,

13、void* payload, uint8_t len) dbg(RadioCountToLedsC, Received packet of length %hhu.n, len); .打印出了收到数据包的长度,是一个8位的无符号值(%hhu)。 dbg(RadioCountToLedsC, Time: %sn, sim_time_string();打印出此处仿真的时间。一旦在事件event 里增加这样的调试语句,需要重新编译make micaz sim 。 dbg语句 TOSSIM 的调试输出可以对每个输出通道进行配置。所以,可以把 “Boot”通道发送到文件和标准输出,而“RadioCoun

14、tToLedsC” 发送到标准输出。 默认情况下,通道是没有目的地的,给它的输出消息也会丢失的。 为了发送到标准输出,需要导入sys: import sys f = open(“log.txt”, “w”) /打开或创建文件log.txt,可写 t.addChannel(“Boot”, f) /发送到文件 t.addChannel(“Boot”, sys.stdout) /发送到标准输出 t.addChannel(RadioCountToLedsC, sys.stdout)调试通道 如果多个通道共用1条信息的输出,那TOSSIM 只打印1次消息。 event void Boot.booted(

15、) call Leds.led0On(); dbg(Boot,RadioCountToLedsC, Application booted.n); dbg(RadioCountToLedsC, Application booted again.n); dbg(Boot, Application booted a third time.n); call AMControl.start(); import sys t.addChannel(Boot, sys.stdout) t.addChannel(RadioCountToLedsC, sys.stdout)t.runNextEvent()DEBU

16、G (32): Application booted.DEBUG (32): Application booted again.DEBUG (32): Application booted a third time.五、配置网络 当开启TOSSIM时,没有一个节点可以与另外的节点通信。为了可以仿真网络行为,需要指定网络的拓扑结构。 默认的TOSSIM无线电模型是基于信号强度的。可以向仿真器提供一组数据来描述传播强度、噪声底层值、接收的灵敏度。 所有的这些是通过脚本接口来实现的,一些底层的原始函数如下:加入噪声TOSSIM 仿真出了RF(无线电频率)噪声,干扰节点的接收,不管信号是来自其他的节点

17、还是外部的信号源。使用了Closet Pattern Matching (CPM) 就近模式匹配算法。CPM根据噪声踪迹noise trace作为输入,由此产生静态的模型。 noise = open(“meyer-heavy.txt”, “r”) / 从tos/lib/tossim/noise 复制lines = noise.readlines()/该文件内一行一个噪声数据for line in lines: str = line.strip() if (str != ): val = int(str) for i in range(0, 7): t.getNode(i).addNoiseTr

18、aceReading(val)for i in range(0, 7): t.getNode(i).createNoiseModel() /要用到这两个函数拓扑结构 无线电的联通数据可以存在一个文件里,可以轻松的在文件里创建拓扑结构,然后使用 Python 脚本 加载这个文件并把这些拓扑信息存到radio 对象里。 这个文件里的每一行用3个数值指明每一个连接:源节点、目标节点和增益gain。 如下:1 2 -54.0意味着: 节点1 发送,节点2以-54dBm接收。创建如下的topo.txt :2 -54.01 -55.03 -60.01 -60.03 -64.03 2 -64.0f = op

19、en(topo.txt, r)lines = f.readlines()for line in lines: s = line.split() if (len(s) 0): print , s0, , s1, , s2; r.add(int(s0), int(s1), float(s2)Test.py#! /usr/bin/pythonfrom TOSSIM import *import syst = Tossim()r = t.radio()f = open(topo.txt, r)lines = f.readlines() /构建拓扑结构for line in lines: s = lin

20、e.split() if (len(s) 0): print , s0, , s1, , s2; r.add(int(s0), int(s1), float(s2)t.addChannel(RadioCountToLedsC, sys.stdout)t.addChannel(Boot, sys.stdout)/加入噪声noise = open(meyer-heavy.txt, r)lines = noise.readlines()for line in lines: str = line.strip() if (str != ): val = int(str) for i in range(1

21、, 4): t.getNode(i).addNoiseTraceReading(val)for i in range(1, 4): print Creating noise model for ,i; t.getNode(i).createNoiseModel()/启动节点t.getNode(1).bootAtTime(100001);t.getNode(2).bootAtTime(800008);t.getNode(3).bootAtTime(1800009);for i in range(0, 100): t.runNextEvent()编写脚本test.py 然后运行$ python t

22、est.py六、变量 TOSSIM 允许在运行的TinyOS程序中观察变量。当前,仅可以观察基本类型变量。不能查看结构体里的域(成员),但可以查看状态变量。 此前make 系统编译产生了一个XML文件,里面包含了大量关于当前TinyOS程序的信息,也包括了其中每个组件变量和它的类型。 观察变量需要在TOSSIM里导入对python的支持包先设定python的目录,此步不可少:$ export PYTHONPATH=/opt/tinyos-2.x/support/sdk/python NescApp 有两个可选参数。 第1个是要加载的应用的名字,默认名字是Unknown App 。 第2个是要加

23、载的XML文件名字,默认的是app.xml,这是make 系统自动生成文件的名字。from tinyos.tossim.TossimApp import *n = NescApp()故等价于:from tinyos.tossim.TossimApp import *n = NescApp(Unknown App, app.xml)接下来调用NescApp 对象的 variables 域里的variables() 函数获得一份变量列表。vars = n.variables.variables()为了观察变量,在创建Tossim对象时,把这份列表传给 Tossim 对象。t = Tossim(va

24、rs) 刚才说过,目前只支持简单类型的变量,不能访问结构体里的域(成员)。但是,如果要读取RadioCountToLedsC 里的counter 值。因为网络中的每个节点都有它自己的变量实例,可以从特定的节点里读取它。m = t.getNode(0)v = m.getVariable(RadioCountToLedsC.counter)counter = v.getData() 变量的名字通常是 C.V的形式,其中C 代表的是组件的名字,而V是变量。 如果是通用组件,那名字就是C.N.V,其中N是个整数,用来表示是哪个实例。 变量的获取variables.py 编写一个脚本,启动5个节点的仿真

25、,一直运行到节点0的counter值计数到10停下。 由于使用了5个节点,需修改topo.txt ,修改如下。 0 2 -66.0 2 0 -67.0 1 2 -54.0 2 1 -55.0 1 3 -60.0 3 1 -60.0 2 3 -64.0 3 2 -64.0这个例子脚本位于 opttinyos-2.xtoslibtossimexamples 目录下:from sys import *from random import *from TOSSIM import *from tinyos.tossim.TossimApp import *n = NescApp()t = Tossim(

26、n.variables.variables()r = t.radio()f = open(topo.txt, r)lines = f.readlines()for line in lines: s = line.split() if (len(s) 0): if (s0 = gain): r.add(int(s1), int(s2), float(s3)noise = open(meyer-heavy.txt, r)lines = noise.readlines()for line in lines: str = line.strip() if (str != ): val = int(str

27、) for i in range(0, 4):4 t.getNode(i).addNoiseTraceReading(val)for i in range (0, 4): t.getNode(i).createNoiseModel() t.getNode(i).bootAtTime(i * 2351217 + 23542399)m = t.getNode(0)v = m.getVariable(RadioCountToLedsC.co unter)while (v.getData() 0): if (s0 = gain): r.add(int(s1), int(s2), float(s3)no

28、ise = open(meyer-heavy.txt, r)lines = noise.readlines()for line in lines: st = line.strip() if (st != ): val = int(st) for i in range(0, 4): t.getNode(i).addNoiseTraceReading(val)for i in range (0, 4): t.getNode(i).createNoiseModel()for i in range(0, 60): t.runNextEvent();packets.py接上一页:msg = RadioC

29、ountMsg()msg.set_counter(7);pkt = t.newPacket();pkt.setData(msg.data)pkt.setType(msg.get_amType()pkt.setDestination(0)print Delivering + str(msg) + to 0 at + str(t.time() + 3);pkt.deliver(0, t.time() + 3)for i in range(0, 20): t.runNextEvent();packets.py八、C+ Python 非常的有用,因为它简捷,容易编写,可以交互式地使用。然而,对pyth

30、on的解释编译需要很高的代价:每个事件从python转变为C的资源代价是很高的 。 利用C+接口的脚本进行TOSSIM仿真时,无法查看变量值。 为了使用C+接口注入消息包类,就必须为消息包建立C语言支持,并手动建立消息包。当前,MIG工具还不支持自动地生成C/C+消息包结构。 C+ 接口与 Python 接口的比较范例请详见书中6.3.8节。九、gdb调试 gdb是一个强大的命令行调试工具,一般来说主要调试C/C+程序。当仿真驱动是C+代码时,可以使用gdb工具单步执行TinyOS代码,从而便于观察变量,设置断点以及其它常见的调试行为。 TOSSIM的一个显著优点就是它可以运行在PC上,这样可以运用传统的调试工具来调试nesC程序。九、gdb调试 - 断点 gdb工具并不是为nesC设计的。nesC的组件模型意味着单个命令可能有多个提供者。所以,单个命令必须指定其所处的模块、配件或者接口,才能唯一地确定究竟是

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论