使用调试器
本节介绍以下几种配置和运行调试器的方法:
关于如何使用 VS Code 进行调试,请参阅文档 使用 VS Code 调试。
使用 Eclipse 调试
作为一款集成开发环境 (IDE),Eclipse 提供了一套强大的工具,用于开发和调试软件应用程序。对于 ESP-IDF 应用程序,IDF Eclipse 插件 提供了两种调试方式:
GDB 硬件调试
默认情况下,Eclipse 通过 GDB 硬件调试插件支持 OpenOCD 调试。该调试方式需要从命令行启动 OpenOCD 服务器,并在 Eclipse 中配置 GDB 客户端,整个过程耗时且容易出错。
为了使调试过程更加容易,IDF Eclipse 插件 提供了定制的 ESP-IDF GDB OpenOCD 调试功能,支持在 Eclipse 内部配置好 OpenOCD 服务器和 GDB 客户端。该插件已经设置好所有必需的配置参数,点击一个按钮即可开始调试。
因此,建议通过 IDF Eclipse 插件 进行 ESP-IDF GDB OpenOCD 调试。
GDB 硬件调试
备注
只有在无法使用 ESP-IDF GDB OpenOCD 调试 的情况下,才建议使用 GDB 硬件调试。
首先,打开 Eclipse,选择 Help
> Install New Software
来安装 GDB Hardware Debugging
插件。
安装完成后,按照以下步骤配置调试会话。请注意,一些配置参数是通用的,有些则针对特定项目。我们会通过配置 "blink" 示例项目的调试环境来进行展示,请先按照 Eclipse Plugin 介绍的方法将该示例项目添加到 Eclipse 的工作空间。示例项目 get-started/blink 的源代码可以在 ESP-IDF 仓库的 examples 目录下找到。
在 Eclipse 中,进入
Run
>Debug Configuration
,会出现一个新的窗口。在窗口的左侧窗格中,双击GDB Hardware Debugging
(或者选择GDB Hardware Debugging
然后按下New
按钮)来新建一个配置。在右边显示的表单中,
Name:
一栏中输入配置的名称,例如: “Blink checking”。在下面的
Main
选项卡中, 点击Project:
边上的Browse
按钮,然后选择当前的blink
项目。在下一行的
C/C++ Application:
中,点击Browse
按钮,选择blink.elf
文件。如果blink.elf
文件不存在,那么很有可能该项目还没有编译,请参考 Eclipse Plugin 指南中的介绍。最后,在
Build (if required) before launching
下面点击Disable auto build
。上述步骤 1 - 5 的示例输入如下图所示。
点击
Debugger
选项卡,在GDB Command
栏中输入xtensa-esp32-elf-gdb
来调用调试器。更改
Remote host
的默认配置,在Port number
下面输入3333
。上述步骤 6 - 7 的示例输入如下图所示。
最后一个需要更改默认配置的选项卡是
Startup
选项卡。在Initialization Commands
下,取消选中Reset and Delay (seconds)
和Halt
,然后在下面一栏中输入以下命令:mon reset halt maintenance flush register-cache set remote hardware-watchpoint-limit 2
备注
如果想在启动新的调试会话之前自动更新闪存中的镜像,请在
Initialization Commands
文本框的开头添加以下命令行:mon reset halt mon program_esp ${workspace_loc:blink/build/blink.bin} 0x10000 verify
有关
program_esp
命令的说明请参考 上传待调试的应用程序 章节。在
Load Image and Symbols
下,取消选中Load image
选项。在同一个选项卡中继续往下浏览,建立一个初始断点用来在调试器复位后暂停 CPU。插件会根据
Set break point at:
一栏中输入的函数名,在该函数的开头设置断点。选中这一选项,并在相应的字段中输入app_main
。选中
Resume
选项,这会使得程序在每次调用步骤 8 中的mon reset halt
后恢复,然后在app_main
的断点处停止。上述步骤 8 - 11 的示例输入如下图所示。
上面的启动序列看起来有些复杂,如果你对其中的初始化命令不太熟悉,请查阅 调试器的启动命令的含义 章节获取更多说明。
如果前面已经完成 配置 ESP32 目标板 中介绍的步骤,目标正在运行并准备好与调试器进行对话,那么点击
Debug
按钮直接进行调试。如果尚未完成前面步骤,请点击Apply
按钮保存配置,返回 配置 ESP32 目标板 章节进行配置,最后再回到这里开始调试。一旦所有 1-12 的配置步骤都已经完成,Eclipse 就会打开
Debug
视图,如下图所示。如果不太了解 GDB 的常用方法,请查阅 使用 Eclipse 的调试示例 文章中的调试示例章节 调试范例。
使用命令行调试
为了能够启动调试会话,需要先启动并运行目标,如果还没有完成,请按照 配置 ESP32 目标板 中的介绍进行操作。
打开一个新的终端会话并前往待调试的项目目录,比如:
cd ~/esp/blink
启动调试器时,通常需要提供一些配置参数和命令。构建系统会生成多个
.gdbinit
文件,以便进行高效调试。这些文件的路径存储在build/project_description.json
文件的gdbinit_files
字段部分,具体路径如下所示进行定义:"gdbinit_files": { "01_symbols": "application_path/build/gdbinit/symbols", "02_prefix_map": "application_path/build/gdbinit/prefix_map", "03_py_extensions": "application_path/build/gdbinit/py_extensions", "04_connect": "application_path/build/gdbinit/connect" }
按照 JSON 键名中的
XX_
前缀进行排序,并以这种顺序将字段信息提供给 GDB。生成的
.gdbinit
文件具有以下不同功能:symbols
- 包含用于调试的符号来源。prefix_map
- 配置前缀映射以修改 GDB 中的源路径。详情请参阅 可重复构建与调试。py_extensions
- 初始化 GDB 中的 Python 扩展。请注意,应使用包含libpython
库、且受 GDB 支持的 Python 版本。若运行以下命令时没有报错,则说明 GDB 和 Python 兼容:xtensa-esp32-elf-gdb --batch-silent --ex "python import os"
。connect
- 包含与目标设备建立连接时所需的命令。
为增强调试体验,你还可以创建自定义的
.gdbinit
文件。自定义文件可以与生成的配置文件一起使用,也可以直替换它们。
准备启动 GDB。请使用以下示例命令加载符号表并连接目标设备(命令中的
-q
选项用于减少启动输出):xtensa-esp32-elf-gdb -q -x build/gdbinit/symbols -x build/gdbinit/prefix_map -x build/gdbinit/connect build/blink.elf
如果前面的步骤已经正确完成,你会看到如下所示的输出日志,在日志的最后会出现
(gdb)
提示符:xtensa-esp32-elf-gdb -q -x build/gdbinit/symbols -x build/gdbinit/prefix_map -x build/gdbinit/connect build/blink.elf user-name@computer-name:~/esp-idf/examples/get-started/blink$ xtensa-esp32-elf-gdb -q -x build/gdbinit/symbols -x build/gdbinit/connect build/blink.elf Reading symbols from build/blink.elf... add symbol table from file "/home/user-name/esp-idf/examples/get-started/blink/build/bootloader/bootloader.elf" [Switching to Thread 1070141764] app_main () at /home/user-name/esp-idf/examples/get-started/blink/main/blink_example_main.c:95 95 configure_led(); add symbol table from file "/home/alex/.espressif/tools/esp-rom-elfs/20241011/esp32_rev0_rom.elf" JTAG tap: esp32.tap0 tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0) [esp32] Reset cause (3) - (Software core reset) Hardware assisted breakpoint 1 at 0x42009436: file /home/user-name/esp-idf/examples/get-started/blink/main/blink_example_main.c, line 92. [Switching to Thread 1070139884] Thread 2 "main" hit Temporary breakpoint 1, app_main () at /home/user-name/esp-idf/examples/get-started/blink/main/blink_example_main.c:92 92 { (gdb)
请注意,以上日志的倒数第三行显示调试器已在
build/gdbinit/connect
函数的断点处停止,该断点在gdbinit
文件中设定。由于处理器已暂停,LED 将不再闪烁。如果你的 LED 也停止了闪烁,则可以开始调试。如果不太了解 GDB 的常用方法,请查阅 使用命令行的调试示例 文章中的调试示例章节 调试范例。
使用 idf.py 进行调试
你还可以使用 idf.py
更方便地执行上述提到的调试命令,可以使用以下命令:
idf.py openocd
在终端中运行 OpenOCD,其配置信息来源于环境变量或者命令行。默认会使用
OPENOCD_SCRIPTS
环境变量中指定的脚本路径,它是由 ESP-IDF 项目仓库中的导出脚本(export.sh
orexport.bat
)添加到系统环境变量中的。 当然,你可以在命令行中通过--openocd-scripts
参数来覆盖这个变量的值。至于当前开发板的 JTAG 配置,请使用环境变量
OPENOCD_COMMANDS
或命令行参数--openocd-commands
。如果这两者都没有被定义,那么 OpenOCD 会使用-f board/esp32-wrover-kit-3.3v.cfg
参数来启动。idf.py gdb
根据当前项目的 ELF 文件自动生成 GDB 启动脚本,然后按照 使用命令行调试 中描述的步骤启动 GDB。详情请参阅 使用命令行调试。
idf.py gdbtui
和步骤 2 相同,但是会在启动 GDB 的时候传递
tui
参数,这样可以方便在调试过程中查看源代码。idf.py gdbgui
启动 gdbgui,在浏览器中打开调试器的前端界面。请在运行安装脚本时添加 "--enable-gdbgui" 参数,即运行
install.sh --enable-gdbgui
,从而确保支持gdbgui
选项。上述这些命令也可以合并到一起使用,
idf.py
会自动将后台进程(比如 openocd)最先运行,交互式进程(比如 GDB,monitor)最后运行。常用的组合命令如下所示:
idf.py openocd gdbgui monitor
上述命令会将 OpenOCD 运行至后台,然后启动 gdbgui 打开一个浏览器窗口,显示调试器的前端界面,最后在活动终端打开串口监视器。