JLink V9虚拟串口:一根USB线搞定SWD调试和串口通信
搞嵌入式开发这几年我踩过最大的一个坑就是调试板子的时候桌上永远缠着两根USB线一根给JLink做SWD下载另一根给USB转TTL做串口打印。直到有一天我仔细翻了JLink V9的原理图才发现自己守着金矿还去讨饭——这家伙本身就内置了虚拟串口VCOM功能。只要正确启用一根USB线就能同时跑SWD调试和串口通信彻底告别USB转TTL。这篇文章我会把JLink V9虚拟串口的原理、驱动、固件版本、使能步骤、接线方法、实战配置以及最常见的SWD/JTAG Communication Failure问题全部摊开讲保证你看完就能动手跑起来。1. 先搞懂原理JLink V9的虚拟串口到底从哪来1.1 为什么JLink能当USB转TTL用很多朋友拿到JLink V9只关注SWD下载从来没注意过板子上的TXD、RXD两个引脚。实际上JLink V9内部有一颗主控芯片负责USB协议与JTAG/SWD协议的转换这颗芯片里同时集成了一个USB转UART的桥接功能。也就是说从USB协议层面看JLink V9插上电脑后枚举出来的是两个设备一个调试器接口用来跑SWD/JTAG一个CDC类虚拟串口就是标准COM口。这个虚拟串口在PC端看起来和你熟悉的CH340、CP2102没有任何区别本质都是USB CDC设备只不过它和SWD调试共享同一个USB物理接口。我用生活类比帮你理解一下USB转TTL相当于你专门雇了一个人什么事都不干只负责递纸条而JLink V9相当于一个助理既能帮你递纸条串口收发又能帮你传话指挥SWD调试而且这个助理只占用一个工位USB口。正因如此一根线搞定两种功能在硬件上完全是可行的。1.2 JLink V9虚拟串口相比USB转TTL的优势和局限先说优势这件事我实测了一整年感受非常直接少占一个USB口笔记本的USB口本来就紧张拔掉USB转TTL之后桌面清爽不少。对经常出差调试的人来说这体验提升非常大。少带一根线USB转TTL模块本身也是成本现在调试器和串口合二为一包里少装一个小模块野外现场少一次翻包找线的痛苦。共用地线少接一根线USB转TTL如果单独用需要额外把模块的GND和目标板GND接在一起用JLink虚拟串口时SWD的GND就是串口的GND天然共地减少了接线出错概率。便于整体断电复位拔插一次USB调试器重新枚举虚拟串口跟着一起重新初始化现场排查问题时更利落。但别以为虚拟串口能完全替代所有USB转TTL场景有几个局限你得有预期流控引脚不全多数JLink V9的虚拟串口只引出TXD、RXD、GND没有CTS/RTS所以硬件流控场景没法用。波特率上限取决于固件我实测常见的V9虚拟串口跑到921600是稳的但再高就不好说了USB转TTL某些型号能上1.5M甚至3M。如果你用115200或者460800这个完全不是问题。接线位置比较隐蔽V9的TXD/RXD引脚通常不是标准20针SWD接口里的定义而是板子侧面的排针或焊盘不同版本的V9位置不一样必须对着板子丝印找。1.3 虚拟串口必须满足一个前提固件里有VCOM功能这里有一个很关键的知识点JLink V9虚拟串口不是硬件上通电路就有的它依赖固件。原厂SEGGER的正品V9固件是带VCOM功能的所以插上就能看到COM口。但市面上流行的高仿V9和所谓“克隆V9”固件来源五花八门有些精简版固件为了降复杂度把VCOM模块砍掉了或者只在特定版本里保留。这就造成一个经典现象同样是V9别人插上有两个COM口你插上只有一个调试器。热词里经常出现的“jlink v9 614e.hex”就是V9固件流传比较广的一个版本。根据我的实操经验614e这个版本在不同来源的克隆V9上表现不完全一样有的插上直接出VCOM口有的需要手动在J-Link Commander里敲vcom enable有的敲了也没反应。所以拿到一个V9第一件事不是急着接线而是先确认固件版本和VCOM是否可用。后面第3节我会给出完整的验证步骤。2. 准备工作驱动、软件、固件一次配齐2.1 安装J-Link软件包和驱动使用JLink虚拟串口我强烈建议安装完整的J-Link软件包而不是只装一个驱动。SEGGER官方软件包里包含J-Link调试器驱动让系统识别调试器J-Link CDC虚拟串口驱动让系统识别COM口J-Link Commander命令行工具用来启用VCOM、查固件版本J-Flash独立烧录工具J-Link Configurator图形化配置工具安装时注意版本号会持续更新但2024年以后的新版软件包默认都支持V9的虚拟串口枚举。装完之后打开设备管理器插上V9理论上应该看到两类设备一个是通用串行总线设备下的“J-Link”设备一个是“端口 (COM和LPT)”下的“J-Link CDC UART Port (COMx)”。如果你只看到一个调试器设备而没看到COM口先别急着重装驱动大概率是固件或VCOM没启用往下看第3节。提示如果你用的是Windows系统碰到“设备描述符请求失败”或者“未知USB设备”的报错优先排查USB线。JLink对USB线质量比较敏感劣质充电线会导致枚举异常。我调试V9时换过三根线最后用一根带屏蔽的短线才稳定识别两个设备。2.2 确认固件版本和设备状态在启用虚拟串口之前先确认手头V9的固件是什么状态。打开J-Link Commander安装目录下通常叫JLink.exe连接目标板或者直接打开命令行会打印当前固件版本号、硬件版本和序列号。比如常见的输出是SEGGER J-Link Commander V7.96 SN: XXXXXX Firmware: J-Link V9 compiled Dec 1 2023 10:30:00 Hardware: V9.40这个“Firmware”字段就是关键。如果固件版本太老有些VCOM相关的指令可能不存在如果固件是第三方精简版甚至可能会提示“VCOM not supported”。所以看到版本信息后先别急着干活记下这个版本然后验证VCOM支持情况。2.3 关于固件版本与VCOM的关系以及刷固件的风险这里专门说一下网上流传的“614e.hex”这类固件。JLink V9因为停产和正品价格等原因市面上存在大量兼容版/克隆版它们用的固件大多来自网络流传的hex或bin镜像。614e这个版本在很多技术论坛里被讨论原因就是它跟虚拟串口功能有直接关联。根据我实际测试多块V9的结果如果固件版本中VCOM模块完好插上就能枚举出“J-Link CDC UART Port”设备管理器中直接多出一个COM口。如果固件是精简版J-Link Commander里输入vcom enable会提示“VCOM not supported”或者干脆不响应。部分特殊固件需要先进J-Link Commander执行一次vcom enable之后才会枚举出COM口而且这个状态会一直保持。如果你确认当前固件不支持VCOM就需要考虑刷固件。但这里我必须提醒刷固件有变砖风险尤其是克隆V9厂家的bootloader可能和原版不完全一致。我的建议是如果当前V9是正品直接在J-Link Configurator里点升级固件SEGGER官方会推送带VCOM的版本。如果是克隆V9先找对应的刷机教程和固件包尽量找和你硬件版本匹配的。刷之前记录当前固件版本万一刷挂了还能刷回去。刷固件方式一般有两条路通过bootloader模式短接触发点后上电使用SAM-BA或专用工具烧录或通过J-Link自身的升级机制。具体操作根据你手上的固件包说明来。我个人不建议新手一拿到V9就刷固件。先按第3节的方法测试一遍如果虚拟串口能用就别折腾。能用就别动这是调试器最朴素的生存法则。3. 启用虚拟串口三步完成配置3.1 用J-Link Commander打开VCOM这里给出标准的启用流程。第一步打开命令行进入J-Link安装目录运行JLink.exe。此时会出现一个命令行交互界面通常会让你选择目标芯片型号和连接方式如果只是启用VCOM可以直接忽略或者随便选一个常见型号。在命令行提示符下输入vcom enable如果固件支持会返回类似VCOM enabled或者OK的提示。如果不支持会报错或提示未知命令。执行成功后必须重新拔插一次USB线让设备重新枚举VCOM口才会出现在设备管理器里。第二步重新插拔后再次打开设备管理器正常情况下“端口 (COM和LPT)”下会出现一个“J-Link CDC UART Port (COMx)”这个COMx就是你的虚拟串口。注意vcom enable这个命令是一次性配置成功后状态会保存在调试器内部下次插上直接就有COM口不需要每次开机都执行。如果哪一天你发现虚拟串口消失了先重新执行一遍这个命令。3.2 管脚定义和接线方法启用VCOM之后剩下的事情就是硬件接线。关于JLink V9的TXD和RXD引脚位置这里我要多说几句因为很多人的接线错误就是死在这上面。不同厂家的V9板子TXD/RXD引出方式不一样有些V9在20针SWD接口旁边多了一个4针排针丝印标着TXD、RXD、GND、VCC。有些V9把TXD/RXD放在板子边缘用测试点或小焊盘的形式。还有一些V9的TXD/RXD直接复用在某个接口上比如和SWDIO共用或和某些预留引脚相邻。所以拿到V9后第一步是拿出放大镜看板子丝印找TXD、RXD、GND三个标记。找不到丝印就上论坛搜对应版本的引脚图这个功夫不能省。接线时请记住这个非常重要的对应关系以STM32为例JLink端引脚连接目标说明SWDIO目标板SWDIO调试数据线SWCLK目标板SWCLK调试时钟线GND目标板GND共地同时也是串口参考地TXD目标板USART的RX引脚JLink发送目标是接收RXD目标板USART的TX引脚JLink接收目标是发送注意TXD要接目标板的RXRXD要接目标板的TX。这是交叉接法和USB转TTL模块的接法一模一样。很多朋友第一次接虚拟串口直接把TXD对TXD、RXD对RXD结果收到全空或乱码。3.3 在串口助手里验证通信接线完成后打开任意串口调试助手我用的是SSCOM和MobaXterm都支持标准COM口。选择你刚才看到的J-Link CDC UART Port对应的COM号波特率先设115200或和你的目标板程序一致的波特率数据位8、停止位1、无校验打开串口。这里有一个验证小技巧如果目标板上电后没有主动打印数据你可以把目标板的USART TX引脚配置成每1秒打印一次“Hello from STM32”然后在串口助手里看是否收到。如果收到说明虚拟串口到目标板的链路完全打通。如果完全没反应按顺序排查波特率不一致最常见TXD/RXD接反第二常见目标板串口初始化有问题第三常见JLink虚拟串口本身没启用成功驱动或固件问题实操心得验证虚拟串口是否可用最简单粗暴的方法是先在J-Link Commander里执行vcom enable然后对比设备管理器在重新插拔前后有没有多出COM口。只要多出来虚拟串口的USB链路就一定是好的剩下的问题全在目标板那边。4. 实战一根线同时跑SWD调试和串口日志4.1 一个STM32的完整接线与配置为了让你能直接照抄我给出一个完整的STM32F103使用JLink V9虚拟串口同时跑SWD和串口日志的实战配置。目标板STM32F103C8T6使用USART1PA9配置为TX发送PA10配置为RX接收。硬件接线JLink SWDIO - STM32 PA13SWDIOJLink SWCLK - STM32 PA14SWCLKJLink GND - STM32 GNDJLink TXD - STM32 PA10USART1_RXJLink RXD - STM32 PA9USART1_TX这里没有接目标板VCC因为STM32板子用USB口单独供电。如果你的板子是裸芯片没有独立供电可以从JLink的3.3V引脚引电源给目标板供电但要确认目标板当前电压等级和JLink输出一致否则可能烧芯片。然后是代码部分以Keil MDK HAL库为例。初始化USART1void MX_USART1_UART_Init(void) { huart1.Instance USART1; huart1.Init.BaudRate 115200; huart1.Init.WordLength UART_WORDLENGTH_8B; huart1.Init.StopBits UART_STOPBITS_1; huart1.Init.Parity UART_PARITY_NONE; huart1.Init.Mode UART_MODE_TX_RX; huart1.Init.HwFlowCtl UART_HWCONTROL_NONE; huart1.Init.OverSampling UART_OVERSAMPLING_16; if (HAL_UART_Init(huart1) ! HAL_OK) { Error_Handler(); } }然后重定向printf到串口int fputc(int ch, FILE *f) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xFFFF); return ch; }主循环里每隔1秒打印一次调试信息while (1) { printf(SWD OK, UART virtual OK, count%d\r\n, count); HAL_Delay(1000); }编译下载后你会发现一个很有意思的现象Keil里用JLink跑在线调试变量Watch窗口实时刷新同时串口调试助手也在同步打印日志。整个过程中PC端只插了一根JLink的USB线。4.2 Keil里同时用调试器和虚拟串口有些朋友会有疑问Keil的调试器占用JLink的同时虚拟串口会不会被顶掉答案是不会。因为虚拟串口和SWD在USB协议层面是两个独立通道就像同一个插座上插了台灯和充电器互不影响。Keil里配置JLink调试的方法很简单打开Options for Target - Debug选择“J-LINK/J-TRACE Cortex”。点击右侧“Settings”确认调试器识别到SW Device并设置为SW模式。下载或在线调试时JLink命令窗口会正常打印连接信息。实测下来在线调试时我在主循环打了断点然后去看串口助手的输出发现最后一条数据停在断点前的位置同时Watch窗口里的count变量和串口数完全对应。这说明调试器和虚拟串口真的在“肩并肩工作”。关于调试器和虚拟串口同时使用还有一个细节JLink的虚拟串口不会因为进入调试状态而断开。即使CPU停在断点上串口上已经发出的数据会完整到达PC端。但注意如果你在断点处停留很久后续的printf数据会堆积在串口缓冲区里恢复运行后会突然冒出来一大串这是正常现象不是设备问题。4.3 还能这么玩在线调试时查看实时打印输出如果你不想额外开一个串口助手还有更骚的操作Keil的Debug (printf) Viewer窗口可以配合JLink的虚拟串口使用。不过要注意Debug (printf) Viewer标准用法是走SWO/ITM通道和虚拟串口是两回事。如果你想把USART的数据直接在Keil里看需要在“Options for Target - Debug - Settings - Trace”中启用Trace功能并把ITM通道和波特率配置正确。这里我建议日常调试用虚拟串口独立串口助手偶尔需要一个无干扰的纯日志窗口时才用ITM。因为虚拟串口的输出依赖USART外设目标芯片的USART工作不正常时虚拟串口也就废了而ITM/SWO走的是调试通道USART挂了也能看内核日志。两者互补不要只依赖一个。4.4 应用场景扩展不只有STM32虚拟串口的用法不限于STM32。最近我在一个FPGA项目里也这么干FPGA逻辑里例化了一个UART发送模块把FPGA的TX引脚接到JLink的RXDPC端直接通过虚拟串口看FPGA内部状态寄存器的值。整个调试过程不需要额外的USB转TTL也不需要单独的串口线。另一个朋友在做基于K230的AI板卡调试时直接把JLink虚拟串口当板卡的业务串口用——板子的主控串口输出应用日志JLink SWD负责在线调试内核。对他这种USB口全插满的机器来说省下一个口等于救了命。实验、RS232、RS485这些场景也一样只要你的目标板主控的UART是TTL电平且引脚引出来了就能和JLink虚拟串口对接。碰到RS232电平的设备加一个电平转换芯片MAX3232之类即可。核心思路是一样的把JLink的TXD/RXD当作一个标准的TTL串口来用。5. 高频报错SWD/JTAG Communication Failure排查实录5.1 先分清是SWD连接失败还是虚拟串口失败说句实话虚拟串口本身很简单真正让无数人头疼的是SWD报错。你电脑上明明装着JLinkKeil里也选了JLink一连接就弹“SWD/JTAG Communication Failure”心态直接炸。根据我这么多年的排查经验这个报错的原因无非以下几类按可能性排序原因概率现象特征接线错误高某个引脚接触不良或接错连接时无反应目标板供电问题高目标板没电或电压不稳JLink检测不到VTref复位电路或下载模式问题中目标主控被代码配置成低功耗或SWD引脚被复用调试时钟速度太高中降低速度后能连上默认速度不稳定固件或驱动问题低换电脑/换JLink正常本机一直失败先说怎么快速定位打开J-Link Commander输入connect如果JLink能识别出目标芯片的ID比如Cortex-M3的IDCODE说明SWD链路是通的问题大概率在Keil配置层面如果连IDCODE都读不到那就是硬件连接问题。5.2 接线与供电的经典坑SWD接线我这里再啰嗦一次标准接法SWDIO、SWCLK是必接的两根信号线方向别搞反。GND必须接这个不用解释。关键来了JLink默认通过VTref引脚检测目标板电压。V9的目标板VTref如果检测不到电压会直接拒绝连接或者报错。所以如果你只接了SWDIO、SWCLK、GND没接VTref而且目标板没有独立供电那JLink会误以为目标板没上电。解决方案有两种目标板独立供电然后把JLink的VTref引脚接到目标板的3.3V电源引脚。目标板不独立供电直接把JLink的3.3V引脚接到目标板的VCC同时VTref也接过去。我推荐第一种因为目标板独立供电时调试器只负责信号不参与供电更安全。5.3 代码把SWD引脚复用掉导致进不了调试这是嵌入式开发特有的坑。很多人写代码时为了省引脚把PA13/PA14或PB3/PB4等SWD引脚复用成普通GPIO了。一旦代码烧进去下次再连接调试器SWD直接被禁用JLink当然连不上。解决方法是“Connect under Reset”在Keil的Debug Settings里选择“Reset and Halt”或“Connect under Reset”。在J-Flash里打开Options - Connection勾选“Connect under Reset”。硬件手法按住目标板的复位键不松开点击连接在“正在连接”那个瞬间松开复位键。这个时机多试几次就有手感了。如果目标板已经彻底跑飞连复位都不好使就用JLink的erase命令擦除整个FlashJLinkExe erase擦除前先确认JLink能读到IDCODE如果读不到还是得回到接线和供电排查。5.4 虚拟串口不出现/打不开的排查虚拟串口本身问题相对少但也不是没有。我整理几个高频现象插上JLink后只有一个调试器设备没有COM口先确认vcom enable是否执行成功。如果执行成功还是没有考虑固件是否支持VCOM。多试几个固件版本或者用J-Link Configurator升级固件。COM口出现但打开失败提示被占用虚拟串口和USB转TTL一样同一时刻只能被一个软件占用。检查是不是有好几个串口软件同时开了或者后台有程序比如某些单片机的烧录监控软件在监听COM口。我的习惯是先在任务管理器里把所有终端工具关掉再重新打开。COM口号一直变体验很差这个其实很好解决在Windows设备管理器里右键点击J-Link CDC UART Port - 属性 - 端口设置 - 高级把COM端口号固定成一个不常用的数字比如COM9或COM20。固定后以后每次插上都是同一个号。Linux下找不到JLink虚拟串口Linux上一般会枚举为/dev/ttyACMx如果没有重点检查udev规则。SEGGER官方文档里有Linux环境配置说明这里不多展开。5.5 虚拟串口乱码和波特率不稳的解决方案如果你用虚拟串口收到的数据是乱码或者时不时丢字节先别怪JLink按这四步排查检查波特率目标板程序写的115200串口助手就设115200目标板用HSE时钟源且倍频不准实际输出频率偏移也会乱码。先用逻辑分析仪量一量目标板TX引脚的波形确认实际波特率。检查TXD/RXD接线TXD和RXD交叉接了吗接成平行线数据像对暗号一样根本对不上。降低波特率如果目标板和JLink之间的杜邦线超过20cm或者环境有电机、电源干扰高速率下误码率会明显升高。把波特率降到38400或9600测试稳定后再逐步提高。换USB口JLink别插在USB Hub上尽量直连主机。我遇到过USB Hub供电不足串口时好时坏直连主板后完全正常。实操心得串口通信这种模块级联调最容易忽略的就是“共地”。JLink虚拟串口虽然和SWD共用GND但如果你目标板是通过另一个电源适配器独立供电的而JLink接的是电脑USB供电两者之间隔着电源隔离串口一样可能工作异常。碰到诡异乱码先把目标板和JLink的GND用杜邦线明确连一次八成能解决。最后再分享几个实际经验折腾JLink V9虚拟串口这一年多我总结下来最值钱的几条经验第一拿到V9别着急写代码先把虚拟串口跑通。确认它枚举出COM口之后再在板子上写一个串口回环测试程序——把RX引脚收到的字节原样从TX发回去然后在串口助手里发一串测试字符能原样返回就说明硬件链路完全OK。这个小测试能帮你排除掉90%的接线问题。第二有条件的话把V9侧面的TXD/RXD引脚直接焊上排针用硅胶线做短跳线。很多V9自带的杜邦线接口在反复插拔后会接触不良特别是TXD/RXD这种不太起眼的位置一旦虚接排查起来极其痛苦。第三如果你现在用的是JLink V9又想尝试把日志输出改成ITM/SWO方式请留好虚拟串口这条退路。ITM调试虽然方便但要目标芯片支持SWO引脚且引出来才能用。在你没有百分百把握之前虚拟串口永远是更稳妥的调试日志通道。最后再提醒一句JLink虚拟串口的启用状态是会跟着固件走的。如果你某天手贱点了J-Link Configurator的固件升级升级完记得看一眼设备管理器如果COM口不见了重新执行一遍vcom enable一切就都回来了。调试工具这东西能稳定复现的操作就是好操作。