关于嵌入式软件开发的内容进阶详述

2019-02-22 10:00:28分类:嵌入式软件开发设计7009

  “嵌入式软件”这个名词很笼统,但一般业内的理解就是直接与硬件打交道的软件。大部分嵌入式软件工程师基本工作内容如下:裸机——RTOS——Linux,以及一些新生的概念。
 

嵌入式软件开发
 

  1、裸机开发

  裸机开发看起来随意性很大,因为没有固定框架、固定接口,从驱动、算法、界面、顶层应用都是自己做。但这往往就是初学者的心态,或刚入行的格局。

  裸机开发的平台虽然不如隔壁互联网那些千变万化的框架多,但数量还是有很多:STM32、AVR(MicroChip)、瑞萨、飞思卡尔(NXP)、新唐电子……开发平台大部分都由芯片厂规定。但这只是表面看起来丰富,对于嵌入式老司机而言,这些杂七杂八的所谓平台都逃不出:编辑器、编译器、链接器、烧写调试器、芯片电路板。在STM32上配置寄存器,难道在RH850上就不会了吗?并不是,嵌入式软件的开发套路是比较固定的,开发工具大同小易。比互联网跳框架难度应该不会大,如果感觉很大,多看几遍芯片的datasheet吧。这几年随着芯片越来越统一化(比如ARM Cortex生态系统),有些厂推出了图形化配置的工具比如STM32CubeMX,其实不过是做了层封装和调用而已,而且仅仅限于引脚、时钟配置、驱动、加载协议栈,对于中间层、应用层帮助不大。但至少配置没那么繁琐和容易出错了,但产生的程序代码可能并不符合很多公司的代码规范和框架。我知道有些公司是自己开发这类配置软件的,当然要项目足够大和稳定才行。

  裸机开发的第一个套路是框架。合理的框架有助于程序阅读、修改、移植。裸机程序的框架一般只有三层:驱动、中间层、应用层。中间层往往被忽略,其实它作为应用和驱动的对接层,写得好对于程序移植和理解好处多多。很多业内的很喜欢把三个搅在一起,因为赶项目所以不太在乎。而且大部分做嵌入式的都是硬件出身,没有软件出身人的满脑子框架束缚。设计可变模块用#ifdef来灵活使用,在应用模块用回调函数控制被调用模块改变。这些都是基本套路。嵌入式软件本质上还是软件,软件那套低耦合、强内聚、模块化等概念是要一脉相承的。这里不拓展讲,业内人士要多看看软件相关书籍,虽然没有几本写的好的。很难找到单纯讨论嵌入式软件的书,那些挂名号的大都是结合硬件讲的,且就讲个驱动设计,连框架、语法、构建都懒得说。这或许还是大家都出身硬件的缘故。如有朋友知道有这方面写的好的书,请推荐。嵌入式软件工程师也要所学学软件的理论,那些封装、面向对象等软件设计基本套路还是要掌握的。

  裸机开发第二个套路是任务调度。因为没有操作系统加持,任务调度要自主实现。嵌入式软件任务调度要考虑硬件性能,放一个while(1)大循环、前后台中断,理想情况下看是所有任务都会即使执行的,实际上芯片压根性能没那么强劲,中断多了任务就不执行了。一般这里有两个分类,一类是基于(中断)事件、一类是基于时间。基于事件基本都是理想主义,认为美好的事总会发生,而基于时间则是物理规律——任一时间芯片只做一件事,并且认为外界的事件发生是有时间间隔的(瞬态无时间间隔的任务,芯片只能说臣妾做不到啊!)。当然一切都要基于需求,假设芯片就是只做一两个任务,那就是一个while(1)+前后台有什么所谓。多任务程序框架就必须要考虑基于时间了。

  裸机开发的第三个套路是状态机。犹记得第一份工作时,面试官的第一个问题就是让我谈谈状态机。状态机在裸机程序设计里应用非常广,也是一种优秀的设计模式。状态机集合了任务调度、程序框架的概念。甚至业内优秀的状态机框架被商业化了比如QT量子状态机框架。状态机不是程序流程图,程序流程图一般是基于用户一步步操作的,状态机是基于系统运行状态的,所以流程图一般用于做需求,状态机用于做开发。状态机程序设计首先要用UML工具画好程序状态图,要明确某一时刻系统智能处于某一状态,以及状态跳转的条件。把状态机和任务调度结合,就是用时间轮询不断执行一个个状态机。状态机内部设计方法非常重要。当熟稔后,状态机就是愉悦的switch case,if else了。

  业内一直有一些偏见认为做裸机程序的人软件水平不行,甚至扬言在目前硬件性能爆炸的年代不应该在乎代码量。这依旧是初出茅庐的人说的,任何开发都要基于明确的需求,那些能用少了几块钱的芯片、少了一两个级别软件复杂度做出产品的工程师才是公司需要的。一个发货量十几万的产品,能提前一周上市,公司盈利很可观了。工程师要做的是用最快的速度满足需求,而不是比较什么技术比较高超,那是象牙塔的理论。
 

嵌入式软件开发
 

  2、RTOS

  RTOS本质上仅仅是个任务内核,对于硬件驱动仅仅涉及到RAM、时钟等这些与任务调度直接相关的驱动。这不就是裸机任务调度那套玩意放大版么。但RTOS任务调度更加复杂,涉及到任务切换、任务通信、内存管理等。看起来RTOS好像内容很多,但其实,其实也就只有这些内容了。作为实时操作系统,RTOS如果涉及太多会拖慢任务调度速度,因此实际上它仅仅扣出操作系统最基本的东西——任务管理和内存管理来实现。如果能结合操作系统知识来学习RTOS收获应该更大,体会为了实现理论家口中的操作系统,RTOS做了怎样的妥协和灵活。RTOS本质上仅仅是个中间模块,把它拿掉,自己设计一个任务管理和内存管理模块,即使糙一点也还是能用的而且还能非常小心地把控硬件资源。但在经过N多项目考验的FreeRTOS、UC/OSII等优异的RTOS面前,加上项目需求的多样,恐怕很少工程师会抵制住诱惑。

  正是因为RTOS仅仅实现了操作系统一部分功能,因此设计一个RTOS好像不是那么难。于是RTOS市场风起云涌,专用的、通用的、内部用的、开源的……但是其实用什么RTOS只要你不是技术总监,选择跟你没有关系。当然DIY除外,笔主比较推崇FreeRTOS、UC/OSII、UcLinux,这些案例多,健壮的RTOS。

嵌入式软件开发

  3、Linux

  本来起个通用操作系统的标题,但发现毫无意义,Windows不开源、Android内核本来就是Linux,兜这么大个圈还不是只能讲Linux,所以还是叫Linux好了。

  Linux作为通用操作系统,在业内是为实现任务种类多、界面多、造价高这类项目准备的。Linux完整实现了操作系统的所有理论,包括驱动管理、文件管理、任务管理、内存管理、网络协议、安全管理等等。虽然看起来好像内容好多,但仅仅就内核而已,除了开发驱动(还要去掉直接与CPU相关的驱动,这些内核已经适配了)、做做中间包、做做应用程序,很多工程师无能为力。真正的内核开发是Linus、intel公司那些大牛做的,我们只能用用。但就是这么少的一部分,已经够折腾人的了。

  对于Linux标准的要求就是会移植、会开发驱动和拼凑进Linux去、会shell C开发调用。做应用层的多的就是QT 环境开发了,这玩意和Java JVM是差不多的逻辑,就是在shell上面再放一层解释器或加入调用包一起编译而已。
 

嵌入式软件开发
 

  4、协议栈、中间包

  这几年嵌入式领域因为硬件性能提升和任务多样化,涌现了很多专一功能的协议栈、中间包。比如蓝牙协议栈包、WIFI协议栈包、STemwin GUI包、安全栈、神经网络加速包等等。很多栈和包实际上已经超出了传统的嵌入式软件领域了。比如无人机姿态控制的PID包、手机人脸识别NPU加速包等,这些对数学的要求高于代码,也不是一般工程师能做的,要有数学功底。当然并不是高不可攀,再说谁不会调基本的PID呢。

上一篇:下一篇: