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的核心操作流程和工具链关系,你可以把它当作速查地图。
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的旧固件坑了三天,升级后一切正常。