两个USB口各走哪条路径
固定IDF5.5.5 / S3-DevKitC1v1.1 / WROOM-1-N8R8;8MiB Flash,PSRAM不初始化。完整debug固件、GDB命令文件、OpenOCD配置与空observations.csv都在包内。无本站USB/JTAG实体连接、断点、继续、复位或板端调用栈结果;本机GDB读取ELF不能替代这些。
板载USB-to-UART口通过CP2102N承担上传和115200日志;另一个ESP32-S3原生USB口直接到GPIO19(D-)/20(D+),使用芯片内建USB Serial/JTAG控制器进入OpenOCD/GDB。CP2102N串口可正常输出,不证明原生JTAG已经连上。只接原生USB不等于这份默认UART日志会出现在原生CDC。
不外接GPIO19/20负载、不初始化TinyUSB、不改eFuse路由,也无需外接四线JTAG器。原生数据线与电脑USB口要能传数据;确认板修订与接口丝印。USB供电按官方板说明(USB域可一个或两个口),不再并板端5V/3V3或外部电源;两个USB均来自同一电脑,不能把这套调试条件当测流条件。
- 做到这里,你应该看到
- 先核固定板型、版本与本例结果范围;将尚未做的实体步骤保留空白。
参考:[1] 固定SDK的S3原生USB/JTAG与Windows驱动[6] 固定官方DevKitC-1 v1.1:N8R8、双USB接口、GPIO与供电
固定工具和系统准备
本机复用与SDK tools.json推荐同版的xtensa-esp-elf-gdb17.1_20260402与openocd-esp32 v0.12.0-esp32-20260424,不另装SDK。先在当前IDF环境核idf.py --version、xtensa-esp32s3-elf-gdb --version、openocd --version;工具存在只证明入口。
Windows按官方5.5.5 built-in JTAG文档安装Espressif WinUSB JTAG驱动,辨认VID303A/PID1001的原生USB JTAG接口,别把CP2102N串口驱动整个替换;macOS使用libusb原生访问,不套Windows驱动;Linux按固定OpenOCD贡献的60-openocd.rules部署udev并重新插拔,别把管理员权限当所有连接问题的通解。Windows路径/终端按E01,不把macOS绝对工具路径复制过去。
如果已有安全配置或eFuse状态不明,只按设备原策略核对。可在授权自己的实验板上执行只读python -m espefuse --chip esp32s3 -p REPLACE_PORT summary并保存状态;本例没有任何burn命令、不通过关闭安全功能或修改eFuse凑通JTAG。永久禁用JTAG的状态不能靠普通RESET恢复。
参考:[1] 固定SDK的S3原生USB/JTAG与Windows驱动[3] 调试限制与注意事项[4] SDK推荐工具版本与各平台下载SHA[5] OpenOCD固定版本的S3内建USB/JTAG入口
有意卡住一个任务,不制造忙等死机
debug_worker每250ms递增probe.iteration,第5次进入noinline debug_pause:phase置1,while(!release_gate)每100ms vTaskDelay。它只是有意等待,heartbeat任务每500ms自增仍可调度;不禁看门狗、不占满CPU。release_gate只有调试器在目标核停止时修改,worker写probe、heartbeat写自己的计数;volatile不被拿来当多线程互斥。
让有意停点可解释:正常result=input*2+1;门未放行时只停worker;放行后phase2、进入debug_checkpoint。每次真正复位BSS重新初始化,门又关闭。这里只用小整数,不把任意外部输入放进乘法造成另一个未解释的故障。
从干净配置构建和保存ELF
固定Og调试信息、源码和ELF必须来自同一次构建;app.bin与ELF不同,不能拿网页复制来的地址套另一镜像。保存bin/ELF/map/config/锁/原日志/SHA,不能只保存串口backtrace。FLASH8MiB与OPI8MiB PSRAM是两种资源,本例不使用后者。既有配置优先,改defaults后若复用旧sdkconfig要核最终生成值。
idf.py -B build -D SDKCONFIG=build/sdkconfig -D SDKCONFIG_DEFAULTS=sdkconfig.defaults build
# 先按F06确认自己的桥接串口,再执行:
idf.py -B build -p REPLACE_UART_PORT flash monitor
先做不连板的本机检查
offline.gdb只读函数/变量地址、Probe类型、源码行和反汇编。OpenOCD配置加载后立即shutdown,不init适配器,不读取任何运行寄存器。本站这两命令实际Exit0,不能据此填写“断点成功”“已读运行变量”或截图伪装实连。若找不到board/esp32s3-builtin.cfg,先核OPENOCD_SCRIPTS属于同一工具版,不改SDK文件。
xtensa-esp32s3-elf-gdb --nx --batch build/esp32_jtag_gdb_debug.elf -x debug/offline.gdb
openocd -f debug/openocd.cfg -c shutdown
参考:[2] GDB断点、线程、调用栈和复位步骤[4] SDK推荐工具版本与各平台下载SHA[5] OpenOCD固定版本的S3内建USB/JTAG入口
真正连接后的断点、继续与复位步骤
终端A运行openocd -f debug/openocd.cfg并保留日志,只有读到真实S3 TAP/CPU后才可记链路成功;本例设10MHz,信号问题可按手册下调,不凭频率猜成功。终端B在工程根执行:
attach连接localhost3333、monitor reset halt、app_main临时硬件断点后continue;exercise在debug_pause停、next执行phase赋值、info threads/bt/print probe/heartbeat_count。此时为让目标实际等待,可手动continue,等待两秒按Ctrl+C,再读heartbeat_count确认它增长,查看worker栈是否位于vTaskDelay/debug_pause。运行中不能把静止调试器的墙钟等待当任务延时。
全部停止后set var release_gate=true,clear debug_pause,break debug_checkpoint,continue,再next/print probe/bt观察恢复;命令文件已经包含这条放行路径,若要先做心跳实验应逐条交互执行而非整段source自动放行。断点数有限,只留必要的断点;不要把Og下可能优化掉的局部变量当内存损坏。再次验证monitor reset halt、thbreak app_main、continue,记录真实复位后门与计数重新开始。以上所有运行数值和栈图在本站仍空,读者自行保存原始日志。
xtensa-esp32s3-elf-gdb --nx build/esp32_jtag_gdb_debug.elf -x debug/attach.gdb
# app_main处停住后,在GDB输入:
source debug/exercise.gdb
参考:[1] 固定SDK的S3原生USB/JTAG与Windows驱动[2] GDB断点、线程、调用栈和复位步骤[3] 调试限制与注意事项
故障分层与恢复
无设备:检查原生口/数据线/驱动/udev/OPENOCD_SCRIPTS;有TAP但一运行失联:检查应用是否复用了19/20或进入不支持的睡眠/安全状态;地址/源码行不匹配:核同次ELF和固件SHA;线程列表异常:先核OpenOCD与FreeRTOS支持再读裸PC/backtrace。不要把别的ESP32 GPIO12启动电压规则套到S3原生USB路径。
清断点后monitor reset run,必要时正常RESET;有意门每次重启仍会重现。完成实验刷回自己已保存的正常固件。没有需要修改eFuse、关闭Secure Boot/Flash Encryption或关闭看门狗的步骤。所有USB枚举/TAP/断点/运行变量/复位实板记录保留pending,QEMU或本机反汇编也不冒充原生USB电气验证。
参考:[1] 固定SDK的S3原生USB/JTAG与Windows驱动[2] GDB断点、线程、调用栈和复位步骤[3] 调试限制与注意事项
许可与具体来源
原创应用/脚本MIT。固定SDK5.5.5的jtag-debugging/configure-builtin-jtag.rst、using-debugger.rst、tips-and-quirks.rst及tools/tools.json是技术依据;OpenOCD固定20260424的board/esp32s3-builtin.cfg/target脚本和GPL-2.0原许可保留其范围。GDB为GPL-3.0+工具,不打包进应用ZIP。官方DevKitv1.1引脚/USB/电源手册独立核对,实际结果表为空。
参考:[1] 固定SDK的S3原生USB/JTAG与Windows驱动[2] GDB断点、线程、调用栈和复位步骤[4] SDK推荐工具版本与各平台下载SHA[5] OpenOCD固定版本的S3内建USB/JTAG入口[6] 固定官方DevKitC-1 v1.1:N8R8、双USB接口、GPIO与供电
有意停点的完整程序
以下为下载工程中对应文件的全文;带文件名的注释只是网页分隔,构建时使用独立原文件。其它构建配置、锁、许可与夹具在完整示例中。
// ---- main/main.c ----
/* SPDX-License-Identifier: MIT */
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
/* Only worker writes probe; only heartbeat task writes heartbeat_count.
* release_gate is modified by GDB while all target cores are halted. */
typedef struct {uint32_t iteration; int32_t result; uint32_t phase; int64_t at_us;} Probe;
volatile Probe probe;
volatile bool release_gate;
volatile uint32_t heartbeat_count;
__attribute__((noinline)) int debug_checkpoint(int input){
int doubled=input*2;
probe.result=doubled+1;
return probe.result;
}
__attribute__((noinline)) void debug_pause(void){
probe.phase=1;
puts("E06 WAIT_GATE: worker yields; heartbeat task continues. GDB set release_gate=true after halting.");
while(!release_gate)vTaskDelay(pdMS_TO_TICKS(100));
probe.phase=2;
puts("E06 RESUMED: debug_checkpoint will run; no watchdog/eFuse settings changed.");
}
static void heartbeat(void *arg){(void)arg;for(;;){++heartbeat_count;vTaskDelay(pdMS_TO_TICKS(500));}}
static void worker(void *arg){
(void)arg;
for(;;){
++probe.iteration;probe.at_us=esp_timer_get_time();
if(probe.iteration==5)debug_pause();
int value=debug_checkpoint((int)(probe.iteration%1000));
printf("E06 iteration=%lu result=%d phase=%lu\n",(unsigned long)probe.iteration,value,(unsigned long)probe.phase);
vTaskDelay(pdMS_TO_TICKS(250));
}
}
void app_main(void){
puts("E06 debug build: use native USB Serial/JTAG for OpenOCD, USB-to-UART for these logs; no peripherals onGPIO19/20.");
if(xTaskCreate(heartbeat,"heartbeat",2048,NULL,2,NULL)!=pdPASS){puts("E06 STOP heartbeat allocation");return;}
if(xTaskCreate(worker,"debug_worker",4096,NULL,3,NULL)!=pdPASS){puts("E06 STOP worker allocation; heartbeat alone is not a successful demo");return;}
}
参考:[1] 固定SDK的S3原生USB/JTAG与Windows驱动[2] GDB断点、线程、调用栈和复位步骤[3] 调试限制与注意事项[4] SDK推荐工具版本与各平台下载SHA[5] OpenOCD固定版本的S3内建USB/JTAG入口[6] 固定官方DevKitC-1 v1.1:N8R8、双USB接口、GPIO与供电
离线、连接与放行命令文件
以下为下载工程中对应文件的全文;带文件名的注释只是网页分隔,构建时使用独立原文件。其它构建配置、锁、许可与夹具在完整示例中。
# ---- debug/openocd.cfg ----
# Only USB Serial/JTAG; no physical eFuse or flash-writing command.
source [find board/esp32s3-builtin.cfg]
adapter speed 10000
# ---- debug/offline.gdb ----
set pagination off
info address debug_pause
info address debug_checkpoint
info address probe
ptype Probe
info line debug_pause
disassemble debug_pause
quit
# ---- debug/attach.gdb ----
set pagination off
set confirm off
target remote localhost:3333
monitor reset halt
thbreak app_main
continue
# Stopped at app_main: source debug/exercise.gdb when ready.
# ---- debug/exercise.gdb ----
break debug_pause
continue
# At the entry of debug_pause, phase may still be0; execute next to see phase1.
next
info threads
bt
print probe
print heartbeat_count
set var release_gate = true
clear debug_pause
break debug_checkpoint
continue
print probe
bt
# Continue manually. To reset: monitor reset halt; thbreak app_main; continue.
- 做到这里,你应该看到
- 按README保存自己的原始日志和SHA;下载包的observations.csv实测列仍为空,不能用合成输入补填。
参考:[1] 固定SDK的S3原生USB/JTAG与Windows驱动[2] GDB断点、线程、调用栈和复位步骤[3] 调试限制与注意事项[4] SDK推荐工具版本与各平台下载SHA[5] OpenOCD固定版本的S3内建USB/JTAG入口[6] 固定官方DevKitC-1 v1.1:N8R8、双USB接口、GPIO与供电
资料来源与版本说明
保留原计划E06用途与slug;固定上游、实际本机构建和适用的逻辑检查独立留证。原生USB/JTAG断点、运行栈、继续和复位仍需实板,离线GDB不代替实体记录。资料核对日期:。资料核对、程序构建与实板测试分别记录,不互相替代。