一段时间以来,很多学习eCos的朋友都在交流、探讨和咨询eCos的调试方法。为此,准备花一些时间来研究研究eCos的调试技术。eCos主要的调试工具为GDB,嵌入式linux开发也是基于该工具来调试。
之前曾粗略使用gdb连接redboot的方法(命令行方式)调试过eCos应用程序。所以本节就说说如何使用这种方法进行eCos应用程序的调试。
什么是GDB
GDB,GNU Debugger,是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。
eCos最初是由负责维护GNU工具链的几位工程师创作的,所以,eCos主要是采用GDB工具进行调试,包括eCosCentric公司开发的商业开发环境也是采用该工具为客户提供调试手段的。
一般情况下,类unix环境如linux、cygwin等都会提供GDB工具。下面将以cygwin环境为例进行介绍。
GDB安装
正常情况下,安装GCC编译器时,就包含了GDB工具的安装。比如,类unix环境一般都带有gcc编译工具,所以这时候gdb也同样安装好了。交叉编译器亦是如此。
GDB调试原理
GDB调试原理可参考这个链接提供的PPT文档:http://linux.chinaunix.net/salon/200712/files/gdb.ppt
由上图可知,GDB调试的组成架构主要由两部分组成,分别是调试机(host,即开发宿主机,运行GDB程序)和目标机(target,即我们的设备,运行GDB Server)。host与target之间通过网络或者串口进行通讯。
对于eCos,其redboot包含有GDB stub,可当作GDB Server用。因此,eCos调试的组成架构如下图所示。
gdb在cygwin中不能运行
在我的cygwin中,出现了GDB不能运行的情况,如果你的cygwin未出现此问题,可跳过本小节。
在cygwin中执行arm-eabi-gdb程序时,出现错误:bash: /opt/ecos/gnutools/arm-eabi/bin/arm-eabi-gdb: Bad address。
像这种问题,可以在windows DOS命令下尝试定位问题。在windows DOS中输入命令:
弹出如下图所示的错误框:
也就是说,cygwin中缺少cygexpat-1.dll库。在cygwin安装路径的bin目录中,确实未找到cygexpat-1.dll库文件。可以通过cygwin的安装程序来安装这个库文件,该库文件实际是Libs下的libexpat1,如下图所示:
当然,你可以直接下载该库,并把它放到cygwin安装路径的bin目录下,下载地址:http://velep.com/downloads?did=11
调试前准备
在调试前,需要准备好以ROM启动的redboot镜像文件,并把它烧写到flash中。 然后准备好以RAM启动的eCos应用程序。关于这两方面工作,请参考我写的关于stm32移植ecos 相关文章。
调试步骤
1. 上电启动redboot,进入redboot命令行,如下图所示:
2. 在cygwin中启动gdb调试,下面贴出调试记录,红色文字为调试操作,后面以中文进行注释。
Administrator@MICROSOF-6F30AF /cygdrive/e/workspace/proj_ecos/src/test_stm32/Debug
$ arm-eabi-gdb test_stm32.elf
GNU gdb (eCos GNU Tools 4.6.3-20120623) 7.4.1
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type “show copying”
and “show warranty” for details.
This GDB was configured as “–host=i686-pc-cygwin –target=arm-eabi”.
For bug reporting instructions, please see:
<http://bugs.ecos.sourceware.org/>…
Reading symbols from /cygdrive/e/workspace/proj_ecos/src/test_stm32/Debug/test_s tm32.elf…done.
(gdb) target remote 192.168.0.24:9000
Remote debugging using 192.168.0.24:9000
0x080073fa in ?? ()
(gdb) load
Loading section .sram, size 0xc10 lma 0x20000400
Loading section .rom_vectors, size 0x8 lma 0x68008000
Loading section .ARM.exidx, size 0x8 lma 0x68008008
Loading section .text, size 0x138d8 lma 0x68008010
Loading section .rodata, size 0x990 lma 0x6801b8e8
Loading section .data, size 0x1328 lma 0x6801c280
Start address 0x68008011, load size 90544
Transfer rate: 54 KB/sec, 299 bytes/write.
(gdb) list
83 main( int argc, char *argv[] ) __attribute__((weak));
84
85 externC void
86 cyg_user_start(void);
87
88 // FUNCTIONS
89
90 externC int
91 main( int argc, char *argv[] )
92 {
(gdb) next
reset_vector ()
at /cygdrive/e/workspace/proj_ecos/src/ecos/packages/hal/cortexm/arch/current/src/vectors.S:108
108 b hal_reset_vsr
(gdb) c
Continuing.
LCD ID : 21536 (0x5420)
70-01-01 09:12:32 T1 cyg_user_start 50 Info :\> ..test hello…
70-01-01 09:12:32 T1 cyg_user_start 54 Debug:\> 12345656777DFAFD
其中,
$ arm-eabi-gdb test_stm32.elf:以命令形式启动gdb调试,调试时必须使用elf格式映像文件。其中,$表示unix环境的命令提示符。
(gdb) target remote 192.168.0.24:9000:表示连接目标设备,这里采用的是网络连接(需指定redboot中设定的设备IP地址和GDB连接端口号,使用redboot的ip命令设定设备的IP,使用fconfig命令设定GDB连接端口号,即GDB connection port)。如果是用串口,这条命令为:target remote /dev/ttyS26,其中,/dev/ttyS26指串口设备。注意:(gdb)表示gdb的命令提示符,以下同。
(gdb) load:把elf格式镜像文件通过网络或串口下载到RAM中。
(gdb) list
(gdb) next
(gdb) c
以上这三条都是具体的GDB指令。在GDB中,提供了很多指令来完成软件的调试。如上面的next表示执行下一行语句等。
常用的gdb命令
backtrace 显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where)
breakpoint 在程序中设置一个断点
cd 改变当前工作目录
clear 删除刚才停止处的断点
commands 命中断点时,列出将要执行的命令
continue 从断点开始继续执行
delete 删除一个断点或监测点;也可与其他命令一起使用
display 程序停止时显示变量和表达时
down 下移栈帧,使得另一个函数成为当前函数
frame 选择下一条continue命令的帧
info 显示与该程序有关的各种信息
jump 在源程序中的另一点开始运行
kill 异常终止在gdb 控制下运行的程序
list 列出相应于正在执行的程序的原文件内容
next 执行下一个源程序行,从而执行其整体中的一个函数
print 显示变量或表达式的值
pwd 显示当前工作目录
pype 显示一个数据结构(如一个结构或C++类)的内容
quit 退出gdb
reverse-search 在源文件中反向搜索正规表达式
run 执行该程序
search 在源文件中搜索正规表达式
set variable 给变量赋值
signal 将一个信号发送到正在运行的进程
step 执行下一个源程序行,必要时进入下一个函数
undisplay display命令的反命令,不要显示表达式
until 结束当前循环
up 上移栈帧,使另一函数成为当前函数
watch 在程序中设置一个监测点(即数据断点)
whatis 显示变量或函数类型
适用人员
本文所介绍的方法适用于那些对GDB指令比较熟悉或者感兴趣的人使用 。可能有的朋友比较喜欢图形界面,对于这种指令形式的调试方式可能难以接受。没关系,在eclipse中提供了图形方式的调试方法。