【小黑嵌入式系统第十八课】结课总结(二)——软件部分(系统架构&调试&测试&运行&系统软件设计)

上一课:
【小黑嵌入式系统第十七课】结课总结(一)------硬件部分(系统&总线&处理器&外设&通信)



前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站:人工智能



文章目录


一、嵌入式系统开发流程

嵌入式系统开发流程------功能和需求分析、系统总体设计(系统分析师)

  • 功能与需求分析
    • 确定设计任务和设计目标,提练设计规格说明书,作为设计指导和验收的标准。
    • 系统功能部分
      • 系统可能有哪些输入;输入量是什么;以何方式输入;是否需前期处理;输入量范围;有无特别需求,如采样频率、信号放大等。
      • 系统需要哪些输出;是否需要进行模数转换;可能需要驱动哪些外设;输出量的范围;有无特殊需求,如输出频率、信号种类等。
      • 通过输入端取得的数据是否需要经过处理;数据需不需要进行存储;要不要进行特殊的数据处理后,再送到输出端等。
    • 系统非功能部分
      • 嵌入式系统可能被应用在各种环境中。温度、湿度、震动、电磁干扰、电源供应、工业安全标准以及是否要在特定的时间内完成某项任务等都是嵌入式系统可能会遇到的环境限制。由于这些和系统所处的环境有关,所以要和专业人员做进一步的确认。
      • 价格的限制会影响到系统的设计与组成组件。在成本的限制下,开发团队需要寻找适当的方案来应付。功耗、体积、重量......

二、嵌入式系统架构

  • 系统设计
    • 系统架构设计
      • 系统如何实现所述的功能性和非功能性需求,包括对硬件、软件和执行装置的功能划分及系统的硬件、软件选型等。
    • 硬件/软件协同设计
      • 硬件构件:硬件平台主要包括处理器及相关外设的选择。
        • 处理器的选择:处理性能 、技术指标、功耗、软件支持工具、是否内置调试工具、供应商是否提供评估板
    • 软件构件
      • 操作系统选择:开发人员是否熟悉此操作系统、开发工具/操作系统向硬件移植的难度、操作系统的内存要求、是否提供一些硬件驱动程序、操作系统的可裁剪性 、实时性能。
      • 编程语言:通用性 、可移植性程度 、执行效率 、可维护性
      • 集成开发环境

三、嵌入式软件的交叉开发环境

  • 交叉开发环境
    • 交叉开发环境由宿主机和目标机组成,宿主机与目标机之间在物理连接的基础上建立起逻辑连接(通信协议)。开发软件建立在宿主机(Host)上,宿主机又称开发机、上位机,一般是一台通用计算机,如PC。对应的嵌入式系统称为目标机(Target)。目标机可以是各式各样的嵌入式设备,例如手机、掌上电脑等;或者是厂商提供的一套专用于开发的评估板(evaluation board),又称开发板;甚至是基于软件的模拟器。开发时使用宿主机上的交叉编译、汇编和链接工具形成可在目标机上执行的二进制代码,然后把可执行代码下载到目标机上运行。此外嵌入式系统的调试也通常采用交叉的方式, 在调试过程中,目标机需接收和执行宿主机发出的各种命令如设置断点、开始/停止运行、读/写存储器等,将结果返回给宿主机,配合宿主机各方面的工作。

  • 宿主机与目标机的区别
    • 体系结构的不同。宿主机和目标机通常是异构的。宿主机一般采用x86体系结构,但是目标机的体系结构则可能非x86的,如是ARM、MIPS、PowerPC等各式各样。
    • 处理能力不同。通常宿主机的处理速度、存储容量等会远远好于目标机。
    • 运行的操作系统不同。宿主机一般运行通用操作系统,而目标机通常运行各种嵌入式操作系统。
    • 输入输出方式不同。相对宿主机,目标机的输入输出功能可能比较单一。

  • 为什么要交叉编译?
    • 目标机上往往无法进行有效率的本地(native)编译
    • 目标机硬件可能本身在开发过程中,还不能使用或还不够稳定;
    • 目标机系统性能太低,无法实现完整的本地编译工具、环境;
    • 目标机系统性能不够,导致编译太慢。嵌入式系统的软件编译,与windows开发不一样,不仅要编译应用程序,还要编译相应的依赖库、操作系统内核等。所以一次完整的编译非常费时。如编译一个Linux内核在奔4级别的PC上都需要十几分钟。从硬件角度,决定编译速度的主要因素是CPU速度、内存容量和文件系统I/O速度。这些在嵌入式系统上往往都要比PC差很多。

四、嵌入式软件实现阶段的开发过程

系统设计完成后,嵌入式软件的开发进入实现阶段,分为三个大的步骤:生成、调试、固化运行

  • 生成 :软件的生成在宿主机上进行,利用各种工具完成程序的编辑、交叉编译和链接工作,生成可供调试或固化的目标代码。
    • 编码阶段:编写软件的源代码,使用的工具是各种文本编辑器。
    • 构建阶段:构建阶段的任务是把源代码转化成在嵌入式处理器上可执行程序的过程。此阶段包括编译、链接、定址和打包。构建的第一步是编译,即将源代码文件翻译成目标文件。编译工作是由编译器完成的,编译器的任务是将由某种程序设计语言编写的源代码翻译成特定处理器上等效的一系列操作码,这些操作码对应的文件称为目标文件。构建的第二步,就是将所有目标文件链接成一个目标文件。链接工作由链接器完成,其主要工作是扫描所有输入的目标文件,然后将多个目标文件的段合并,并解决它们之间的依赖关系(这一过程称为符号解析),最终生成一个可执行文件。将编译器和链接器的过程在使用形式上做在了一起,称为Build。构建的第三步是定址和打包。定址和打包的目标是将可重定位执行文件整合为一个可运行在嵌入式系统中的二进制映像文件。

  • 调试 :通过宿主机上运行的交叉调试软件(配合调试器硬件)完成目标机软件的调试工作。基本调试完成后还需进行必要的测试工作。
    与普通桌面应用程序开发相比,嵌入式软件调试的最大问题是缺少监控程序实时运行的手段。
    调试的一个基本原则是不要做"睁眼瞎",需要找出一种监控程序运行的手段,让自己知道代码到底是如何运行的。

  • 固化运行:先用一定的工具将代码固化到目标机存储器上,然后启动目标机,在没有任何工具干预的情况下使代码能自动地启动运行。

交叉调试器:调试程序和被调试程序运行在不同款处理器上;通过调试器能控制目标机上被调试程序的运行方式;通过调试器能查看和修改目标机上的寄存器、内存、以及被调试程序中的变量等。


五、交叉调试方式

与非交叉方式比较:

1、Crash and Burn

在宿主机上编写代码,编译生成可执行程序,将程序固化(Burn)到目标机的非易失性存储器(UV-EPROM、FLASH等)中,启动宿主机运行并观察,检查代码,查找问题根源,改写代码。重复上述过程直到程序正常工作。


2、ROM Monitor - 驻留监控程序

ROM Monitor是被固化且运行在目标机上的一段程序,负责监控目标机上被调试程序的运行,与宿主机端的调试器一起完成对应用程序的调试。调试器与ROM Monitor之间的通信遵循某种远程调试协议。

调试过程

(1)启动目标机,监控器掌握对目标机的控制,等待和调试器建立连接;

(2)启动调试器,并和监控器建立起通信连接;

(3)使用调试器将应用程序下载到目标机上的RAM空间中;

(4)使用调试器进行调试,发出各种调试命令,监控器解释并执行这些命令,将命令执行结果回传给调试器;

(5)如果程序有问题,在调试器帮助下定位错误。修改之后再重新编译链接并下载程序,开始新的调试,如此反复直至程序正确运行为止。

优点:提高调试程序的效率 ,缩短开发周期,降低成本;简单、方便;可扩展性强,可支持许多高级调试功能;成本低廉,不需专门的调试硬件支持。几乎所有的交叉调试器都(能)支持这种方式

缺点:目标机必须能支持外部ROM存储空间,而且由于其通常要和ROM Monitor配合使用,因此它拥有ROM Monitor的所有缺点。


3、ROM Emulator - ROM仿真器

利用这种设备,目标机可以没有ROM芯片,但目标机的CPU可以读取ROM Emulator设备上ROM芯片的内容:ROM Emulator设备上的ROM芯片的地址可以实时地映射到目标机的ROM地址空间,从而仿真目标机的ROM。ROM Emulator的调试方式是一种不完全的调试方式:ROM Emulator设备只是为目标机提供ROM芯片和在Target和Host间建立一条高速的通信通道,因此它经常和前面两种调试方式结合起来形成一种完备的调试方式。ROM Emulator的典型应用就是和ROM Monitor的调试方式相结合。

优点:目标机可以没有ROM芯片、可以使用ROM Emulator提供的ROM空间且不需要用别的工具来写ROM。

缺点:目标机必须能支持外部ROM存储空间,而且由于其通常要和ROM Monitor配合使用,因此它拥有ROM Monitor的所有缺点。

注:Emulator、Simulator中文都叫"仿真器",但Emulator是有硬件基础的(硬件仿真器),而Simulator是纯软件的(软件模拟器)。


4、Crash and Burn

5、ROM Monitor - 驻留监控程序

6、ROM Emulator - ROM仿真器

7、In Circuit Emulator - 在线仿真器

  • ICE(In-Circuit Emulator、在线/在电路仿真器)的一种含义是指用于替代目标机上CPU的设备。它比一般的CPU有更多的引出线,能引出一些内部信号。ICE上的Memory也可以被映射到用户的程序空间,这样即使目标机不存在的情形下也可以进行代码的调试
  • 连接ICE和目标机时,一般是将目标机的CPU取下,而将ICE的CPU引出线接到目标机的CPU插槽。用ICE进行调试时,在Host端运行的调试器通过ICE来控制目标机上运行的程序
    适用于
  • 调试实时的应用系统;调试设备驱动程序;对硬件进行功能和性能的测试;实时性能分析
  • 缺点:价格太昂贵,不利于团队开发;所仿CPU有限

8、On Chip Debugging - 片上调试

  • OCD(On Chip Debugging,片上调试)是CPU芯片提供的一种调试功能(芯片内部集成了用于调试的硬件电路部分),可以认为是一种廉价的ICE
  • 功能:OCD的价格只有ICE的20%,但提供了ICE 80%的功能。
    OCD调试方法
  • 将CPU的运行模式分为一般模式和调试模式:一般模式下,CPU从内存读取指令执行;调试模式下,CPU首先从调试端口读取指令, Host端的调试器可以通过调试端口直接向目标机发送要执行的指令、读写目标机的内存和各种寄存器、控制目标程序的运行以及完成各种复杂的调试功能。Host端的调试器通过调试端口可以控制CPU进入和退出调试模式;
  • 优点:不占用目标机的资源;调试环境和最终的程序运行环境基本一致;支持软硬断点、Trace功能;精确计量程序的执行时间;提供时序分析功能;结构简单得多,可能仅仅起接口信号转换的作用,成本低。
  • 缺点:调试的实时性不如ICE;不支持非干扰调试查询;处理器必需具有OCD功能
  • 主要实现:BDM(Background Debugging Mode)、OnCE(On Chip Emulation)、JTAG(Joint Test Access Group)(主流方式)

9、Simulator方式(软件模拟器,非交叉)

  • 一种软件仿真器,在宿主机上创建一个虚拟的目标机环境,再将应用系统下载到这个虚拟目标机上运行/调试。

  • 优点:最大好处就是可以不用真正的硬件目标机,可以在目标机环境并不存在的条件下开发目标机上的应用系统,并且在调试时可以利用Host资源提供更详细的错误诊断信息。

  • 缺点:和实际的运行环境差别很大;设备模拟的局限性较大;实时特性较差;对Host的资源要求较高

  • 适用范围:对时间特性没有严格要求、没有特殊外设、只需要验证逻辑正确的应用程序。


六、嵌入式软件的测试

嵌入式软件测试中经常用到的测试工具有:

内存分析工具、性能分析工具、覆盖分析工具、缺陷跟踪工具等


七、嵌入式软件的固化运行

  • 当调试完成之后,程序代码需要被完全烧入到目标板的非易失性存储器(如UV-EPROM或闪存)中,并且在真实的硬件环境上运行,这个过程叫做固化。将数据写入到这些存储器中需要有一个专门的烧写过程。

  • 调试环境与固化环境的主要区别:代码定位不同、初始化部分不同

  • Flash芯片的烧写,类似可编程器件的烧录:
    • 离线(Offline)方式:需要将Flash ROM芯片从目标板上取下;目标板上将Flash ROM做成插座式安装,而非焊死;使用专门的编程器和配套软件
    • 在线编程(In-system-programming)方式:无需将Flash ROM芯片从目标板上取下;一般就是通过JTAG-ICE仿真器;方便,廉价,重用了JTAG-ICE的投资

八、嵌入式系统软件设计

函数的可重入性

  • 重入即表示重复进入。函数在自己调用自己的时候,不必担心数据被破坏。从软件工程角度对函数可重入的作用可以解释为:具有可重入性的函数能够被多个任务同时调用。

程序设计规范

  • 必要性
    • 程序不仅要被计算机执行,还要给程序员阅读,以及被今后重复使用。
    • 一个风格清爽而严谨、规范化的程序更容易被读懂,更容易被修改、排错和移植。
    • 规范化编程、高度一致的风格和正确的习惯还有助于保持思维清晰,写出正确无误的代码。特别是一个开发团队共同工作时,规范一致化的编程尤其重要。
    • 每个初学者在项目初期都会因为不良编程习惯浪费大量时间,因此若能在开始写程序时就重视规范化问题,对顺利渡过提高阶段有很大帮助。
  • 程序规范的基本原则
    • 一致的代码风格,统一的变量名、函数名命名规则
    • 符合英语语法、可阅读的代码
    • 关键代码100%注释
    • 硬件有关、硬件无关代码分离,可移植性强。
    • 每个对象都具有完善的封装,接口形式简洁、易用。
    • 对所有资源严格要求硬件隔离层,软件中不允许直接访问硬件,不允许跨层调用。

前后台多任务程序设计

  • 基本概念
    • 任务(Task) :指完成某一单一功能的程序
    • 后台程序:对时间要求不严格的任务,通常在主循环内执行。一般在 主函数循环中依次处理各项工作,这部分可以看成后台行为,后台也可以叫做任务级。
    • 前台程序:要求快速响应或者时间严格的任务,通常在中断内,也叫中断级。
    • 队列/缓冲:用于暂存后台来不及处理的前台事件
  • 编写原则
    • 任何一个任务都不能阻塞CPU。每个任务都应主动结束,让出CPU。不能有等待、死循环、长延时等环节。
    • 关注函数重入问题:在前后台程序中,任务都是顺序执行的,不存在多个任务同时调用一个函数的情况。但可能出现前台中断服务程序与后台任务同时调用某个函数。因此对于前后台公用函数,必须是可重入的。
    • 临界代码保护(Critical Code Protection):临界代码即运行时不可分割的代码,这部分代码不允许被中断打断。包括:依靠软件产生时间严格时序的程序段;共享资源互斥性造成的临界代码;函数重入造成的临界代码;CPU字长造成的临界代码。保护方法:关中断、开中断(使用该方法时,不能在临界代码区调用任何具其他有临界代码的函数)等。
  • 特点总结
    • 后台中任务顺序执行。每个后台任务中的内存(局部变量)在任务结束后可以全部释放,让给下一个任务使用。即使在RAM很少的处理器上也能同时执行众多任务。
    • 后台中任务顺序执行。天然避免了后台任务资源互斥问题,但仍需考虑前后台之间的资源互斥问题 。
    • 前后台程序的结构灵活,实现形式与实现手段多样,是使用最广的程序结构,但缺乏架构标准,维护、升级、排错都很困难。
    • 必须要程序员自己来判断和处理临界代码的隐患。
    • 程序多任务的执行依靠每个任务的非阻塞性来保证,是编程最大的难点。
    • 前后台系统结构简单,很多基于微处理器的产品都采用了前后台系统设计,例如微波炉、电话机、玩具等。而在一些基于微处理器的应用中,从省电的角度出发,平时微处理器处在停机状态,所有事都靠中断服务来完成。

FSM:状态机建模

  • 基本概念:有限状态自动机(Finite-State Machine, FSM),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。

  • 为什么要引入状态机?

    • 流程图不能用于描述"任何时候"发生的事件;无法描述"由外部事件决定流程"的程序;不适合描述带有阻塞的并发过程;难以描述大量的独立事件。
    • 需要:能够描述并发结构的软件,能从行为的角度来描述软件,且能够根据模型生成代码,也能够对软件进行完整测试的新手段---状态机模型。
    • 状态机就是一种基于"状态"与"事件"的软件描述手段!其优势在于:
      a. 能够处理并发。由于系统在每一时刻只能有唯一的状态,在每一个状态下,可能发生的事件也是有限的。因此系统中即使存在有大量的独立事件,软件描述也会简单得多。
      b. 能够消除阻塞。真正需要CPU处理的只有系统状态发生改变的那一刻,在系统等待事件到来的期间,是不需要CPU处理的。如果能够用状态与事件的形式来描述软件,能够将CPU从等待事件发生的过程中解放出来,从而生成无阻塞的代码。
      c. 能够降低系统的复杂度,提高可测性。
  • 状态机的表示方法:状态转移图

    • 由状态转移图生成代码
      • 方法1、在状态中判断事件(事件查询)
      • 方法2、在事件中判断状态(事件触发)
  • 状态机建模举例

    • 电子表程序

A键中断

c 复制代码
switch (Status)   /*根据当前状态处理A键所引发的状态跳转*/
{
			 case DISP_TIME: Status= DISP_DATE; break;    //时间显示时按A键,显示日期
			 case DISP_DATE: Status= DISP_SEC; break;
			 case DISP_SEC:    Status= DISP_TIME; break;
			 case SET_HOUR: if(++Hour>23) Hour=0; break; //小时设置时按A键调整小时
			 case SET_MINUTE: if(++Min>59) Min=0; break;
			 case SET_MONTH: if(++Month>12) Month=0; break;
			 case SET_DATE:  if(++Date>31) Date=0; break;
}

B键中断


模块化程序的原则


事件触发多任务程序设计

  • 什么是事件触发程序?
    • 任务全部在中断内完成,主程序休眠。
    • 可以看做前后台程序中,只有前台任务。
    • 特点:1)实时性较好,事件响应较快;2)低功耗
  • 程序架构
    • 中断:获取原始的事件信息。
    • 事件引擎:判断何种事件发生,并调用相应处理程序。(一个中断有多个中断源时)
    • 事件处理程序:只负责某个事件的处理,要求非阻塞。

时间触发系统

  • 什么是时间触发系统?
  • 时间触发系统可以理解为一种特殊的按时间触发的事件触发系统。事件触发系统中,若出现处理同时发生的多个事件的情况,不但增加了系统复杂性,而且降低了对事件触发系统在所有情况下的行为做出预计的能力。相比而言,在时间触发的嵌入式系统中,设计人员能够通过仔细安排可控的顺序,保证一次只处理一个事件。许多嵌入式系统并不需要睡眠,采用时间触发方法有很多好处,有助于改善可靠性和安全性(如广泛应用于航空航天工业和汽车工业),主要原因在于系统的行为可以预计。时间触发方法还能降低CPU的负荷,并减少存储器的使用量。
  • 嵌入式系统需要执行的任务分为两种
    • 周期性任务 ,比如每100ms执行一次;单次任务,如在50ms的延迟后执行一次
  • 解决方案
    • 基于定时器中断:适用于少量定时任务场景,可能浪费硬件资源(或者不够用)、增加硬件的维护成本等
    • 使用调度器:调度器可以看作是一个简单的操作系统,允许以周期性或单次方式来调用任务(如uC/OS)。
相关推荐
A懿轩A4 分钟前
C/C++ 数据结构与算法【树和森林】 树和森林 详细解析【日常学习,考研必备】带图+详细代码
c语言·c++·考研·数据结构与算法·树和森林
C语言编程小刘 129 分钟前
C语言期末复习1.1
c语言·算法·leetcode
Bucai_不才44 分钟前
【C++】初识C++之C语言加入光荣的进化(下)
c语言·c++·面向对象编程
浊酒南街1 小时前
决策树(理论知识3)
算法·决策树·机器学习
A懿轩A1 小时前
C/C++ 数据结构与算法【哈夫曼树】 哈夫曼树详细解析【日常学习,考研必备】带图+详细代码
c语言·c++·学习·算法·哈夫曼树·王卓
cxr8282 小时前
洪水灾害多智能体分布式模拟示例代码
深度学习·机器学习·迁移学习
hope_wisdom3 小时前
实战设计模式之策略模式
设计模式·系统架构·软件工程·策略模式·架构设计
一入程序无退路3 小时前
c语言传参数路径太长,导致无法获取参数
linux·c语言·数据库
lili-felicity3 小时前
指针与数组:深入C语言的内存操作艺术
c语言·开发语言·数据结构·算法·青少年编程·c#
可喜~可乐3 小时前
循环神经网络(RNN)入门指南:从原理到实践
人工智能·rnn·深度学习·神经网络·机器学习·lstm