ESP32 JTAG 调试

前言

  1. 个人邮箱:zhangyixu02@gmail.com
  2. 本人使用的是 Ubuntu 环境,采用 GDB 方式进行调试。
  3. 对于新手,我个人还是建议参考ESP32S3学习笔记(0)—— Vscode IDF环境搭建及OpenOCD调试介绍进行图形化的方式调试。
  4. 如果是希望在 Windows 环境下进行 GDB 调试,可以参考 Windows 环境下,使用 ESP32-S3 USB 接口进行 JTAG 调试的流程。

GDB 介绍

两种调试方式

  1. ESP32 提供了两种调试方式,一种是利用串口进行日志打印。这种方式是常用的,我们可以根据日志信息知道程序的运行信息。
  2. 但是在一些特殊场景,例如我需要让程序在某个时刻停下来进行调试,日志打印的方式就并不那么好用了。我们此时就可以使用 JTAG 调试的方式进行。

在这里插入图片描述

GDB 和 Openocd 介绍

  1. 电脑端,我们需要先运行 Openocd 充当调试代理用于与目标硬件进行直接通讯,他提供一个 GDB 服务器接口(通常在TCP端口 :3333 上),GDB 可以通过该接口与 OpenOCD 通信。 GDB 会向 OpenOCD 发送调试命令,例如设置断点、查看寄存器、单步执行等。当 OpenOCD 接收到来自 GDB 的命令后,负责将这些命令转换成特定的硬件指令,并执行到目标设备上
  2. GDB 是一个高层的调试器,用户通过它来编写和管理调试会话。GDB本身不直接与硬件通信,它通过GDB服务器(如OpenOCD提供的)与设备进行交互。
  3. 如下为 电脑端 <—> 调试器 <—> ESP32C3 的方式进行调试。调试器为 FT2232/FT232 芯片。

在这里插入图片描述

  1. 这种外置调试器的方法相对麻烦,还需要自行准备调试芯片,后面乐鑫将调试器集成到了芯片内部。

在这里插入图片描述

  1. 我们可以通过乐鑫官方选型网站得知哪些芯片内部集成了 JTAG 调试接口。

在这里插入图片描述

  1. 如果当前使用的芯片内部没有 JTAG 调试接口,我们可以购买 ESP-Prog 进行调试。

环境准备

打开 Openocd

  1. 通过上面的内容我们知道,要进行 GDB 调试 ESP32-S3 的话,需要先打开 Openocd 提供一个接口。我们可以输入如下命令进行开启 Openocd。
openocd -f board/esp32s3-builtin.cfg
  1. 这个 cfg 文件在如下目录中,我们可以在该目录中选择合适的文件打开 Openocd。

注:随着版本更新,你可能并不是 v0.12.0-esp32-20230921。

~/.espressif/tools/openocd-esp32/v0.12.0-esp32-20230921/openocd-esp32/share/openocd/scripts/board
  1. 这个时候肯定就会有人要说了,我怎么知道应该选择哪个 cfg 文件呢?
  • 如果是内部集成了 JTAG 接口,一般选择 builtin 名称的 cfg 文件。
  • 如果是使用的 ESP-Prog 调试器,那么就选择 bridge 名称的 cfg 文件。
  • 如果你发现上述做法都不对,那就找到对应的芯片前缀名,然后一个一个的试吧。(哭笑)
  1. 在 Ubuntu 环境中,你打开 Openocd 发现如下报错,那么说明当前用户没有足够的权限访问 USB 设备
Error: libusb_open() failed with LIBUSB_ERROR_ACCESS
Error: esp_usb_jtag: could not find or open device!
  1. 此时你需要创建一个 udev 规则文件添加规则。
sudo vim /etc/udev/rules.d/99-openocd.rules
  1. 添加如下内容。
SUBSYSTEM=="usb", ATTR{idVendor}=="303a", ATTR{idProduct}=="1001", MODE="0666"
  1. 重新加载 udev 规则。
sudo udevadm control --reload-rules
sudo udevadm trigger

进入 GDB 调试

  1. 我们需要在项目根目录中创建 gdbinit 文件,并且在该文件中加入如下内容。

tui enable 命令能够在终端中增加一个 UI 界面方便我们知道当前调试的位置,如果觉得这个 UI 界面看的不舒服,可以将这一行给删除

# 告诉 GDB 连接到运行在本地(即当前计算机)上的 OpenOCD 服务,监听端口 3333
target remote :3333
# 设置硬件观察点限制
set remote hardware-watchpoint-limit 2
# 重置并停止目标设备
mon reset halt
# 刷新寄存器状态
flushregs
# 在 app_main 函数处设置临时断点
thb app_main
# 继续执行程序
c
# 使能 UI 界面
tui enable
  1. 此时我们需要再打开一个终端,输入如下命令即可进入 GDB 调试界面。

注:当前 elf 文件应该是你烧录到芯片时,生成的 elf 文件! 调试过程中,工程代码建议不要修改。

xtensa-esp32s3-elf-gdb -x gdbinit build/gatt_client_demo.elf
  1. 不同的芯片/架构使用的 GDB 调试器不同,具体参考如下:
架构/芯片命令
Xtensa ESP32xtensa-esp32-elf-gdb
Xtensa ESP32-S2xtensa-esp32s2-elf-gdb
Xtensa ESP32-S3xtensa-esp32s3-elf-gdb
RISC-Vriscv32-esp-elf-gdb

GDB 命令

控制命令

运行命令

命令作用
continue/c运行程序,直到遇到断点才停止
next/n单步执行, 跳过函数调用
next/n count运行多步, 跳过函数调用(count 要跳过运行的步骤次数)
step/s单步调试,进入函数调用
step/s count多步调试,进入函数调用(count 要跳过运行的步骤次数)
finish继续执行,直到当前函数返回
until num运行到指定行号(num 行号)
jump/j num直接跳转到指定行数代码,相当于 C 语言的 goto 语句
monitor reset halt复位开发板

set 命令

命令作用
set 变量名=num将指定变量设置为指定值(num 数值)
set $变量名=num设置一个 GDB 的内部变量,此方法可以用于进行特定的调试计算。具体参考ESP32 JTAG Debug 14: GDB Set 命令的第 6 min
set print address off/on打印数据时,关闭/开启 打印对应数据地址
set style address foreground 设置内存地址的前景色(字体颜色)
set style address background 设置内存地址的背景色

信息查看命令

命令作用
list/l列出当前位置往下10列源代码
backtrace/bt查看函数调用信息
where查看当前程序运行到了哪里
info locals查看当前作用域的局部变量信息
info registers/reg显示所有寄存器的值
info registers/reg 显示指定寄存器的值

print 命令

命令作用
print 变量名/数组/字符串/结构体查看指定变量的值
print /x 变量名以 16 进制形式打印变量值
print /d 变量名以 10 进制形式打印变量值
print /u 变量名以无符号 10 进制形式打印变量值
print /o 变量名以 8 进制形式打印变量值
print /t 变量名以 2 进制形式打印变量值
print /a 变量名以地址格式打印变量值
print /c 变量名以字符形式打印变量值
print /f 变量名以浮点数形式打印变量值
print /s 变量名以字符串形式打印变量值
print 函数名 :: 变量名打印指定函数中,指定变量的数据
print ‘指定文件路径’ :: 变量打印不同文件中变量的信息
print pretty on启动 “漂亮打印”(pretty-printing)功能,这将允许 GDB 以更可读的格式输出复杂数据结构(如结构体、类、数组等),使得调试时的输出更加清晰易懂

display 命令

命令作用
display 变量名持续监视某个变量
display /x 变量名以 16 进制形式持续监视某个变量
info display查看 display 列表
disable display num失能 display 列表中指定监视
enable display num使能 display 列表中指定监视
undisplay num删除 display 列表中指定监视
delete display num删除 display 列表中指定监视

地址信息打印命令

格式 :

x/<count><format><size> <address>
  • <count>:要显示的内存单元的数量(可选,默认值为 1)。
  • <format>:指定输出格式,可以是以下之一:
    • x:十六进制(hexadecimal)
    • d:十进制(decimal)
    • u:无符号十进制(unsigned decimal)
    • o:八进制(octal)
    • t:二进制(binary)
    • c:字符(character)
    • f:浮点数(float)
    • s:字符串(string)
    • i:指令(instruction)
  • <size>:指定每个单元的大小,可以是以下之一:
    • b:字节(byte)
    • h:半字(halfword,2 bytes)
    • w:字(word,通常为 4 bytes)
    • g:巨字(giant word,通常为 8 bytes)
  • <address>:要查看的内存地址,可以是变量名、指针或具体的内存地址。

断点命令

添加断点

命令作用
break/b ngdb 运行到的当前文件中的某一行设置断点(n : 当前文件行号)
break/b filename: n向指定文件的指定行设置断点(filename : 指定)
break/b func在指定函数开头设置断点(func : 函数名)
tbreak n/func设置临时断点,在设置之后只起作用一次(n : 当前文件行号 func : 函数名)

断点控制

命令作用
disable n失能指定断点号断点 (n : 断点号)
enable n使能指定断点号断点 (n : 断点号)
delete/d删除所有断点
delete/d n删除指定断点号断点 (n : 断点号)
clear n清除行 n 上面的所有断点

查看断点信息

命令作用
info break/b查看所有断点信息
info break/b n查看指定断点号断点信息 (n : 断点号)

观察断点

命令作用
watch 变量名给指定变量名设置一个观察断点,所有与该变量名发生变化的地方进行打断,在运行到发生修改地方时,会停止并且打印该变量的原来值修改之后的值。在相同的地方,如果只有第一次该变量发生变化,那么该地方只有第一次会被打断
info watch查看观察断点相关信息
watch 表达式给一个表达式观察断点,例如表达式 i+j,如果变量 i 不发生变化,j 发生变化,依旧会在 j 发生变化的地方进行打断

其他命令

命令作用
shell clear调用 shell 清屏命令
quit/q退出 gdb 调试
define my_command自定义命令,能够进行自定义调试,具体用法参考ESP32 JTAG Debug 15: GDB Define 命令

TUI 使用

命令作用
上下左右箭头向上/下/左/右向滚动代码
PgUP/PgDn向上/下翻页
update回到当前运行的位置
list/l num查看指定行号信息(num 行号)
layout asm查看汇编代码
layout regs显示寄存器相关信息
layout src回到源代码

参考

  1. Windows 环境下,使用 ESP32-S3 USB 接口进行 JTAG 调试的流程
  2. B站:ESP32 JTAG Debug 01: JTAG接口简介
  3. 利用 Guru Meditation 错误打印定位问题
  4. GDB常用命令大全 GDB 命令详细解释
  5. gdb调试常见命令详细总结(附示例操作)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146121.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

占领矩阵-第15届蓝桥省赛Scratch中级组真题第5题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第190讲。 如果想持续关注Scratch蓝桥真题解读&#xff0c;可以点击《Scratch蓝桥杯历年真题》并订阅合集&#xff0c;…

Python酷库之旅-第三方库Pandas(122)

目录 一、用法精讲 541、pandas.DataFrame.take方法 541-1、语法 541-2、参数 541-3、功能 541-4、返回值 541-5、说明 541-6、用法 541-6-1、数据准备 541-6-2、代码示例 541-6-3、结果输出 542、pandas.DataFrame.truncate方法 542-1、语法 542-2、参数 542-3…

植保无人机是朝阳产业还是夕阳产业?

植保无人机产业是朝阳产业还是夕阳产业&#xff0c;可以从多个维度进行分析&#xff1a; 一、市场需求与增长趋势 市场需求&#xff1a;随着农业现代化的推进和劳动力成本的上升&#xff0c;植保无人机因其高效、安全、节省农药等优势&#xff0c;在农业生产中的应用越来越广…

自闭症能上寄宿学校吗?了解解答与选择

在探讨自闭症儿童教育的话题时&#xff0c;寄宿学校作为一种特殊的教育模式&#xff0c;常常引发家长们的关注与讨论。对于自闭症儿童而言&#xff0c;寄宿学校既是一个充满挑战的新环境&#xff0c;也是一个能够促进他们独立成长与社交融合的重要平台。今天&#xff0c;我们将…

自制数据库空洞率清理工具-C版-03-EasyClean-V1.3(支持南大通用数据库Gbase8a)

目录 一、环境信息 二、简述 三、升级点 四、支持功能 五、空洞率 六、工具流程图 1、流程描述 2、注意点 &#xff08;1&#xff09;方法一 &#xff08;2&#xff09;方法二 七、清理空洞率流程图 八、安装包下载地址 九、参数介绍 1、命令模板 2、命令样例 3…

【C语言-数据结构】单链表的定义

单链表的定义&#xff08;实现&#xff09; 比较顺序表和单链表的物理存储结构就能够清楚地发现二者的区别 用代码定义一个单链表 typedef struct LNode{ElemType data; //每个结点存放一个数据元素struct LNode* next; //指针指向下一个结点 }LNode, *LinkList;//要表示一个…

[JavaEE] TCP协议

目录 一、TCP协议段格式 二、TCP确保传输可靠的机制 2.1 确认应答 2.2 超时重传 2.3 连接管理 2.3.1 三次握手 2.3.2 四次挥手 2.4 滑动窗口 2.4.1 基础知识 2.4.2 两种丢包情况 2.4.2.1 数据报已经抵达&#xff0c;ACK丢包 2.4.2.2 数据包丢包 2.5 流量控制…

【时时三省】(C语言基础)指针笔试题2

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 笔试题2 这里的0x1是16进制的1 跟十进制的1一样 这道题考察的是&#xff1a;指针类型决定了指针的运算 p是上面结构体的指针 它指向的大小结果是20个字节 指针…

项目第五弹:队列消息管理模块

项目第五弹&#xff1a;队列消息管理模块 一、消息如何组织并管理1.消息结构体2.消息持久化管理模块设计1.数据消息文件名2.临时消息文件名3.对外接口与包含成员 二、自定义应用层协议解决文件读写的粘包问题1.Length-Value协议 三、队列消息管理模块设计1.待确认消息哈希表2.待…

[数据结构]动态顺序表的实现与应用

文章目录 一、引言二、动态顺序表的基本概念三、动态顺序表的实现1、结构体定义2、初始化3、销毁4、扩容5、缩容5、打印6、增删查改 四、分析动态顺序表1、存储方式2、优点3、缺点 五、总结1、练习题2、源代码 一、引言 想象一下&#xff0c;你有一个箱子&#xff08;静态顺序…

【医学半监督】对比互补掩蔽的自监督预训练半监督心脏图像分割

SELF-SUPERVISED PRE-TRAINING BASED ON CONTRASTIVE COMPLEMENTARY MASKING FOR SEMI-SUPERVISED CARDIAC IMAGE SEGMENTATION 2024 IEEE International Symposium on Biomedical Imaging (ISBI) 摘要: 心脏结构分割对心脏病诊断非常重要,而使用大量注释的深度学习在这项任…

Buck变换器闭环控制,simulink仿真模型(适合初学者学习)

Buck变换器&#xff0c;又称为降压斩波器&#xff0c;是一种常见的DC-DC转换器&#xff0c;广泛应用于电源管理领域。它通过开关元件&#xff08;通常是MOSFET或BJT&#xff09;的导通与截止&#xff0c;改变输入电压到负载的平均电压&#xff0c;从而实现电压的降低。在实际应…

harbor私有镜像仓库,搭建及管理

私有镜像仓库 docker-distribution docker的镜像仓库&#xff0c;默认端口号5000 做个仓库&#xff0c;把镜像放里头&#xff0c;用什么服务&#xff0c;起什么容器 vmware公司在docker私有仓库的基础上做了一个web页面&#xff0c;是harbor docker可以把仓库的镜像下载到本地&…

tauri嵌入自定义目录/文件,并在代码中读取文件内容的操作流程

可以看官方文档&#xff1a;Embedding Additional Files | Tauri Apps 在绑定了文件之后&#xff0c;可以在js中访问嵌入的文件或者在rust中读取嵌入的文件内容&#xff0c;详细的配置操作如下。 在src-tauri中创建自定义文件夹或文件&#xff0c;并在在tauri.conf.json中配置…

Java多线程Thread及其原理深度解析

文章目录 1. 实现多线程的方式2. Thread 部分源码2.1. native 方法注册2.2. Thread 中的成员变量2.3. Thread 构造方法与初始化2.4. Thread 线程状态与操作系统状态2.4. start() 与 run() 方法2.5. sleep() 方法2.6. join() 方法2.7. interrupt() 方法 本文参考&#xff1a; 线…

Spring自定义参数解析器

在这篇文章中&#xff0c;我们认识了参数解析器和消息转换器&#xff0c;今天我们来自定义一个参数解析器。 自定义参数解析器 实现HandlerMethodArgumentResolver的类&#xff0c;并注册到Spring容器。 Component&#xff0f;&#xff0f;注册到Spring public class UserAr…

Java集合必知必会:热门面试题汇编与核心源码(ArrayList、HashMap)剖析

写在前面 &#x1f525;我把后端Java面试题做了一个汇总&#xff0c;有兴趣大家可以看看&#xff01;这里&#x1f449; ⭐️在无数次的复习巩固中&#xff0c;我逐渐意识到一个问题&#xff1a;面对同样的面试题目&#xff0c;不同的资料来源往往给出了五花八门的解释&#…

【Linux进程控制】自主Shell

目录 自主shell实现 获取基本变量 实现命令行 获取用户命令字符串 命令行字符串分割 内建命令CD() chdir getcwd putenv 检查是否为内建命令 检查是否为重定向 执行命令 主函数设置 测试用例 项目代码 自主shell实现 根据之前学的内容&#xff0c;我们已经可以模…

【学习笔记】SSL/TLS安全机制之CAA

1、概念界定 CAA全称Certificate Authority Authorization&#xff0c;即证书颁发机构授权&#xff0c;每个CA都能给任何网站签发证书。 2、CAA要解决的问题 例如&#xff0c;蓝色网站有一张橙色CA颁发的证书&#xff0c;我们也知道还有许多其他的CA&#xff1b;中间人可以说服…

网址链接能做成二维码吗?在线网址二维码生成的操作技巧

现在用二维码能够展示很多的内容&#xff0c;将内容放入二维码后&#xff0c;通过扫码的方式获取内容会更加的方便快捷&#xff0c;简化获取内容的流程。比如在分享网上内容时&#xff0c;可以将链接生成二维码的方式来让用户扫码访问网页&#xff0c;那么网址转二维码具体该怎…