1. 这个报错到底在说什么
第一次在KEIL里点下Debug按钮,弹出来一个“TRACE HW not present”,很多人第一反应是驱动没装好,或者ST-LINK坏了。其实这个提示跟驱动关系不大,它说的是另一件事:你当前选用的调试器配置里,启用了Trace(跟踪)功能,但手上的硬件并不具备对应的跟踪引脚或跟踪能力。
先把概念理清楚。KEIL MDK在Debug配置里有两个容易混淆的模块,一个是Debug,负责下载、断点、单步这些基本调试动作;另一个是Trace,负责指令流跟踪、性能分析、代码覆盖率统计这类高级功能。Trace又分两种实现路径:一种是ETM/ETB这类需要额外引脚的高速并行跟踪,另一种是SWO/ITM这种复用SWD引脚的单线跟踪。前者对芯片封装和调试器都有硬性要求,后者相对宽松,但也不是所有ST-LINK都引出了SWO脚。
“TRACE HW not present”这句话翻译过来就是:软件想启动跟踪,但没找到能用的跟踪硬件。它可能出现在几个位置——Debug选项卡里勾了“Trace”相关选项、Target选项卡里开了“Use MicroLIB”之外的跟踪配置、或者工程从别人那里拷过来时带着一份启用了Trace的调试配置。搞清楚这一点,后面排查就有方向了,不用再盲目重装驱动。
这个内容适合谁看?刚接触STM32和KEIL的新手、从别人手里接过工程的中级开发者、以及那些明明只想打个断点却被Trace配置卡住的人。下面我按实际排查顺序,把这个问题拆开讲透。
2. 先分清Debug和Trace,别把两件事混在一起
2.1 Debug配置管什么
Debug配置的核心是连接方式和下载算法。在KEIL的Options for Target里,Debug选项卡左侧选调试器(比如ST-Link Debugger),右侧点Settings进去,能看到Port选项:SWD还是JTAG。SWD只需要两根线(SWCLK、SWDIO),JTAG要五根。现在绝大多数STM32开发板用的都是SWD,因为省引脚。
这个界面里还有Reset方式的选择,常见的有“Normal”“Core”“SYSRESETREQ”等。选错了会出现“能连上但下载失败”或者“下载成功但跑不起来”的情况,这跟Trace报错是两码事,但经常一起出现,容易让人误判。
2.2 Trace配置管什么
Trace配置在同一个Settings窗口的另一个标签页里,叫Trace。这里才是“TRACE HW not present”的直接来源。这个页面里有几个关键项:
- Core Clock:填你芯片实际运行的主频,比如STM32F103常见72MHz,F407常见168MHz。填错了不会报“HW not present”,但会导致时间戳不准。
- Trace Enable:勾上就启用跟踪。问题就出在这里——如果你的调试器没有引出SWO线,或者芯片没接SWO,勾了就会报错。
- ITM Stimulus Ports:控制哪些ITM通道打开,用于printf重定向之类的场景。
很多人是在配置printf重定向时,照着网上教程一路勾选,把Trace Enable打开了,结果每次调试都弹窗。其实printf重定向到ITM并不一定需要开Trace Enable,只要SWO线接好、ITM端口配置对就行。
2.3 为什么KEIL要把这两个放一起
因为Trace功能依赖Debug建立的物理连接。SWD连接建立后,SWO是复用在同一组引脚上的(具体是SWDIO旁边的SWO脚,不同封装位置不同)。KEIL在Debug连接成功的基础上,再去尝试初始化Trace硬件。如果Trace配置要求的能力超出了当前硬件,就报“TRACE HW not present”。
这里有个容易忽略的点:ST-LINK V2和ST-LINK V2-1的SWO支持不一样。V2-1(常见于Nucleo板载)引出了SWO,V2(常见于淘宝十几块的那种独立调试器)很多版本没有引出SWO,或者引出了但排线里没接。所以同样的工程,在Nucleo上不报错,换到独立ST-LINK就报错,原因就在这里。
3. 按这个顺序排查,基本一次解决
3.1 第一步:确认你到底需不需要Trace
先问自己一个问题:我是不是真的要用指令跟踪、性能分析、代码覆盖率?如果只是打断点、看变量、单步执行,那完全不需要开Trace。直接去Trace选项卡,把“Trace Enable”取消勾选,报错立刻消失。
这是最省事的做法,也是我推荐给90%以上场景的做法。很多人是被教程带偏了,以为调试就必须开Trace。实际上日常开发中,断点加Watch窗口加串口打印,已经能解决绝大多数问题。
注意:取消Trace Enable后,如果你之前用ITM做printf重定向,printf会失效。这时候要么改用串口重定向,要么单独配置ITM而不开Trace Enable(部分KEIL版本允许)。
3.2 第二步:如果确实需要Trace,检查硬件连线
假设你就是要用SWO做printf,或者要做性能分析,那得把硬件链路打通。需要确认三件事:
- 调试器是否支持SWO:ST-LINK V2-1、J-LINK、DAPLink大多支持。独立ST-LINK V2要看具体版本,有些便宜货确实没引出SWO。
- SWO引脚是否接到芯片:STM32的SWO通常和JTAG的TDO复用,在SWD模式下是PB3(不同型号有差异,查数据手册确认)。开发板上一般有引出,自制板要检查。
- 排线是否包含SWO:标准20pin JTAG排线里SWO在第13脚,10pin SWD排线里SWO在第6脚。如果你用的是四线SWD(VCC、GND、SWCLK、SWDIO),那就没有SWO。
我遇到过好几次,客户说“我调试器支持SWO啊”,结果一看用的是四根杜邦线接的,SWO根本没连。这种情况要么换排线,要么放弃Trace。
3.3 第三步:检查KEIL里的Trace参数
硬件没问题了,再看软件配置。Trace选项卡里几个参数必须和实际一致:
| 参数项 | 常见值 | 说明 |
|---|---|---|
| Core Clock | 72MHz / 168MHz | 必须等于芯片实际主频 |
| Trace Enable | 勾选 | 启用跟踪 |
| Trace Port | SWO | 单线跟踪选这个 |
| SWO Clock | 与主频匹配 | 一般设为主频的1/2或1/4 |
Core Clock填错不会报“HW not present”,但会导致时间戳错乱。SWO Clock设太高会丢数据,设太低会拖慢跟踪速度。一般STM32F103用72MHz主频时,SWO Clock设36MHz或18MHz比较稳。
3.4 第四步:确认芯片型号和封装
有些STM32型号或封装确实不支持SWO。比如某些小封装的STM32F0,引脚复用里没有SWO功能。这种情况无论怎么配都会报“TRACE HW not present”,只能放弃Trace,改用其他调试手段。
查数据手册的Pinout章节,看有没有SWO或TRACESWO引脚。没有就是硬件不支持,不用再折腾软件了。
4. 实操:从报错到正常调试的完整过程
4.1 场景还原
假设你手上是一块STM32F103C8T6最小系统板,调试器是淘宝常见的ST-LINK V2,用四根杜邦线连接(3.3V、GND、SWCLK、SWDIO)。工程是从网上下的例程,打开后点Debug,弹出“TRACE HW not present”。
4.2 排查动作
第一步,打开Options for Target,进Debug选项卡,点Settings,切到Trace页。看到“Trace Enable”是勾选状态。取消勾选,点确定,再点Debug。报错消失,正常进入调试界面。
第二步,如果你确实需要printf,那不能就这么算了。先确认ST-LINK V2有没有SWO引出。拆开外壳看PCB,找标注SWO或TDO的焊盘。没有的话,这个调试器就不支持SWO,换调试器或者改用串口printf。
第三步,假设调试器有SWO,那就把SWO线接到STM32的PB3。然后在Trace页重新勾选Trace Enable,Core Clock填72MHz,SWO Clock填18MHz。再点Debug,应该能正常进入,并且ITM窗口能看到printf输出。
4.3 关键配置代码
如果要用ITM做printf重定向,需要在代码里加一段重定向函数。以STM32F103为例:
#include "stdio.h" int fputc(int ch, FILE *f) { ITM_SendChar(ch); return ch; }这段代码依赖CMSIS里的ITM_SendChar,需要包含core_cm3.h。然后在KEIL的Target选项卡里勾选“Use MicroLIB”,否则printf可能不工作。
注意:ITM_SendChar在Trace未启用时也能调用,但数据发不出去。所以要么开Trace Enable并接好SWO,要么改用串口重定向。
4.4 验证Trace是否真的在工作
进入调试后,打开View菜单里的“Trace”窗口,再打开“ITM Viewer”。如果配置正确,运行代码时ITM Viewer里能看到printf输出。如果一片空白,说明SWO链路有问题,回去检查连线或SWO Clock设置。
另外可以看Trace窗口里的指令计数是否在增长。增长说明跟踪正常,不增长说明Trace没真正启动。
5. 常见问题速查与避坑经验
5.1 常见问题对照表
| 现象 | 可能原因 | 解决方向 |
|---|---|---|
| 报TRACE HW not present | Trace Enable勾了但硬件不支持 | 取消勾选或换调试器 |
| 取消后printf失效 | ITM依赖Trace | 改用串口重定向 |
| Trace窗口无数据 | SWO线没接或SWO Clock不对 | 检查连线、调低SWO Clock |
| 能调试但下载失败 | Reset方式选错 | 改SYSRESETREQ或Core |
| 换电脑后报错 | 工程带了旧调试配置 | 重新配置Debug和Trace |
5.2 几个容易踩的坑
坑一:以为所有ST-LINK都支持SWO。实际上独立ST-LINK V2很多版本没引出SWO,买之前要问清楚。Nucleo板载的V2-1肯定支持。
坑二:Core Clock填了默认值没改。KEIL新建工程时Core Clock可能是空白或默认值,不填或填错会导致Trace时间戳错乱,但不一定报“HW not present”。养成习惯,建工程先填主频。
坑三:用四线SWD却想开Trace。四线SWD没有SWO,物理上就不支持Trace。要么换排线,要么放弃Trace。
坑四:工程拷贝后配置残留。从别人那里拷来的工程,Debug和Trace配置可能带着对方的设置。接手后第一件事就是检查这两个选项卡,按自己的硬件重新配。
坑五:以为取消Trace Enable就万事大吉。如果工程里用了ITM printf,取消后printf会静默失效,不报错但也没输出。要么改代码,要么把SWO链路打通。
5.3 我的实操心得
我自己的习惯是:新工程第一件事就是把Trace Enable取消掉。除非明确要做性能分析或ITM printf,否则不开Trace。这样能避免90%的“TRACE HW not present”报错,也省去检查SWO连线的麻烦。
如果确实要用ITM printf,我会在工程里同时保留串口重定向作为备选。调试时用ITM,量产测试时切串口。这样即使换了不支持SWO的调试器,代码也不用大改。
还有一点,KEIL的调试配置是存在.uvoptx文件里的,不是.uvprojx。拷贝工程时如果只拷了.uvprojx,调试配置会丢,反而不会报这个错。但如果两个都拷了,就会带着对方的配置。知道这一点,排查时能少走弯路。
6. 不同调试器的Trace支持情况
6.1 ST-LINK系列
ST-LINK V2-1(Nucleo板载)支持SWO,排线里引出了SWO脚。ST-LINK V2独立版要看具体设计,很多便宜版本只引出了SWD四线,没有SWO。ST-LINK V3支持SWO,且性能更好。
6.2 J-LINK系列
J-LINK几乎全系支持SWO,包括OB版本(板载)。J-LINK的SWO性能比ST-LINK好,高速跟踪时丢数据少。如果项目对Trace要求高,J-LINK是更稳的选择。
6.3 DAPLink
DAPLink也支持SWO,但不同固件版本支持程度不一样。有些DAPLink固件默认不开SWO,需要重新烧录固件。用之前查一下固件说明。
6.4 选型建议
如果只是偶尔用ITM printf,ST-LINK V2-1够用。如果要做性能分析、代码覆盖率,建议上J-LINK。如果预算有限又想要SWO,可以找明确标注支持SWO的DAPLink。
提示:买调试器时别只看价格,问清楚是否引出SWO。很多“TRACE HW not present”的根源就是调试器本身不支持,软件怎么配都没用。
7. 从根上避免这个报错
7.1 工程模板化
建一个自己的工程模板,Debug配置固定为SWD、Reset用SYSRESETREQ、Trace Enable不勾。以后新工程都从这个模板复制,就不会带着乱七八糟的Trace配置。
7.2 调试配置分离
如果团队协作,把.uvoptx加入版本控制时要谨慎。不同人用的调试器可能不一样,调试配置应该各自维护。可以只提交.uvprojx,.uvoptx放本地忽略。
7.3 文档化硬件连接
在项目README里写清楚用的什么调试器、怎么接线、是否支持SWO。换人接手时不用重新踩坑。这个习惯看起来麻烦,但能省下大量沟通成本。
7.4 备选调试手段
不要把所有调试都押在ITM printf上。串口printf、GPIO翻转加示波器、SEGGER RTT,都是可靠的备选。多准备几种手段,遇到硬件限制时能快速切换。
SEGGER RTT值得一提,它不需要SWO,通过SWD读写内存实现输出,速度也很快。J-LINK和部分DAPLink支持。如果ST-LINK不支持SWO,可以考虑换支持RTT的调试器。
8. 几个延伸问题
8.1 为什么有时候不报错但Trace也不工作
这种情况通常是Trace Enable勾了,硬件也“看起来”支持,但SWO Clock设得太高导致数据丢包。表现是ITM窗口偶尔有输出但不完整。解决方法是把SWO Clock降下来,比如从36MHz降到18MHz甚至9MHz。
8.2 换芯片后报错怎么办
换了不同型号的STM32,主频变了,Trace配置里的Core Clock也要跟着改。另外要确认新芯片的SWO引脚位置,可能和原来不一样。查数据手册确认。
8.3 能不能只用SWO不用Trace Enable
部分KEIL版本允许单独配置ITM而不开Trace Enable。具体做法是在Trace页只配置ITM Stimulus Ports,不勾Trace Enable。但这样时间戳和指令计数不可用,只能做printf输出。实测下来,这个方式在MDK5.30以上版本可行,旧版本可能不行。
8.4 调试器固件版本有影响吗
有。ST-LINK的固件版本会影响SWO支持。旧固件可能不支持某些Trace功能,升级固件后可能就好了。用ST-LINK Utility或STM32CubeProgrammer可以升级固件。升级前备份,升级有风险。
9. 最后分享几个实用技巧
第一个技巧:用条件断点代替Trace。很多人开Trace是为了看程序执行路径,其实条件断点加Watch窗口也能达到类似效果,而且不依赖SWO硬件。比如在可疑函数入口设断点,条件设为某个变量等于特定值,命中时停下来看调用栈。
第二个技巧:用GPIO翻转做时间测量。如果只是想知道某段代码执行多久,在代码前后翻转一个GPIO,用示波器看脉宽。精度比Trace时间戳还高,而且不需要任何Trace硬件支持。
第三个技巧:KEIL的Event Recorder。这是KEIL自带的一个组件,可以不依赖SWO做事件记录,通过调试器的内存读写实现。配置比ITM简单,输出也直观。在Run-Time Environment里勾选Event Recorder即可。
第四个技巧:定期清理调试配置。如果工程改来改去,Debug和Trace配置可能残留无效项。遇到奇怪报错时,可以删掉.uvoptx文件让KEIL重新生成,然后重新配置。这个操作相当于“恢复出厂设置”,能解决很多玄学问题。
第五个技巧:看编译输出里的调试器信息。KEIL在进入调试时,Build Output窗口会打印调试器连接信息,包括检测到的硬件能力。如果里面明确写了“no SWO”或“Trace not supported”,那就别再折腾软件配置了,硬件确实不支持。
这些技巧都是我在实际项目中反复用到的,尤其是条件断点和GPIO翻转,几乎能替代大部分Trace场景。Trace功能强大,但不是唯一手段,根据实际硬件条件灵活选择才是正道。