嵌入式系统概述(中国大学Mooc)的课堂笔记
嵌入式系统的定义,组成及一般开发流程
目前国内普遍接受的概念[1]:嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可裁剪,适于应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。
嵌入式系统的一般设计过程[1]:
- 硬件原理图的设计
- PCB设计
- 硬件制板
- 硬件元器件的安装
- 嵌入式操作系统的移植
- 嵌入式软件设计
嵌入式系统的设计,通常要考虑到实时性、可靠性、稳定性。具体的问题包括:
- 硬件资源、运行环境和设计指标
- 升级方式
- 开发和测试策略
嵌入式的概念,是相对于通用计算机的,当然,这种通用也是相对的,嵌入式强调的是一种专用用途,应用场景常常是资源受限的,优先考虑的也不是用户友好性,是安全性和可靠性。嵌入式系统的用途非常广,包括但不限于无人驾驶、通信设备、军事武器等等。
嵌入式C语言编程写法及优化技巧
嵌入式开发过程中,最为常用的编程语言是C语言,原因很多,很重要的一个原因,内核通常是用C语言写的。
一般的单任务嵌入式程序典型架构是:
- 从cpu复位时的指定地址开始执行
- 跳转至汇编代码startup处执行,完成部分初始化动作
- 跳转至用户主程序main执行,在main中完成:
- 初始化部分硬件设备
- 初始化各软件模块
- 进入死循环(无线循环),调用各模块的处理函数
尽管C语言并不是一门面向对象的语言,但是,通过sturct和函数指针,仍然可以很好的模拟”类”的写法,使得写出的代码,具备很好的维护性。
以下,是这种写法的一种实例:
1 | #define C_Class struct |
嵌入式平台中,最常用的芯片是arm系列,因此,如果需要处理一些性能敏感的场景,需要结合生成的arm汇编代码一起查看。
尽管现在的编译器已经非常智能,能够帮助程序员处理很多情况。但是,在一些存在歧义的情况下,编译器一般会采取保守的判断,以防止程序行为超出预期。因此需要对编译器有一定的了解,了解编译器在哪些方面是保守的,了解编译器对应的处理器体系结构。
以指针别名为例,来展示编译器的保守方面以及对应的优化策略:
考虑以下代码
1 | void timers_v1(int *timer1, int *timer2, int *step) |
对应的arm汇编为
1 | LDR r3, [r0, #0] --> r3 = *timer1 |
可以看到, step指针指向的值被取出来两次,有一次是明显多余的。出现这种情况的原因,是编译器必须考虑所有可能的情况,假设step跟timer1指向同一个地址,那么第一次运算后,timer和step的值都被更新了,所以第2次重取step的值,才能保证在这种情况下,行为也符合预期。
但是如果程序员确定step和timer指向不同的地址,那么可以采取下面的写法,来减少一次step取值:
1 | void timers_v2(int *timer1, int *timer2, int *step) |
除此之外,数据结构在内存中的布局也能极大影响程序的效率,如果结构的成员变量不全是内存对齐的,那么在取值时,就需要多余的操作。
总之,嵌入式程序的优化,是在基于对所写程序面向的场景,编译器和程序语言的了解上,使得生成的arm汇编最为精简。需要说明的是,效率最优并不总是程序首先考虑的事情,代码的可维护性以及优化所要付出的努力和优化带来的效果对比,这些都是优化前所要考虑的事情。
Linux C的编程工具链以及构建系统
嵌入式开发过程中,涉及到的编译器,调试器,构建工具等等一系列的工具,被称之为工具链。
嵌入式系统开发中,开发环境和运行环境常常是不同架构的,因此就需要交叉编译,即在开发环境中编译出与之不同的运行环境的可执行文件。
当前使用最为广泛的为GNU工具链,GNU支持本地程序开发,也交叉编译,即GNU工具链包括 :
- GNU Tools (GNU Development Toolchains)
- GNU Tools交叉开发环境 (GNU Cross-Platform Development Toolchains)
嵌入式C语言最早流行的构建系统是make,后来进一步发展出了CMake,CMake足够处理一些常见的项目场景,但在更复杂的构建场景中,比如系统的生成需要从多个仓库获取源码,进行编译链接时。对于这种复杂的场景,当前比较主流的构建系统是yocto。
一个嵌入式系统通常由3部分构成:
- Bootloader
- 嵌入式操作系统内核
- 文件系统
Bootloader可以分为单阶段和多阶段。多阶段的Bootloader能提供更加复杂的功能,以及更好的移植性。大多数Bootloader都有两种工作模式,分别是Bootloader自动加载操作系统运行,全程不需要用户介入,即正常工作模式;以及通过串口或者网络等方式首先下载所需文件,再进行后续引导,即下载模式,通常首次启动时使用。
嵌入式系统书籍推荐
- 嵌入式软件设计(清华大学出版社)
- ARM嵌入式系统开发 - 软件设计与优化(北京航空航天大学出版社)
- Linux程序设计(人民邮电出版社)
- Linux设备驱动程序(中国电力出版社)
- Linux设备驱动开发详解(人民邮电出版社)
- Proteus电子电路设计及仿真(电子工业出版社)