在tinyos/NesC当中,debug的方式主要有两个:
TOSSIM自身的调试信息和使用gdb的调试.
TOSSIM调试功能:
优点是可以像 printf一样,在程序中各个希望知道变量结果的地方,加入相应的输出信息.
缺点是和printf一样麻烦,要在所有需要的地方写代码.
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。所以在linux下是可以直接使用的,所以对于作为linux模拟器的cgywin来说,当然也是可以直接使用的.
优点是有他就是一个debug工具,所以拥有强大的功能,比如设置断点.在循环结构和有关时间的程序当中,还是非常重要的。
缺点是他是c语言的调试工具,而不是nesc,所以它不太认识nesc,在调试的时候,很多东西都要转换.
以下分别介绍如何使用:
1. TOSSIM
缺省情况下,TOSSIM 在console输出所有调试信息。但用户更关心的是数据包的输出和节点上LED 的显示值。TOSSIM 输出可以通过在shell 中设置DBG 环境变量而进行配置,输入命令:
export DBG=am,led,
这条命令使得只有LED 和AM(活动消息)数据包才可以输出。
为了把console的调试信息保存到文件中, 可以采用如下命令:
make build/pc/main.exe 1 > tossim.txt
文件名可以自定.所生成的文件会放在cygwin当前的工作目录下。
那么就只会在文件当中显示调试信息,而在console当中不会显示。所以感觉在console当中是死机了一样,卡住了,其实后台正在运行。同样用Ctrl+C结束程序。
TinyOS 代码中,调试消息命令如下:
dbg(<mode>, const char* format, ...);
那么这里一目了然,以dbg当中的内容就是需要输出的内容.
其中mode 参数指定在哪种DBG 模式下将输出这条消息。一般而言,在运行模拟器时,TinyOS 代码中DBG 的模式名是预先指定的名称。例如:
am 是DBG_AM,packet 就是DBG_PACKET,而boot 也即是DBG_BOOT。
dbg模式可以有很多种, 比如temp,usr1,usr2,am,led等等.
参数format 及其后面的其他参数指明将要输出的字符串,并且具有与 printf()相同的语义。例如,在编程器中打开tos/lib/Counters/Counter.nc,在 Timer.fired()中返回语句之前加上这一行语句:
dbg(DBG_TEMP, “Counter: Value is %i/n”, (int)state);
注意到这里使用的是%i,而不是我们熟悉的%d,后面也采用了强制类型转换(int)state。
在console输入DBG= temp
将DBG 设置为temp 并运行模拟将可以看到计数器在增加。
在运行模拟时不仅可以指定多个模式,而且单个调试消息可以在多种模式下激活,对它们使用所有标准逻辑操作,如|,~。
例如:
dbg(DBG_TEMP|DBG_USR1, "Counter: Value is %i/n", (int)state);
此时,只要DBG 模式是temp 或者usr1,都可以看到结果。
可用的所有DBG调试模式如下:
all: Enable all available messages
boot: Simulation boot and StdControl
clock: The hardware clock
task: Task enqueueing/dequeueing/running
sched: The TinyOS scheduler
sensor: Sensor readings
led: Mote leds //单机程序和观察节点变化常用
crypto: Cryptographic operations (e.g., TinySec)
route: Routing systems
am: Active messages transmission/reception //无线传输常用
crc: CRC checks on active messages //通讯信息发送接收常用
packet: Packet-level transmission/reception
encode: Packet encoding/decoding
radio: Low-level radio operations: bits and bytes
logger: Non-volatile storage
adc: The ADC
i2c: The I2C bus
uart: The UART (serial port)
prog: Network reprogramming
sounder: The sounder on the mica sensor board
time: Timers
sim: TOSSIM internals
queue: TOSSIM event queue
simradio: TOSSIM radio models
hardware: TOSSIM hardware abstractions
simmem: TOSSIM memory allocation/deallocation (for finding leaks)
usr1: User output mode 1 //debug专用
usr2: User output mode 2 //debug专用
usr3: User output mode 3 //debug专用
temp: For temporary use //debug专用
2. gdb
我本身对GDB不熟悉, 还是习惯那种图形界面方式的,像VC、Eclipse等IDE的调试方式,不过现在都玩传感器了,还是要熟悉这个命令行的调试方式,也许功能更为强大.
一次典型的gdb使用如下(基于我自己的理解):
To start a gdb debugging for a general NesC application, I used the following command:
$ gdb --args build/pc/main.exe 4
The gdb console gave the following information:
GNU gdb 2003-09-20-cvs (cygwin-special)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-cygwin"...
screenshot 1 start a application with gdb
因为gdb不能兼容nesc, 所以在用gdb来调试nesc程序的时候,其实质是调试c代码,所以存在一个映射的问题.
As we know before, gdb does not (yet!) have a nesC-specific mode. Instead, in gdb you are effectively debugging the C code generated by the nesC compiler. However, the nesC compiler includes #line directives in the code it generates, so single-stepping through nesC code will display the correct nesC source code, and breakpoints can be set based on the line numbers and file names of nesC components. The situation for variable, function, command and event names is however not as straightforward.
To set up a break point, I used the following command:
(gdb) break *BlinkM$StdControl$init (这里存在nesC到C的映射关系)
映射关系如下:
Note the * and $ here, Types, variables and functions in C files (included via the includes statement) are left unchanged in the generated C code, except if they correspond to a nesC keyword. There is a mapping from nesC names to C names.
A module variable (top-level data declarations in modules) X in module M is called M$X in the generated C code.
A function F in module M is called M$F in the generated C code.
Local variable names in modules are left unchanged in the generated C code.
A command or event C in module M is called M$C in the generated C code.
A command or event C of interface instance I in module M is called M$I$C in the generated C code.
The gdb console gave the following information:
Breakpoint 1 at 0x4073e4: file BlinkM.nc, line 52.
screenshot 2 set breakpoint in gdb
To make the application run, I used the following command:
(gdb) run
The gdb console gave the following information:
Starting program: /opt/tinyos-1.x/apps/Blink/build/pc/main.exe 4
SIM: EEPROM system initialized.
SIM: event queue initialized.
SIM: Random seed is 282250
SIM: Initializing sockets
SIM: Created server socket listening on port 10584.
SIM: Created server socket listening on port 10585.
SIM: eventAcceptThread running.
SIM: Time for mote 0 initialized to 19258390.
SIM: commandReadThread running.
SIM: Time for mote 1 initialized to 38233659.
SIM: Time for mote 2 initialized to 29605707.
SIM: Time for mote 3 initialized to 81760.
3: BOOT: Scheduling for boot at 0:0:4.81459750.
3: BOOT: Scheduling for boot at 0:0:9.55841475.
3: BOOT: Scheduling for boot at 0:0:7.40142675.
3: BOOT: Scheduling for boot at 0:0:0.02044000.
3: Popping event for mote 3 with time 0:0:0.02044000.
Program received signal SIGSEGV, Segmentation fault.
0x7c809eb4 in KERNEL32!IsBadWritePtr ()
from /cygdrive/c/WINDOWS/system32/kernel32.dll
(gdb)
screenshot 3 run after setting up a breakpoint
简单说下关于教程中使用gdb工具进行调试的这段:
首先我假设这个main.exe是CntToLedsAndRfm的。
1, 通过输入 gdb build/pc/main.exe 来启动gdb调试模式
2, 这里大家一定要注意!!!!!(gdb) break *LedsM$Leds$redOff
注意教程当中的错误,不是LedsC而应是LedsM
3, run 1
# 在使用gdb命令:查看某个运行时变量时,
(gdb) print LedsC$ledsOn
我没有成功,显示的是:
No symbol “LedsC$ledsOn” in current context!
有成功的同学请告知,谢谢!
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。