做了很多年的嵌入式开发,也做过很多年PC应用软件开发,每次在两者之间切换,总要花费一段时间来适应其编程思想的差异。就像表演硬气功头顶碎砖一样,得先运运气。

我做嵌入式开发,早期使用PL/M-51语言,后来使用C语言,不过基本上都还是使用结构化、模块化的设计方法。后来做了PC应用软件开发,接触到了面向对象的设计方法,看了很多面向对象的设计原则、模式等方面的书籍,应用这些原则、模式完成了很多软件,感觉设计良好的代码,通用性、可移植性都很好,代码构架上看着就有一种难以表述的美感。

再后来又回来做嵌入式开发,看到别人写的代码,总有一种抓狂的感觉。嗯,其实我以前也是这么写嵌入式程序的代码的。这种代码,简单的说就是程序是采用了结构化、模块化的设计,但是不同模块耦合性很强,源码文件也没有很好整理,互相之间依赖性很强,底层代码检测到硬件事件,直接调用上层的处理函数,上层的处理函数又需要依赖底层函数操作硬件,其结果就是函数和文件之间的关系好象一团乱麻,紧紧地缠绕在一起。

嵌入式软件一般要求比较高的性能,这也往往是导致代码构架比较混乱的一个原因,但实际上,根据我多年的嵌入式开发的经验,其实嵌入式软件在设计的时候,如果没有必要,大多数情况下是不用特别考虑性能问题的。譬如把寄存器读写操作封装成函数,而不是代码中到处直接读写,性能上会因为增加了函数调用而增加一点时间,但是随着硬件性能的提高,或者在硬件不变的情况下,这一点点的小差异根本表现不出来,反而会因为程序中大量充斥着直接操作寄存器硬件的代码,导致难以阅读和迁移。

目前C语言是使用的最多的嵌入式开发语言,它不是一种面向对象的语言,但是可以借鉴面向对象的思想,来设计和构架代码。我认为比较好的结构就是采用分层的设计方法,把需要实现的功能按照从上到下,分成若干层,从业务逻辑一层层调用到底层的硬件接口,每一层都只依赖于下一层的代码。底层代码检测到了硬件的某个事件,不是直接调用上层代码去处理,而是放到消息队列中,上层代码在主循环中检查到消息队列有新的内容,则调用相应接口开始从上到下的处理。

这样分层+消息队列的构架,可以消除上下层代码的交叉依赖,而且层次之间接口明确,可以很容易的编写单元测试代码。其实对于嵌入式开发来说,一般只有最底层才是跟硬件打交道,其它各部分在业务上来说都可以是与硬件无关的,再加上C语言的通用性,完全可以针对每一层的业务逻辑编写单元测试代码,在计算机上就对业务逻辑进行自动化测试,不用等到硬件出来,就可以在计算机上完成绝大部分功能及其测试,工作效率的可以得到很大的提升。