一、前言
对于单片机的开发,我们离不开仿真器(烧录器)的使用,平常我们都是图形界面下操作,而本文主要介绍命令窗口下的仿真器驱动安装与使用。目前的 DSP、FPGA、ARM、部分单片机等主流芯片均支持 JTAG 协议,也就是说绝大部分仿真器都是 JTAG 接口。JTAG(Joint Test Action Group 联合测试行动小组)作为一项国际标准测试协议(IEEE 1149.1 兼容),主要用于芯片内部测试和调试。SWD(Serial Wire Debug 串行线调试)是 ARM 设计的协议,用于对其微控制器进行编程和调试。支持 JTAG 接口必定支持 SWD,而且 SWD 使用引脚更少、速度更快、稳定性更好、且支持打印调试信息!
二、安装
1、j-link 应用驱动安装
待续……
2、st-link 应用驱动安装
官方开源驱动、ST-Link 的安装教程
待续……
3、OpenOCD 应用驱动安装
OpenOCD(Open On-Chip Debugger)是一个开源的 JTAG 上位机调试程序,支持驱动 st-link、j-link 等多种主流的调试器,支持 ARM7、ARM9、ARM10、ARM11 和 Cortex(如:STM32F103) 等多种内核处理器。听说它是一位国外研究生在上学时构思与完成的软件,更多介绍可到【开源中国】看看。OpenOCD 以提供源码方式来编译及安装,所以事先需要安装 make、gcc 工具!关于 OpenOCD 下载,进入【代码仓库站点】,点击里面的 Download 按钮下载 【openocd-0.11.0.zip】 压缩包。如果你没编译条件,也可直接【下载】第三方编译好的软件,解压后配置环境变量即可(执行文件所在目录,如:openocd-0.11.0-5/bin/)。特别说明:由于 OpenOCD 是上位机软件(是仿真器与调试软件之间的连接器),压根不能驱动仿真器,所以事先需要安装 USB 硬件驱动程序 【libusb】!资料:官网、官方手册。扩展:【openOCD RISC-V 版】为 RISC-V 处理器专用版,具体参考【网文】;【OpenOCD for Windows】为已编译好的 Windows 版,直接复制到对应目录并加入环境变量即可使用!
3.1、linux 系统下安装:
1
2
3
4
5
6
7
8
9
10
|
unzip -q openocd-0.11.0.zip # 解压zip压缩包
cd openocd-0.11.0/ # 进入刚才解压出的文件夹
sudo apt-get install libusb-1.0-0-dev # 安装依赖Libusb库(./configure时会检查libusb组件,找不到会显示:- USB .... no)
./configure # 进行自动默认配置(在最后可以看到支持的调试器类型以及是否已打开)
# ./configure --enable-jlink # 如果你使用调试器是J-Link,但默认配置里它没被打开,运行本行命令!
# ./configure -h # 当你的是其它调试器,运行帮助命令查看具体是哪条选项来打开调试器。
make # 编译OpenOCD软件(OpenOCD可以使用gcc和clang两个编译器进行编译)
sudo make install # 安装OpenOCD软件(默认安装到 /usr/local/share/openocd/)
openocd -v # 查看OpenOCD版本(用于验证是否安装成功,当前版本为:0.11.0)
|
3.2、安装不正确出现的问题:
3.2.1、libusb 组件的安装问题
3.2.2、烧录固件提示找不到驱动
4、libusb USB 低层硬件驱动介绍
libusb 是一个由 C 语言开发的开源库,可帮助开发者在应用层面上直接与 USB 硬件进行通讯,它属于通用的 USB 硬件驱动库,可跨平台移植。安装 libusb 的目的,其实就是因为 OpenOCD 只把 J-link 等仿真器当作普通的 USB 设备来使用,不使用 J-link 自带的仿真器驱动程序。注意:由于 libusb 操作需要 ROOT 权限,需要手工配置普通用户拥有读写权限!资料:libusb 新官网、libusb 旧官网、libusb Windows 版、libusb sourceforge 下载、libusb github 下载。
4.1、linux 系统下的编译安装:
1
2
3
4
5
6
|
tar -xjvf libusb-1.0.26.tar.bz2 # 解压压缩包
cd libusb-1.0.26 # 进入刚才解压出的文件夹
./configure --build=x86_64-linux --disable-udev # 进行基本配置(Windows系统选项参数貌似为:--build=mingw32)
# ./configure -h # 可查看一些选项参数内容
make # 编译libusb软件
sudo make install # 安装libusb软件(默认安装到 /usr/local/lib/)
|
4.2、Windows 系统下的安装工具:
在 Windows 系统下,我们把 j-link 原厂驱动转换成 openocd 可以识别的 Libusb-WinUSB 驱动之后,j-flash、j-Men 等软件就无法使用了,也无法在 Keil 中使用 j-link 烧录和调试程序。如果想使用这些工具,就必须把驱动还原回去,这时候 USBDriverTool 软件就派上用场了。在 USBDriverTool 软件界面上操作如下:
a)先插好 j-link 然后在 j-link 设备上单击右键;
b)转换:选择Install Libusb-WinUSB
即可完成驱动的转换。
c)恢复:选择Restore default driver
即可恢复原驱动。
补充:关于【USBDriverTool】与【Zadig】两款驱动工具,可以阅读【解决 openocd 无法识别 jlink 问题】的博文介绍。
4.3、linux 系统下的 root 权限操作:
在 linux 系统下操作 USB 设备,必须需要 root 权限,由于 OpenOCD 需要调用 libusb 驱动库来操作 USB 设备,所以在后面介绍的openocd
命令前面都加入sudo
的权限操作!每次手工输入openocd
前增加sudo
还无所谓,但在自动脚本执行就不允许加sudo
了,要事前设置当前用户拥有指定 USB 设备的操作权限。因为【st-link 官方开源驱动】与【OpenOCD】都是使用 libusb 来驱动 USB 设备,所以它们的设置方法是一样的。如果是使用 st-link,直接使用 stlink 开源代码中 stlink/config/udev/rules.d/
目录下对应的配置文件(如:49-stlinkv1.rules
);如果使用 j-link 则参照 ST 改写为另一个配置文件50-jlink.rules
即可。具体如下:
● 第一步:创建权限配置文件,其内容如下:
1
2
3
4
5
6
7
8
9
10
11
|
# SEGGER J-Link PLUS
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", \
MODE:="0666", \
SYMLINK+="J-Link"
#【注释说明】
# idVendor: 可以在命令窗口输入 lsusb -vv 列出所有 USB 设备信息中找出 J-Link 对应的 ID 值。
# idProduct: 可以在命令窗口输入 lsusb -vv 列出所有 USB 设备信息中找出 J-Link 对应的 ID 值。
# MODE: 应该是操作限权(例如"0666"应该是"可读+可写")
# SYMLINK: 给 J-Link 这个设备取一个别名。
|
● 第二步:将配置文件加入系统,操作如下:
1
2
3
4
5
6
7
|
#####[加入配置文件]#####
sudo cp 49-stlinkv* /etc/udev/rules.d/ # 将st-link所有的权限配置文件复制到linux系统(目录:stlink/config/udev/rules.d/)
sudo cp 50-jlink.rules /etc/udev/rules.d/ # 将刚制作的j-link权限配置文件复制到linux系统
#####[生效配置文件]##### (备注:也可以重启电脑实现)
sudo udevadm control --reload-rules # 重新加载所有权限配置文件(加载规则)
sudo udevadm trigger # 接收内核发送来的设备事件(使能规则)
|
三、使用
1、使用 OpenOCD 软件下载固件
1.1、介绍:openocd 命令行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# openocd命令行格式:
openocd -f <下载器配置文件> -f <目标芯片配置文件> -c <执行命令>
# 下载固件实用指令:
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c init -c "reset halt; wait_halt; flash write_image erase out/project.hex" -c reset -c shutdown
# 相关参数补充说明:
-f interface/stlink.cfg #下载器配置文件,表示使用stlink烧录器 (配置文件完整路径:/usr/local/share/openocd/scripts/interface/stlink.cfg)
-f target/stm32f1x.cfg #目标芯片配置文件,表示烧录stm32f1x单片机(配置文件完整路径:/usr/local/share/openocd/scripts/target/stm32f1x.cfg)
-c init #表示烧录前初始处理器(补充说明:-c init -c halt 是很多博文给出的参数,但应用中出现第一次成功第二次失败的现象,估计 -c halt 有时失效,改为下一行加相关参数)
-c "reset halt; wait_halt; flash write_image erase out/project.hex" #表示烧录前先复位并暂停处理器,再对flash擦除并写入十六进制文件。如果是二进制文件,其后面空格后加入地址,如: 0x08000000
-c reset #表示烧录后复位处理器
-c shutdown #表示烧录后退出openocd
|
1.2、准备:烧录器配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#######################################################
# 由于我使用的是 jlink 仿真器,并且接口为 SWD,所以要将
# /usr/local/share/openocd/scripts/interface/jlink.cfg
# 配置脚本另存为:jlink_swd.cfg,并在其里面增加两项参数:
# 1、接口改为:SWD
# 2、速度改为:20000KHz
#######################################################
#
# SEGGER J-Link
#
# http://www.segger.com/jlink.html
#
adapter driver jlink
# add swd config (1、接口改为:SWD)
transport select swd
# add speed(KHz) config(2、速度改为:20000KHz)
adapter speed 20000
# The serial number can be used to select a specific device in case more than
# one is connected to the host.
#
# Example: Select J-Link with serial number 123456789
#
# jlink serial 123456789
|
1.3、烧录:固件烧录操作
1.3.1、第一步:
1.3.2、第二步:
1
2
3
4
5
6
7
|
#######################################################
# 由于我使用的是 jlink 仿真器,并且接口为 SWD,单片机为
# STM32F103RC,烧录文件为十六进制文件,文件所在相对路径
# 为 out/project.hex,则直接运行下面命令烧录固件:
#######################################################
sudo openocd -f interface/jlink_swd.cfg -f target/stm32f1x.cfg -c init -c "reset halt; wait_halt; flash write_image erase out/project.hex" -c reset -c shutdown
|
1.3.3、最终结果:
2、使用 OpenOCD 软件仿真程序
2.1、第一步:查看 arm-none-eabi-gdb 版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 查看版本,用于验证其是否可正常工作
arm-none-eabi-gdb --version # CGDB(v0.8.0)要求 gdb 版本≥7.12
##############################################
# 出现问题:提示信息显示找不到 libncurses.so.5
##############################################
arm-none-eabi-gdb: error while loading shared
libraries: libncurses.so.5: cannot open shared
object file: No such file or directory
##############################################
# 解决方法:安装所需32位依赖库 lib32ncurses5 !
##############################################
sudo apt-get install lib32ncurses5
|
备注-1:启动 gdb 对 C/C++ 程序的调试,必须要在编译前就加上 -g 选项!
备注-2:CGDB(v0.8.0)要调用 arm-none-eabi-gdb,要求 gdb 的版本必须大于等于 7.12
2.2、第二步:在命令窗口启动 OpenOCD 服务
前提条件:
输入命令:
1
|
sudo openocd -f interface/jlink_swd.cfg -f target/stm32f1x.cfg # 配置文件完整路径:/usr/local/share/openocd/scripts/ 下的 interface/jlink_swd.cfg 和 target/stm32f1x.cfg
|
结果如下:
备注:在 Windows 系统下,j-link 的原厂应用驱动软件,也提供 GDB 对接服务,直接打开【J-Link GDB Server】可视界面操作即可!
2.3、第三步:在另一命令窗口运行 GDB 调试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
##############################################
# ①、在 shell 命令窗口运行
##############################################
# 1.1、运行 gdb
arm-none-eabi-gdb ./build/gcc/rt-thread.elf
##############################################
# ②、在 gdb 命令窗口运行
##############################################
# 2.0、修改 gdb 本次连接超时时间(防止openocd与仿真器速度低造成超时)
set remotetimeout 60 #修改超时时间
#show remotetimeout #查看超时时间
# 2.1、连接 openocd
target remote localhost:3333
# 2.2、复位并暂停处理器(monitor表示向外部服务传送命令)
monitor reset halt
# 2.3、下载固件(实测无需复位暂停处理器直接load也可以)
load
|
3、使用 OpenOCD 总结
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
########连接USB ########
虚拟机/可移动设备/SEGGER J-Link/连接
########下载固件########
sudo openocd -f interface/jlink_swd.cfg -f target/stm32f1x.cfg -c init -c "reset halt; wait_halt; flash write_image erase out/project.hex" -c reset -c shutdown
# 备注:/usr/local/share/openocd/scripts/ 下的 interface/jlink_swd.cfg 和 target/stm32f1x.cfg
#(1)####调试程序######## #【在一个命令窗口启动openocd服务】 # 备注:编译要加[-g]选项!
sudo openocd -f interface/jlink_swd.cfg -f target/stm32f1x.cfg
#(2) #【在另一命令窗口启动gdb服务】
arm-none-eabi-gdb ./build/gcc/rt-thread.elf #(也可先运行命令 arm-none-eabi-gdb 进入gdb后再运行命令 file ./build/gcc/rt-thread.elf 装载调试文件)
set remotetimeout 60 # 在gdb里:修改gdb本次连接超时时间(防止openocd与仿真器速度低造成超时)
target remote localhost:3333 # 在gdb里:连接openocd服务(但会提示:首选GDB命令为 target extended-remote localhost:3333 而不是 target remote localhost:3333)
monitor reset halt # 在gdb里:复位并暂停处理器(monitor表示向外部服务传送命令)
load # 在gdb里:装载调试固件(实测无需复位暂停处理器直接load也可以)
tb main # 在gdb里:在main函数设置临时断点
c # 在gdb里:运行程序(可用 ctrl+c 强制退出运行,暂停运行时可 monitor reset halt 复位程序,再 c 运行程序)
|
3.1、GDB 常用命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
c #【运行程序】继续运行程序
s #【运行程序】单步运行(会进入子函数)
n #【运行程序】单步运行(不进入子函数)
finish #【运行函数】完成运行并跳出当前函数
l 100 #【查看文件】指定当前运行文件行号查看
l max.c:5 #【查看文件】指定文件行号查看
l #【查看文件】继续向下查看文件
b 100 #【设置断点】指定当前运行文件行号断点(注意:当前文件是指程序暂停运行所在的文件!)
b main #【设置断点】指定函数断点
tb 100 #【临时断点】指定当前运行文件行号断点(注意:当前文件是指程序暂停运行所在的文件!)
tb main #【临时断点】指定函数断点
u 100 #【运行到行】运行到当前文件指定行断点(注意:当前文件是指程序暂停运行所在的文件!)
watch i>9 #【条件断点】不固定位置的变量条件断点 (只能设置全局变量)
rwatch i #【条件断点】不固定位置的读变量条件断点 (只能设置全局变量)
awatch i #【条件断点】不固定位置的读写变量条件断点(只能设置全局变量)
clear #【清除断点】清除当前程序所在的断点
clear main #【清除断点】清除某个指定函数断点
d #【删除断点】所有断点
d 2 #【删除断点】删除某个指定编号的断点 (备注:需要 i b 查看断点编号来配合使用!)
d display 2 #【删除显示】删除某个指定编号的变量显示(备注:需要 i display 查看变量编号来配合使用!)
i b #【查看断点】查看断点信息(查看使用 break 设置的断点)
i display #【查看信息】查看变量信息(查看使用 display 显示的变量)
i locals #【查看信息】查看当前函数所有局部变量值(注意:当前函数是指程序暂停运行所在的函数!)
display cnt #【查看变量】查看变量信息(默认显示格式显示)【程序运行到暂停后会自动显示】
p i=1 #【变量赋值】给变量赋值 (支持局部变量操作)
p cnt #【查看变量】查看变量信息(默认显示格式显示)(支持局部变量操作)
ptype i #【查看变量】查看变量类型(普通变量)(可查看程序暂停运行所在函数的局部变量)
x/3xb 0x8003000 #【查看数据】查看[0x8003000]起始地址的数据(数量:3个单元,格式:十六进制,单元大小:1字节)
x/3uh buf #【查看数据】查看[buf]变量内存数据 (数量:3个单元,格式:无符号十进制,单元大小:2字节)
bt #【查看调用】查看函数调用栈信息
help info #【查看帮助】查看info命令帮助
|
更多命令请查看《linux-调试-linux 调试仿真工具》的【使用】章节!
三、扩展
1、IDE 集成开发环境的组成
组件 |
说明 |
代码编辑工具 |
IDE 直接使用 QScitinal 这类的编辑器库 |
代码智能提示 |
IDE 后台调用 clang 工具 |
语法错误检测 |
IDE 后台调用 gcc 或者 clang 对代码语法错误动态检测 |
工程文件组织 |
IDE 使用的是 makefile,后台调用 make 工具 |
编译 |
IDE 后台调用 gcc 或者 clang 编译器编译 |
调试器 |
IDE 后台调用 OpenOCD 连接调试器和板子 |
下载 |
IDE 后台调用 OpenOCD 命令下载固件 |
调试 |
IDE 后台调用 gdb,给 gdb 发命令,gdb 再给 OpenOCD 发命令,OpenOCD 再指挥调试器控制板子。实现单步执行,查看变量值,寄存器等 |
2、CGDB/GDB 应用及命令知识
《linux-调试-linux 调试仿真工具》