在此篇博客中,你将学习到如何使用 gdbgui 进行 ESP32 JTAG 调试。博客将分为以下几个部分:
-
- gdbgui 的安装
-
- ESP-Prog/Jlink 硬件接线方法
-
- 打开 OpenOCD
-
- 打开 gdbgui 并进行调试
-
- gdbgui 相关操作
1. gdbgui 的安装
gdbgui 有两种主流安装方式(来自于 gdbgui 官方教程):
- 使用 pipx 进行安装
- 使用 pip 进行安装
1.1 使用 pipx 进行安装(推荐)
在终端里输入以下内容来安装 pipx:
python3 -m pip install --user pipx
python3 -m userpath append ~/.local/bin
然后使用 pipx 来安装 gdbgui
pipx install gdbgui
To upgrade run
pipx upgrade gdbgui
当安装完成,在终端输入 gdbgui
来运行 gdbgui 即可,或者输入 gdbgui -h
来查看帮助
如果要卸载 gdbgui,在终端输入
pipx uninstall gdbgui
你也可以使用 pipx 免安装 gdbgui 而直接使用,在终端输入以下指令:
pipx run gdbgui
然后在你的浏览器中会自动打开 gdbgui。
1.2 使用 pip 进行安装
Method 2: Using pip
如果你偏向于使用虚拟环境,你可以激活一个虚拟环境然后运行:
pip install gdbgui
你可以使用如下指令更新 gdbgui:
pip install --upgrade gdbgui
如果要卸载 gdbgui,在终端输入:
pip uninstall gdbgui
2. ESP-Prog/Jlink 硬件接线方法
如果要使用 JTAG/Jlink 调试,你需要在硬件上做一些额外的准备,在此篇博客里就不赘述了。具体请进入以下链接:
3. 安装 & 打开 OpenOCD
3.1 安装 OpenOCD
如果你已经按照 esp-idf 快速入门 一文中的介绍安装好了 ESP-IDF 及其 CMake 构建系统,那么 OpenOCD 已经被默认安装到了你的开发系统中。在 设置开发环境 结束后,你应该能够在终端中运行如下 OpenOCD 命令来查看 OpenOCD 版本:
openocd --version
3.2 进入 openocd-esp32
目录
首先你需要在终端里进入到 openocd-esp32
目录:
cd ~/esp/openocd-esp32/v0.10.0-esp32-20200406/openocd-esp32
上述 openocd-esp32
目录请按照自己的 openocd-esp32
目录调整。
3.3 查看 openocd-esp32
版本(如使用 Jlink,则需要关注这一步,其他请忽略)
然后你需要查看 openocd-esp32
版本,一般已经标注在对应的文件夹上,比如 /esp/openocd-esp32/v0.10.0-esp32-20200406
。如果是 2019 及以前版本,请忽略此步并直接跳转至 3.3 运行 openocd-esp32
。如果是 2020 及以后版本,需要执行以下操作:
- 进入
openocd-esp32
的以下目录:/esp/openocd-esp32/v0.10.0-esp32-20200309/openocd-esp32/share/openocd/scripts/interface
,在interface
文件夹中找到jlink.cfg
并打开 - 在
jlink.cfg
中添加adapter_khz 9600
,然后保存文件并关闭(如果不添加,会在后续运行 openocd 指令时报错)
添加 adapter_khz 9600
后的 jlink.cfg
应如下:
#
# SEGGER J-Link
#
# http://www.segger.com/jlink.html
#
interface jlink
adapter_khz 9600
# 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
3.4 运行 openocd-esp32
最后你只需要使用如下指令运行 openocd-esp32
,此处确保调试器已按上述硬件配置连接,如使用 Jlink 还需要同时确保 2020 版本已进行 3.2 查看 openocd-esp32 版本
中的配置。默认指令为:openocd -s $OPENOCD_PATH/scripts/ -f "source [find interface/$DEBUG_DEVICE.cfg]" -f $OPENOCD_TARGET_SCRIPT
。
示例:使用 Jlink 进行 JTAG 调试时的 3.3 运行 openocd-esp32
对应操作与指令
对应操作:
- 在终端里进入对应的
openocd-esp32
目录 - 配置与运行
openocd-esp32
终端指令:
cd ~/esp/openocd-esp32/v0.10.0-esp32-20200406/openocd-esp32
./bin/openocd -s share/openocd/scripts -f interface/jlink.cfg \
-f board/esp-wroom-32.cfg
特别注意:上述指令中第二行和第三行请一并粘贴进入终端,因为单行指令太长,直接转成 PDF 会出现不必要的错误(使用 \ + 回车进行了指令换行)。
上述 openocd-esp32
目录请按照自己的 openocd-esp32
目录调整。上述 -f board/esp-wroom-32.cfg
请按照自己实际使用的开发板进行调整。
4. 打开 gdbgui 并进行调试
4.1 编译烧写需要调试的程序
首先你需要将需要调试的程序编译烧录至 ESP32 中(参考 ESP-IDF 快速入门),同时你需要找到并记录对应 elf 文件存在的路径。比如编译并烧录 esp-idf 里的 examples/getting-started/hello_world
示例后,你能在 examples/getting-started/hello_world/build
目录下找到 hello-world.elf
文件。此时路径为 /home/username/esp/esp-idf/examples/get-started/hello_world/build/hello-world.elf
。
4.2 打开 & 配置 gdbgui
使用以下指令打开 gdbgui:
pipx run gdbgui --gdb $PATH_TO_ARM_GDB
其中你需要把 $PATH_TO_ARM_GDB
改成你电脑中对应的 gdb 工具地址,比如 gdb 存在于 /home/username/.espressif/tools/xtensa-esp32-elf/esp-2020r1-8.2.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb
下可以使用以下指令:
pipx run gdbgui --gdb /home/username/.espressif/tools/xtensa-esp32-elf/esp-2020r1-8.2.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb
你会发现 gdbgui 会在你的浏览器上自动打开,然后你需要进行以下配置:
- 在 gdbgui 界面最下方的控制台里输入
target remote :3333
- 在 gdbgui 界面上方的
Load Binary
中输入在4.1 编译烧写需要调试的程序
中需调试的程序编译生成的 elf 文件地址
你也可以使用 pipx run gdbgui --gdb xtensa-esp32-elf-gdb "build/hello-world.elf"
来省去 Load Binary
步骤。
此时图形界面里应会显示被调试的代码,可以进行开始调试了,如果提示 Function "main" not defined.
。在 app_main 函数入口处添加断电并继续调试即可,指令如下:
b app_main
c
或者
thb app_main
c
以下是不同类型断点的简介
- break(b) 普通断点
- tbreak(tb) 表示临时断点,如果在这个断点暂停了,那么这个断点就被自动删除了
- rbreak(rb) 后面的参数是一个正则表达式,凡是和该正则表达式相匹配的所有函数名称都设置为断点
- hbread(hb) 硬件辅助断点,一般和具体硬件相关
- thbreak(thb) 表示硬件辅助的临时断点。是 tbreak 和 hbreak 的复合
然后你可以试着输入相关 gdb 指令进行调试,比如输入 list
就可以看到控制台输出 app_main 函数里的代码。此时 gdbgui 界面如下:
开始尽情使用 gdbgui 调试 ESP32 吧~
4.3 知识扩展:gdbinit 配置文件的生成 & 运行(非必须)
gdbgui 的配置也可以参考 gdbinit
,参考如下:
target remote :3333
set remote hardware-watchpoint-limit 2
mon reset halt
flushregs
thb app_main
c
首先你要在当前目录下编写 gdbinit
文件,然后你同时也需要在 home 目录下创建另一个 .gdbinit
文件,并在 .gdbinit
里写入以下内容:
set auto-load safe-path /
set print pretty on
set print elements 0
在完成上述配置后,每次你打开 gdbgui 时,会自动运行当前目录下的 gdbinit 文件来帮助我们进行初始化配置。
5. gdbgui 相关操作
基础指令如下:
- 继续:
c
- 下一步:
n
- 跳转:
s
- 向上:
u
6. 相关资源
- gdbgui 其他指令 & API 可参考:gdbgui API