4. JTAG接口电路设计(备选方案):TMS/TCK/TDI/TDO连接、JTAG链配置、调试接口复用

JTAG,说白了就是调试和烧录的"最后一道防线"。SWD虽然只用了两根线,但JTAG有它不可替代的地方——边界扫描、多核调试、FPGA联合调试,这些场景下JTAG才是正主。

我做运动控制卡这么多年,遇到过好几次SWD死活连不上,换JTAG一把就通的怪事。所以虽然本章叫"备选方案",但我建议你认真看完。说不定哪天就靠它救场。

4.1 JTAG vs SWD:什么时候选谁?

先看一张对比表,帮你快速决策:

特性 JTAG(4线) SWD(2线)
引脚数 4(TMS/TCK/TDI/TDO) 2(SWDIO/SWCLK)
调试速度 最高可达几十MHz 通常4-10MHz
边界扫描 ✅ 原生支持 ❌ 不支持
多核调试 ✅ 一条链上挂多个核 ❌ 单核
FPGA联合调试 ✅ 标准接口 ❌ 不适用
PCB占用面积 较大(10pin或20pin座) 小(4pin或5pin座)
典型场景 研发调试、产线烧录 现场维护、空间受限

我的建议:运动控制卡研发阶段,板上同时保留JTAG和SWD焊盘。JTAG用于深度调试,SWD用于日常烧录。量产时根据成本取舍,但至少留一组SWD。

4.2 JTAG信号详解:TMS/TCK/TDI/TDO

JTAG的核心就这四根线,外加一个可选的nTRST(复位)和nSRST(系统复位)。

  • TCK(Test Clock):测试时钟,所有操作同步于这个时钟。我习惯在TCK上串一个22Ω电阻,靠近MCU放置,减少反射。
  • TMS(Test Mode Select):模式选择,控制JTAG状态机跳转。这个信号在TCK上升沿采样。
  • TDI(Test Data In):数据输入,串行移入指令或数据。
  • TDO(Test Data Out):数据输出,串行移出数据。注意TDO在TCK下降沿输出数据。

这里有个坑——TDO的驱动能力。我曾经在一个项目里,JTAG线缆拉到了30cm,结果TDO信号变形严重,调试器频繁报错。后来在TDO上加了一个33Ω的串联电阻,问题解决。

经验值:TCK频率建议控制在10MHz以内。超过这个值,PCB走线长度、阻抗匹配、信号完整性都要仔细算。运动控制卡通常不需要那么高的调试频率,4-8MHz足够用。

4.3 JTAG链配置:多器件串联

JTAG链,说白了就是把多个支持JTAG的器件串成一串。TDI进第一个,TDO出最后一个。调试器通过一条链访问所有器件。

运动控制卡上常见的JTAG链成员:

  • 主控STM32
  • FPGA(如果有)
  • CPLD(如果有)
  • 某些专用运动控制芯片

链的拓扑结构很简单:

TDI → [器件1 TDI→TDO] → [器件2 TDI→TDO] → ... → [器件N TDI→TDO] → TDO

每个器件在链上有一个唯一的IR(指令寄存器)长度。调试器通过IR扫描识别链上器件。我遇到过一个问题:链上某个器件的IR长度和调试器预期不符,导致整条链无法识别。排查了半天,发现是FPGA的JTAG IP核配置错了。

注意:链上所有器件的TCK和TMS必须并联,不能串联。TDI/TDO才是串联的。这个搞反了,整条链都废了。

4.4 调试接口复用:一针多用

STM32的JTAG引脚和GPIO是复用的。默认复位后,这些引脚是JTAG功能。如果你要用作普通GPIO,需要在代码里关闭JTAG。

复用配置表(以STM32F4为例):

引脚 默认功能 复用功能 关闭方式
PA13 JTMS/SWDIO GPIO DBGMCU->CR 或 AFIO->MAPR
PA14 JTCK/SWCLK GPIO 同上
PA15 JTDI GPIO/SPI_NSS 关闭JTAG后可用
PB3 JTDO GPIO/SPI_SCK 关闭JTAG后可用
PB4 NJTRST GPIO/SPI_MISO 关闭JTAG后可用

代码示例:关闭JTAG,释放引脚给GPIO

// 关闭全部JTAG功能,保留SWD
// 注意:一旦执行,JTAG调试器将无法连接
// 必须用SWD或重新上电才能恢复

void JTAG_Disable(void)
{
    // 对于STM32F4系列
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 使能GPIO时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    
    // 配置PA15(PB3,PB4)为推挽输出
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 关闭JTAG,保留SWD
    // 0x02 = 关闭JTAG-DP,保留SW-DP
    // 0x01 = 全部关闭(包括SWD)
    HAL_DBGMCU_DisableDBGStopMode();
    __HAL_AFIO_REMAP_SWJ_DISABLE();  // 全部关闭
    // 或者 __HAL_AFIO_REMAP_SWJ_NOJTAG();  // 只关JTAG,保留SWD
}

血的教训:我曾经在产线固件里加了关闭JTAG的代码,结果有一批板子烧录完就再也连不上了。排查发现是关闭代码执行得太早,调试器还没来得及断开。正确的做法是:在固件启动后延迟几秒再关闭JTAG,给调试器留足断开时间。

4.5 电路设计实战:JTAG接口原理图

下面是我常用的JTAG接口电路,20pin标准座,兼容ARM 20pin定义:

// JTAG 20pin接口连接(ARM标准)
// 引脚号  信号名    连接目标
// 1       VREF     3.3V(通过10kΩ上拉)
// 2       nSRST    MCU的NRST(通过10kΩ上拉)
// 3       TDI      MCU的PA15(串22Ω电阻)
// 4       nTRST    MCU的PB4(通过10kΩ上拉)
// 5       TMS      MCU的PA13(串22Ω电阻)
// 6       GND      GND
// 7       TCK      MCU的PA14(串22Ω电阻)
// 8       GND      GND
// 9       TDO      MCU的PB3(串33Ω电阻)
// 10      GND      GND
// 11-20   GND      GND(或NC)

关键设计要点:

  • 上拉电阻:TMS、TDI、nTRST、nSRST各加一个10kΩ上拉到3.3V。TCK和TDO不需要上拉。
  • 串联电阻:TDI、TMS、TCK串22Ω,TDO串33Ω。靠近MCU引脚放置。
  • ESD保护:如果接口要引出到机箱外部,加TVS管(如PESD5V0S1UB)。
  • 滤波电容:VREF引脚对地加100nF电容。

我的习惯:在JTAG接口旁边加一个LED指示灯,通过MCU的GPIO控制。调试时亮起,烧录完成后熄灭。产线工人一眼就能看出烧录状态,不用看电脑屏幕。

4.6 JTAG状态机与调试流程

JTAG的核心是一个16状态的有限状态机。你不需要背下所有状态,但要知道几个关键路径:

  • Test-Logic-Reset:上电默认状态,TMS保持高5个TCK周期进入此状态。
  • Run-Test/Idle:空闲状态,等待指令。
  • Shift-IR:移入指令。
  • Shift-DR:移入数据。

调试器通过TMS控制状态跳转。每次跳转都在TCK上升沿采样TMS。这就是为什么TMS和TCK的时序必须干净——任何毛刺都会导致状态机跑飞。

下面这张图展示了JTAG状态机的核心路径:

JTAG状态机核心路径 Test-Logic-Reset Run-Test/Idle Select-DR-Scan Select-IR-Scan Shift-DR Shift-IR TMS=0 TMS=1 TMS=1 TMS=0 TMS=0 TMS=1连续5个TCK周期回到Reset状态

4.7 避坑指南:JTAG设计常见问题

  1. 信号反射:TCK走线过长或阻抗不匹配,导致信号过冲。解决方案:串22-33Ω电阻,走线控制在10cm以内。
  2. 电平不匹配:调试器是5V,MCU是3.3V。必须加电平转换,否则烧MCU。我推荐TXS0104E或分立MOS管方案。
  3. 上电时序:MCU还没上电,调试器先给了JTAG信号,可能导致MCU锁死。解决方案:在JTAG接口上加一个延迟上电电路,或者用调试器控制nTRST。
  4. 地线回路:调试器和目标板地电位差过大,导致通信不稳定。解决方案:用粗地线连接,或者加隔离器(如ADuM1201)。
  5. 引脚复用冲突:JTAG引脚被其他外设占用,调试时冲突。解决方案:设计阶段就规划好引脚分配,JTAG引脚尽量不与其他功能复用。

总结一下:JTAG接口设计,说白了就是四根信号线的物理层和时序层设计。物理层做好上拉、串联电阻、ESD保护;时序层保证TCK干净、TMS稳定。做到这两点,JTAG基本不会出问题。运动控制卡对调试接口的可靠性要求高,我建议你花点心思在PCB布局上——JTAG走线远离电机驱动、PWM等强干扰源。