整理东西时翻出了刚入行那几年的笔记本,上面密密麻麻记满了寄存器地址、时序图和各种调试命令。翻了几页,回想起那时候确实干劲十足,但有些选择放到现在看,确实走了不少弯路。
写下来权当是个复盘。如果你刚入行或者还在读书,或许能帮你少踩几个坑。
后悔一:头两年只看代码,不看原理图
刚工作那会儿,我总觉得软件工程师就该专注软件。拿到新板子,第一件事就是找硬件同事要 SDK 和 demo,原理图基本不翻。
有一次调 I2C 设备,从机一直不回 ACK。我在软件层面查了整整两天——时钟极性、传输速率、驱动加载顺序,能试的都试了,毫无进展。
后来硬件同事过来瞄了一眼原理图,拿万用表量了两分钟,说了一句我至今记得的话:
这个 Pin 的上拉电阻没焊。
从那以后,凡是涉及外设的问题,我都会先翻一眼原理图。确认电源、上拉、电平匹配这些基础条件没问题了,再动手查软件。总共花不了十分钟,却能省下好几天的排查时间。
嵌入式开发和纯软件最大的区别就在这里——你绕不开硬件。不一定非得会画板子,但一定要能看懂原理图。很多软件问题的根因在硬件上,反过来也是一样。
很多时候我们卡在某个问题上兜圈子,恰恰是因为没先做那十分钟的硬件检查。
后悔二:笔记记了一大堆,但没有体系
我有遇到问题就记笔记的习惯,几年下来攒了几百篇记录:某天怎么配 UART DMA、某个内核编译报错怎么处理、某颗芯片的勘误表需要注意什么。
记的时候觉得挺充实。可半年后再翻,完全想不起来当时写的是什么意思。有些坑甚至踩了两次——第一次记了,第二次忘了自己记过,又从头查了一遍。
后来我才发现,效率高的人记笔记的方式跟我完全不一样。他们不是在记录,而是在建索引。一个问题解决了,不单单记答案,还会记下怎么查出来的、用了哪些命令、背后的原因是什么。下次再遇到类似问题,脑子里能自动跳出排查链路,而不是一个孤零零的命令。
我现在改成按子系统整理笔记。比如“调试工具”一个目录,从 OOPS 信息解读到 ftrace 再到 kdump,串成一条完整的线。不再是今天记一条 strace 用法,明天记一条 perf 命令,各管各的。
你以为自己在积累,可能只是在堆积。
后悔三:不敢拆别人的代码
刚工作的时候拿到一份老代码,宏的嵌套、结构体的套娃,看着就头疼。第一反应是“这代码写得真烂”,然后绕道走了。
现在回头看,更应该问的是:这段代码为什么长这样?哪些是自己没看懂的设计?看起来很丑的部分,是不是在解决什么实际问题?
后来跟一位做驱动的前辈合作项目,他每次提交的代码,命名规范、错误处理路径、注释位置,像同一个模子刻出来的。我问他怎么做到的,他说他早期把内核里某个驱动源码抄了三遍。
不是读,是抄。一行一行抄,边抄边琢磨为什么这么写。
代码很多时候不是看会的,是写会的。抄过、改过、跑过、崩过,下次遇到自然知道该怎么处理。
后悔四:太晚意识到英语的重要
做嵌入式 Linux,好一点的资料基本全是英文的。芯片手册是英文的,内核邮件列表是英文的,Stack Overflow 上高质量的回答也是英文的。现在调芯片驱动,第一件事就是翻 Reference Manual,全英文,动辄好几百页。
中文博客不是没有好东西,但搜到的很可能是二手的、不完整的,甚至是过时的信息。芯片勘误表更新了,中文博客不会跟着更新;内核版本迭代了,中文教程不会同步修订。
我现在遇到不熟的芯片,官方文档翻一遍,比自己瞎搜一堆中文笔记管用得多。
后悔五:太晚建自己的 demo 平台
前两年做项目都是基于公司开发板。能跑,但每次换平台就要重新折腾一遍环境。后来自己花了几百块买了一块二手的 i.MX6ULL 板子,周末捣鼓。从 U-Boot 移植到内核编译再到驱动加载,完整走了一遍。
走完这一遍,对启动流程和系统构成的理解,比看半年书都深。
自己折腾的好处在于:一是没压力,崩了大不了重新刷;二是能接触到公司项目里不会遇到的分支——比如从零移植内核、从头写驱动框架。这些看起来用不上的东西,恰恰是理解系统最缺的那块拼图。
说来说去,嵌入式开发别把自己框死在代码里。原理图要看,硬件同事要多聊,英文文档要硬读。笔记要有体系,代码敢拆。
这些事都不难,难在早点开始做。