Tornado代表嵌入实时应用中最新一代的开发和执行环境。 Tornado 包含三个完整的部分:(1)Tornado系列工具, 一套位于主机或目标机上强大的交互式开发工具和使用程序; (2)VxWorks 系统, 目标板上高性能可扩展的实时操作系统;(3)可选用的连接主机和目标机的通讯软件包 如以太网、串行线、在线仿真器或ROM仿真器。
使用步骤
使用Tornado集成环境一般需要经过以下步骤:
运行TCP/IP端口管理器Portmapper
运行注册器Tornado Registry,如果使用的是试用版,注意是否注册成功,是否修改了日期
运行并配置Ftp Server点击菜单命令Security | Users | rights弹出配置窗口,点击New User,在New User弹出窗口加入需要加入的用户名在改变密码弹出窗口设置该用户的密码在Home Directory中设置相应的目录,MCP750为c:\tornado\target\config\mcp750,MCPN750为c:\tornado\target \config\mcpn750,X86为c:\tornado\target\config\pc486 。
目标板上电或复位
在控制台上可以看到启动信息。如果需要修改,在等待用户配置时,按c键,进行相应修改。修改结束后,按@键重新启动目标机。
运行Tornado(tornado.exe)
执行菜单命令Tools | Target Server | Configure,弹出目标服务器设置对话框,点击New产生一个新的配置。设置Description域(可以任意设置);设置Target Server域;在Change Property域选取Back End项,如果使用网口调试,选择wdbrpc,在目标IP名或地址域中给出目标机的IP名或地址,如果给出的是IP名,需要在HOSTS文件中给出IP名与IP地址的对应关系,如果用串口调试,选择wdbserial,选择相应的串口和波特率;在Change Property域选取Core File and Symbols项,选中File项输入相应的文件,点击Launch,运行目标服务器。
执行菜单命令File | New 创建一个新的文件,并打开编辑器Editor。
单独编译生成的源文件,生成目标文件,编译连接过程的详细介绍请见后面。
选取相应的目标服务器。
执行菜单命令Tools | Debugger运行调试器。
执行菜单命令Debug | Download下载要调试的目标文件。
在Editor窗口设置断点。
执行菜单命令Debug | Run弹出对话框,要求输入调试入口函数,输入要调试的函数。
进行源码级调试
执行菜单命令Tools | Shell运行Shell。可以在Shell窗口查看/修改全局变量、内存,查看任务列表、各模块使用内存的情况、对象等信息。
执行菜单命令Tools | Browser运行Browser。在Browser中可以查看任务列表、各模块使用内存的情况、对象等信息。
6、编译链接
VxWorks的开发调试环境可以把VxWorks内核和应用分开,分别加载。 VxWorks内核在目标机启动过程中通过ftp协议加载到目标机中运行,应用模块在调试中动态下载,目标代理把下载的应用模块动态链接到系统中,应用模块的调试是通过在用户执行运行命令时提供入口函数实现的。
通用平台VxWorks 3.1版扩展了的3.0功能:它扩展了架构支持、多处理器消息处理、增强了网络堆栈以及支持风河Workbench的最新版本。
VxWorks的开发调试环境也提供把应用模块与系统内核链接在一起,通过ftp协议加载执行。这需要经过两个步骤:把应用模块的入口代码加到usrConfig.c文件中的usrRoot函数的尾部;把应用模块编译链接到VxWorks内核中,这种编译链接方式一般用于后期调试。
6.1 单个应用模块的编译
单个应用模块的编译可以通过使用菜单命令Project | Make Current Source File进行编译,要编译的源文件必须已经用Editor打开并且为当前窗口在弹出的创建缺省makefile窗口的CPU域选择相应的项,在ADDED_FLAGS域输入-g,确定。生成的目标文件在Debugger环境中动态加载,与内核动态链接到一起。
6.2 系统内核vxWorks的编译链接
系统内核vxWorks是调试中使用最多的内核映象。它的作用通常是进行软硬件初始化,等待加载应用模块,进行程序调试。
在Project菜单下,选择相应硬件平台的生成vxWorks的命令,进行编译链接。在编译链接之前先使用clean命令删除以前生成的文件。
6.3 应用模块与系统内核一起编译链接
VxWorks 是美国 Wind River System 公司推出的一个实时操作系统。Tornado 是WRS 公司推出的一套实时操作系统开发环境,类似Microsoft Visual C,但是提供了更丰富的调试、仿真环境和工具。
VxWorks的开发调试环境也提供把应用模块与系统内核链接在一起,vxWorks内核自动执行应用模块。这需要经过两个步骤:把应用模块的入口代码加到usrConfig.c文件中的usrRoot函数的尾部;在makefile中把待生成的应用模块的目标文件名加到宏定义MACH_EXTRA中,再把相应的编译规则加到makefile中。
6.4 Project菜单下其它编译链接命令介绍
vxWorks_rom :可以写到ROM的、没有带符号表和Shell的、没有压缩的vxWorks。
vxWorks.st :带有符号表的vxWorks。
vxWorks.st_rom:可以写到ROM的、带有符号表和Shell的、压缩的vxWorks。
vxWorks.res_rom :可以写到ROM的、带有符号表和Shell的、只有数据段拷贝到内存的、没有压缩的vxWorks。
vxWorks.res_rom_nosym:可以写到ROM的、只有数据段拷贝到内存的、没有压缩的vxWorks。
bootrom:压缩的 bootrom
bootrom_uncmp:没有压缩的bootrom
7、调试时的常用方法
下面是一些调试手段在调试器中的相应命令
调试手段
相应操作
设置断点
菜单命令Debug|Toggle BreakPoint
删除断点
菜单命令Debug|Toggle BreakPoint
运行
菜单命令Debug|Run
单步执行(进入函数)
菜单命令Debug|Step
单步执行(不进入函数)
菜单命令Debug|Next
继续执行(停下后的程序)
菜单命令Debug|Continue
执行完当前的函数,停在调用它的函数的下一条语句
菜单命令Debug|Finish
查看变量的值
菜单命令Debug|Inspect
查看当前函数的所有局部变量
菜单命令Debug|Locals
查看内存
菜单命令Debug|Memory
查看寄存器
菜单命令Debug|Registers
修改内存
Shell命令m
修改寄存器
Shell命令mRegs
修改变量
在Shell中直接给该变量赋值
卸载一个加载的模块
Shell命令unld
删除任务
Shell命令td
复位目标机
Shell命令reboot
用该命令的好处:目标服务器自动与目标代理重新链接,Shell自动重启
查看任务
在Browser对象信息窗口输入待查看的任务名或ID
查看信号量
在Browser对象信息窗口输入待查看的信号量名或ID
查看消息队列
在Browser对象信息窗口输入待查看的消息队列命或ID
内存分区
在Browser对象信息窗口输入待查看的内存分区ID
看门狗
在Browser对象信息窗口输入待查看的看门狗ID
类(class)
在Browser对象信息窗口输入待查看的类的ID
查看内存使用
Browser的内存使用窗口
查看任务列表
Browser的任务列表窗口
查看CPU占用率
Browser的Spy窗口
查看堆栈使用情况
Browser的堆栈检查窗口
注:
Shell可以通过菜单命令Debug | Shell启动
Shell的原语可以通过在Shell中输入help列出
Browser可以通过菜单命令Debug | Browser启动
Debugger命令窗口的命令可以通过在命令窗口输入help列出
8、任务调试模式下的多任务调试
在任务调试模式下,在一个集成环境中,在一个任务中调试,在另一个任务中设置断点,设置的断点不起作用。这是因为一个调试器只能处理一个TCB(任务控制块),每个任务都有一个TCB,因此一个调试器只能调试一个任务,要调试几个任务就要启动几个调试器。另外,需要在被调试的任务的待调试的第一条语句前加入taskSuspend语句,挂起该任务,否则任务就可能会在调试前被执行。
下面是多任务调试的测试用例的源代码
/* 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");
/*start point of debugging for MultiTaskTestTaskA*/
taskSuspend(0);
for(;;)
{
printf(" Hello from MultiTaskTestTaskA \n");
/*Send message to MultiTaskTestTaskB*/
msgQSend(g_MsgQ1id,cMsgToTaskB,sizeof(cMsgToTaskB),WAIT_FOREVER, MSG_PRI_NORMAL);
/*Receive message from MultiTaskTestTaskB*/
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");
/*start point of debugging for MultiTaskTestTaskA*/
taskSuspend(0);
for(;;)
{
printf(" Hello from MultiTaskTestTaskB \n");
/*Send message to MultiTaskTestTaskA*/
msgQSend(g_MsgQ2id,cMsgToTaskA,sizeof(cMsgToTaskA),WAIT_FOREVER, MSG_PRI_NORMAL);
/*Receive message from MultiTaskTestTaskA*/
msgQReceive(g_MsgQ1id,cMsgFromTaskA,100,WAIT_FOREVER);
printf("%s",cMsgFromTaskA);
}
}
/*This function spawns MultiTaskTestTaskA and MultiTaskTestTaskB , creates g_MsgQ1id and g_MsgQ2id , is entry for debugging.*/
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);
}
多任务调试步骤:
用-g选项编译源代码产生目标文件
下载产生的目标文件
在MultiTaskTestInit函数的开始设置断点
把MultiTaskTestInit设置为调试任务的人口函数
单步执行产生MultiTaskTestTaskA任务的语句后可以在串口(超级终端)上看到字符串Hello from MultiTaskTestTaskA,用Browser查看任务,可以看到任务MultiTaskTestTaskA出于挂起态,表明程序执行了taskSuspend语句。
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的接收队列中。
9、系统调试模式下程序的调试
Tornado允许开发者增量式地加载目标模块到目标系统。动态链接和加载目标模块的能力作为Tornado结构的核心,使开发者避免了在宿主机上链接应用到内核,然后再下载整个可执行映像到一个静态环境的这样通常采用的步骤。这样,就大大地缩短了每个编辑—测试—调试的周期。
Tornado包括强大的开发和调试工具, 尤其适用于面对大量问题的嵌入式开发人员。这些工具包括C和C++远程源级调试器, 目标和工具管理, 系统目标跟踪, 内存使用分析和自动配置。
系统缺省使用网口通信,如果需要使用串口通信,需要修改文件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。
在启动目标服务器时,要选择串口通信,并进行相应配置。
9.1 系统调试模式下多任务的调试
去掉为了能够在任务调试模式下进行多任务调试的MultiTaskTestTaskA和MultiTaskTestTaskB中的语句taskSuspend。
多任务调试步骤:
用-g选项编译源代码产生目标文件。
下载产生的目标文件。
在MultiTaskTestInit函数的开始设置断点。
在Debugger命令窗口输入命令attach system进入系统调试模式。
在Shell窗口输入命令sp MultiTaskTestInit产生一个以MultiTaskTestInit为入口函数的任务,因为整个系统都停下了,新产生的任务还没有执行,这可以通过在Debugger命令窗口输入命令info threads显示当前系统中的任务列表看出来。
执行菜单命令Debug | Continue继续运行程序。
系统在设置的断点处停下。
在函数MultiTaskTestTaskA中的语句msgQReceive(g_MsgQ2id,cMsgFromTaskB, 100,WAIT_FOREVER)的下一条语句处设置断点。
执行菜单命令Debug | Continue继续运行程序。
程序在任务MultiTaskTestTaskB中的断点处停下。
执行菜单命令Debug | Continue继续运行程序。
程序在任务MultiTaskTestTaskA中的断点处停下。
执行菜单命令Debug | Continue继续运行程序。
程序又一次在任务MultiTaskTestTaskA中的断点处停下。
执行菜单命令Debug | Continue继续运行程序。
程序在任务MultiTaskTestTaskB中的断点处停下。
9.2 中断服务程序的调试
中断服务程序调试步骤:
用-g选项编译源代码产生目标文件。
下载产生的目标文件。
在MultiTaskTestInit函数的开始设置断点。
在Debugger命令窗口输入命令attach system进入系统调试模式。
执行菜单命令Debug | Continue继续运行程序。
如果产生相应的中断,程序就会在中断服务程序的断点处停下。进行需要的调试。
VxWorks具备一个高效的微内核。微内核支持实时系统的一系列特征包括多任务,中断支持,任务抢占式调度和循环调度,微内核设计使VxWorks缩减了系统开销并加速了对外部事件的反应。程序的设计,让主机更加方便,功能更加强大,新技术的诞生意味着科技发展又有了跨越性的进展,在市场上有了竞争的资本。