尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Keil 增量编译的坑:烧录的固件比代码老了一版,排查一下午

Keil 增量编译的坑:烧录的固件比代码老了一版,排查一下午 Keil 增量编译的坑烧录的固件比代码老了一版排查一下午一句话: Keil 增量编译下源码改了但没触发重编译时hex 文件还是老版本的——直接把旧 hex 复制去烧录芯片里跑的就是旧代码。烧完功能不对先查 hex 时间戳别一头扎进代码里。适合谁读用 Keil 命令行UV4 -b编译 J-Link 脚本烧录烧完功能不对第一反应是查代码的嵌入式工程师。现象烧录很顺利功能却丢了一次固件改动改完代码、Keil 命令行编译、日志 0 Error 0 Warning复制 hex 烧录输出Downloading fileProgram Verify全都有——烧录过程完美。然后测功能坏事了新加的逻辑cmd 6 未使能推 0完全不存在另一条命令cmd 12 带地址读发出去无响应于是开始查代码逻辑明明写了啊编译也没报错啊是不是哪里没使能是不是初始化顺序问题排查了一下午一无所获。最后对了一下 hex 文件时间戳真相大白烧录的 hex 是上一次编译的旧产物这次的源码改动根本没编译进去。根因Keil 增量编译不重编译 hex 不更新Keil 增量编译Incremental Build的机制源码没变→ 跳过该文件编译 → 链接产物不变 →hex 时间戳不更新源码变了→ 重编译该文件 → hex 更新看起来没毛病。但命令行批量编译时有个致命场景你改的源码和 hex 的时间戳只差几分钟甚至相同——因为你上一轮编译过这一轮 Keil 判断没有变化直接跳过了但你自己不知道还当它编译过了。更隐蔽的是上一轮编译是另一份代码比如调试中途改坏又改回或者 hex 是从别的目录复制来的。你手上这个 hex可能比源码老了好几版。关键认知编译日志 0 Error ≠ hex 包含最新代码。增量编译下日志只能证明编译没报错不能证明编译发生过了。对策烧录前三步走一步都不能省从此烧录流程固定为三步中间不插任何其他操作① UV4 -b 重新编译 ② 对比 hex 时间戳 vs 最近源码修改时间不一致就停 ③ 复制 hex 到烧录目录 → J-Link 烧录第 ② 步是核心命令行一条命令就能比# 烧录前hex 时间必须 最近源码修改时间 test $(stat -c %Y hex/firmware.hex) -ge $(find src -name *.c -o -name *.h | xargs stat -c %Y | sort -n | tail -1) \ || echo 警告hex 比源码旧禁止烧录没有比对工具也可以人肉看编译输出到烧录复制之间看一眼 hex 文件的修改时间。它是几分钟前还是昨天一目了然。还有个铁律编译和复制之间不插别的操作。先编译 → 立刻复制 → 烧录一气呵成。中间哪怕去改了个宏、加了行注释hex 都可能是旧的。事后复盘为什么排查了一下午回过头看排查之所以浪费时间是因为默认假设错了默认烧的就是最新代码—— 编译日志没问题烧录输出没问题自然怀疑代码逻辑。但这个假设恰恰不成立增量编译 手动复制中间任何一步都可能拿到旧产物。没先做版本自证—— 设备有读版本号/读状态命令的话烧完先读一发功能对不对一目了然。我们这次设备有 cmd 19 读版本但版本号没改读出来一样也没想到去对 hex 文件。正确顺序应该是功能不对 → 先自证烧的版本 → 再查代码。版本对了才能信任问题在代码里。总结环节陷阱对策增量编译源码没变就不重编hex 是旧的烧录前对比 hex 与源码时间戳手动复制复制了上次的旧 hex编译 → 复制 → 烧录中间不插操作烧后测试功能不对就查代码先自证烧录版本再查代码编译通过只证明编译成功时间戳对得上才证明烧的是最新代码。烧录前 30 秒的比对省下来的是几个小时的无头排查。实测对比改完源码直接复制hex烧录新功能全失效排查一下午 | 编译后先比对hex时间戳一次看穿是旧产物有用的话点个收藏下次命令行编译烧录前先对一眼 hex 时间戳。有问题欢迎评论区交流看到了都会回。
返回列表