一.嵌入式系统的软件组成与实时操作系统
1.嵌入式系统软件组成
(1)高端嵌入式系统的软件组成
1)应用程序
2)应用程序接口函数库
3)文件系统、图形用户界面、网络协议栈
4)操作系统
5)引导加载程序、驱动程序
引申:除了操作系统、设备驱动程序和应用软件之外的系统软件称为中间件
(2)嵌入式系统软件和通用计算机系统软件的异同
1)嵌入式操作系统的软件配备没有通用系统多,嵌入式系统软件和通用计算机系统软件都可以实现用户界面
2)通用软件系统无疑是以操作系统为核心,不可或缺,但是嵌入式系统具有功能专用性,有些情况下可以不使用操作系统,特别是低端嵌入式系统功能单一,使用循环程序作为主控程序就能够满足需要
3)嵌入式系统应用软件具有内部结构精简化、代码轻量化、占用存储资源少等特点
(3)自由软件
1)自由软件是一种可以不受限制的自由使用、赋值、研究、修改和分发的软件,并不代表四免费软件
2)大部分自由软件通过互联网发布且不收取任何费用
(4)嵌入式软件特点
1)软硬件一体,软件固化存储
2)软件对代码时空效率和实时性要求高
3)软件可裁剪,要尽可能去除冗余
4)大多数低端嵌入式系统不用操作系统,所以软件的生命周期相对较长
(5)嵌入式软件结构
1)选择软件结构的一个基本原则是:选择可以满足响应时间需求的最简单的结构(而非轮询结构)
2)简单的轮询结构只适用于系统的任务数量较少、任务处理简单,且实时性要求不高的场景
3)带中断的轮询结构也称为中断驱动结构或前后台结构,但并没有因为中断的引入而使软件的复杂度明显降低
2.嵌入式操作系统的发展
在嵌入式操作系统中的核心部分称为内核
(1)Tiny OS操作系统
1)开源深度轻量级操作系统
2)专为嵌入式无线传感网络设计,功耗较低,特别适合传感器这种受内存、功耗限制的设备
3)技术特点:轻线程、主动消息、事件驱动、组件化编程
(2)Android 操作系统
1)以Linux为基础半开放源代码的操作系统,主要用于移动便携设备
2)使用不同的软件开发包,则使用的编程语言也不同
3)采用堆层式软件架构,分为四层,从低层到高层分别是:内核、系统运行库、应用程序框架、应用程序
4)是针对特定应用领域的完整的软件平台,由操作系统、中间件和若干典型的移动应用软件组成
5)高度的应用便利性,能够提供研发机构快捷的开发能力
(3)QNX操作系统
1)分布式实时操作系统,符合POSIX基本标准和实时标准,使其应用可以方便的移植
2)微内核提供的4种服务:进程调度、进程通信、底层网络通信、中断处理
3)硬实时微内核嵌入式操作系统
(4)VxWorks
1)目前公认实时性最强、可靠性最高的嵌入式实时操作系统
2)在该操作系统中,所有与特定电路板上硬件相关的功能都集成在一个库中,该库的名称为板级支持包BSP
3)属于硬实时微内核嵌入式操作系统
4)在航空航天、通信和国防领域具有广泛应用
5)类Unix系统
(5)开源操作系统
1)免费获得,成本较低
2)获得技术支持困难、配套开发工作量大、系统可靠性低、完工后维护困难
3)典型例子:RTLinux、μCLinux、μC/OS-II
(6)其他嵌入式操作系统
1)WinCE:微软公司在Windows 95代码基础上开发的嵌入式操作系统
2)Nios II:不是免费开源的
3)FreeRTOS:迷你的实时操作系统,完全没费,源码公开、可移植、可裁剪、调度策略灵活,可以方便的移植到各种单片机上运行
4)Windows Embedded:普通实时嵌入式操作系统
5)eCos:红帽公司开发的源代码开放的嵌入式RTOS产品,是以个可配置、可移植的嵌入式实时操作系统
6)Monta Vista Linux:是一种嵌入操作系统发行版,开放所有源代码
7)RTEMS:实时多处理器系统,开源的无版税实时嵌入式操作系统,从体系结构上来看,属于微内核抢占式的实时系统,并非Linux的发行版
8)iOS:类Unix系统
9)嵌入式Linux发行版:RTAL、Xenomai、MontaVista Linux
3.实时系统(必须在有限和确定的时间内对外部事件作出响应的信息系统)
(1)多数嵌入式系统有时间约束性,但并非嵌入式系统都是实时系统;通用计算机系统像因特网域名服务系统也是实时系统
(2)根据实时系统的定义,实时系统对外界的响应是否正确不仅取决于功能正确性,而且取决于对事件处理的时间正确性
(3)任务时限有两种:截止时间和任务执行预设时间
(4)可预测性:实时系统对时间约束严格,它是指实时操作系统能对外部事件的响应时间和实时任务的执行事件进行判断
(5)衡量实行性能的三个指标
1)响应时间:系统从事件请求开始到任务完成的时间间隔
中断延迟时间:从接收到可屏蔽中断请求信号到操作系统做出响应并转入中断服务程序所需要的最长时间,该时间包括两部分:一是最长关中断时间,是指系统因执行临界区代码等原因不允许响应中断请求的时间;二是从硬件开始响应中断到开始执行中断服务程序第一条指令之间的时间
任务切换时间(任务抢占时间属于任务切换时间)
2)吞吐量(Throughput):在给定时间内系统可以处理的事件总数
3)生存时间:衡量输入数据的有效时间
(6)按照实时性分类
1)硬实时系统:任务执行时间超过截止时间,系统的总损益就变为负,导致严重的后果,例如导弹控制系统、高铁自动驾驶系统、飞行控制器、核反应堆处理装置等
2)软实时系统:虽然存在时限指标,但是如果输出响应超过时限,一般不会造成严重后果,例如DVD播放机的视频播放任务、程控电话交换机送拨号音任务等
3)非实时系统
(7)按照响应时间的快慢分类
1)强实时系统:VxWorks、μC/OS-II
2)普通实时系统:Symbian
3)弱实时系统
(8)单一的实时系统中可以同时包含硬实时任务和软实时任务,硬实时、软实时与准实时的概念与时限的长短没有关系
(9)实时性要求高的系统既需要足够强大的硬件平台支撑,也要有专门设计的实时软件并合理安排任务的优先级,才能满足实时处理的要求
4.实时操作系统
(1)七个特征
1)异步I/O和中断处理能力
2)任务切换时间和中段延迟时间确定
3)优先级中断和调度
4)抢占式调度
5)内存锁定
6)连续文件
7)同步
(2)实时操作系统完成每次任务所需时间的偏差称为抖动,也就是时间一致性,硬实时操作系统的抖动比软实时操作系统的抖动要小
5.宏内核(单内核)
(1)典型例子
Linux·、Android OS、UNIX、WinCE、Mac OS、DOS
(2)优点
1)应用程序生成效率高
2)内核功能切换开销小
3)对外来时间反应速度快
4)操作系统内核的运行效率高
5)各个模块之间的耦合度很高,通过函数调用实现模块之间的通信
(3)缺点
1)占内存空间大,缺乏可扩展性,维护困难
2)任务执行事件的可预测性较低
2)可靠性较低
3)排除故障和增加新功能需要重新编译
6.微内核:对单内核进行了结构改进(不是结构扩展),将任务管理、调度器、中断管理和进程间通信等多个模块编译成一个功能精简、空间紧凑的模块,称为微内核
(1)典型例子
QNX、VxWorks、Symbian、μC/OS-II、iOS
(2)特点
1)内核小巧
2)接口一致,所有进程请求使用统一接口,进程不需要区分用户模式还是内核模式
3)各功能模块松散耦合,只完成服务功能,系统管理功能交给一个或多个特权服务程序
4)内核功能扩充方便
5)功能切换开销大
6)基于客户机/服务器体系结构
7)在微内核操作系统中,任务间通信机制-消息机制是系统的基础,操作系统的各种功能都以服务器方式实现
二.嵌入式系统底层软件组成
1.硬件抽象层HAL
(1)在嵌入式领域,HAL主要用来简化嵌入式操作系统的移植作业,如果要移植操作系统,就要对HAL驱动函数进行改写,以满足具体操作系统的上层函数接口的规范
(2)它对底层硬件的初始化程序或者控制程序进行了封装,向操作系统内核提供了访问底层硬件的函数接口,隐藏了硬件的差异性,避免了操作系统对硬件的直接访问,使得操作系统在HAl基础上运行,
(3)HAl位于内核操作系统和硬件平台之间
(4)构建和使用HAL的不足之处在于系统开销稍有增大
2.板级支持包BSP
(1)BSP实际上是一些汇编程序和C语言代码相结合的操作系统底层软件
(2)包括初始化程序、设备驱动程序(对硬件设备进行控制和管理的模块称为驱动程序)、配置文件、引导加载程序
(3)所有与特定电路板上硬件相关的功能都集成在板级支持包的库里,操作系统的上层代码通过板级支持包访问底层硬件
关于设备驱动程序:一般而言,设备驱动程序的功能包括设备打开和关闭、设备初始化、设备读取和 写入,不包括设备文件管理
3.引导加载程序Bootloader
(1)嵌入式系统加电后进行的第一批最初操作就是引导或自举(Boot),对应的程序就是引导或者加载程序**,CPU执行程序的第一条指令就是Bootloader中的第一条指令**,这个指令一般会存储在某种类型的固态存储设备上,比如ROM、EEPROM、Flash ROM等
(2)功能:内存加电自检、外设存在自检、内存地址映射、内存寻址定位、加载和启动操作系统
(3)由于Bootloader的实现依赖于CPU的体系结构,因此大多数Bootloader都分为两个阶段
1)第一阶段:依赖于CPU的体系结构的代码通常放在阶段一,处理器内部的基本寄存器设置、系统基本参数设置、时钟初始化往往也是在第一阶段
2)第二阶段:调用内核代码、向操作系统内核传递参数、将内核代码和根文件系统映像从ROM存储器赋值到RAM内存储器,通常用C语言来实现,这样可以实现更复杂的功能,而且代码具有更好的可读性和可移植性
(4)Bootloader通常支持启动加载模式和下载模式
1)启动加载模式:嵌入式系统正常工作时使用的启动方式是从非易失性存储介质中引导和加载操作系统代码
2)下载模式:在调试或维护更新阶段使用的系统启动方式则通过通信端口从调试主机上下载操作系统映像
(5)由于硬件平台的不同,每种平台的引导加载程序不同
4.U-boot及其移植
(1)U-boot是一种通用的引导加载程序,对PowerPC系列处理器支持最为丰富,对Linux操作系统的支持最为完善
三.嵌入式Linux操作系统
(1)Linux系统最初以Unix为原型,以实现POSIX标准作为其目标,命令的功能、处理结果、函数名称和参数十分相同,但是二者的源代码完全不同,到目前为止,Linux的运行效率尚未达到Unix的水平;Linux是目前唯一可免费获得,能为多用户提供多任务、多线程功能的大型单内核操作系统,遵从GNU计划下的通用公共许可协议(GPL)
(2)Linux操作系统组成
1)用户进程:是在Linux系统上运行的应用程序集合,某个应用程序在Linux·操作系统环境下运行是,它就称为一个用户进程
2)OS服务组件:位于Linux操作系统内核之上的一层服务模块或实用程序的集合
3)Linux内核:为用户进程提供了一个虚拟接口(系统调用),内核运行在单独的内核地址空间,每个用户进程则使用自己的虚拟地址空间;应用程序通过GLIBC(由可移植的标准C库函数实现,提供标准I/O和标准流的一系列接口)调用通用函数和内核的内部功能,创始人是芬兰学生Linus torvalds,2011年升级到3.0版本
(3)Linux内核主要由5个子系统组成
1)进程调度
2)内存管理
3)虚拟文件系统(VFS):是Linux的通用文件系统模型,该模型包括了连接在Linux上的所有文件系统的常用数据结构和功能集,在系统调用接口和内核所支持的文件系统之间提供了一个交换层
4)网络接口:包含两部分,一部分提供对各种网络资源访问的控制,称为网络协议;另一部分提供对各种网络硬件的支持,称为网络驱动程序
5)进程间通信
(4)对于Linux来说,Bootloader完成的步骤如下:
1)初始化处理器及硬件资源配置
2)建立内存空间的映射关系,使能MMU,将系统的内存外存地址变换激活,为最终调用操作系统内核做好准备
3)装载操作系统映像到内存:从串口、以太网、USB接口、非易失性存储器装载
4)对Flash存储器编程
5)运行操作系统
6)传递系统启动参数
7)命令行解析和输入/输出控制
解析:引导加载操作系统时,设置相关的寄存器和资源,跳转到操作系统所在的空间,执行其引导,这个过程中可以给内核传递参数,可以控制系统启动的模式
(5)Linux特点
1)开放源代码,不存在黑箱计数
2)由于开放源代码,成本低
3)内核紧凑,占内存空间最小为140KB
4)网络功能强
5)可移植性强
6)可裁剪性强
7)支持多任务
(6)对于不同体系结构的CPU,Linux内核的源代码各不相同
(7)驱动程序可以被直接编译到Linux内核中并在内核启动时加载到内存,也可以模块形式存储在文件系统中并在需要时被动态加载和卸载
四.嵌入式操作系统μC/OS-II
(1)可以认为μC/OS-II是嵌入式操作系统领域中最小内核之一,不含设备驱动程序和文件系统,只是一个纯内核。其驱动程序属于底层,需要系统开发商自行开发,支持抢占式任务调度,不支持时间片轮转调度,绝大部分代码使用ANSI C语言编写
(2)基于μC/OS-II的嵌入式系统软件架构是一个建立在硬件系统上的四层软件结构,从上到下的顺序是
1)应用软件层
2)应用程序接口(API)层
3)μC/OS-II内核
4)设备驱动层
(3)内核提供的基本功能
1)任务调度:运行态的任务因等待某一事件而被阻塞时,或者当前有更高优先级的任务处于就绪态时,都有可能进行任务级的任务调度;任务调度可以发生在任何时刻,任务级的调度是有函数OSSched()完成的,因为这个函数是任务调度的前导函数;中断级的调度是调用函数OSIntExit()完成;在发生任务级的任务调度时,内核进行任务级的任务切换,保存当前任务的上下文,并恢复新任务的上下文
2)任务间通信:利用信号量、消息队列、消息邮箱、互斥信号量、事件标志组,一般用OSQPend()函数来等待并获得消息,用OSQPost()来发送信息
3)同步
4)任务管理:调用任务管理函数OSTaskSuspend()可以挂起一个任务
5)时间管理
6)内存管理
(4)μC/OS-II操作系统的基本调度单位:任务
1)由三部分组成:程序代码(没有返回值的C函数)、任务堆栈(保存任务的工作环境)、任务控制块TCB(保存任务状态和属性)
2)具有良好的可移植性和可裁剪性
3)能够支持的任务数最多为64(8个系统任务,56个用户任务)
4)创建任务可以使用OSTaskCreate()函数或OSTaskCreateExt()函数,分别用于基本型任务创建和扩展性任务创建。都是用于从休眠态到就绪态
5)每个任务拥有自用栈,以便减少应用程序对RAM的需求,任务按优先级抢占式调度进行,这意味着μC/OS-II只提供一个操作系统的最低限度的任务运行机制,不涉及硬件驱动程序,最高优先级为0(运行任务),最低优先级为63(空闲任务)
6)空闲任务OS-Taskldle是是必不可少的一个系统任务,是操作系统初始化函数创建的第一个任务,自创建之后永远不会处于挂起态,因为他占据了最低优先级63,所以只有在其他的任务都因为等待事件的发生而被阻塞的时候才能得到运行
7)系统预定义的两个系统任务中,优先级高的是统计任务,优先级低的是空闲任务
7)完成任务切换所需的时间取决于CPU有多少寄存器要入栈,任务切换也称为上下文切换,实际含义是任务的CPU寄存器内容切换,当内核决定运行别的任务时,正在运行任务的工作现场被保存到任务的自由栈之中
(5)绝大情况下,系统的每个任务都是一个无限的循环,在任务的5大状态之一
1)休眠态:相当于该任务驻留在内存中,但还没有交给内核管理
2)就绪态:意味着该任务已经准备好,可以运行但由于该任务的优先级比正在运行的任务优先级低,暂时还不能运行,执行OSTaskDel()函数后转入休眠态;μC/OS-II就绪表为每一个优先级的任务提供了一个位元,登记该任务是否就绪,就绪时取值为1,没有就绪时取值为0,这样就绪位为1的所有任务就构成了当前就绪任务集
3)运行态:执行节拍延时函数OSTimeDly()后(即该任务需要等待键盘中断服务程序向其发送信息),该任务将转入挂起态,一旦预定的延时时间达到,该任务立即转入就绪态;执行OSTaskDel()后转入休眠态
4)挂起态(等待态):延时函数OSTimeDly()和OSSemPend()函数(用于等待一个信号量)都可以使运行态任务转入挂起态,任务正在等待键盘输入消息,能使等待态任务转入就绪态的系统函数是OSSemPost()
5)被中断态:运行态的任务发生中断时进入被中断态,被中断的任务是不能直接转入等待态的,要先结束被中断态进入运行态
(6)操作系统内核进行任务级的调度有三个条件
1)所有的中断服务程序ISR均已经执行完毕(OSIntNesting = 0)
2)任务调度加锁层数共享全程变量,也就是调度没有被禁止(OSLockNesting = 0)
3)任务就绪表中查到的最高优先级任务的优先级比当前运行任务的优先级高
(7)保护任务间的共享数据并支持任务之间的通信的三种方法
1)利用宏OS-ENTER-CRITICAL()和OS-EXIT-CRITICAL()来关闭中断和打开中断
2)利用函数OSSchedLock()和OSSchekUnlock()对μC/OS-II中的任务调度函数上锁和开锁
3)利用信号量(OS-EVENT-TYPE-SEM)、互斥信号量(OS-EVENT-TYPE-MBOX)、消息队列(OS-EVENT-TYPE-Q)进行任务间通信
(8)中断
1)μC/OS-II允许中断嵌套,嵌套层数可达255层
2)中断服务子程序执行事件处理有两种方法:一种是通过OSMboxPost()、OSQPost()、OSSEMPost()等函数去通知真正做该事件处理的那个任务,让任务完成中断事件的处理;另一种是由中断服务子程序本身完成事件处理
3)中断服务子程序的伪码结构如下:保存全部CPU寄存器到栈;调用OSIntEnter()或者对OSIntNesting变量加1;执行中断服务代码,或者发出IPC消息通知特定任务去执行中断服务;调用中断退出OSintExit()函数(标志着中断服务子程序的终结,将中断嵌套层数计数器减一);恢复所有CPU寄存器;执行中断返回指令(中断返回之前可能进行任务切换)。切记不包括将被中断的任务挂起
4)为确保临界区(处理时不可分割的代码)代码的执行,在进入临界区之前必须关中断,执行完临界区代码之后要立即开中断,μC/OS-II系统调用宏OS-ENTER-CRITICAL()执行关中断操作,当需要实现对不可分割数据的原子访问时,也可调用函数void **OSSchedLock(void)锁定任务调度器,**取代关中断
(9)事件控制块ECB(Event Control Block)
1)用于实现信号量管理、互斥型信号管理、消息邮箱以及消息队列管理的ITC功能函数的基本数据结构
2)操作系统通过事件控制块支持任务间通信
3)任务或中断服务子程序可以给ECB发信号
4)只有任务可以等待另一个任务或中断服务子程序通过ECB给发信号,而中断服务子程序是不能等待ECB给他发信号的处于等待状态的任务可以指定一个最长等待时间,以防止因等待的事件没有发生而无期限的等待下去
5)多个任务可以同时等待同一事件的发生,在这种情况下,当该事件发生后,所有等待该事件的任务中,只有优先级最高的任务得到该事件并进入就绪状态,准备执行
6)当ECB是一个信号量时,任务可以等地爱它,也可以给他发信息
7)互斥信号量可以解决优先级反转问题,而事件控制块可以用于对信号量的管理,适合处理多事件同步的是事件标志组
(10)任务控制块OS-TCB
1)内核通过任务控制块管理任务
2)用于保存任务状态和属性的数据结构,在任务创建被初始化
3)包括任务的优先级、任务的状态字、指向任务堆栈栈顶的指针
(11)时间管理
1)调用OSTimeDly()函数会使系统进行一次任务调度,并且执行下一个优先级最高的就绪态任务
2)任务调用OSTimeDlyHMSM()后,一旦规定的时间期满或者有其他的任务通过调用OSTimeDlyResume()取消了延时,它就会马上处于就绪态
3)用户调用OSTimeDlyHMSM()后,就可以按小时H、分M、秒S和毫秒M来定义时间了,这样会显得更自然些
4)μC/OS-II能够提供周期性时钟信号(也就是时钟节拍),用于实现任务的正确延时和超时确认,**用户必须在多任务系统启动以后再激活时钟节拍器,也就是在调用OSStart()之后,**换个说法,在调用OSStart()之后做的第一件事就是初始化定时器中断
(12)操作系统的启动过程中三个主要的函数
1)OSInit():内核初始化
2)OSTaskCreate():启动多任务调度并从就绪态任务中选择最高优先级的任务转入运行态
3)OSStart():启动多任务调度
(11)μC/OS-II开源;μC/OS-III是商用操作系统;μC/OS是μC/OS-II的早期版本,源码公开,但不是完全免费