做嵌入式开发这些年,被问得最多的问题就是:“为什么我的J-Link连不上板子?”很多人一上来就把JTAG、SWD、ST-Link这些嵌入式调试接口混在一起看,线序更是全靠猜。结果要么报“Could not stop Cortex-M device”,要么干脆识别不到芯片,能急出一头汗。这篇保姆级指南我就把JTAG和SWD的来龙去脉、J-Link接线方法、调试引脚复用,以及我踩过的那些通信失败坑一次讲清楚,给正在被调试器折磨的你一份可以直接照着接的完整方案。
1. 先搞清楚:JTAG和SWD到底差在哪
1.1 从调试的本质说起
不管接口叫什么名字,调试器做的事情本质上是同一件事:访问目标芯片的内核寄存器、读写内存、设置断点、单步执行、下载程序。而这些操作都依赖一个叫“调试访问端口”的硬件模块,JTAG和SWD就是通往这个模块的两种“路”。
JTAG的全称是Joint Test Action Group,对应的标准是IEEE 1149.1,最早是1990年为了板级测试设计出来的。它最初的目的不是调试,而是边界扫描测试——也就是通过芯片引脚上的边界扫描单元,把板子上的焊接关系“扫”一遍,看看有没有虚焊、短路。后来ARM和其他厂商发现这套机制用来做调试也很顺手,于是JTAG就成了嵌入式调试的事实标准。
JTAG硬件上最少需要5根线:TMS(模式选择)、TCK(时钟)、TDI(数据输入)、TDO(数据输出),以及可选的TRST(测试复位)。如果需要让目标系统复位,通常还要拉一根nRESET。信号通过一组有限状态机来驱动,这套状态机包含Test-Logic-Reset、Run-Test/Idle、Select-DR-Scan、Select-IR-Scan、Capture-DR、Shift-DR、Exit1-DR、Update-DR等一系列状态。你可以把它理解成一条流水线:TCK每个上升沿,TDI上的数据就会往状态机的移位寄存器里推一格,TDO对应的数据被挤出来,连续推几个周期就能完成一次寄存器写入。
JTAG还有个很实用的特性,就是支持菊花链。多个芯片的TDI和TDO可以首尾串联,调试器通过TMS和TCK统一控制整条链上的所有芯片。如果你在一个板子上串联了多颗支持JTAG的器件,这种拓扑结构就非常方便。
1.2 为什么SWD能“后来居上”
SWD全称Serial Wire Debug,是ARM专门为Cortex-M系列设计的调试接口。它在JTAG的基础上做了极大的精简,数据线只剩两根:SWDIO(双向数据线)和SWCLK(时钟线)。换句话说,SWD是把JTAG的TMS和TDO合并成了一根双向线,TDI干脆就不需要了。再加上一根公共地,绝大多数情况下三根线就能完成调试。
SWD能够后来居上,核心原因是嵌入式系统的体积越来越小,单片机引脚越来越紧张。ST-Link、J-Link、DAP-Link这些调试器都同时支持JTAG和SWD,但实际项目里,我几乎99%都在用SWD。它占用引脚少、排线简单、PCB布线方便,而且下载和调试性能完全够用。在Cortex-M上,SWD的连接速率通常可以跑几十MHz,配合J-Link这种调试器,烧录几十KB固件基本是秒级完成。
有人担心SWD两根线会不会不稳,其实ARM在设计SWD时专门考虑了可靠性,加入了一套同步机制:调试器在启动时会发送一长串的切换序列,将目标芯片从JTAG模式切到SWD模式,并且通过线复位来重新建立连接。只要接线正确、电平匹配,SWD的稳定性并不比JTAG差。
1.3 你手里的连接器是哪种
实际到板子层面,JTAG和SWD往往不以裸线的形式出现,而是以排针、牛角座、扁平电缆的形式集成在调试器或开发板上。最常见的几种规格:
- 20针JTAG:J-Link上最典型的接口,2.54mm双排排针,带防呆缺口。
- 14针JTAG:老式开发板常见,比如一些ARM9、Cortex-A板子。有一个物理定位键防止插反,就是热词里提到的“14针双排jtag定位键”。
- 10针JTAG/SWD:很多国产开发板喜欢用这种,引出的引脚可能同时包含JTAG和SWD信号。
- 9针SWD:J-Link V9这种调试器侧面的小插座,很多转接板也做成9针。
- 4针/5针SWD:目标板上的调试排针,一般是VCC、SWDIO、SWCLK、GND,有的再加一个RST。
这里必须强调一点:连接器的物理形态不能决定协议,必须看具体哪个引脚连到芯片的哪个功能上。比如一个10针的座子,丝印上标了TMS、TCK、TDO、TDI,那它就是完整JTAG;如果只标了SWDIO和SWCLK,哪怕它是10针的,也只能走SWD。判断一个调试口是JTAG还是SWD,永远看信号名,不看针数。
2. J-Link接线:20针、9针与SWD的最小系统
2.1 J-Link 20针座子引脚定义
标准J-Link的20针接口定义如下,记住这张表,很多问题都能省掉。这个接口是2.54mm双排母座,针脚排列为奇数在第一排、偶数在第二排,左上角通常是Pin 1,丝印处有三角标记或圆点。
| 引脚 | 信号 | 说明 | 引脚 | 信号 | 说明 |
|---|---|---|---|---|---|
| 1 | VTref | 目标板参考电压 | 2 | NC / VCC | 某些版本接VCC |
| 3 | nTRST | JTAG测试复位 | 4 | GND | 地 |
| 5 | TDI | JTAG数据输入 | 6 | GND | 地 |
| 7 | TMS | 模式选择/SWDIO | 8 | GND | 地 |
| 9 | TCK | 时钟/SWCLK | 10 | GND | 地 |
| 11 | RTCK | 返回时钟 | 12 | GND | 地 |
| 13 | TDO | JTAG数据输出 | 14 | GND | 地 |
| 15 | nRESET | 系统复位 | 16 | GND | 地 |
| 17 | DBGRQ | 调试请求(可选) | 18 | GND | 地 |
| 19 | 5V-Supply | 5V电源输出(可选) | 20 | GND | 地 |
VTref这脚非常关键。J-Link会通过它检测目标板的参考电压,从而调整输出电平。如果VTref没有连接,J-Link不知道目标板是3.3V还是5V,很多后续操作都没法进行。所以哪怕你只用四根线连SWD,VTref也推荐接上。而第19脚的5V输出是可选的,设计目标是从调试器给目标板供电时才会用到,多数情况下不建议用,否则一旦目标板已有供电,可能会形成两个电源打架。
2.2 9针接口的SWD定义与对应关系
J-Link V9侧面那个9针小插座,实际上就是SWD模式最常见的引出方式。这个排针的引脚定义如下:
| 引脚 | 信号 | 说明 |
|---|---|---|
| 1 | VTref | 目标板参考电压 |
| 2 | SWDIO | 双向数据 |
| 3 | GND | 地 |
| 4 | SWCLK | 时钟 |
| 5 | GND | 地 |
| 6 | SWO | 串行跟踪输出(可选) |
| 7 | TDI | 保留/NC |
| 8 | TDO | 保留/NC |
| 9 | RESET | 目标复位(可选但推荐) |
不同品牌、不同版本的J-Link 9针接口定义可能略有差别,有些会把NC脚换成其他信号,所以接线前先对一下调试器外壳上的丝印。我见过不少人拿着淘宝十几块的转接板,丝印印错了或者没印,结果插一次烧一次。
如果用9针座接目标板的4针SWD,只需要对应:1接VTref,2接SWDIO,4接SWCLK,3或5接GND。SWO在普通调试中不需要,只有用ITM/SWO做printf输出时才会用到。RESET在某些异常情况下很有用,后面会专门讲。
2.3 只接4根线,原来SWD这么接
如果你不想被20针的排线折磨,最省心的办法是直接绕开JTAG座,把J-Link的SWD信号用杜邦线或者飞线接到目标板的SWD排针。这里我给出一套经过验证的对应关系:
| J-Link 20针 | J-Link 9针 | 信号 | 目标板SWD排针 |
|---|---|---|---|
| 1 | 1 | VTref | VCC/3.3V |
| 7 | 2 | TMS/SWDIO | SWDIO |
| 9 | 4 | TCK/SWCLK | SWCLK |
| 4/6/8/10等 | 3/5 | GND | GND |
如果目标板没有VCC排针,那就只接三根:SWDIO、SWCLK、GND。但要注意,这种情况下J-Link无法检测目标板电压,部分芯片或调试器可能拒绝连接。所以做开发板留调试口时,VCC一定要引出。
接好线以后,打开J-Link Commander(JLink.exe),选择设备型号时如果里面的芯片型号列表和你手头芯片不完全一致,选同系列的替代型号通常也能连。输入connect命令后,J-Link会自动检测目标电压,如果显示Voltage measured:3.3V,就说明VTref接对了。接着它会提示选择连接方式,输入S(SWD)或者按提示选择SWD模式,然后就能看到目标芯片的IDCODE。此时调试链路就通了。
2.4 连接图的正确“读法”:从丝印到线序
因为这里没法放实物图,我把一张典型的“J-Link 20针转目标板SWD 4针”画成字符图,你对着实物一看就懂:
J-Link 20针母座 目标板SWD排针 ┌──────────────┐ ┌──────────┐ │ 1 VTref ────┼────────┤ VCC/3.3V │ │ 3 nTRST │ │ │ │ 5 TDI │ │ │ │ 7 TMS ─────┼────────┤ SWDIO │ │ 9 TCK ─────┼────────┤ SWCLK │ │ 11 RTCK │ │ │ │ 13 TDO │ │ │ │ 15 nRESET │ │ │ │ 17 DBGRQ │ │ │ │ 19 5V-Supply │ │ │ │ 偶数是GND ───┼────────┤ GND │ └──────────────┘ └──────────┘ Pin1标记(三角/圆点)有几个读图规律:第一,J-Link 20针上Pin1的位置,通常母座旁边有白色小三角、圆点或者“1”字丝印,杜邦线按这个方向排就不会错。第二,目标板上的SWD排针,很多板子设计成4针或5针,注意别把SWDIO和SWCLK接到VCC/GND上。第三,如果开发板丝印上写的是TMS而不是SWDIO,那是同一根线,直接接SWDIO即可;写的是TCK,就直接接SWCLK。
3. 接线后连不上?从灯和报错定位问题
3.1 J-Link指示灯到底在说什么
接线完成不代表万事大吉,报错信息才是第一手线索。J-Link上的指示灯颜色能帮你快速判断状态:绿灯常亮表示USB连接正常,等待操作;红色闪烁通常表示没有检测到目标电压或者正在报错;黄色灯在不同版本上含义不同,一般是固件初始化或忙状态。如果你看到灯完全不亮,先换USB线。这里要提醒一句,有些USB线只有供电没有数据线,或者线材劣质导致USB枚举失败,这是“假性故障”里最高发的一种。
如果USB正常,但一连接就报No J-Link found,那问题多半在驱动和权限。Windows下换一个USB口重新插,打开设备管理器看有没有识别到J-Link;Linux下可能需要处理udev规则,否则普通用户访问不到USB设备。
3.2 连接失败:No J-Link found与SWD/JTAG Communication Failure
在Keil、IAR或者JLink Commander里,最常见的两个报错是“No J-Link found”和“SWD/JTAG Communication Failure”。前者是USB层没通,后者是USB通了但目标芯片没响应。
SWD/JTAG Communication Failure的排查顺序,我的习惯是:
- 用万用表蜂鸣档量SWDIO、SWCLK、GND是否一一对应,很多时候是杜邦线插错孔位。
- 量目标板供电,确认核心电压存在,且VTref引脚能测到对应电压。
- 确认BOOT引脚状态。一部分芯片如果BOOT0悬空或拉错,可能停留在系统存储器或内部ROM里,导致调试口不响应。特别是通过串口下载过的板子,很容易忽略改跳线。
- 断开目标板上的其他外设,某些外设会把SWDIO/SWCLK拉死。这种情况在批量板上尤其常见,量测时是通的,一跑系统就失败。
- 降低连接速率。在J-Link设置里,把接口速度从自动改成最低的100kHz,常常能救回一些布线比较差的板子。
3.3 经典报错:Could not stop Cortex-M device! Please check the JTAG cable.
这句话几乎每个用Keil的人都被吓过。它字面意思其实是“连接已经建立,但无法停止Cortex-M内核”,不是线完全没通。最常见的原因是目标芯片干活干得太投入,根本不鸟调试器的暂停信号。比如程序里有STOP、STANDBY低功耗模式,或者关掉了调试时钟,内核睡眠到连调试器都拉不醒。
处理这个报错,有几个实测有效的方法:
- 先按住目标板的复位键,再点击连接,在Keil里下载/调试开始后一两秒内释放复位。这个操作的本质是让内核从复位向量开始运行前,调试器已经抢占先机并接管了内核。
- 把BOOT0拉到1(高电平),让芯片从系统存储器启动,绕过用户Flash里的“跑飞程序”。连接成功后,再切回Flash启动重新下载。这招对STM32、GD32都有效。
- 检查nRESET电路。如果复位引脚上挂的电容太大,复位时间太长,调试器也可能报这个错。把电容从100nF换成10nF再试。
- 检查SWCLK线上是否被强上拉或强下拉。SWCLK信号在部分芯片上需要弱下拉,如果板子上焊接了10k以上的下拉,通常没问题;如果下拉太强,时钟信号可能被压到无法跳变。
另外,SWDIO上串联33Ω电阻、SWCLK上串联33Ω电阻,是很多量产板的标准做法,能在一定程度上抑制信号反射,但别用大阻值,否则信号幅度不够也会导致通信失败。
3.4 J-Link clone警告怎么处理
热词里那句“J-Link software with a clone is forbidden and illegal. Proper operation cannot be guaranteed”是Segger驱动的防盗版弹窗。如果你遇到这个弹窗,说明当前调试器不是官方正版设备,驱动检测到了克隆版本,拒绝继续工作。
我不能教你绕过这个检测,因为那涉及侵权和固件安全问题。但可以给几个实际可行的替代方案:
- 预算允许就买官方正版J-Link,或者使用Segger授权的调试器。
- 学生党、个人开发者完全可以用ST-Link或者DAP-Link代替。DAP-Link是CMSIS-DAP标准调试器,开源的,淘宝几十块就能买到,STM32、GD32、NXP、瑞萨都能连,Keil和IAR也支持得很好。
- 如果现有J-Link克隆只是触发警告,但还能连接,我建议立刻备份当前固件,不要贸然升级驱动。当然这种状态随时可能失效,重要项目还是要尽早换正规工具。
我见过有人为了绕检测专门找老版本驱动,结果驱动崩溃导致系统蓝屏,实在得不偿失。
4. 引脚被“抢”了:调试引脚复用与关闭
4.1 STM32/GD32的调试引脚默认状态
很多人不理解热词里“stm32禁用jtag”是什么意思。其实在STM32、GD32的大多数型号上,PA13、PA14、PA15、PB3、PB4这五个引脚上电后默认并不是普通GPIO,而是SWD和JTAG的调试引脚。它们的默认功能是:
- PA13:SWDIO(JTAG的TMS)
- PA14:SWCLK(JTAG的TCK)
- PA15:JTDI
- PB3:JTDO
- PB4:JNTRST
也就是说,如果程序里想把这几个引脚当普通IO用,必须先把它们从调试功能里“释放”出来。STM32F1芯片复位后的SWJ_CFG配置是“完整JTAG+SWD”都使能,PA15、PB3、PB4都被调试器占着。如果你的项目只用SWD,最合理的做法是关闭JTAG、保留SWD,这样PA15、PB3、PB4就能当普通GPIO用了。
4.2 关闭JTAG保留SWD的寄存器操作
STM32F1系列通过AFIO_MAPR寄存器中的SWJ_CFG字段控制调试引脚功能。标准库写法:
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);这行代码执行后,JTAG功能关闭,SWD保留,PA15、PB3、PB4恢复为GPIO。如果你要彻底关闭所有调试口,用下面的写法:
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);注意,这个操作会同时关闭SWD,执行完这条代码后,这块板子就没法再用调试器连了。必须提前确认程序里还有其他升级通道,比如串口Bootloader,否则就要用ST-Link的复位连接技巧才能救回来。
STM32F4系列和GD32F4系列用的是SYSCFG_CFGR1寄存器的SWJ_CFG字段。HAL库里有现成宏:
__HAL_AFIO_REMAP_SWJ_NOJTAG(); // 关闭JTAG,保留SWD这个宏会把SWJ_CFG字段设置为“JTAG-DP Disabled,SW-DP Enabled”,PA15、PB3、PB4释放为普通IO,同时保留PA13、PA14的SWD调试功能。这是我在GD32F4和STM32F4项目里最常用的初始化配置。
要注意一点:释放调试引脚必须在系统时钟和外设初始化之前完成,否则用到了PA15等引脚的初始化时序可能错乱。更关键的是,如果在程序里关闭了SWD,但之后串口下载通道又失效,这片芯片就只能靠BOOT0强制恢复后再烧录。所以量产产品要谨慎设计调试口的可用性。
4.3 Zynq 7000用JTAG固化Flash一定要DDR吗
热词里还有一个非常具体的场景:“zynq 7020 使用jtag固化flash时必须使用ddr吗”。这个问题在FPGA圈子里争论很多,其实结论很清晰:JTAG固化Flash这件事本身不强制要求DDR,但Vivado生成的FSBL(第一阶段引导程序)默认会初始化DDR并把bitstream或者应用程序拷贝到DDR中执行。
Zynq的启动过程通常是:BootROM从QSPI/NAND/SD读取FSBL,FSBL在OCM里运行,初始化DDR,然后加载bitstream和后续应用。如果你的工程不包含FSBL,或者FSBL被裁剪成不从DDR运行,那就不用DDR。但大多数Vivado工程默认生成的FSBL都会访问DDR,所以结论就是:使用标准固化流程时,DDR必须可用;如果DDR焊接有问题,JTAG能识别到Zynq,但固化后启动大概率卡死。
在调试这种问题的时候,我建议先用Vivado Hardware Manager通过JTAG读Zynq的IDCODE,确认连接链路没问题,再单独测试DDR的读写。别一上来就怀疑JTAG线序,Zynq的JTAG信号在PS侧和PL侧都可能被复用,具体要看原理图。
5. 经验总结与几个能救命的小习惯
5.1 我踩过的那些接线坑
按重要性排一下,过去十年我踩过的坑至少有这几条:
第一,颜色不能代表一切。红黑白三根杜邦线,看着好像“正、负、信号”,实际上很多转接板的配色根本没有统一标准。接线前必须用万用表通断档从J-Link针脚量到目标板排针,确认每一根线和丝印一致。
第二,SWD线不是越长越好。杜邦线超过20cm后,时钟信号会产生明显的过冲和反射,尤其是SWCLK频率较高时,通信失败率会显著上升。如果必须长线连接,把SWCLK频率降到100kHz~400kHz。
第三,VTref不接,惨案频发。有些J-Link在VTref没有检测到电压时,会默认输出一个较低的参考电平,导致SWDIO/SWCLK的判定阈值错乱。凡是调试口上预留了VCC引脚,就顺手接上。
第四,批量调试的板卡,SWDIO/SWCLK上一定要放ESD保护器件和串联电阻。ESD静电枪一打,调试口损坏的板子我见过无数块。量产烧录工装更要注意,建议加电平转换芯片。
5.2 把调试接口当工具,而不只是下载线
JTAG和SWD的价值不只是烧录程序。掌握好它们,还能做很多实际工作:读Flash内容备份固件、擦除芯片保护位、修改芯片选项字节、用J-Link Commander执行脚本批量烧录、用SWO输出调试日志、在低功耗调试时用reset引脚辅助连接。
我个人调试时特别喜欢用JLink.exe命令行,因为它比IDE早暴露问题。一个小技巧:连接后输入mem32 0x08000000, 32,如果能在终端看到Flash内容,说明整个链路完全正常,这时候再回Keil调试,基本不会出幺蛾子。
最后再分享一个习惯:拿到一块不熟悉的新板子,第一件事不是写代码,而是把调试口的所有信号用万用表量一遍,记录VCC、GND、SWDIO、SWCLK、RST的实际连接关系。这半小时的测量工作,能替你省下后面无数个“怎么又连不上”的深夜。