4. JLink与ST-Link实战:JLink Commander与ST-Link Utility的使用、固件烧录、RTT日志输出、SWO调试

调试器这东西,说白了就是嵌入式工程师的“听诊器”。JLink和ST-Link,我估计你手头至少有一个。很多新手觉得它们就是用来烧程序的,其实远不止如此。今天咱们就把这两个工具彻底聊透,从命令行到图形界面,从烧录到日志输出,全走一遍。

本章核心能力:掌握JLink Commander和ST-Link Utility的常用命令与操作流程,能独立完成固件烧录、RTT日志采集和SWO波形调试。

4.1 调试器选型与连接检查

先说说选型。我个人习惯是:Cortex-M4以上、需要高频调试的场景,优先用JLink;如果是STM32的常规开发,ST-Link完全够用,还省钱。但有一点要注意——市面上很多“山寨JLink”在高速SWO和RTT上会掉链子,我踩过这个坑。

特性 JLink (SEGGER) ST-Link (ST)
最大SWD时钟 50 MHz (V11) 4 MHz (V2-1)
RTT支持 原生,无额外硬件 需JLink驱动模拟
SWO频率 最高 100 MHz 通常 ≤ 2 MHz
价格 高(正版) 低(板载免费)
推荐场景 性能调优、RTOS调试 常规开发、教学

连接之前,先确认驱动。Windows下JLink驱动装好后,设备管理器里能看到“J-Link”或者“STMicroelectronics STLink”。如果识别不到,八成是USB线的问题——别笑,我遇到过三次,换根线就好了。

4.2 JLink Commander 命令行实战

JLink Commander是SEGGER提供的命令行工具,轻量、高效。很多老工程师喜欢用它,因为可以写脚本批量操作。我第一次用的时候也觉得麻烦,但用顺手之后,比IDE里点点点快多了。

4.2.1 启动与连接

打开命令行,输入:

JLinkExe

然后你会看到SEGGER的logo和提示符“JLink>”。接下来指定设备型号和接口:

device STM32F407VG
interface SWD
speed 4000
connect

这里有个细节:speed的单位是kHz,4000就是4 MHz。如果连接不稳定,降到1000试试。我曾经在F103上设到8000,直接连不上,后来发现是杜邦线太长,信号衰减了。

小技巧:如果不想每次手动输入,可以把命令写进脚本文件,比如 connect.jlink,然后执行 JLinkExe -CommanderScript connect.jlink。

4.2.2 固件烧录

烧录固件是基本功。假设你的固件是 app.bin,起始地址0x08000000:

loadfile app.bin 0x08000000
r
g

解释一下:loadfile 把文件加载到指定地址,r 是复位,g 是go(运行)。如果是hex文件,不需要指定地址,因为hex里自带地址信息:

loadfile app.hex
r
g

嗯,这里要注意:烧录前最好先执行 erase 擦除整片,否则旧数据残留可能导致奇怪的问题。我有个同事没擦除就烧,结果程序跑飞了,查了两天才发现是Flash里有上一版的异常向量表。

4.2.3 内存读写与寄存器查看

调试时经常要看某个地址的值:

mem 0x20000000, 64

这条命令从0x20000000开始读64字节。写内存用 w4(写32位)或 w2(写16位):

w4 0x20000000, 0xDEADBEEF

查看CPU寄存器:

regs

你会看到R0-R15、PC、LR、SP等。如果怀疑某个外设没配置好,直接读它的寄存器地址,比在IDE里打断点快得多。

4.3 ST-Link Utility 图形化操作

ST-Link Utility是ST官方工具,图形界面,对新手友好。我个人觉得它最大的优点是烧录进度可视化和批量生产支持。

4.3.1 连接与识别

打开ST-Link Utility,点击“Target” -> “Connect”。如果连接成功,界面会显示芯片型号和Flash大小。如果失败,检查一下SWD的4根线:SWDIO、SWCLK、GND、VCC(可选)。

警告:ST-Link的VCC引脚输出3.3V,但电流有限(约100mA)。如果你的板子功耗大,建议外接电源,否则可能烧坏ST-Link的稳压器。我烧过一个V2-1,就是因为板子短路没发现。

4.3.2 固件烧录与校验

点击“File” -> “Open file”,选择你的hex或bin。然后点击“Program & Verify”。Utility会自动擦除、编程、校验。校验这一步很重要,它能确保烧进去的数据和源文件完全一致。

批量生产时,可以用命令行模式:

STM32_Programmer_CLI -c port=SWD -w app.hex 0x08000000 -v

参数 -v 表示校验。我建议永远不要省略校验,尤其是在产线上。有一次产线反馈烧录后有几台不工作,排查发现是Flash供电不稳导致个别字节写失败,没有校验根本发现不了。

4.4 RTT日志输出实战

RTT(Real-Time Transfer)是SEGGER的杀手锏。它不需要额外硬件,只用SWD的两根线就能实现高速日志输出。相比串口,RTT的速度快一个数量级,而且不占用外设。

4.4.1 在工程中集成RTT

首先,从SEGGER官网下载RTT实现包,把 SEGGER_RTT.c 和 SEGGER_RTT.h 加入工程。然后在代码里包含头文件,用 SEGGER_RTT_printf() 输出:

#include "SEGGER_RTT.h"

int main(void) {
    SEGGER_RTT_ConfigUpBuffer(0, "RTT_UP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
    while (1) {
        SEGGER_RTT_printf(0, "System tick: %u\n", HAL_GetTick());
        HAL_Delay(100);
    }
}

这里 SEGGER_RTT_MODE_NO_BLOCK_SKIP 的意思是:如果缓冲区满了,丢弃新数据,不阻塞CPU。调试时用 SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL 更保险,但实时性要求高的场景慎用。

4.4.2 用JLink RTT Viewer查看

打开JLink RTT Viewer,选择设备型号和接口,连接后就能看到日志了。你想想看,不用串口线,不用额外引脚,只要SWD连着就能看日志,是不是很方便?

我曾经在一个项目里,板子已经装进密封外壳了,串口没引出,但SWD调试口留着。靠RTT,我硬是在不拆机的情况下定位了一个死锁问题。那感觉,就像隔着墙听诊。

性能对比:115200波特率的串口,每秒约11.5 KB;RTT在4 MHz SWD下,实测可达500 KB/s以上。打印大量调试信息时,RTT几乎不影响程序实时性。

4.5 SWO调试:指令追踪与时间分析

SWO(Serial Wire Output)是SWD协议的一个扩展引脚,用于输出调试信息。它比RTT更底层,可以输出指令地址、数据访问、时间戳等信息。说白了,SWO能让你看到CPU内部在执行什么。

4.5.1 硬件连接

SWO需要一根额外的线:PB3(SWO)接到调试器的SWO引脚。JLink有专门的SWO引脚,ST-Link V2-1也有,但V2没有。如果你用的是ST-Link V2,抱歉,SWO用不了。

调试器 SWO引脚 备注
JLink V9/V10/V11 Pin 13 (SWO) 直接连接
ST-Link V2-1 Pin 5 (SWO) 部分版本需跳线
ST-Link V2 无 不支持SWO

4.5.2 配置SWO输出

在代码中使能ITM(Instrumentation Trace Macrocell):

ITM->TCR = ITM_TCR_ITMENA_Msk;          // 使能ITM
ITM->TER = 0x1;                          // 使能端口0
*((volatile uint32_t *)0xE0000000) = 0x1; // 使能DWT时钟

然后通过ITM端口0输出字符:

ITM_SendChar('A');

在JLink Commander里,用 SWO Enable 0 0 0 2000000 配置SWO频率(2 MHz),然后用 SWO Read 查看输出。或者用JLink SWO Viewer图形界面,更直观。

4.5.3 时间戳与性能分析

SWO最强大的功能是输出DWT(Data Watchpoint and Trace)时间戳。你可以测量两个断点之间的精确时间:

uint32_t start = DWT->CYCCNT;
// 要测量的代码段
uint32_t end = DWT->CYCCNT;
uint32_t cycles = end - start;

假设CPU主频168 MHz,每个周期约5.95 ns。如果 cycles = 1000,那么这段代码耗时约5.95 μs。用SWO把这两个时间戳输出,就能在PC端看到精确的时间线。

实战案例:我在优化一个电机控制算法时,发现中断响应时间不稳定。通过SWO输出中断进入和退出的时间戳,发现有一个外设的中断优先级设置错误,导致高优先级中断被低优先级中断阻塞。调整优先级后,响应时间从平均3.2 μs降到1.1 μs。

4.6 本章知识体系

下面这张图总结了JLink与ST-Link的核心操作流程和工具链关系,你可以把它当作速查地图。

JLink与ST-Link实战知识体系 JLink 与 ST-Link 实战知识体系 JLink (SEGGER) ST-Link (ST) JLink Commander (命令行) ST-Link Utility (图形化) 固件烧录 loadfile / Program RTT日志输出 SEGGER_RTT_printf SWO调试 ITM / DWT 内存/寄存器 mem / regs 批量生产 实时日志 性能分析 故障定位 核心原则:先连接 → 再操作 → 最后校验,每一步都要确认状态

4.7 避坑指南与经验总结

最后,把我这些年踩过的坑总结一下,你遇到了可以直接翻到这里查:

  • 连接不上:先检查USB线,再检查SWD接线顺序,最后看驱动是否安装。我遇到过最离谱的一次,是目标板没上电。
  • 烧录后不运行:检查启动地址是否正确,Flash是否擦除干净。用 mem 0x08000000, 4 看看向量表第一个字(栈指针)是否合理。
  • RTT无输出:确认 SEGGER_RTT_ConfigUpBuffer 已调用,且JLink RTT Viewer选择的设备型号正确。有时候是缓冲区大小不够,设成1024试试。
  • SWO数据乱码:SWO频率配置错误。CPU主频和SWO频率必须匹配,公式是 SWO_freq = CPU_freq / (SWO_prescaler + 1)。
  • 山寨JLink的坑:固件版本低,不支持RTT或SWO。建议用 JLinkInfo 查看固件版本,低于V6.0的尽早升级。

重要提醒:调试器也是设备,有固件版本。JLink和ST-Link都可以升级固件。如果遇到奇怪的问题,先升级固件试试。我曾经被一个ST-Link V2-1的旧固件坑了三天,升级后一切正常。