目录

linux-STM32F开发㈡-调试器的安装与使用

一、前言

对于单片机的开发,我们离不开仿真器(烧录器)的使用,平常我们都是图形界面下操作,而本文主要介绍命令窗口下的仿真器驱动安装与使用。目前的 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 版,直接复制到对应目录并加入环境变量即可使用!

../img/20220808_2_300.jpg

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 组件的安装问题

../img/20220808_2_321.jpg

3.2.2、烧录固件提示找不到驱动

../img/20220808_2_322.jpg


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、第一步:

../img/20220808_3_131.jpg

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、最终结果:

../img/20220808_3_132.jpg


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 服务

前提条件:

../img/20220808_3_131.jpg

输入命令:

1
sudo openocd -f interface/jlink_swd.cfg -f target/stm32f1x.cfg  # 配置文件完整路径:/usr/local/share/openocd/scripts/ 下的 interface/jlink_swd.cfg 和 target/stm32f1x.cfg

结果如下:

../img/20220808_3_22.jpg

备注:在 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 调试仿真工具