Keil MDK 生产落地案例
五、生产落地案例
案例一:从「下载成功但不跑」到定位到半主机模式
业务背景:一个电机控制项目,从旧工程拷贝了 printf 调试代码,MDK 里编译下载全部成功,但板子上电后没有任何反应,连 LED 都不闪。
怎么用:先在 main 函数第一行加一个 LED 翻转确认程序根本没跑起来;用调试器单步,发现程序停在一个 BKPT 指令处;查 .map 文件确认链接进来的库是标准 C 库而不是 MicroLIB;结论是标准库的半主机模式在等调试通道,而这个工程没连调试器。
关键配置:Target 页勾选 Use MicroLIB,或者保留标准库但补上 _sys_exit / _ttywrch 等重定向函数禁用半主机。
效果指标:问题从「完全没头绪」变成「10 分钟内定位并修复」,且这类问题再也不复现——因为团队把「是否勾选 MicroLIB」写进了工程检查清单。
踩过的坑:一是只看编译输出,编译零错误零警告并不代表运行没问题;二是没看 .map 文件,链接了哪个库其实一目了然;三是调试手段太单一,早期只在代码里加 printf,而 printf 本身就是问题源头,必须先用 GPIO 翻转这类最小手段确认程序死活。
案例二:用 .map 文件把 Flash 占用砍下来
业务背景:一个产品需要在现有硬件上增加功能,但 Flash 剩余空间不足以放下新代码,且使用的是免费版 MDK,体积限制就在眼前。
怎么用:先看 .map 文件里各目标文件与库的占用排名,找出前几名;关闭不必要的调试输出(浮点格式化会引入大量代码);把只用了几个函数的库替换成自己写的精简实现;确认优化等级从 Debug 的低优化换成 Release 的高优化;必要时开启链接期优化。
关键配置:Release 目标单独一套优化与宏定义;把「是否生成调试信息」也区分开,调试信息不占 Flash 但会影响编译产物体积。
效果指标:Flash 占用下降,腾出空间容纳新功能(具体降幅取决于项目里日志与浮点使用的比例,以自家 .map 前后对比为准)。
踩过的坑:一是直接开最高优化就发货,某些依赖时序的代码被优化掉或被重排,出现偶发故障,后来对时序敏感模块单独用低优化编译;二是用优化等级掩盖问题,本该精简的冗余代码没删,只是被优化器藏起来了;三是没有保留 Release 目标的 .map 存档,后续出问题时无法回溯体积变化的原因。

