1. 嵌入式软件体系
两种嵌入式软件体系:
- 逻辑软件:无EOS(嵌入式操作系统),嵌入式软件直接运行在硬件上;
- 基于EOS的软件:运行在EOS上;
①轮转结构
软件中仅有一个循环结构的代码在执行,该段循环代码顺序查询条件,执行相应的分支。它的优点是,结构简单,在结构中不存在中断,没有数据共享,主循环简单的依次检查每个IO设备,并且为其提供服务。缺点是,不同IO功能要求不同的响应速度,轮转结构很难保证,当分支处理时间达到秒级的时候,操作系统响应变慢,当设备增加的时候,时间片可能变小,单个分支响应变慢,并且如果CPU全速运行,功耗将会比较大,电池供电系统难以承受。其主要应用有:微波炉、电话机、电子玩具等。
②带中断的轮转结构
中断程序可以处理硬件特别紧急的需求,然后设置事件到来标志,主循环轮询这些标志,然后依据需求进行处理。是一种前后台系统,轮询程序是后台,负责具体事务,中断程序是前台,辅助检查服务请求。和轮转结构的区别在于优先级高的请求将得到及时的响应,而轮转结构只能顺序响应。
③基于定时器中断的轮转结构
引入了低功耗模式。
④中断(事件)驱动系统
后台 -- 主程序 -- 初始化系统 -- 进入低功耗模式
⑤函数队列调度结构
中断程序不处理事务,只在函数指针队列中添加相应函数指针。主程序仅仅从该队列中读取相应指针并调用相关函数。main函数不再按顺序执行,而是读队列,并且有优先级。
2. 中断机制与ISR设计
运行过程中,EOS主要通过两种方式快速响应外部事件:
- 查询方式:降低里吞吐量,增加了功耗,但是需要不断查询。
- 中断方式。
①中断机制
中断机制是处理器快速响应外部事件的异步机制,可能在系统执行的任何时候随机到来。中断发生过后,处理器识别中断请求(IRQ)并将自动跳转到该中断请求所对应的中断服务程序去执行。
中断检测,中断响应到中断处理的过程可以全部由处理器独立完成。
中断是一种硬件机制,与是否使用操作系统无直接关系。
在宏观上不是一种查询机制,但是在微观上是一种硬件查询机制。
检测:
- 可屏蔽中断:可通过响应寄存器来关闭中断; - 不可屏蔽中断NMT:不可通过寄存器来操作;
响应:
- 直接中断:处理器查到中断,直接跳转到ISR入口; - 寄存器间接中断:通过寄存器寻址间接跳转; - 向量中断:查询中断向量表中的偏移量;
处理:
- 禁止/恢复中断 - 保存/恢复上下文 - 轮询设备的中断状态寄存器,逻辑处理
②EOS终端管理
硬件中断,软件中断以及异常等可能引起程序正常执行流程发生改变的事件,都被广义的定义为中断或异常。
EOS内核中有一个中断接管程序和映射至中断向量表的虚拟中断向量表,中断产生后,中断接管程序接收该中断事件,进而在虚拟中断向量表中查询,获得相应的中断服务程序。
运行中断服务程序前,接管程序保存上下文信息,并在中断栈中设置起始位置。
中断服务程序可以使用被中断任务的堆栈,但是为了提高可靠性,内核通常会为所有中断程序划定一个单独的中断栈。
中断服务程序完成后,接管程序恢复上下文和堆栈,并负责使处理器恢复到之前被中断的任务或中断服务程序继续执行。
③中断程序设计规则
规则1:中断程序不能调用任何可能会阻塞自己的RTOS服务 规则2:确保RTOS调用返回中断程序 规则3:避免执行分配、释放内存的操作
3. 数据共享
原子操作是最小单元,不可拆分
disable(); /*临界区,不可产生中断*/ enable();
4. 看门狗任务
部署一个看门狗任务TWDG来检测系统中的一组关键任务,看门狗使用与逻辑,当一个人物出现故障时,认定整个系统故障。看门狗可以通过定时向被检测任务发送检测信号,或者收集这些任务定期上传的状态来感知每一个被检测任务的运行是否正常,故障时软件定位或通过看门狗电路复位。
①几种监测方法
通用实现方法:
TWDG与第i个被检测的任务Ti共享一个变量f_WDi;Ti执行f_WDi++
操作,TWDG执行f_WDi--
操作,并判断f_WDi是否小于之前的值,如果小于则Ti任务故障。
任务间通信机制:TWDG任务向Ti任务发送消息,并等待该任务反馈,根据反馈确定状态。
就可靠性来说,看门狗任务大于硬件看门狗电路。
5. 代码共享——可重入函数
text段:只读,存放程序代码,编译时确定。 data段:静态存储区,存放在编译阶段(而不是运行时)就能确定的数据,存放赋了初值的全局变量、静态变量、常量。 bss段:存放定义但未赋值的全局变量和静态变量。
代码的可重入性
可重入代码reentrant code,也叫做纯代码,是影响多任务嵌入式系统可靠性的重要方面。它的本质是变量、资源的共享问题,代码不能同时被多个任务调用执行,即可重入问题。
可重入函数是一个能被多个任务调用的函数。可重入函数可以由多个任务并发调用,而不必担心数据错误。不可重入non-reetrant函数不能由多个任务所共享,除非能确保函数的互斥,或者使用信号量,或在代码关键部分禁用中断。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据,可重入函数要么使用本地变量,要么使用全局变量时保护自己的数据。
判断一个函数是否可重入的基本规则:
①一个可重入函数一般用于原子的方法使用变量,除非这些变量存储再调用这个函数的堆栈中或者这些变量是任务的私有变量; ②一个可重入函数一般不调用其他不可重入的函数; ③一个可重入函数一般不用于非原子的方法使用硬件;