开发必备手册:
一、开发环境
- 软件准备
- VS Code
- ESP-IDF v5.4.2
- 硬件准备
- 微雪电子的
ESP32S3最小系统版


二、下载监听接口
esp32s3有三种接口:- 普通
UART串口:U0RX/U0TX; - 普通
JTAG调试:MTCK/MTDO/MTDI/MTMS; - 通用
USB接口:USB_D-/USB_D+;集成了USB 2.0、USB UART、USB JTAG;
- 普通
USB 串口/JTAG 控制器这给内置的接口很方便, 可以不依靠额外芯片就实现一条线完成下载/调试/复位等功能。需要注意的是有些型号可能不内置个外设。- 如果用普通UART串口下载,就需要准备一个USB转TTL串口模块;如果使用普通JTAG接口下载,还需要用ESP32官方推出的
ESP-Prog模块。某宝售价99软妹币。

ROM日志:可通过普通串口和通用usb串口打印;- 另外,esp32内包含多种日志类型
printf- 普通打印(普通串口貌似只能用这个?)ESP_LOGE- 错误(最低级别)ESP_LOGW- 警告ESP_LOGI- 普通ESP_LOGD- 调试ESP_LOGV- 冗余(最高级别)

- 下载模式:
- 串口下载:
UART0串口和usb串口都可以下载,不过UART0串口只能在启动下载模式(按住BOOT键上电)时才能用。 - JTAG下载:
普通JTAG接口和USB JTAG接口可以下载。
- 串口下载:
Joint Download Boot模式相当于是强制等待下载程序, 如果用户程序卡死跑飞一直重启,会很有用。- 另外,因为通用USB接口有时可能需要用作其他USB用途,那就不能用
USB UART和USB JTAG了, 这时就只能用UART0了,所以要注意保留引出接口。

三、启动流程和内存结构
推荐笔记:
笨拙的理解:
- esp32的启动流程感觉要复杂很多,和stm32等32系列差别较大。
- 比如esp32内部有rom和ram,不带flash的,即使手册有写,那也只是集成在内部的片外flash。和stm32那种内部flash不一样,而且stm32的内部flash就是rom。
- 最后放弃了,先死记以下知识点,用多后再回头看看怎么理解。
- esp32启动是会打印ROM日志, 可以结合打印内容理解。后面也可以使用调试功能,逐步看看FreeRTOS的启动流程。



四、第一个工程
- 从
IDF的例程目录追踪拷贝一个闪灯例程C:\Espressif\esp_idf_541\frameworks\esp-idf-v5.4.1\examples\get-started\blink。原始文件内容如下:

- 然后我在此建立Git仓库,这样每次改动了什么就能显示出来,方便对比学习。

- 看看配置文件有哪些可以配置的内容
./Kconfig.projbuild,我使用的板子是WS2812 RGB LED,所以选择LED strip,RMT,IO是38, 闪烁频率默认1000ms就好了。
menu "Him Example Configuration"
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" # 尝试添加默认配置,获取 ENV_GPIO_RANGE_MIN 和 ENV_GPIO_OUT_RANGE_MAX 作为判断范围条件
# 关键字作用分别为:
# choice / config :会定义的宏定义名字;
# prompt :在 menuconfig 中显示的名字;
# default :默认值;
# help :提示帮助内容;
# 用到再查吧, 或是直接套用模板;
choice BLINK_LED
prompt "Blink LED type"
default BLINK_LED_GPIO
help
Select the LED type. A normal level controlled LED or an addressable LED strip.
The default selection is based on the Espressif DevKit boards.
You can change the default selection according to your board.
config BLINK_LED_GPIO
bool "GPIO"
config BLINK_LED_STRIP
bool "LED strip"
endchoice
choice BLINK_LED_STRIP_BACKEND
depends on BLINK_LED_STRIP
prompt "LED strip backend peripheral"
default BLINK_LED_STRIP_BACKEND_RMT if SOC_RMT_SUPPORTED
default BLINK_LED_STRIP_BACKEND_SPI
help
Select the backend peripheral to drive the LED strip.
config BLINK_LED_STRIP_BACKEND_RMT
depends on SOC_RMT_SUPPORTED
bool "RMT"
config BLINK_LED_STRIP_BACKEND_SPI
bool "SPI"
endchoice
config BLINK_GPIO
int "Blink GPIO number"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 8
help
GPIO number (IOxx) to blink on and off the LED.
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
config BLINK_PERIOD
int "Blink period in ms"
range 10 3600000
default 1000
help
Define the blinking period in milliseconds.
endmenu
- 然后更改默认配置文件
./Kconfig.projbuild的default,或是更改./sdkconfig.defaults文件。方便一会编译后直接下载。 - 目录下还有很多其他
./sdkconfig.defaults.esp32??文件,是参考作用,可以删掉。只有./sdkconfig.defaults在./sdkconfig文件还没生成时,编译才有用。
CONFIG_BLINK_LED_STRIP=y
CONFIG_BLINK_LED_STRIP_BACKEND_RMT=y
CONFIG_BLINK_GPIO=38
- 看一眼
./main/idf_component.yml文件,定义了要用哪些组件,这里使用了led_strip组件,这样可以快速使用led的初始化和闪烁功能,避免再去配置寄存器。我发现用esp32貌似就不用再看寄存器了。 - 编译时会自动下载添加组件到工程中。
dependencies:
espressif/led_strip: "^2.4.1"
./CMakeLists.txt文件定义了CMake的版本和路径,还有工程的名字;
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(blink)
./main/CMakeLists.txt文件定义了.c/.h的 单文件路径 或 文件夹目录路径;
idf_component_register(SRCS "blink_example_main.c"
INCLUDE_DIRS ".")
- 最后有个测试脚本
./pytest_blink.py,删掉略过;然后就可以编译, 以下是编译前修改的内容对比:

五、编译下载工程
编译的时候,不知道为啥有时会卡在
随机的进度,需要手动按一下回车才会继续。
- 常用指令:
idf.py --help 帮助
idf.py --version 版本
idf.py clean 删掉 build 文件
idf.py build 编译文件
idf.py [-p COMx] flash 下载文件 (不指定端口就会自动轮询所有可用端口)
idf.py [-p COMx] monitor 监听串口 (不指定端口就会自动轮询所有可用端口)
idf.py menuconfig 修改配置
idf.py set-target [ESP32S3] 修改芯片
- 编译完后,就多了官方组件文件夹
managed_components和dependencies.lock官方组件的哈希值记录文件,官方组件是不建议修改的,所以编译器生成了 哈希值 ,每次编译都对比一下。如果哈希值改变了,就直接重新加载组件。如果要修改建议改成 本地的自定义组件 再修改。

- 对于
build、managed_components、dependencies.lock,是每次编译都自动刷新的,所以没必要添加git管理,使用忽略文件.gitignore移除。
dependencies.lock
managed_components/
build/
- 最后文件目录就是这样:


- 使用本系列教程后续都会用usb接口下载、监听和调试,使用是数据线连接电脑,查看电脑设备管理器,确认有正确识别。
- 在
端口(COM和LPT)中有USB JTAG/serial debug unit (Interface 0) (COM3),驱动程序提供商是Iibwdi; - 在
通用串行总线设备中有USB JTAG/serial debug uint,驱动程序提供商是Iibwdi; - 以上2个东西应该属于
即插即有,注意不是通用串行总线控制器,别搞混了。 - 如果你使用额外的
USB转串口或是USB转JTAG的模块,那可能需要安装驱动,这里不赘述了。
- 在

- 编译工程后下载报错:提示芯片类型不对,识别到是
ESP32-S3, 但是下载的设定是ESP32。属于前面忘记换芯片类型。

- 更换芯片类型后,配置文件
sdkconfig就会重新生成,同时旧的会保留一个备份sdkconfig.old; - 可以对比前后2给文件, 变动还是挺多地方的。而且变更
sdkconfig文件后,总是会需要(完全)重新编译。


- 奇怪的错误,居然报错
esp32-idf的组件库有错误,官方怎么可能有错了~错的肯定是我,使用指令清空编译目录,然后再重新编译。果然,没有错误,顺利通过。证明有时候遇事不决,不能怎么解决,清空以下重新编译,是一个选择。

- 编译成功后就下载进去, 下载成功后监听看看,可以看到有
ROM日志的启动流程打印。其中在flash中报错,说flash芯片大小不对,配置文件为2MB,实际上4MB。

- 打开配置菜单
(Top) → Serial flasher config → Flash size逐级找到该配置项,改为4MB,重新编译下载即可,再监听时,启动流程就没有这句警告了。

- 最后使用git对比,改了flash配置后
sdkconfig有哪些变动:可以看到4MB的宏定义变成y,表示被定义,而2MB的宏定义变成注释,下面的选项字符串也变更了。


六、调试工程
推荐教程: ESP32 JTAG Debug 教程 Michael_ee
以下内容大部分都是来自视频教程的截图笔记
JTAG的全称是Joint Test Action Group(联合测试行动组),最初是由几家电子厂商联合制定的标准,后成为国际通用的硬件调试与测试接口标准。JTAG是接口,记住四线定义。ESP32S3除了标准的四线JTAG,还额外配置了USB-to-JTAG模块。
USB插入电脑,在
通用串行总线设备中有USB JTAG/serial debug uint,驱动程序提供商是Iibwdi;

OpenOCD的全称是Open On-Chip Debugger,是一个开源的片上调试工具,主要用于嵌入式系统的调试、编程和边界扫描测试。
就是提供一种免费的调试方法?想起来STM32的调试器卖得老贵了?

- 安装esp-idf,tool工具中,已经包含了
OpenOCD,打开idf终端,输入指令openocd --version就可以查看版本。输入指令echo %OPENOCD_SCRIPTS%可以查看安装路径。

- 安装目录的
board文件夹内的esp32s3-builtin.cfg是之后需要用的配置文件, 里面规定了使用esp_usb_jtag和esp32s3。注释还写明了,使用指令可以启动OpenOCD。
openocd -f board/esp32s3-builtin.cfg

- 还是在idf终端,输入命令即可,注意需要将JTAG插入后才能打开
OpenOCD。如果要关闭进程, 连续输入两次Ctrl+C即可。

-
GDB的全称是 GNU 调试器(GNU Debugger)- 核心功能:用于调试 C、C++、汇编等编程语言的程序,支持断点设置、单步执行、变量查看、堆栈分析等。
GDB通常与GCC编译工具链配合使用,需在编译时添加-g选项生成调试信息。- 启动
GDB连接OpenOCD之前,确保下载了新的程序,并且打开了OpenOCD。
-
在 idf 的 tool 目录中可以找到
gdb.exe文件。虽然不同 idf 版本结果不太一样,但是名字一样,所以直接按名字找(猜)一下即可。如下,在 idf 终端中输入,如果有响应返回即可。
xtensa-esp32s3-elf-gdb --version # ESP32S3
xtensa-esp32-elf-gdb --version # ESP32
riscv32-esp-elf-gdb --version # ESP32-C3/C6

- 为 GDB 指定对应 flash 下载
.bin文件的.elf文件。.map文件就是熟悉的内存分配文件了。

- 还需要使用
-x指定启动参数,在工程本地目录创建文件gdbinit无后缀名。注意:文件内不可以有注释,下面只是笔记。
# 以下是 工程目录/gdbinit 的内容
set remotetimeout 100 # 超时时间
target extended-remote :3333 # 连接端口
set remote hardware-watchpoint-limit 2 # 硬件支持断电
mon reset halt # 重启 CPU
flushregs # 复位
thb app_main # 卡函数断点
c # 继续运行
- 最后使用命令启动。如何可以看到已经卡在断点处了,在命令行输入
q可以退出。
xtensa-esp32s3-elf-gdb build/blink.elf -x gdbinit # 启动指令, 指定 .elf 文件和 gdbinit 文件

- 常用指令有下面这些,由ai总结:我也懒得记了,主要是了解启用流程,这样如果用不了就可以排查问题。
- 小白实际上手还得是有图形界面。试用了几条指令,确认无误后即可。
以下是 **GDB(GNU Debugger)** 常用的 **8个核心调试指令**,适合嵌入式(如 ESP32)和通用程序调试:
以下 () 代表缩写,<> 代表参数。
---
### **1. 启动/附加调试**
#```bash
gdb <可执行文件> # 启动调试(如 xtensa-esp32-elf-gdb build/app.elf)
attach <进程ID> # 附加到正在运行的进程(Linux 下常用)
#```
---
### **2. 断点管理**
#```bash
break <函数名> # 在函数入口设断点(如 break app_main)
break *<地址> # 在内存地址设断点(如 break *0x400d1000)
break <文件名:行号> # 在指定文件行号设断点(如 break main.c:42)
info breakpoints # 查看所有断点
delete <编号> # 删除断点(如 delete 1)
#```
---
### **3. 运行/继续/单步执行**
#```bash
run # 从头运行程序(直到断点/崩溃)
continue (c) # 继续执行到下一个断点
next (n) # 单步执行(跳过函数)
step (s) # 单步进入函数
finish # 执行完当前函数并暂停
#```
---
### **4. 查看变量/内存**
#```bash
print <变量名> # 打印变量值(如 print x)
print *<指针> # 打印指针内容(如 print *ptr)
x/<格式> <地址> # 检查内存(如 x/8xw 0x3ffb0000 显示8个32位十六进制值)
info locals # 查看当前函数的局部变量
#```
---
### **5. 堆栈回溯**
#```bash
backtrace (bt) # 查看调用堆栈(定位崩溃位置)
frame <编号> # 切换到指定堆栈帧(如 frame 2)
info args # 查看当前帧的函数参数
#```
---
### **6. 监视点(Watchpoint)**
#```bash
watch <变量名> # 当变量被修改时暂停(如 watch global_var)
rwatch <变量名> # 当变量被读取时暂停
awatch <变量名> # 读写均暂停
#```
---
### **7. 线程调试(多线程程序)**
#```bash
info threads # 列出所有线程
thread <ID> # 切换到指定线程(如 thread 2)
thread apply all bt # 查看所有线程的堆栈
#```
---
### **8. 退出/保存断点**
#```bash
quit (q) # 退出 GDB
save breakpoints <文件> # 保存断点到文件(如 save breakpoints ~/gdb_breaks)
#```
---
### **附:常用组合技巧**
#```bash
start # 运行到 main 函数暂停(等效于 break main + run)
layout src # 显示源代码窗口(TUI 模式)
ctrl + x + a # 切换图形/命令行模式(TUI)
#```
---
### **适用场景**
- **ESP32 开发**:结合 OpenOCD 和 GDB 调试(如通过 `idf.py gdb` 启动)。
- **崩溃分析**:`bt` 查看崩溃时的调用栈。
- **硬件调试**:`x/` 检查内存映射寄存器(如外设寄存器)。
七、使用 VS Code
- 经过上面的流程已经对 ESP 项目的构成有大概认知了,现在开始使用 vs code 快捷操作。
- 先创建一个空的文件夹,用 vscode 打开文件夹,第一件事就是打开设置,选择一个合适的 配置文件 避免混乱!!!

- 然后开始创建工程,大体内容上一篇教程已经说过了。
配置 ESP-IDF 扩展:选择离线安装的 IDF 目录。展示示例项目:选择闪灯例程。- 或
新项目向导:一个空的 Hello 工程。

- 用 vscode 创建的话,目录下默认就有
.devcontainer和.vscode。前者掠过,重点是后者。其中包含3个内容:c_cpp_properties.json:C 和 C++ 代码导航及语法高亮。launch.json:调试配置。settings.json:工作区设置。

- 使用快捷键
Ctrl+Shift+P打开命令面板,输入指令可以打开对应设置页面。有些指令可以输入中文,有些不行,所以建议统一输入英文检索指令。 - 注意!!!有
首选项:打开用户设置和首选项:打开工作区设置。不要弄混了。前者是全局,后者是当前目录。
中文:C/C++: 编辑配置 (UI)
英文:C/C++: Edit Configurations (UI)
中文:首选项:打开工作区设置
英文:Preferences: Open Workspace Settings
- 我们可以把三个文件都删了,然后尝试重新配置生成。
- 首先是工作区设置
settings.json,只需要把 idf 的指令点击一边, 跟着选择配置即可。烧录端口,烧录方式,芯片类型,OpenOCD的.cfg文件,idf路径。全都弄好了。

- 最后别忘记更改
sdkconfig里的配置,改flash为4MB,改闪灯方式。

- 其次是语法高亮和跳转的C/C++配置文件,这给需要用指令打开配置界面,会自动添加
settings.json文件。里面的设置就这条比较关键一点,将编译后的包含路径一次性导入。这样就可以跳转代码了。如果.c文件还报错显示红色波浪线,那可能是因为你写了一些多余的东西在includePath、defines、forcedInclude和browse.path。
{
"configurations": [
{
"name": "ESP IDF",
"compileCommands": [
"${workspaceFolder}/build/compile_commands.json"
], // 注意手动将这给放在前面,否者会报莫名其妙的警告。应该是路径优先级覆盖问题。
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "${default}"
}
],
"version": 4
}

- 最后一个就是调试配置文件
launch.json,直接点击生成默认的内容,就可以使用GDB。

- 手动用命令行开启
GDB还需要一个gdbinit的设置文件,使用 vscode 应该是集成在launch.json中了。
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "gdbtarget",
"request": "attach",
"name": "Eclipse CDT GDB Adapter"
}
]
}
- 其实上面三个文件也可以使用这功能
添加 .vscode 子目录文件, 一次性添加默认值模板。和刚创建工程时差不多。
中文:ESP-IDF:添加 VS Code 配置文件
英文:ESP-IDF: Add VS Code Configuration Folder

- 然后直接点击
ESP-IDF:构建、烧录和监视,一气呵成。然后点击运行调试,也是没有问题的。可以单步,虽然好像有点卡。 - 调试可以看到寄存器信息,不过需要
.svd文件。到官方仓库 espressif/svd 获取,这个仓库要魔法才能打开。

- 将
esp32s3.svd文件放在工程内,然后设置idf.svdFilePath工作区的参数。再次打开调试界面就能看到寄存器列表了。


八、总结
- 至此算是打通基本流程了。还剩下组件的创建和修改没讲。留到下一篇笔记。
877

被折叠的 条评论
为什么被折叠?



