虽然软件并不会随着时间推移而磨损,但是硬件会,随即也需要对软件做相应改动。硬件更新换代是非常快的。
如果没有妥善管理硬件依赖和固件依赖,未来将会非常麻烦。
什么是固件,有很多种答案:
- 固件通常被存储在非可变内存设备,例如
ROM
,EPROM
或者闪存中。 - 固件是直接编程在硬件设备上的一组指令或者一段程序。
- 固件是嵌入在一个硬件中的软件程序。
- 固件是被写入到只读内存设备中的
(ROM)
程序或数据。
大家对固件的认识普遍是错误的,或者说至少是过时的。
固件并不一定是指存储在ROM
中的代码,也不是依据其存储的位置来定义的。固件是由其代码依赖关系,以及随着硬件的演进在变更难度上的变化来定义的。
我们应当少写固件,多写软件。如果在代码中嵌入了SQL
或者引入对某个平台的依赖的话,其实就是在写固件代码。比如Android
工程师,如果没有将业务逻辑和Android
的API
分离开的话,实际上也是在写固件代码。
再比如,命令消息是通过串行端口传递给系统的,这就需要一个消息处理器/分发器系统
。其中消息处理器需要了解消息格式,使其可以解析消息,然后再将消息分发到具体的处理代码中。
但是消息处理器/分发器
的代码,和操作UART硬件(平台)
的代码往往会被放在同一个文件中,消息处理器中的代码往往充斥着UART
相关的实现细节。这样一来,消息处理器代码就变成了一段固件代码。
我们应该少写这种固件代码。
“程序适用测试”测试
为什么会出现很多固件代码?是因为我们做设计时,只关注代码是否能正常运行,并不关心其结构是否能够支撑一个较长的生命周期。
软件构建的三个阶段:
- 先让代码工作起来——不能工作,就没有价值。
- 然后试图将它变好——通过重构,让我们和他人更好理解代码,并使其变得更易修改。
- 最后试着让它运行得更快——按照性能要求来重构代码。
很多人,只能做到1,3这两个阶段,而忽视了2。在《人月神话》中,作者建议我们应当随时准备抛弃一个设计。在实践中学习正确的工作方法,然后重写一个更好的版本。
如果程序员写代码,只能做到1,3这两件事,这对程序员和老板来说都不是一件好事。编程不仅是让程序跑起来这么简单。只能做到跑起来,充其量只能算作是程序适用测试
,而不能算作是一套整洁的嵌入式架构
。
目标硬件瓶颈
嵌入式程序员,通常会写很多与处理很多和硬件,平台,物理世界的链接代码,程序员在编写这种代码的时候,通常是软件固件并行进行开发的,通常这个时候还没有拿到硬件,即没有地方可以运行这些代码。如果我们要等到真正拿到硬件时,才能了解代码在该硬件上存在哪些意料之外的缺陷。
嵌入式开发有其特殊性,但是没有特殊到本书中所讲的原则都不适用的程度。
目标硬件瓶颈,是嵌入式开发所特有的问题,如果我们没有采用某种清晰的架构,来设计嵌入式系统的代码结构,就经常会面临只能在目标平台上测试代码的难题。如果只能在特定的平台上测试代码,那就会拖慢开发进度。
整洁的嵌入式架构就是可测试的嵌入式架构-分层
分层有很多种方式,以三层为例。由于硬件随着科技发展一定会变,所以嵌入式工程师应当避免硬件的变动导致更多的变动。所以硬件需要和软件和固件,进行依赖管理。
而软件和固件也做不到完全的隔离,但是它们还是需要一条分割线,我们要做的就是使这条分界线更加清晰。软件和固件中间的边界,被称为HAL
,硬件抽象层
。这不是一个新概念,在Windos
诞生前就有了。
HAL应当依赖于软件,更多属于接口层。这样软件就可以脱离硬件平台进行测试了。
四层结构,还考虑操作系统:
本章小结
嵌入式编程人员,应该多学习一些非嵌入式系统的编程经验。为了软件长期保持健康,别让代码都变成固件。