任务1.3 熟悉嵌入式系统的学习方法
关于嵌入式系统的学习方法,因学习经历、学习环境、学习目的、已有的知识基础等不同,可能在学习顺序、内容选择、实践方式等方面有所不同。但是,应该明确哪些是必备的基础知识,哪些应该先学,哪些应该后学;哪些必须通过实践才能了解;哪些是与具体芯片无关的通用知识,哪些是与具体芯片或开发环境相关的知识。
嵌入式系统的初学者应该通过一个具体MCU作为蓝本,经过学习实践,获得嵌入式系统知识体系的通用知识, 其基本原则是:入门时间较快、硬件成本较少、软硬件资料规范、知识要素较多、学习难度较低。
由于微处理器与微控制器种类繁多,人们对微控制器及应用处理器的发展,在认识与理解上存在差异,一些初学者有些困惑。下面简要分析初学者可能存在的3个困惑。
(1) 嵌入式系统学习困惑之一——选择入门芯片:是微控制器还是应用处理器?
在了解嵌入式系统分为微控制器与应用处理器两大类之后,入门芯片选择的困惑表述为: 选微控制器,还是应用处理器作为入门芯片呢? 从性能角度看,与应用处理器相比,微控制器工作频率低、计算性能弱、稳定性高、可靠性强。从使用操作系统角度看,与应用处理器相比,开发微控制器程序一般使用RTOS,也可以不使用操作系统;而开发应用处理器程序,一般使用非实时操作系统。从知识要素角度看,与应用处理器相比,开发微控制器程序一般更需要了解底层硬件;而开发应用处理器终端程序,一般是在厂商提供的驱动基础上基于操作系统开发,更像开发一般PC软件的方式。从上述分析可以看出, 要想成为一名知识结构合理且比较全面的嵌入式系统工程师,应该选择一个较典型的微控制器作为入门芯片,且从不带操作系统(Non Operating System,NOS)学起,由浅入深,逐步推进。
关于学习芯片的选择还有一个困惑,是系统的工作频率。误认为选择工作频率高的芯片进行入门学习,表示更先进。实际上,工作频率高可能给初学者带来学习过程中的不少困难。
实际上,嵌入式系统设计不是追求芯片的计算速度、工作频率、操作系统等因素,而是追求稳定、可靠、维护、升级、功耗、价格等指标。
(2 )嵌入式系统学习困惑之二——选择操作系统:NOS、RTOS或EOS。
操作系统选择的困惑表述为: 开始学习时,是无操作系统(NOS)、实时操作系统(RTOS),还是一般嵌入式操作系统(EOS)? 学习嵌入式系统的目的是为了开发嵌入式应用产品,许多人想学习嵌入式系统,不知道该从何学起,具体目标也不明确。一些初学者,往往选择一个嵌入式操作系统就开始学习了。用不十分恰当的比喻,这有点儿像“盲人摸大象”,只了解其中一个侧面。这样难以对嵌入式产品的开发过程有全面了解。 针对许多初学者选择“xxx嵌入式操作系统+xxx处理器”的嵌入式系统的入门学习模式,本书认为是不合适的。本书的建议是:首先把嵌入式系统软件与硬件基础打好,再根据实际应用需要,选择一种实时操作系统(RTOS)进行实践。 读者必须明确认识到,RTOS是开发某些嵌入式产品的辅助工具和手段,而不是目的。况且,一些小型微型嵌入式产品并不需要RTOS。因此,一开始就学习RTOS,并不符合“由浅入深、循序渐进”的学习规律。
另外一个问题是:选RTOS,还是EOS?面向微控制器的应用,一般选择RTOS, 如RT-Thread、mbedOS、MQXLite、FreeRTOS、μCOS-III和μCLinux等。RTOS种类繁多,实际使用何种RTOS,一般需要工作单位确定。基础阶段主要学习RTOS的基本原理,并学习在RTOS之上的软件开发方法,而不是学习如何设计RTOS。 面向应用处理器的应用,一般选择EOS, 如Android、Linux、WindowsCE等,可根据实际需要进行有选择的学习。
对于嵌入式操作系统,一定不要一开始就学,这样会走很多弯路,也会使读者对嵌入式系统感到畏惧。 等软件硬件基础打好了,再学习就感到容易理解。实际上,众多MCU嵌入式应用,并不一定需要操作系统或只需要一个小型RTOS,也可以根据实际项目需要再学习特定的RTOS。一定要重视实际嵌入式系统软件和硬件基础知识的学习。无论如何,以开发实际嵌入式产品为目标的学习者,不要把过多的精力花在设计或移植RTOS、EOS上面。正如很多人使用Windows操作系统,而设计Windows操作系统的只有Microsoft公司;许多人“研究”Linux系统,但从来没有使用它开发过真正的嵌入式产品;人的精力是有限的,因此学习必须有所选择。有的学习者,学了很长时间的嵌入式操作系统移植,而不进行实际嵌入式系统产品的开发,最后,做不好一个稳定的嵌入式系统小产品,偏离了学习目标,甚至放弃了嵌入式系统领域。
(3) 嵌入式系统学习困惑之三——硬件与软件:如何平衡?
以MCU为核心的嵌入式技术的知识体系必须通过具体的MCU来体现、实践与训练。但是,选择任何型号的MCU,其芯片相关的知识只占知识体系的20%左右,剩余80%左右的是通用知识。但是,这80%左右的通用知识,必须通过具体实践才能进行,因此学习嵌入式技术要选择一个系列的MCU。但是,嵌入式系统均含有硬件与软件两大部分,它们之间的关系如何呢?
有些学者,仅从电子角度认识嵌入式系统,认为“嵌入式系统=MCU硬件系统+小程序”。 这些学者,大多具有良好的电子技术基础知识。实际情况是,早期MCU内部RAM小、程序存储器外接,需要外扩各种I/O,没有像现在的USB、嵌入式以太网等较复杂的接口,因此,程序占总设计量的50%以下,使人们认为嵌入式系统(MCU)是“电子系统”,以硬件为主、程序为辅。但是,随着MCU制造技术的发展,不仅MCU内部RAM越来越大,Flash进入MCU内部改变了传统的嵌入式系统开发与调试方式,固件程序可以被更方便地调试与在线升级,许多情况与开发PC程序的难易程度相差无几,只不过开发环境与运行环境不是同一载体而已。这些情况使得嵌入式系统的软硬件设计方法发生了根本变化。特别是因软件危机而发展起来的软件工程学科对嵌入式系统软件的发展也产生重要影响,产生了嵌入式系统软件工程。
有些学者,仅从软件开发角度认识嵌入式系统,甚至有的仅从嵌入式操作系统认识嵌入式系统。 这些学者,大多具有良好的计算机软件开发基础知识,认为硬件是生产厂商的事,他们没有认识到,嵌入式系统产品的软件与硬件均是需要开发者设计的。本书作者常常接到一些关于嵌入式产品稳定性的咨询电话,发现大多数是由于软件开发者对底层硬件的基本原理不理解造成的。特别是,有些功能软件开发者,过分依赖底层硬件驱动软件的设计,自己对底层驱动原理知之甚少。实际上,一些功能软件开发者,名义上是在做嵌入式软件,但仅是使用嵌入式编辑、编译环境与下载工具而已,本质与开发通用PC软件没有两样。而底层硬件驱动软件的开发,若不全面考虑高层功能软件对底层硬件的可能调用,也会使得封装或参数设计得不合理或不完备,导致高层功能软件的调用相对困难。
从上述描述可以看出,若把一个嵌入式系统的开发孤立地分为硬件设计、底层硬件驱动软件设计、高层功能软件设计,一旦出现了问题,就可能难以定位。 实际上,嵌入式系统设计是一个软件和硬件协同设计的工程,不能像通用计算机那样,软件和硬件完全分开来看,要在一个大的框架内协调工作。 在一些公司,需求分析、硬件设计、底层驱动、软件设计、产品测试等过程可能是由同一个团队完成的,这就需要团队成员对软件、硬件及产品需求有充分认识,才能协作完成开发。甚至许多实际情况是在一些小型公司,这个“团队”可能就是一个人。
面对学习嵌入式系统以软件为主还是以硬件为主,或是如何选择切入点,如何在软件与硬件之间找到平衡。对于这个困惑的建议是: 要想成为一名合格的嵌入式系统设计工程师,在初学阶段,必须重视打好嵌入式系统的硬件与软件基础。 以下是从事嵌入式系统设计二十多年的美国学者John Catsoulis在 Designing Embedded Hardware 一书中关于这个问题的总结: 嵌入式系统与硬件紧密相关,是软件与硬件的综合体,没有对硬件的理解就不可能写好嵌入式软件,同样没有对软件的理解也不可能设计好嵌入式硬件。
充分理解嵌入式系统软件与硬件相互依存关系,对嵌入式系统的学习有良好的促进作用。一方面,既不能只重视硬件,而忽视编程结构、编程规范、软件工程的要求、操作系统等知识的积累;另一方面,也不能仅从计算机软件角度,把通用计算机学习过程中的概念与方法生搬硬套到嵌入式系统的学习实践中,而忽视嵌入式系统与通用计算机的差异。在嵌入式系统学习与实践的初始阶段,应该充分了解嵌入式系统的特点,根据自身已有的知识结构,制定适合自身情况的学习计划。 其目标应该是打好嵌入式系统的硬件与软件基础,通过实践,为成为良好的嵌入式系统设计工程师建立起基本知识结构。 学习过程可以具体应用系统为实践载体,但不能拘泥于具体系统,应该有一定的抽象与归纳。例如,有的初学者开发一个实际控制系统,没有使用实时操作系统,但不要认为实时操作系统不需要学习,要注意知识学习的先后顺序与时间点的把握。又例如,有的初学者以一个带有实时操作系统的样例为蓝本进行学习,但不要认为,任何嵌入式系统都需要使用实时操作系统,甚至把一个十分简明的实际系统加上一个不必要的实时操作系统。因此, 片面认识嵌入式系统,可能导致学习困惑。 应该根据实际项目需要,锻炼自己分析实际问题、解决问题的能力。这是一个较长期的、需要静下心来的学习与实践过程,不能期望通过短期培训完成整体知识体系的建立,应该重视自身实践,全面地理解与掌握嵌入式系统的知识体系。
从由浅入深、由简到繁的学习规律来说,嵌入式学习的入门应该选择微控制器,而不是应用处理器,应通过对微控制器基本原理与应用的学习,逐步掌握嵌入式系统的软件与硬件基础,然后在此基础上进行嵌入式系统其他方面知识的学习。
本书主要阐述以MCU为核心的嵌入式技术基础与实践。 要完成一个以MCU为核心的嵌入式系统应用产品设计,需要有硬件、软件及行业领域的相关知识。硬件主要有MCU的硬件最小系统、输入/输出外部电路、人机接口设计。软件设计有固化软件的设计,也可能含PC软件的设计。行业知识需要通过协作、交流与总结获得。
概括地说,学习以MCU为核心的嵌入式系统,需要以下软件和硬件基础知识与实践训练,即以MCU为核心的嵌入式系统的基本知识体系如下。
1) 掌握硬件最小系统与软件最小系统框架 。硬件最小系统是包括电源、晶振、复位、写入调试器接口等可使内部程序得以运行的、规范的、可复用的核心构件系统。软件最小系统框架是一个能够点亮一个发光二极管的、甚至带有串口调试构件的、包含工程规范完整要素的可移植与可复用的工程模板。
2) 掌握常用基本输出的概念、知识要素、构件使用方法及构件设计方法。 如通用I/O(GPIO)、模/数转换ADC、数/模转换DAC、定时器模块等。
3) 掌握若干嵌入式通信的概念、知识要素、构件使用方法及构件设计方法。 如串行通信接口UART、串行外设接口SPI、集成电路互联(I 2 C)总线,CAN、USB、嵌入式以太网、无线射频通信等。
4) 掌握常用应用模块的构件设计方法、使用方法及数据处理方法。 如显示模块(LED、LCD、触摸屏等)、控制模块(控制各种设备,包括PWM等控制技术)等。数据处理如图形、图像、语音、视频等处理或识别等。
5)掌握一门实时操作系统的基本用法与基本原理。作为软件辅助开发工具的实时操作系统,也可以作为一个知识要素。可以选择一种实时操作系统(如:RT-Thread、mbedOS、MQXLite、µC/OS等)进行学习实践,在没有明确目的的情况下,没有必要选择几种同时学习。学好其中一种,在确有必要使用另一种实时操作系统时,再学习,也可触类旁通。
6)掌握嵌入式软、硬件的基本调试方法。如断点调试、打桩调试、printf调试方法等。在嵌入式调试过程中,特别要注意确保在正确硬件环境下调试未知软件,在正确软件环境下调试未知硬件。
这里给出的是基础知识要素,关键还是看如何学习,是开发人员直接使用他人做好的驱动程序,还是开发人员自己完全掌握知识要素,从底层开始设计驱动程序,同时熟练掌握驱动程序的使用,体现在不同层面的人才培养中。而应用中的硬件设计、软件设计、测试等都必须遵循嵌入式软件工程的方法、原理与基本原则。因此,嵌入式软件工程也是嵌入式系统知识体系的有机组成部分,只不过,它融于具体项目的开发过程之中。
若是主要学习应用处理器类的嵌入式应用,也应该在了解MCU知识体系的基础上,选择一种嵌入式操作系统(如Android、Linux等)进行学习实践。目前,APP开发也是嵌入式应用的一个重要组成部分,可选择一种APP开发进行实践(如Android APP、iOS APP等)。
与此同时,在PC上,利用面向对象编程语言进行测试程序、网络侦听程序、Web应用程序的开发及对数据库的基本了解与应用,也应逐步纳入嵌入式应用的知识体系中。此外,理工科的公共基础本身就是学习嵌入式系统的基础。
十多年来,嵌入式开发工程师们逐步探索与应用构件封装的原则,把硬件相关的部分封装底层构件,统一接口,努力使高层程序与芯片无关,可以在各种芯片应用系统移植与复用,试图降低学习难度。学习的关键就变成了解底层构件设计方法,掌握底层构件的使用方式,在此基础上,进行嵌入式系统设计与应用开发。当然,掌握底层构件的设计方法,学会实际设计一个芯片的某一模块的底层构件,也是本科学生应该掌握的基本知识。对于专科类学生,可以直接使用底层构件进行应用编程,但也需要了解知识要素的抽取方法与底层构件基本设计过程。对于看似庞大的嵌入式系统知识体系,可以使用“电子札记”的方式进行知识积累与补缺补漏,任何具有一定理工科基础的学生,通过一段稍长时间的静心学习与实践,都能学好嵌入式系统。
下面针对嵌入式系统的学习困惑,从嵌入式系统的知识体系角度,对广大渴望学习嵌入式系统的读者提出4点基础阶段的学习建议。
(1) 遵循“先易后难,由浅入深”的原则,打好软硬件基础
跟随本书,充分利用本书提供的软硬件资源及辅助视频材料,逐步实验与实践 ;充分理解硬件基本原理、掌握功能模块的知识要素、掌握底层驱动构件的使用方法、了解1~2个底层驱动构件的设计过程与方法;熟练掌握在底层驱动构件基础上,利用C语言编程实践(读者可通过“附录嵌入式系统常用的C语言基本语法概要”,快速复习相关的C语言知识点)。理解学习嵌入式系统,必须勤于实践。关于汇编语言问题,随着MCU对C语言编译的优化支持,可以只了解几个必需的汇编语句,但最好通过一个简单程序理解芯片初始化过程、中断机制、程序存储情况等区别于PC程序的内容。另外,为了测试的需要,最好掌握一门PC方面面向对象的编程高级语言(如C#),本书电子教学资源中给出了C#快速入门的方法与实例。
(2) 充分理解知识要素、掌握底层驱动构件的使用方法
本书对诸如GPIO、UART、定时器、PWM、ADC、DAC等模块,首先阐述其通用知识要素,随后给出其底层驱动构件的基本内容。期望读者在充分理解通用知识要素的基础上,学会底层驱动构件的使用方法。即使只有这一点,也要下一番功夫。俗话说:“书读百遍,其义自见”,有关知识要素涉及硬件基本原理,以及对底层驱动接口函数功能及参数的理解,需反复阅读、反复实践,查找资料,分析、概括及积累。对于硬件,只要在深入理解MCU的硬件最小系统基础上,对上述各硬件模块逐个实验理解,逐步实践,再通过自己动手完成一个实际小系统,就可以基本掌握底层硬件基础。同时,这个过程也是软硬件结合学习的基本过程。
(3) 掌握单步跟踪调试、打桩调试、printf输出调试等调试手段
在初学阶段,充分利用单步跟踪调试了解与硬件打交道的寄存器值的变化,理解MCU软件干预硬件的方式。单步跟踪调试也用于底层驱动构件设计阶段。不进入子函数内部执行的单步跟踪调试,可用于整体功能跟踪。打桩调试主要用于编程过程中,功能确认。一般编写几句程序语句后,即可打桩,调试观察。通过串口printf输出信息在PC显示器上显示,是嵌入式软件开发中重要的调试跟踪手段,与PC编程中printf函数功能类似,只是嵌入式开发printf输出是通过串口输出到PC显示器上,PC上需用串口调试工具显示,PC编程中printf直接将结果显示在PC显示器上。
(4) 日积月累,勤学好问,充分利用本书及相关资源
有副对联:“智叟何智只顾眼前捞一把,愚公不愚哪管艰苦移二山”。学习嵌入式切忌急功近利,需要日积月累、循序渐进,充分掌握与应用“电子札记”方法。同时,要勤学好问,下真功夫、细功夫。人工智能学科里有个术语叫无教师指导学习模式与有教师指导学习模式,无教师指导学习模式比有教师指导学习模式复杂许多。因此,要多请教良师,少走弯路。此外,本书提供了大量经过打磨的、比较规范的软硬件资源,充分用好这些资源,可以更上一层楼。
以上建议,仅供参考。当然,以上只是基础阶段的学习建议,要成为良好的嵌入式系统设计工程师,还需要注重理论学习与实践、通用知识与芯片相关知识、硬件知识与软件知识的平衡。要在理解软件工程基本原理的基础上,理解硬件构件与软件构件等基本概念。在实际项目中锻炼,并不断学习与积累经验。