2.4. 嵌入式软件开发需要学习哪些知识

由于嵌入式本身是个复杂的概念,为了便于理解,此处用类比的手段去好好解释一下,嵌入式开发和从事建筑行业的关系,以便解释清楚,嵌入式学习,需要掌握哪些知识:

举个例子:就像,你从事的是建筑行业

有些是相对通用的基本知识和技能:(不论你是干体力活的各种工种的工人,还是大楼的整个架构的设计师)进入建筑工地,都要戴安全帽

不论你是干哪个工种的,比如瓦工,水电工,木工等等,那基本上都要具备的基本素质都是:

身体素质本身要好,要能吃苦

但是,很明显,有些知识和技能,就属于领域相关的知识:

如此等等。但如果是你瓦工,则不需要关心木工需要了解的技能,反之亦然。

而搞嵌入式,这上面这几点上,有点类似于搞建筑行业:

2.4.1. 嵌入式领域内相对通用的知识和技能

2.4.1.1. 嵌入式相对通用的知识:计算机编程语言

比如C语言,汇编语言,C++语言等等

2.4.1.1.1. 嵌入式相对通用语言:C语言

2.4.1.1.2. 嵌入式相对通用语言:汇编语言

2.4.1.1.3. 嵌入式相对通用语言:C++语言

2.4.1.2. 嵌入式相对通用的知识:芯片架构

硬件采用何种芯片,比如是ARM内核还是MIPS内核

是ARM内核的话,具体是哪种内核,比如ARM9TDMI还是Cortex-M3等等

不过,关于芯片架构的事情,要好好解释解释:

经常看到,嵌入式方面,介绍arm的架构

但是却又感觉学了也没啥用,和工作的内容也对不上号,纯粹就是在死读书,读死书

至少我最开始的感觉就是这样

现在其实也还是没有透彻理解,不过有一点点心得了,总结如下

比如以ARM Cortex-M3为例:

图 2.1. ARM的Cortex-M3架构概述

ARM的Cortex-M3架构概述

解释我所能够理解的,架构中的内容,和你后续嵌入式Linux开发之间的关系:

  • ARM架构中的AMBA总线

    里面有AHB和APB

    对应Linux中就是有对应的AMBA的概念的定义的,好像是在设备注册期间也有涉及到,比如probe的时候

  • ARM核是否带MMU

    决定了是用uclinux还是linux

  • 采用哪款ARM内核

    比如说Cortex-M3采用了ARMv7内核

    则意味着你选择交叉编译器(甚至是自己用crosstool-ng去制作交叉编译器)的时候内核选择是armv7。

  • 指令集

    比如说Cortex-M3是Thumb2的指令集

    意味着,比如后期制作或用交叉编译器时,编译代码、生成什么样的汇编指令,都是要设置为thumb2

如此,一点点地,把芯片架构是什么,以及不同的值的真正含义是什么,对后续开发有何影响,都说清楚了

这样才能说,明白了芯片的架构

2.4.1.3. 嵌入式相对通用的知识:嵌入式操作系统

相对通用的操作系统:嵌入式Linux,ucOS/II,VxWorks等等

2.4.1.3.1. 嵌入式常用操作系统:嵌入式Linux

此处的嵌入式Linux,是有别于普通桌面电脑所使用的普通桌面Linux系统。

2.4.1.3.2. 嵌入式常用操作系统:μC/OS-II

2.4.1.3.3. 嵌入式常用操作系统:ThreadX

2.4.1.3.4. 嵌入式常用操作系统:VxWorks

TODO:http://www.windriver.com/evaluations/gpp-ve/可以下载试用包,有空去试试。

2.4.1.3.5. 嵌入式常用操作系统:WinCE

2.4.1.3.6. Android不是传统意义上的嵌入式操作系统

此处需要专门解释一下,被很多人归类为嵌入式操作系统的Android,实际上不是传统意义上的嵌入式操作系统。

2.4.1.3.6.1. Android和嵌入式Linux的区别

典型的Android系统中,根据开发所用语言不同和开发环境不同,可以划分为:

  • 上层应用:用java语言在Eclipse+ADT或者Android Studio的IDE中开发Android的app应用程序
  • 嵌入式底层:用C,C++等语言实现底层的,以Linux为基础的,在Android框架下的,设备的驱动相关的开发,其中更多的是涉及到Linux驱动开发,Java的JNI,Android的驱动框架模型等等内容。

此时,对于传统意义上的,嵌入式软件开发,尤其是嵌入式Linux驱动开发,基本上是和,上述的Android开发中的,嵌入式底层开发中的Linux驱动开发,是基本上一样的。

而Android系统中的其他内容,包括嵌入式底层的Java的JNI,Android驱动模型,以及上层应用的Java的Android的app开发,都是和传统的Linux的驱动开发,没什么关系,也是差别很大的,包括所使用的语言,以及所使用的开发环境。

即,Android的开发,基本上都是基于app那层去开发app的,都是用Java语言去写代码的。且底层有Android的运行时作为支持

而Linux的开发,对于Linux驱动开发,都是基于底层的内核去开发的,用的都是C语言,甚至偶尔还会涉及到汇编代码;对于Linux的应用层面的开发,都是Application Framework级别的,应用程序的开发,往往都是去写C语言代码的。

对应的传统Linux嵌入式驱动开发,以及Android中的app开发,以及Android中的驱动移植,所处于不同层次的关系,可以用下图表示:

图 2.2. 传统Linux和Android的不同的开发所处层次关系对比图

传统Linux和Android的不同的开发所处层次关系对比图

而对于Android的中间的Libraris,Android Runtime,以及Application Framework,很多时候,是各种(C,C++,Java等)不同的语言的混合体,包括中间的Android Runtime是利用到了Java的JNI,为Java和C或C++语言之间,提供一个接口,可以互相通讯。

而对于Android这套框架来说:

  • 如果是你做Application,即做Android的应用,现在流行称其为app,的话

    则是去开发上层的应用->比如基于Android做一个收音机,做一个音乐播放器等等的应用

    ->都是在Android的框架之下(用Android相关的工具,比如Eclipse+ADT) 去写Java代码去实现对应的功能

  • 如果你是做Android底层嵌入式开发的话

    ->那就是在Linux内核框架下,去实现各种功能和模块

    ->典型的工作要属,你是一个做硬件的公司,做了块开发板,为了使得其支持Android系统,需要在开发板这个硬件的基础上,去为开发板中的各个硬件模块,比如Nand Flash存储芯片,SD卡芯片,网卡芯片等等,去写对应的模块的驱动

    ->此时主要就是在Linux框架下写C(或C++)代码去实现模块驱动

    ->当然有时候为了支持Android,还需要了解Android本身的框架,可能还需要加上一些JNI的代码支持

2.4.1.4. 嵌入式相对通用的知识:嵌入式开发环境搭建和使用

对于嵌入式开发来说,不论你是用何种嵌入式操作系统,都会涉及到,嵌入式环境的搭建和如何使用,如何去搞嵌入式开发。

比如,如果是嵌入式Linux的话,则要去搞懂常见的uboot+kernel+rootfs开发环境

2.4.1.4.1. 嵌入式开发环境:交叉编译器

相关内容:交叉编译详解

相关内容:crosstool-ng详解

2.4.1.4.2. 嵌入式开发环境:固件的烧写

不论是嵌入式Linux,还是WinCE等环境,都会涉及到,将程序交叉编译成可执行文件后,要下载到目标环境中。

这个动作,往往被叫做burn,烧录,烧写。

比如嵌入式Linux中,有很多种烧写方式:tftp,通过uboot,专门的烧写工具等等

如何用tftp下载文件

WinCE平台,也有特定的烧写工具

相关内容:【详解】嵌入式开发中固件的烧录方式

2.4.1.4.3. 嵌入式开发环境:调试

此处的嵌入式环境中的调试,包括不同的调试方法和用不同的调试工具去调试。

2.4.1.4.3.1. 嵌入式开发调试方法和调试工具
  • 软件:

    • printf

      嵌入式Linux中经典的printf

    • 利用NFS实现快速测试

      如何利用NFS实现快速的驱动的开发测试:方便的下载新编译好的驱动.ko文件并insmod去测试

  • 硬件

    • JTAG

      利用硬件的支持,比如JTAG实现调试

    • MultiICE

    • Jlink

      TODO:把之前折腾过的Jlink的帖子都整理过来

2.4.1.4.4. 嵌入式开发环境:嵌入式IDE

详见:第 7.1 节 “嵌入式开发的IDE”

换句话说,不论你在嵌入式行业内,具体做什么“工种”,以我之前所遇到,见到,听到的为例:

  • 所在公司是做消费类数码产品研发,比如做Linux底层驱动开发
  • 比如工业控制领域内的现场总线开发
  • 汽车电子行业内的嵌入式开发

那么C语言,基本都是必备的,基本功,因此:不论你做相关的哪种领域的嵌入式开发,那么都要努力学好C语言

[注意] 学好C语言是什么意思

学好C语言的意思是:不单单掌握C语言的语法,更要:

  • 有良好的编程思想
  • 良好的编写高质量代码的编码习惯
  • 良好的处理问题的思路
  • 良好的代码风格
  • 了解写出高质量C语言代码需要注意哪些细节

等等。

另外,由于一些嵌入式操作系统,比如嵌入式Linux系统,ucOS/II(以及其他很多常见的嵌入式操作系统,比如VxWorks等)都是相对通用的。

所以,为了学好嵌入式,也要尽量找机会去多学习和了解这些系统的特点和使用方法,最好找机会多去实际动手练习。

2.4.2. 嵌入式领域内某领域内相关特定知识

同理:有些是Domain knowledge,即领域相关的知识

关于这部分,之前见过的,一个老外写的,不错的嵌入式的教程:

第 16.1.1 节 “Embedded Systems Architecture: A Comprehensive Guide for Engineers and Programmers”

中所给出的例子,就是个很好的,domain knowledge的例子:

如果打算从事嵌入式机顶盒方面的嵌入式开发的话,那么往往又要涉及到

DVB,MHP,EGB,和其他的协议,架构,软件库,等等等等

所以说对于不同的领域,其所相关的东西,光是新名词就一堆一堆的

更别说,每个名字后面都对应着一堆规范说明,都N多页N多页

往往还都是英文的

此时你所面对这些技术(名字和规范说明)的心情

有点类似于:你是干木匠的,然后让你去把瓦工干的活,不仅仅要把名词搞懂了,还要搞懂如何实现的,并且还要把活干得好

这时候,往往就是:需要你有足够的背景知识:对于该领域所涉及的到的技术,即使没实际经验,也要最好有个概念

加上良好的学习能力:有了其他领域的背景知识,以便于稍微帮助你学习新领域的知识

以及良好的悟性:很多时候,学习新东西,出了基础和经验,剩下就是悟性了

加上:足够的耐心,毅力

以及实际动手能力:把所理解的内容,能转化有有效的代码,

最终:

真正去用高质量的代码,实现软件的功能

由此,算是:

在建筑领域内混的一个木工,靠着基础知识,努力学习瓦工方面的知识,加上良好的悟性和动手能力,

最终把瓦工的活干了,而且干得还不错

当然老板最希望你是:干的比原来的瓦工干的还好

如此,正所谓:嵌入式开发中

最先要,也最重要的,是把基础知识学好了,基础打牢了;

然后是,针对所要学习和工作的相关领域的知识,去用最短的时间,最大的学习热情,加上悟性,和学习方法,最终掌握该领域的知识,并且实际动手去锻炼,最终实现目标:

用高质量的代码实现嵌入式领域内的相关的软件功能

2.4.2.1. 嵌入式领域相关知识之消费类数码

如果做消费类数码方面的嵌入式研发,往往会涉及到嵌入式开发板

以某个SoC芯片为核心的开发板,然后上面有各种接口

为各种接口去开发不同平台下,比如嵌入式Linux,ucOS/II等等,的驱动,或者上层应用层的软件。

2.4.2.2. 嵌入式领域相关知识之工业自动化控制

其实严格区分的工业自动化控制的话,算是两个方向,工业控制和工业自动化,这两个领域,也是不同,各有侧重点的。

但是此处也还是算是工业方面的领域,所以就放在一起说了。

可能会涉及的技术:现场总线

2.4.2.3. 嵌入式领域相关知识之汽车电子

汽车电子领域内,在协议和接口方面,相对用的最多的是CAN总线协议,也常会涉及到MOST(Media Oriented Systems Transport)总线

相对来说其他行业就很少用到这类技术。

除了汽车电子领域相关的技术,往往还会涉及到相关的标准,比如SPICE等等。

2.4.2.4. 嵌入式领域相关知识之医疗器械

2.4.2.5. 嵌入式领域相关知识之航空航天

这个领域不熟悉。但是了解过一些相关知识。比如美国的好奇号火星探测器,里面用的操作系统就是VxWorks。