主要介绍在Tornado综合开发环境下的调试方法,以及支持定位问题的步骤和思路。
1Tornado的调试工具
嵌入式实时操作系统VxWorks以及集成开发环境Tornado组成结构如下图1所示。分为主机和目标机系统。
简单解释各菜单项的功能
1.1WindShell
1.1.1简介
Vxworks的Shell分为两种:hostshell 和 target shell;
Tornado提供的WindShell从宿主机到目标机,建立了两者之间的桥梁和命令 shell。WindSh 它是一种非常流行的开发工具,具有很强的交互性和可操作性,允许用户在内存中调用应用程序模块或 VxWorks模块中的任何例程。它不仅具有一般命令语言的功能,而且具有 C 语言的设计特征几乎可以解释任何特征 C 语言表达式, 执行大多数 C 语言算子,符号表数据分析。对于初用者,WindSh学习简单,使用方便。对于熟练用户来说,有更先进的手段可以应用。
WindSh它是一个停留在主机中的C语言解释器,下载到目标机上的所有函数,包括VxWorks系统调用和应用函数。Tornado外壳还可以解释常规工具命令语言TCL。
WindSh它不仅能解释几乎所有的C语言表达式,还能实现所有的调试功能。主要具有下列调试功能:下载软件模块;删除软件模块;生成任务;删除任务;设置断点;删除断点;操作、单步、继续执行程序;检查内存、寄存器、变量;修改内存、寄存器、变量;检查任务列表、内存使用情况CPU利用率;查看特定对象(任务、信号量、消息队列、内存分区、类别);复位目标机等。
1.1.2功能键
Tab
补充剩余部分
Ctrl D
l 所有符号与显示匹配
-> CurM^D
_CurMaster_CurModule
l 补充剩余部分:
->CurMo^D
->CurModule
l 显示命令摘要
->moduleShow ^D
moduleShow() - show the current status for all theloaded modules (WindSh)
STATUS moduleShow
(
char *moduleNameOrId /* name or ID of the module to show */
)
Ctrl W
输入完整命令后,继续输入空间 [Ctrl W]。将会显示html页帮助信息.
Ctrl H
删除一字符
Ctrl U
删除一行
CTRL C
重起shell
CTRL X
Reboot
CTRL S
临时悬挂输出
CTRL Q
恢复挂起
Esc
在输入和编辑模式之间切换
输入类似Vi编辑命令, 如[Esc k]:显示前一次输入的命令
h←j↓k↑l→
h()设置命令缓冲区的长度。->h 500
1.1.3特殊控制符
?
C和TCL模式转换符号, 在c模式下敲入tcl模式, 在tcl下敲进入c模式;
@
在target还是在host上运行,添加到指令前@则在target上运行, 否则在host上运行
>
指令输出重定向
<
指令输入重定向
1.1.4计算功能
数据转换:输入整数或字符后,返回车辆可显示整数的十进制和十六进制值。还可以输入字符常量或符号地址。
比如:
->0x54 64
value = 148 = 0x94
->x = (8 * 6) / 4
x = 0x20ff378: value = 12 = 0xc
->Nom = “Nelson”
new symbol “Nom” added to symbol table.
Nom = 0x23fe798: value = 37742496 = 0x23fe7a0 =
Nom 0x8
1.1.5环境变量
使用?shConfig命令修改环境变量:
SH_GET_TASK_IO
设置调用函数I/O重定向。ON:重定向到WindSh;OFF:I/O显示到目标机控制台。
LD_PATH
为模块设置搜索路径,用;隔开。 例如:ld 命令提交后,Shell搜索模块的路径顺序是:首先在当前目录中,然后到达LD_PATH路径。
LD_SEND_MODULES
设置load模式。
不能使用以下三个
LD_CALL_XTORS
LD_COMMON_MATCH_ALL
DSM_HEX_MOD
1.1.6内置指令
tcl> setshellProcList
b bh bd bdall ccret e s so sysResume sysSuspend d l ld lkAddr lkup m mRegs unld agentMode Showbrowse checkStack classShow devs i intVecShow iStrict iosDevShow iosDrvShowiosFdShow memPartShow memShow moduleIdFigure moduleShow mqPxShow mqShowmsgQShow rBuffShow semPxSho w semShow show smMemPartShow smMemShowsysStatusShow taskShow trgShow version wdShow sp sp s taskIdDefaulttaskIdFigure td ti tr ts tt bootChange cd h help ls period printErrno printLogo pwd quit reboot repeat shellHistory shellPromptSet cplusXtorSetcplusStratShow cplus Ctors cplusDtors wvHostInfoShow evtBufferToFile hostShowicmpstatShow ifShow inetstatShow ipstatShow routestatShow taskCreaeHookShowtaskDeleteHookShow taskSwitchHookShow taskRegs Show tw w taskWaitShowtcpstatShow tftpInfoShow udpstatShow
用缺省参数创建一个任务(priority=100 返回值为任务ID,或错误),立刻返回。任务的I/O不被重定向到shell。
如果直接敲例程名,回车,执行完才返回。I/O被重定向。
与上者不同在于启动该任务后马上将其挂起
恢复一个挂起的任务
挂起一个任务
删除一个任务
创建一个周期调用函数的任务
period 5testPrn 每隔5秒调用testPrn,易于做调试打印。
创建一个重复调用函数的任务
repeat 10testFunc1 连续执行10次testFunc1函数,易于做测试用。
修改任务的寄存器变量。比较有用的是修改pc值,使程序退回到具体位置再运行。 程序位置可以使用shift+F7(混合汇编方式显示代码)
-> mRegs"pc", s1u0
pc : 0499efd7 - 0x499efd1
显示系统信息:
NAME ENTRY TID PRI STATUS PC SP ERRNO DELAY
---------------------- -------- --- ---------- -------- -------- ------- -----
tExcTask _excTask 4b79170 0 PEND 4276be 4b7908c d0003 0
类似于i,但只查询目标机一次
显示相应任务的TCB信息:
-> ti tWdbTask
NAME ENTRY TID PRI STATUS PC SP ERRNO DELAY
---------------------- -------- --- ---------- -------- -------- ------- -----
tWdbTask 0x417cc4 4b70c08 3 READY 4276be 4b70ae4 d0003 0
stack: base 0x4b70c08 end 0x4b6ccc8 size 16176 high 3840 margin 12336
options: 0xe
VX_UNBREAKABLE VX_DEALLOC_STACK VX_FP_TASK
edi = ffffffff esi = 4b70fb8 ebp = 4b70aec esp = 4b70ae4
ebx = 0 edx = 4276be ecx = 10101 eax = 0
eflags = 212 pc = 4276be
显示任务TCB信息, 基本同ti
显示任务创建调用例程列表
_fppCreateHook 0x177008
_envCreateHook 0x156954
___wdbTaskCreat 0x114718
显示任务删除调用例程列表
显示任务切换调用例程列表
_dbgTaskSwitch 0x180384
_SwitchHook 0xde7b78
显示所有或者一个挂起任务的信息
-> w s1u1
NAME ENTRY TID STATUS DELAY OBJ_TYPE OBJ_ID OBJ_NAME
-------------------- -------- ---------- ----- ---------- -------- ------------
s1u1 _t2 4b65898 PEND 0 SEM_M 4b7ea48 N/A
显示某挂起任务的详细信息。
-> tw s1u1
NAME ENTRY TID STATUS DELAY OBJ_TYPE OBJ_ID OBJ_NAME
---------- ---------- -------- ---------- ----- ---------- --------------------
s1u1 _t2 4b65898 PEND 0 SEM_M 4b7ea48 N/A
Semaphore Id : 0x4b7ea48
Semaphore Type : MUTEX
Task Queueing : FIFO
Pended Tasks : 1
State : Owner=0x4b6c960
同tw
w
显示任务寄存器的内容
->taskRegsShow 0x1c615534
edi = 0 esi = 1dd65514 ebp = 1c61546c esp = 1c615458
ebx = 1 edx = 1dfccac8 ecx = 7 eax = 0
eflags = 246 pc = 119604
显示一个任务的使用堆栈的情况,没有定义任务时显示所有
-> checkStack tWdbTask
NAME ENTRY TID SIZE CUR HIGH MARGIN
------------ ------------ -------- ----- ----- -----------
tWdbTask 0x417cc4 4b70c08 16176 292 3840 12336
显示一个任务的调用状况,解析堆栈
-> tt tShell
地址 函数名 偏移 被调用函数(函数参数)
43ad37 _vxTaskEntry +47 : _shell (1, 0,0, 0, 0, 0, 0, 0, 0, 0)
41c414 _shell +13c: 41c438 ([1,0, 0, 0, 41c23c])
41c52e _shell +256: _ledRead(522efb8, 51e45e4, 80)
如果认为被挂起,可找出在哪个函数调用时失败。
报告任务的ID,以及名称
设置或者取得缺省的任务id
int taskIdDefault
(
int tid /* user-supplied task ID; if 0,return default */
)
实时改变任务运行的优先级
显示目标机内存, 可以替代内存观察;
如: d 0x12345, 128, 1 显示128个字节
d 0x12345, 32, 4 显示32个DWORD
m 0x12345, 128, 1
m 0x12345, 32, 4
修改内存
void m
(
void * adrs, /* address to change */
int width /* width of unit to be modified (1, 2, 4, 8) */
)
显示指定符号信息, 和以下指令使用可以找到该变量附近变量, 对于查找变量被更改很有益处
-> lkup "CurModule"
_CurModule 0x01fd3160 comm (down.out)
-> lkup (“^_print”)
_printf 0x00029622 text (vxWorks)
_printErr 0x00029640 text (vxWorks)
_printExc 0x0002965e text (vxWorks)
value = 0 = 0x0
根据指定值搜索符号表,显示的符号地址小于并最接近指定值
-> lkAddr 0x01fd3160
_CurUnit 0x01fd315c comm (down.out)
_CurModule 0x01fd3160 comm (down.out)
_IsFsStarted 0x01fd3164 comm (down.out)
_IntTaskSemaphore 0x01fd3168 comm (down.out)
_gtSemTaskTable 0x01fd316c comm (down.out)
_tR04ModuleReportState 0x01fd3174 comm (down.out)
显示从指定位置开始多少行的汇编
将错误号翻译为具体错误信息。前16位错误号为:module 在vwModNum.h中定义,对应不同头文件。后16位错误号为:error number在相应的头文件中定义。
-> printErrno 0x110001
0x110001 = S_memLib_NOT_ENOUGH_MEMORY
加载模块到系统
[syms[,noAbort][,"name"]]Load stdin, or file, into memory
(syms = add symbols to table: -1 = none, 0 = globals, 1 = all)
修改启动行参数
boot device : fei
processor number : 0
host name : host
file name : vxWorks
inet on ethernet (e) : 168.2.11.41:ffff0000
inet on backplane (b) :
host inet (h) : 168.2.111.1
gateway inet (g) :
user (u) : x86
ftp password (pw) (blank = use rsh) : x86
flags (f) :
target name (tn) :
startup script (s) :
other (o)
列出目标机系统上的所有设备, host:是指映象文件所在目录,有些上面为mars:
-> devs
drv name
0 /null
2 /pcConsole/0
2 /pcConsole/1
7 host:
8 /vio
9 /tgtsvr
4 /HDisk
3 prnpip
基本同devs
显示系统中的驱动状态
drv create delete open close read write ioctl
1 421db4 0 421db4 421ddc 42b76c 42b69c 421e08
2 0 0 424fd4 0 425004 425044 425130
3 426e88 426f04 427170 426e34 427228 427254 426ffc
4 415f40 0 415f40 416000 42b76c 42b69c 416074
5 41626c 41642c 416288 416520 4165d0 416670 416710
显示系统中的文件标识符
fdname drv
3/tyCo/0 1
4/vio/1 4
5/vio/2 4
6/vio/3 4
查看中断向量表,
void intVecShow
(
int vector /* interrupt vector number or -1 to display the whole vectortable */
)
显示系统中所有加载的模块
MODULENAME MODULE ID GROUP # TEXT START DATA START BSS START
------------------------ -------------------- ---------- ---------- ----------
vxWorks.exe 0x365420 1 0x401000 0x43f000 0x442000
test.o 0xd32888 2 0x499efac 0x499eff4
显示队列的使用状况
Message Queue Id : 0x1c710c0c
Task Queueing : FIFO
Message Byte Len : 8
Messages Max : 4000
Messages Queued : 0
Receivers Blocked : 1
Send Timeouts : 0
Receive Timeouts : 709968
显示信号量的信息
STATUS semShow
(
SEM_ID semId,/* semaphore to display */
int level /* 0 = summary, 1 = details */
)
->semShow NodeSemaphore ,0
Semaphore Id : 0x1c7a443c
Semaphore Type : MUTEX
Task Queueing : FIFO
Pended Tasks : 0
State : NotOwned
显示POSIX信号量的信息
显示看门狗的信息
显示POSIX消息队列的信息
显示分区块及统计信息
显示系统分区上空闲和已分配空间的总数等等
SUMMARY:
status bytes blocks avg block max block
------ ----------------- ---------- ----------
current
free 443257168 140 3166122 442697252
alloc 27726464 517 53629 -
cumulative
alloc 50636892 5873 8621 -
显示host列表
hostname inet address aliases
-------- ------------ -------
vxTarget 168.2.11.9
localhost 127.0.0.1
host 168.2.111.1
显示arp列表
LINK LEVEL ARP TABLE
destination gateway flags Refcnt Use Interface
--------------------------------------------------------------------------
168.2.111.1 00:05:5d:e4:14:3b 405 0 6897 fei0
--------------------------------------------------------------------------
显示网口信息
fei (unit number 0):
Flags:(0x8063) UP BROADCAST RUNNING ARP MULTICAST
Type:ETHERNET_CSMACD
Internetaddress: 168.2.11.9
Broadcastaddress: 168.2.255.255
Netmask0xffff0000 Subnetmask 0xffff0000
Ethernetaddress is 00:d0:d0:10:0b:09
Metric is 0
MaximumTransfer Unit size is 1500
11325 packetsreceived; 6965 packets sent
4374 multicastpackets received
11 multicastpackets sent
0 inputerrors; 0 output errors
0 collisions;0 dropped
lo (unit number 0):
Flags:(0x8069) UP LOOPBACK RUNNING ARP MULTICAST
Type:SOFTWARE_LOOPBACK
Internetaddress: 127.0.0.1
Netmask0xff000000 Subnetmask 0xff000000
Metric is 0
MaximumTransfer Unit size is 32768
0 packetsreceived; 0 packets sent
0 multicastpackets received
0 multicastpackets sent
0 inputerrors; 0 output errors
0 collisions;0 dropped
显示ip信息
total 7571
badsum 0
tooshort 0
toosmall 0
badhlen 0
badlen 0
infragments 0
fragdropped 0
fragtimeout 0
forward 0
cantforward 0
redirectsent 0
unknownprotocol 6996
nobuffers 0
reassembled 0
outfragments 0
noroute 0
显示icmp信息
ICMP:
7060 calls toicmp_error
0 error notgenerated because old message was icmp
Outputhistogram:
destinationunreachable: 7060
0 message withbad code fields
0 message <minimum length
0 bad checksum
0 message withbad length
0 messageresponse generated
显示路由信息
routing:
0 bad routingredirect
0 dynamicallycreated route
0 new gatewaydue to redirects
12 destinationsfound unreachable
0 use of a wildcard route
显示tcp信息
TCP:
11740 packets sent
2840 data packets (137764 bytes)
6 data packets (1867 bytes)retransmitted
5642 ack-only packets (0 delayed)
0 URG only packet
0 window probe packet
0 window update packet
3254 control packets
8485packets received
44 acks (for 2429 bytes)
2801 duplicate acks
0 ack for unsent data
2840 packets (2128 bytes) receivedin-sequence
1 completely duplicate packet (29 bytes)
0 packet with some dup. data (0 byte duped)
2 out-of-order packets (0 byte)
0 packet (0 byte) of data after window
0 window probe
0 window update packet
0 packet received after close
0 discarded for bad checksum
0 discarded for bad header offset field
0 discarded because packet too short
2953 connection requests
0 connection accept
2802 connections established (includingaccepts)
2950 connections closed (including 2798drops)
147 embryonic connections dropped
2846 segments updated rtt (of 5797 attempts)
304 retransmit timeouts
0 connection dropped by rexmit timeout
0 persist timeout
147 keepalive timeouts
0 keepalive probe sent
147connections dropped by keepalive
显示udp信息
UDP:
7759 total packets
7757 input packets
2 output packets
0 incomplete header
0 bad data length field
0 bad checksum
581 broadcasts received with no ports
0 full socket
7176 pcb cache lookups failed
7176 pcb hash lookups failed
显示连接信息
Active Internetconnections (including servers)
PCB Proto Recv-Q Send-Q Local Address Foreign Address (state)
-------- ----------- ------ ------------------------------------ -------
1de70b94TCP 0 0 0.0.0.0.111 0.0.0.0.0 LISTEN
1de70a08UDP 0 0 0.0.0.0.111 0.0.0.0.0
显示ftp信息
注意分清是对target还是host上的文件进行操作, 而相应使用
改变工作目录
列出工作目录下的文件
显示当前工作目录
拷贝文件
copy “host:cnset.cfg”,“/HDisk/cnset.cfg”
删除文件
remove “/HDisk/trace/error.log”
更改文件名称
将ATA硬盘作为一个dos文件系统加载
STATUS usrAtaConfig
(
int ctrl, /* 0: primary address, 1: secondary address */
int drive, /* drive number of hard disk (0 or 1) */
char * fileName /* mount point */
)
如在MP上配置电子盘和硬盘:
usrAtaConfig(0,0,“HDISK”) 加载硬盘
usrAtaConfig(1,0,“FDISK”) 加载电子盘
将Flash作为一个dos文件系统加载
usrTffsConfig(int drive, int removable, char * fileName)
如在PPC板上配FLASH:
usrTffsConfig(0,0,“输入自己的设备名”) 加载Flash盘
格式化flash:
STATUS tffsDevFormat
(
int tffsDriveNo, /* TrueFFS drive number (0 - DRIVES-1) */
int arg /* pointer to tffsDevFormatParams structure */
)
例如: tffsDevFormat 0, 0
1) shell 本身的一些指令
help Print this list
h Print (or set) shell history
shellHistory 设置或显示Shell命令
shellPromptSet 改变C解释器Shell 提示
printLogo 显示Tornado Shell 登陆
version Print VxWorks version info, andboot line
exit 退出shell
quit 退出shell
2) 几个系统调试指令
b Display breakpoints
b Set breakpoint
bd Delete breakpoint
bdall Delete all breakpoints
c Continue from breakpoint
s Single step
bh Set hardware breakpoint
sysSuspend Suspend the system
sysResume Resume the system
agentModeShow 显示代理模式(系统模式 或 任务模式)
sysStatusShow 显示系统上下文(suspend或 running,系统模式下使用)
3) 几个不常用的指令
smMemShow show the shared memory systempartition blocks and statistics
smMemPartShow show user's shared memory systempartition blocks and statistics
trgShow show trigger information
show 在shell窗口打印特定对象的信息
browse 在Tornado browser 显示特定的对象
注:某些命令只在TargetServer上执行,如lkAddr。
某些需要到Target上执行,如period()、repeat()。
1.2 BROWSE
可对系统对象(任务、消息队列、信号量等)和存储器使用情况进行观察的浏览器。可以方便地监视用户的目标系统。Browser汇总了应用进程,内存消耗和一个目标内存的映像。通过Browser,用户可以观察信号量、消息队列、内存分配、看门狗计时器、堆栈使用情况、目标 CPU使用率、对象模块结构和符号表以及每个任务的详细信息。
可以分析: 内存泄漏、内存碎片、堆栈溢出、优先级反转
1.2.1 内存查看
Tools条显示的是归taget agent管理的内存,归Tornado tools使用;
Application条显示的是归目标系统内所有任务使用;
以上2者独立分开,共同占用目标板的内存;
栏内显示的是所有模块的所占用内存的信息;
1.2.2 模块信息
可以知道该模块的地址空间,比较有用的是他的符号表;
1.2.3 堆栈使用率
可以检查堆栈状况
1.2.4 CPU占有率
由于辅助时钟和目前3gcn内的冲突,建议不要使用,否则会造成系统紊乱;
1.2.5 任务信息
1.2.6 中断向量表
standard exception handler
default trap (Sparc)
uninitialized interrupt vector
corrupted interrupt vector
1.2.7 实体查看
可以查看诸如消息队列、信号量、watchdog、任务、系统内存等的状况。如:
1.3 Debugger
1.3.1 条件断点
condition 填入条件,变成条件断点
keep 指一直有效
delete 在断点到达后将之删除
disable 先不让该断点有效
1.3.2 代码显示
以高级语言(c、c++)显示,缺省的显示方式
以反汇编方式显示
混合高级和反汇编方式显示,配和修改一些寄存器值如pc,来达到控制调试流程。
1.4 Target Server
创建Target Server时需要配置的变量。
1.4.1 使用串口调试
提供了几种target/host联系方式:
一般用于vxworks目标模拟
我们用不着
用的最多的一种,只要是ip连接的都行,需要配置目标机的IP地址
使用串口,填入连接的串口号,及其波特率即可
1.4.2 重定向
重定向目标机上的全局、 和 到target server。如果没有创建控制台窗口,当有字符从目标机发送过来的时候, WTX 事件被发送给所有的WTX 工具 。
在target server 所在的主机上创建一个虚拟控制台窗口作为目标机的I/O口。
创建一个虚拟控制台窗口,当前target shell的标准input、output和error被重定向到该窗口。
1.5 WindView
在运行中可以记录一些重要信息(比如:任务调度状况、信号量、消息队列、watchdog,、内存、信号)的状况,从而便于对复杂的实时系统运行状况进行分析。
可以对调度异常、资源挂死、死机等进行分析。
1.5.1 记录层次
根据需要,可以记录3个层次上数据:
- Context Switch Event-Logging Level (CSE Level)
- Task State Transition Event-Logging Level (TST Level)
- Additional Instrumentation Event-Logging Level (AIL Level)
1.5.2 记录数据存储方式
可以设定一定大小的内存,在target上作为保存数据的缓冲。有这样几种方式将该缓冲输出,一般用前两者:
直接显示到屏幕
送到target server上的一个文件中/tgtsvr/XXX.Wvr文件。Targetserver的路径如下在TargetServer Configuration 中设置
通过菜单打开/tgtsvr/TCP:xiaxinguo:6164[其实是创建了个连接]来接收taget的输出到屏幕
通过菜单打开xiaxinguo:6164[其实是创建了个连接]来接收taget的输出到屏幕
保存到文件
1.5.3 传送方式
host取一次,taget记一次。
target在记到一定程度后,传送到后台,继续记录,连续进行。
target将数据记录到保留内存,在异常热启动后可再取得相应数据,从而可以知道是异常在哪里。
1.5.4 数据分析
Ø 具体图形的意义可以参看帮助”Event Dictionary”。
Ø 可以选择关心的任务,关心的实体,而将不关心的部分隐藏掉。
Ø 为便于查找,可以自己创建几个实体以便标识,比如信号量。在错误处操作,从而可以很快定位,而不用再达海中捞针。
1.6 Trigger
Ø 可以监控变量,函数的执行情况,特别对变量被修改这种问题有帮助。
Ø 和windview配合使用,使记录可控。
1.7 telnet
telnet功能类似shell,不用起tornado而已,省却启动target server,对release比较有用。使用方法如下:
在包含了INCLUDE_TELNET 后能使用telnet;如果要加上user/pass验证,则需要加上 INCLUDE_SECURITY 。但注意的是,下图中的pass为加密后的密码,可以使用/host/x86-win32/bin/vxencrypt来将密码加密。
1.8 调试模式
Tornado集成环境提供两种调试模式:任务调试模式和系统调试模式。在任务调试模式下,在一个集成环境下一个时间内只能调试一个任务。调试只影响当前被调试的任务,其它任务正常运行。在系统调试模式下,可以同时调试多个任务、中断服务程序(ISR),调试影响整个系统。
通过下面的例子说明调试步骤:
/* VxWorks includes */
#include "vxWorks.h"
#include "taskLib.h"
#include "stdio.h"
#include "msgQLib.h"
int g_lTaskATid;
int g_lTaskBTid;
MSG_Q_ID g_MsgQ1id;
MSG_Q_ID g_MsgQ2id;
void MultiTaskTestTaskA(void)
{
char cMsgToTaskB[100];
char cMsgFromTaskB[100];
sprintf(cMsgToTaskB,"To TaskB \n");
printf(" Hello from MultiTaskTestTaskA \n");
taskSuspend(0); /*挂起*/
for(;;)
{
printf(" Hello from MultiTaskTestTaskA \n");
msgQSend(g_MsgQ1id,cMsgToTaskB,sizeof(cMsgToTaskB),WAIT_FOREVER, MSG_PRI_NORMAL);
msgQReceive(g_MsgQ2id,cMsgFromTaskB,100,WAIT_FOREVER);
printf("%s",cMsgFromTaskB);
}
}
void MultiTaskTestTaskB(void)
{
char cMsgToTaskA[100];
char cMsgFromTaskA[100];
sprintf(cMsgToTaskA,"To TaskA \n");
printf(" Hello from MultiTaskTestTaskB \n");
taskSuspend(0);
for(;;)
{
printf(" Hello from MultiTaskTestTaskB \n");
msgQSend(g_MsgQ2id,cMsgToTaskA,sizeof(cMsgToTaskA),WAIT_FOREVER, MSG_PRI_NORMAL);
msgQReceive(g_MsgQ1id,cMsgFromTaskA,100,WAIT_FOREVER);
printf("%s",cMsgFromTaskA);
}
}
void MultiTaskTestInit(void)
{
printf(" Hello from MultiTaskTestInit \n");
g_MsgQ1id=msgQCreate(20,100,MSG_Q_FIFO); /*创建消息队列*/
if(g_MsgQ1id==NULL)
{
printf(" ERROR: create g_MsgQ1 error \n");
}
g_MsgQ2id=msgQCreate(20,100,MSG_Q_FIFO);
if(g_MsgQ1id==NULL)
{
printf(" ERROR: create g_MsgQ2 error \n");
}
printf(" Spawning a new task called MultiTaskTestTaskA \n\n");
g_lTaskATid=taskSpawn("MultiTaskTestTaskA",100,0,10000, (FUNCPTR)MultiTaskTestTaskA,0,0,0,0,0,0,0,0,0,0);
if(g_lTaskATid == ERROR)
{
printf(" ERROR: task did not spawn \n");
exit(1);
}
printf(" Spawning a new task called MultiTaskTestTaskB \n");
g_lTaskBTid=taskSpawn("MultiTaskTestTaskB",100,0,10000, (FUNCPTR)MultiTaskTestTaskB, 0,0,0,0,0,0,0,0,0,0);
if(g_lTaskBTid == ERROR)
{
printf(" ERROR: task did not spawn \n");
exit(1);
}
exit(0);
}
1.8.1 任务调试模式下的多任务调试
在任务调试模式下,在一个集成环境中,在一个任务中调试,在另一个任务中设置断点,设置的断点不起作用。这是因为一个调试器只能处理一个TCB(任务控制块),每个任务都有一个TCB,因此一个调试器只能调试一个任务,要调试几个任务就要启动几个调试器。一个集成环境只能启动一个调试器,所以要调试几个任务就要启动几个集成环境。另外,需要在被调试的任务的待调试的第一条语句前加入taskSuspend(0)语句,挂起该任务,否则任务就可能会在调试前被执行。
多任务调试步骤:
* 用-g选项编译源代码产生目标文件
* 下载产生的目标文件
* 在MultiTaskTestInit函数的开始设置断点
* 把MultiTaskTestInit设置为调试任务的人口函数
* 单步执行产生MultiTaskTestTaskA任务的语句后可以在串口(超级终端)上看到字符串Hello from MultiTaskTestTaskA,用Browser查看任务,可以看到任务MultiTaskTestTaskA出于挂起态(suspended),表明程序执行了taskSuspend(0)语句。
* 运行另一个Tornado集成环境
* Attach任务MultiTaskTestTaskA,
* 在语句msgQReceive(g_MsgQ2id,cMsgFromTaskB,100,WAIT_FOREVER)的下一条语句处设置断点
* 运行任务MultiTaskTestTaskA。可以看到没有执行到断点处,用Browser查看任务状态,MultiTaskTestTaskA出于阻塞态(pended),因为它在等待消息。
* 单步执行MultiTaskTestInit到产生MultiTaskTestTaskB任务的下一条语句,可以看到MultiTaskTestTaskB任务处于挂起态
* 再运行另一个Tornado集成环境
* Attach任务MultiTaskTestTaskB,
* 在语句msgQReceive(g_MsgQ1id,cMsgFromTaskA,100,WAIT_FOREVER)下一条语句处设置断点
* 运行任务MultiTaskTestTaskB。可以看到执行到断点处停下。这是因为MultiTaskTestTaskA任务已经发送一条消息到MultiTaskTestTaskB的接收队列中。
* 此时,可以看到MultiTaskTestTaskA任务也运行到断点处,因为为MultiTaskTestTaskB任务已经发送一条消息到MultiTaskTestTaskA的接收队列中。
1.8.2 系统调试模式下多任务的调试:
Tornado2.0集成环境提供了通过网口进行系统模式调试的功能。系统缺省使用网口通信,如果需要使用串口通信,需要修改文件C: \ Tornado \ target \ config\ all \ configAll.h的一些宏定义,修改为:
#define WDB_COMM_TYPE WDB_COMM_SERIAL /*使用串口通信*/
#define WDB_TTY_CHANNEL 0 /*使用第一个串口*/
#define WDB_TTY_BAUD 38400 /*波特率:38400bps*/
重新编译链接vxWorks。 在启动Target server时,要选择串口通信,并进行相应配置。
调试使用的源代码与任务调试模式中使用的代码相同。但是,需要去掉为了能够在任务调试模式下进行多任务调试的MultiTaskTestTaskA和MultiTaskTestTaskB中的语句taskSuspend(0);。
多任务调试步骤:
* 用-g选项编译源代码产生目标文件。
* 下载产生的目标文件。
* 在MultiTaskTestInit函数的开始设置断点。
* 在Debugger命令窗口输入命令attach system进入系统调试模式。
* 在Shell窗口输入命令sp MultiTaskTestInit产生一个以MultiTaskTestInit为入口函数的任务,因为整个系统都停下了,新产生的任务还没有执行,这可以通过在Debugger命令窗口输入命令info threads显示当前系统中的任务列表看出来。
* 执行菜单命令Debug | Continue(F5)继续运行程序。
* 系统在设置的断点处停下。
* 在函数MultiTaskTestTaskA中的语句msgQReceive(g_MsgQ2id,cMsgFromTaskB, 100,WAIT_FOREVER)的下一条语句处设置断点。
* 在函数MultiTaskTestTaskB中的语句msgQReceive(g_MsgQ1id,cMsgFromTaskA, 100,WAIT_FOREVER)的下一条语句处设置断点。
* 执行菜单命令Debug | Continue继续运行程序。
* 程序在任务MultiTaskTestTaskB中的断点处停下(为什么不是在任务MultiTaskTestTaskA中停下?请考虑)。
* 执行菜单命令Debug | Continue继续运行程序。
* 程序在任务MultiTaskTestTaskA中的断点处停下。
* 执行菜单命令Debug | Continue继续运行程序。
* 程序又一次在任务MultiTaskTestTaskA中的断点处停下(为什么停两次?请考虑,以后依次增加停的次数)。
* 执行菜单命令Debug | Continue继续运行程序。
* 程序在任务MultiTaskTestTaskB中的断点处停下。
1.8.3 中断服务程序的调试
中断服务程序只能在系统调试模式下调试,不能在任务调试模式下调试。因为中断服务程序是作为系统的一部分运行,不是以任务方式运行,因此不需要为它产生任务。
中断服务程序调试步骤:
* 用-g选项编译源代码产生目标文件。
* 下载产生的目标文件。
* 在MultiTaskTestInit函数的开始设置断点。
* 在Debugger命令窗口输入命令attach system进入系统调试模式。
* 执行菜单命令Debug | Continue继续运行程序。
* 如果产生相应的中断,程序就会在中断服务程序的断点处停下。进行需要的调试。
使用logMsg()打印,不能用printf()。
2 V2支撑的调试手段
2.1 各模块提供的函数
R01提供的调试函数:需要将MEM_TRACE_ON宏定义打开,重新编译生成目标文件。
Ÿ VOID r01UBUseStatShow (VOID);
显示所有内存池的占用信息,包括内存池大小, 总共个数, 使用个数, 使用峰值个数, 失败个数。如果用的个数不变小,可以使用r01UBPoolShow来看是被谁占用;
Ÿ VOID r01DispCpu (VOID);
打印当前CPU占用情况
Ÿ BOOL r01PcbShow (WORD16 wPno);
打印进程的运行状态
Ÿ BOOL r01UBShowByPno (WORD16 pno)
显示所有进程占用内存情况
Ÿ BOOL r01ProcShow (WORD16dwFlag)
显示当前激活的进程信息,包括进程名, 任务号,PID, 运行时间(pentium为ms,powerpc为10ms), 进程堆栈使用率。DwFlag低四位=1,dwRunTickSum字段清零;其余不清零。
Ÿ BOOL r01TcbShow (WORD1