一,安装前准备
1,软件安装平台:CentOS 5.5
2,开发板硬件环境:Mini2440
3,下载最新版http://www.linuxidc.net/thread-2217-1-1.html,当前版本Openocd-0.4.0
安装时参考文章http://www.linuxidc.com/Linux/2011-05/35966.htm
这里http://www.linuxidc.com/Linux/2011-05/35967.htm说,很重要的一步是安装libusb工具。不安装,编译openocd 时会提示找不到usb.h文件,该文件即为libusb工具的头文件。该工具可在sourceforge上找到。但是我在安装之前没有安装这个libusb库,也没发现有报错问题,这可能与具体的系统软件环境有关。
二,安装过程(安装时还要注意参考OpenOCD Manual)
1,解压当前目录下
[root@localhost ~]# unzip /smbroot/openocd-0.4.0.zip
3,进入openocd目录
[[root@localhost ~]# cd openocd-0.4.0
[root@localhost openocd-0.4.0]#
[root@localhost openocd-0.4.0]# ls
aclocal.m4 config.guess configure.in doc ltmain.sh NEWS TODO
AUTHORS config.h.in contrib Doxyfile.in Makefile.am README tools
ChangeLog config.sub COPYING INSTALL Makefile.in src
compile configure depcomp install-sh missing tcl
[root@localhost openocd-0.4.0]#
4,执行 configure 配置命令
在执行配置命令之前,先了解下相关配置选项的作用。
有关configure 配置参数可参考http://www.linuxidc.com/Linux/2011-05/35968.htm
–prefix=PREFIX 用来指定安装位置,默认是安装在/usr/local/下
–enable-FEATURE用来启用被禁用的特性,FEATURE是特性的名字
root@localhost openocd-0.4.0]# ./configure –enable-jlink
checking for a BSD-compatible install… /usr/bin/install -c
checking whether build environment is sane… yes
…… ……
config.status: executing depfiles commands
config.status: executing libtool commands
[root@localhost openocd-0.4.0]#
5,然后执行make 编译和make install安装
[root@localhost openocd-0.4.0]# make
…… ……
[root@localhost openocd-0.4.0]# make install
…… ……
make install-data-hook
make[3]: Entering directory `/root/openocd-0.4.0′
for i in $(find ./tcl -name ‘*.cfg’ -o -name ‘*.tcl’ | sed -e ‘s,^./tcl,,’); do \
j=”/usr/local/share/openocd/scripts/$i” && \
mkdir -p “$(dirname $j)” && \
/usr/bin/install -c -m 644 ./tcl/$i $j; \
done
make[3]: Leaving directory `/root/openocd-0.4.0′
make[2]: Leaving directory `/root/openocd-0.4.0′
make[1]: Leaving directory `/root/openocd-0.4.0′
[root@localhost openocd-0.4.0]#
6,查看安装结果,
[root@localhost openocd-0.4.0]# openocd -v
Open On-Chip Debugger 0.4.0 (2011-03-28-11:40)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.berlios.de/doc/doxygen/bugs.html
[root@localhost openocd-0.4.0]#
清除安装时产生的中间文件
[root@localhost openocd-0.4.0]# make distclean
Making distclean in doc
….. ……
rm -f Makefile
[root@localhost openocd-0.4.0]#
三,调试测试
四,在Eclipse IDE中编译并连接上openocd 调试(注意不要关闭openocd 运行的终端)
1,在启动OpenOCD连接JLink之前需要进行配置,可以用OpenOCD的帮助命令看有那些命令可以用来和OpenOCD进行交互操作,当然需要看下OpenOCD Manual来了解这些命令怎么使用。
[root@localhost ~]# openocd –h
Open On-Chip Debugger 0.4.0 (2011-03-28-11:40)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.berlios.de/doc/doxygen/bugs.html
Open On-Chip Debugger
Licensed under GNU GPL v2
–help | -h display this help
–version | -v display OpenOCD version
–file | -f use configuration file <name>
–search | -s dir to search for config files and scripts
–debug | -d set debug level <0-3>
–log_output | -l redirect log output to file <name>
–command | -c run <command>
–pipe | -p use pipes for gdb communication
[root@localhost ~]#
2,进入到Leds工程目录下,用vi命令新建一个配置openocd.cfg
[root@localhost Leds]# vi openocd.cfg
然后将以下内容粘贴其中
#The configuration script can be divided in the following 5 sections:
#————————————————————————-
#No.1 the interface configuration
#————————————————————————-
interface jlink
#————————————————————————-
#No.2 daemon configuration
#————————————————————————
#The default telnet port setup
#—————————————————————-
telnet_port 4444
#—————————————————————-
#The default tcl port setup
#—————————————————————-
#tcl_port 6666
#—————————————————————-
#GDB setup
#—————————————————————-
gdb_port 2331
#—————————————————————-
#gdb breakpoint override <hard|soft|disabled>
#Note that GDB will use hardware breakpoints
#if the memory map has been set up for flash regions.
#—————————————————————-
#gdb_breakpoint_override hard
#—————————————————————-
#gdb memory map <enable|disable>
#enable when to set hardware breakpoints, and program flash
#using the gdb load command,enable is default.
#—————————————————————-
#gdb_memory_map enable
#gdb_flash_program enable
#————————————————————————-
#No.3 target configuration
#————————————————————————-
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME s3c2440
}
if { [info exists ENDIAN] } {
set _ENDIAN $ENDIAN
} else {
# this defaults to a bigendian
set _ENDIAN little
}
if { [info exists CPUTAPID ] } {
set _CPUTAPID $CPUTAPID
} else {
# force an error till we get a good number
set _CPUTAPID 0x0032409d
}
#————————————————————————-
#No.4 jtag scan chain
#————————————————————————-
#In order for OpenOCD to control a target, a JTAG tap must be defined
#/created.
#jtag newtap CHIPNAME TAPNAME configparams ….
#Required configparams
# -irlen NUMBER – the length in bits of the instruction register
# -ircapture NUMBER – the ID code capture command.
# -irmask NUMBER – the corresponding mask for the ir register.
#Optional configparams
#-expected-id NUMBER By default it is zero. If non-zero represents the
#expected tap ID used when the Jtag Chain is examined. See below.
# -disable
# -enable By default not specified the tap is enabled.
#newtap is a sub command of the “jtag” command.
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0x0f -expected-id $_CPUTAPID
target create mini2440 arm920t -endian $_ENDIAN -chain-position $_CHIPNAME.cpu -variant arm920t
mini2440 configure -work-area-virt 0 -work-area-phys 0x200000 -work-area-size 0x4000 -work-area-backup 1
#————————————————
# ARM SPECIFIC
#————————————————
targets
#arm7_9 dcc_downloads enable
#arm7_9 fast_memory_access enable
#arm7_9 dbgrq enable
#—————————————————————-
# JTAG ADAPTER SPECIFIC
#—————————————————————-
#To set the JTAG frequency(khz)
jtag interface
jtag_khz 12000
#————————————————————————-
#No.5 flash configuration
#————————————————————————-
#fash bank cfi <base> <size> <chip width> <bus width> <target#>
#[jedec_probe|x16 as x8]
#chip width and bus width are specified in bytes.
# 1MBx16 NOR Flash
#flash bank cfi 0x40000000 0x200000 2 2 mini2440 #jedec_probe
# NAND flash
#nand device s3c2440 mini2440
#—————————————————————-
#reset configuration
#—————————————————————-
#How long (in milliseconds) OpenOCD should wait after deasserting nSRST
#before starting new JTAG operations.
#—————————————————————-
jtag_nsrst_delay 100
#—————————————————————-
#it are useful if reset circuitry (like a big resistor/capacitor,reset
#supervisor, or on-chip features). This keeps the signal asserted for
#some time after the external reset got deasserted.
#—————————————————————-
jtag_ntrst_delay 100
#—————————————————————–
#reset_config <signals> [combination] [trst type] [srst type]
#[combination] is an optional value specifying broken reset signal.
#The default behaviour if no option given is `separate’.
#The [trst type] and [srst type] parameters allow the driver type of
#the reset lines to be specified. Possible values are `trst_push_pull’
# (default) and `trst_open_drain’ for the test reset signal, and
#`srst_open_drain’ (default) and `srst_push_pull’ for the system reset.
#—————————————————————–
reset_config trst_and_srst
保存并退出,有关openocd脚本编写可以参考
/usr/local/share/openocd/scripts/board 和usr/local/share/openocd/scripts/target相关内容
3,确保j-link正确连到了CentOS
启动openocd服务
在启动时最好测试一下,有时会出现如下情形
[root@localhost Leds]# JLinkExe
SEGGER J-Link Commander V4.22 (‘?’ for help)
Compiled Dec 17 2010 17:41:09
Can not connect to J-Link via USB.
J-Link>
如果上面链接不上的情形,就先断开和CentOS的连接,并在windows下启动J-Link Commander,如下图所示
可以看到连接成功,这时再重新断开windows连到CentOS,然后执行usb连接命令
J-Link>usb
Connecting to J-Link via USB (Port: 0)
DLL version V4.22, compiled Dec 17 2010 17:41:06
Firmware: J-Link ARM V8 compiled Dec 1 2015 11:42:48
Hardware: V8.00
S/N: 20080643
Feature(s): RDI,FlashDL,FlashBP,JFlash,GDBFull
VTarget = 3.254V
Info: TotalIRLen = 4, IRPrint = 0x01
Info: CP15.0.0: 0x41129200: ARM, Architecure 4T
Info: CP15.0.1: 0x0D172172: ICache: 16kB (64*8*32), DCache: 16kB (64*8*32)
Info: Cache type: Separate, Write-back, Format A
Found 1 JTAG device, Total IRLen = 4:
#0 Id: 0x0032409D, IRLen: 04, Unknown device
Found ARM with core Id 0x0032409D (ARM9)
JTAG speed: 100 kHz
J-Link>
4,启动openocd服务
[root@localhost Leds]# openocd
Open On-Chip Debugger 0.4.0 (2011-03-28-11:40)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.berlios.de/doc/doxygen/bugs.html
force hard breakpoints
trst_and_srst separate srst_gates_jtag trst_push_pull srst_open_drain
12000 kHz
jtag_nsrst_delay: 100
jtag_ntrst_delay: 100
trst_and_srst separate srst_gates_jtag trst_push_pull srst_open_drain
Info : J-Link initialization started / target CPU reset initiated
Info : J-Link ARM V8 compiled Dec 1 2015 11:42:48
Info : JLink caps 0xb9ff7bbf
Info : JLink hw version 80000
Info : JLink max mem block 9576
Info : Vref = 3.254 TCK = 1 TDI = 0 TDO = 1 TMS = 0 SRST = 1 TRST = 0
Info : J-Link JTAG Interface ready
Info : clock speed 12000 kHz
Info : JTAG tap: s3c2440.cpu tap/device found: 0x0032409d (mfg: 0x04e, part: 0x0324, ver: 0x0)
Info : Embedded ICE version 2
Info : s3c2440.cpu: hardware has 2 breakpoint/watchpoint units
5,在另一个终端中启动调试程序
在终端的命令行调试程序有两种调试方式:
A,直接调用openocd调试命令进行调试
【1】openocd常用命令
<1>连接命令
telnet ip port :ip表示远程或本地主机(如localhost),port表示端口号,即配置脚本中telnet_port指定端口号。
<2>目标板状态处理命令(Target state handling)
poll :查询目标板当前状态。
halt :中断目标板的运行。
resume [address] :恢复目标板的运行,如果指定了address,则从address 处开始运行。
step [address] :单步执行,如果指定了address,则从address 处开始执行一条指令。
reset :复位目标板。
<3>断点命令
bp <addr> <length> [hw] :在地址addr 处设置断点,指令长度为length,hw 表示硬件断点。
rbp <addr> :删除地址addr 处的断点。
<4>内存访问指令(Memory access commands)
mdw [‘phys’] <addr> [count] :显示从(物理)地址addr 开始的count(缺省是1)个字(4 字节)。
mdh [‘phys’] <addr> [count] :显示从(物理)地址addr 开始的count(缺省是1)个半字(2 字节)。
mdb [‘phys’] <addr> [count] :显示从(物理)地址addr 开始的count(缺省是1)个字节。
mww [‘phys’] <addr> <value> :向(物理)地址addr 写入一个字,值为value。
mwh [‘phys’] <addr> <value> :向(物理)地址addr 写入一个半字,值为value。
mwb [‘phys’] <addr> <value> :向(物理)地址addr 写入一个字节,值为value。
load_image <file> <address> [‘bin’|‘ihex’|‘elf’] :
将文件<file>载入地址为address 的内存,格式有‘bin’、‘ihex’、‘elf’。
dump_image <file> <address> <size> :
将内存从地址address 开始的size 字节数据读出,保存到文件<file>中。
verify_image <file> <address> [‘bin’|‘ihex’|‘elf’]:
将文件<file>与内存address 开始的数据进行比较,格式有‘bin’、‘ihex’、‘elf’。
<5>CPU 架构相关命令(Architecture Specific Commands)
reg: 打印寄存器的值。
arm7_9 fast_memory_access [‘enable’|’disable’] :使能或禁止“快速的内存访问”。
arm mcr cpnum op1 CRn op2 CRm value :修改协处理器的寄存器,比如:arm mcr 15 0 1 0 0 0 关闭MMU。
arm mrc cpnum op1 CRn op2 CRm:读出协处理器的寄存器,比如:arm mcr 15 0 1 0 0读出cp15协处理器的寄存器1。
arm920t cp15 regnum [value] :修改或读取cp15 协处理器的寄存器,比如arm920t cp15 2 0 关闭MMU。
virt2phys virtual_address: 获得虚拟地址对应的物理地址。
<6>其他命令
script <file> :执行file 文件中的命令。
【2】启动openocd调试器
[root@localhost ~]# telnet localhost 4444
Trying 127.0.0.1…
Connected to localhost.localdomain (127.0.0.1).
Escape character is ‘^]’.
Open On-Chip Debugger
>
【3】命令测试
> poll
background polling: on
TAP: s3c2440.cpu (enabled)
target state: running
> halt
target state: halted
target halted in ARM state due to debug-request, current mode: System
cpsr: 0x6000005f pc: 0x33f08f7c
MMU: enabled, D-Cache: enabled, I-Cache: enabled
> arm920t cp15 2 0
2: 00000000
> step
target state: halted
target halted in ARM state due to single-step, current mode: System
cpsr: 0x6000005f pc: 0x33f08f80
MMU: disabled, D-Cache: disabled, I-Cache: disabled
【4】加载测试文件
> load_image leds_elf
360 bytes written at address 0x30000000
downloaded 360 bytes in 0.092932s (3.783 kb/s)
>
【5】恢复运行
> resume
这时可以看到mini2440上led在闪烁
【6】暂停后退出调试
> halt
target state: halted
target halted in ARM state due to debug-request, current mode: System
cpsr: 0x6000005f pc: 0x33f08f58
MMU: disabled, D-Cache: disabled, I-Cache: disabled
> exit
Connection closed by foreign host.
[root@localhost ~]#
B,在新打开的终端中用GDB中用dgb端口进行连接
【1】GDB常用命令
<1>启动/退出
gdb [FILE] 或xxx-xxxx-xxxx-xxxx-gdb [FILE]:x表示前缀字符,启动gdb,调试FILE(也可以先不指定文件)。
quit 退出gdb。
<2>连接操作
target remote ip:port :远程连接,ip表示主机IP地址或主机名(如localhost),port表示端口号,即配置脚本中gdb_port指定端口号。
<3>文件操作
file <FILE> :载入文件FILE,注意:不会下载到目标板上。
load [FILE] :把文件下载到目标板上,如果不指定FILE,则下载之前指定过的(比如file 命令指定的,或是gdb 运行时指定的文件)。
<4>查看源程序
list <FUNCTION>: 列出某个函数FUNCTION。
list <LINENUM> :以当前源文件的某行LINENUM为中间显示一段源程序。
list 接着前一次继续显示。
break *<address> :在某个地址上设置断点,比如 break *0x84。
list – :显示前一次之前的源程序。
list <FILENAME:FUNCTION>或list <FILENAME:LINENUM>:显示指定文件的一段程序。
info source: 查看当前源程序。
info stack :查看堆栈信息。
info args: 查看当前的参数。
<5>断点操作
break <FUNCTION> :在函数入口设置断点。
break <LINENUM> :在当前源文件的某一行上设置断点。
break <FILENAME:LINENUM> :在指定源文件的某一行上设置断点。
info br :查看断点。
delete <number>: 删除断点。
diable <number>: 禁止断点。
enable <number> :使能断点。
<6>监视点(watch)操作
watch <EXPRESSION> :当指定变量被写时,程序被停止。
rwatch <EXPRESSION> :当指定变量被读时,程序被停止。
<7>数据操作
print < EXPRESSION > :查看数据。
set varible=value :设置变量。
x /NFU ADDR: 检查内存值。
① N 代表重复数
② F 代表输出格式
x :16 进制整数格式
d :有符号十进制整数格式
u :无符号十进制整数格式
f :浮点数格式
③ U 代表输出格式:
b :字节(byte)
h :双字节数值
w :四字节数值
g :八字节数值
比如“x /4ub 0x0”将会显示0 地址开始到4 个字节。
<8>执行程序
step :单步执行,会跟踪进入一个函数。
next :单步执行,指令则不会进入函数。
nexti :单步执行,执行一条汇编指令。
continue 继续执行程序,加载程序后也可以用来启动程序
<9>帮助
help [command] :列出帮助信息,或是列出某个命令的帮助信息。
<10>其他命令
monitor <command …> :调用gdb 服务器软件的命令,比如:“monitor mdw 0x0”就是调用openocd 本身的命令
“mdw 0x0”。
【2】 启动调试程序
[root@localhost ~]# arm-none-eabi-gdb
GNU gdb (Sourcery G++ Lite 2010.09-51) 7.2.50.20100908-cvs
Copyright (C) 2010 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-linux-gnu –target=arm-none-eabi”.
For bug reporting instructions, please see:
<https://support.codesourcery.com/GNUToolchain/>.
(gdb)
【3】建立gdb和openocd之间的连接
(gdb) target remote localhost:2331
Remote debugging using localhost:2331
0x33f08f58 in ?? ()
(gdb)
【4】停止开发板上其它可能运行的程序
(gdb) monitor halt
target state: halted
target halted in ARM state due to debug-request, current mode: System
cpsr: 0x6000005f pc: 0x33f08f7c
MMU: enabled, D-Cache: enabled, I-Cache: enabled
(gdb)
【5】禁止MMU
(gdb) monitor arm920t cp15 2 0
2: 00000000
(gdb) monitor step
target state: halted
target halted in ARM state due to single-step, current mode: System
cpsr: 0x6000005f pc: 0x33f08f80
MMU: disabled, D-Cache: disabled, I-Cache: disabled
(gdb)
【6】下载elf镜像文件
(gdb) load leds_elf
Loading section .text, size 0x168 lma 0x30000000
Start address 0x30000000, load size 360
Transfer rate: 4 KB/sec, 360 bytes/write.
(gdb)
【7】进入开始执行调试
<1>设置断点(break point)
(gdb) b main
Breakpoint 1 at 0x300000c8: file leds.c, line 19.
(gdb)
<2>单步运行(next)
(gdb) n
20 rGPBUP = 0x7ff;
<3>退出调试(quit命令)
(gdb) q
A debugging session is active.
Inferior 1 [Remote target] will be killed.
Quit anyway? (y or n) y
[root@localhost Leds]#
至此在命令行执行调试成功。
在Eclipse IDE中编译并连接上J-Link GDB Server 调试(注意不要关闭JLinkGDBServer运行的终端)
有两种方法可以实现:
第一种方法:通过ZylinCDT嵌入式调试插件
1,安装嵌入式调试插件ZylinCDT。ZylinCDT是一个非常优秀的交叉调试插件,操作简单,具体操作步骤:
首先确认你的操作系统可以上网(实际的、虚拟机里的都一样);
然后在Eclipse的菜单里选择Help->Software Updates;选择Available Software选项卡,点Add Site按钮;
输入地址http://www.zylin.com/zylincdt,列表里就多了一项;刷新之后点上面的Install按钮安装。
2,在Eclipse环境下导入现有的工程Leds.rar
执行Eclipse->File->New->Makefile Project with Existing Code,在Existing Code Location 栏点击Browse按钮,定位到现有的工程Leds,然后在Toolchain for Indexer Settings栏的列表框中选中ARM Linux GCC(Sourcery G++ Lite),如下图所示,点击Finish关闭对话框。
3,修改Makefile以使用现有的arm-none-eabi-gcc编译器
将文件中的arm-elf-替换为arm-none-eabi-,并用赋给变量CROSS=arm-none-eabi-,如下图所示。然后按Ctrl+B编译。
4,点击Run->Debug Configurations,如图,在左侧列表项中的Zylin Embedded debug(Native)上双击,在右侧的Name栏保留默认的debug configuration名称,在Main选项页的Project(optional)栏右侧点击Browse按钮定位到Leds工程所在的工程目录。
5,在Debugger选项页的Debugger Options栏的Main选项页上,在GDB debugger栏输入arm-none-eabi-gdb,然后将GDB command file栏的内容清空。如下图所示
6, 在Commands选项页的’Initialize’ commands栏内,如下图所示,将下列内容粘贴进去:
target remote localhost:2331
monitor halt
monitor arm920t cp15 2 0
monitor step
load
b main
点击Apply按钮,然后点击Close关闭对话框。
7,配置外部工具,目的是能在Eclipse中启动openocd服务
执行Run->External Tools->External Tools Configurations…,打开如下图所示对话框,在左侧列表Program上双击,然后在右侧Name栏输入OpenOCD,在Location 栏按图示定位到openocd命令所在位置,在Working Directory 栏定位到当前工作目录,在Arguments栏输入openocd命令启动参数,这里不带参数,该命令则会按默认在当前工作目录下查找openocd.cfg文件。
设置完成后,切换到build选项页,去掉勾选的Build before launch选项。设置完成后,点击Apply按钮,然后点击Run按钮启动openocd服务。
8,开始调试
按下F11或执行Run->Debug命令,启动Debug程序,可以看到主界面底部的Console控制台显示初始化文件正在执行的过程。最后停在main函数中设定的断点处。
按下F8可以跳到设置的main断点处。
按下F5或者F6可以单步执行。按下Ctrl+F2或者Run->Terminate终止调试。