嵌入式实时操作系统的设计与开发(txt+pdf+epub+mobi电子书下载)


发布时间:2020-09-27 03:35:28

点击下载

作者:廖勇

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

嵌入式实时操作系统的设计与开发

嵌入式实时操作系统的设计与开发试读:

前言

在后 PC 时代的今天,嵌入式操作系统琳琅满目,在各行各业已有广泛应用,嵌入式Linux、VxWorks、INTEGRITY、Nuclear、DeltaOS、pSOS+、VRTX、QNX、RTEMS、Cisco-IOS、ERISON-EPOC、uC/OS、uC/OSII、uC/OSIII、TinyOS、T-kernel、Windows CE、Windows mobile、Symbian、Android、Apple-IOS在一些大学,本科生编写一个简易的操作系统内核也不是什么难事。此外,市面上也已出版了一些关于嵌入式操作系统(或者操作系统)设计和代码实现的书籍,比如,1999年出版的《MicroC/OS-II:The Real-Time Kernel》,2005年出版的《自己动手写操作系统完全版》,2011年出版《一步步写嵌入式操作系统:ARM编程的方法与实践》等。为什么还要撰写一本关于嵌入式操作系统设计的书呢?其目是从本科教学特点出发,顺应国内高校“工程教育”的发展趋势(比如:“卓越工程师计划”的实施),根据计算机专业及相关专业嵌入式方向系列教材建设的需要,将课程知识体系与操作系统设计实现过程有机结合,让学生更好地理解课程知识点,通过操作系统在具体嵌入式平台ARM9 Mini2440的设计与实现,融会贯通相关核心知识点,进而激发读者自己设计操作系统的热情(写操作系统不是最终目的),其最终目的是通过写的过程来锻炼学生的系统设计能力、工程实现能力、分析与解决问题能力,充分体现教育家约翰.杜威先生“To learn by doing”的教学理念。

本书以aCoral的设计过程为线索,首先从ARM9 Mini2440的裸板串口驱动开始,介绍如何用汇编语言实现一个轮询结构的简单嵌入式系统。然后,引入中断机制,介绍如何实现一个前后台系统,以满足用户更为复杂的应用要求。在前两步的基础上,一步一步叙述aCoral实现细节,比如:从任务定义开始,逐步启发读者思考如何用C语言描述一个任务、创建任务,如何将任务挂载到就绪队列上、从就绪队列中找到最高优先级任务、在ARM9 Mini2440上实现任务切换、触发任务调度、协调任务执行、响应用户的外部请求、通过时钟推动操作系统运行、启动内核、移植内核、搭建aCoral的交叉开发环境、编译与运行aCoral、支持多核(以ARM公司ARM11MPCORE的四核心嵌入式处理器为例)等等。全书将原理与代码紧密结合;从工程实践中发现问题,在理论上对其进行详细分析并最终指导操作系统设计与实现;此外,本书还对嵌入式实时操作系统编写过程中设计的相关知识进行了整合。

贯穿本书的嵌入式实时操作系统源代码来自电子科技大学嵌入式实时计算实验室设计的aCoral,参考了三星公司ARM9 S3C2440A、S3C2410A芯片手册、ARM11MPCORE芯片手册、Linux开源社区、实时系统及实时调度学术论文等资料。此外,还借鉴了邵贝贝教授翻译Jean J.Labrosse先生的《MicroC/OS-II:The Real-Time Kernel》、C.M.Krishna和KANG G.Shin的《Real-Time Computing》、罗蕾教授的《嵌入式实时操作系统及应用开发(第4版)》、桑楠教授的《嵌入式系统原理及应用开发技术(第2版)》、李无言老师的《一步步写嵌入式操作系统:ARM编程的方法与实践》,于渊老师写的《自己动手写操作系统完全版》等书籍。

本书在撰写过程中得到了电子工业出版社“卓越工程师计划”系列教材建设项目的支持和电子科技大学教务处特色教材建设项目的支持,作者对此深表感谢。此外,本书的撰写得到了电子科技大学计算机学院熊光泽教授、罗克露教授、罗蕾教授,信息与软件学院桑楠教授、雷航教授、蔡竟业教授、江维副教授、陈丽蓉副教授、李允副教授、徐旭如老师,厦门大学于杰老师,电子工业出版章海涛老师、裴杰老师的帮助,他们为本书的撰写提供了许多宝贵的意见和建议。

感谢电子科技大学实时计算实验室的研究生杨茂林、蒋世勇、李恒瑞、刘黎民、张晋川、陈泽玮、罗超、Furkan Hassan Saleh Rabee以及宾夕法尼亚大学研究生廖聪、南加州大学研究生李龙杰、国防科技大学研究生龚俊如、上海交通大学读研的罗赟、复旦大学研究生胡伟松、人民大学研究生范旭、清华大学研究生陆文详、核九院研究生张朝,电子科技大学实时计算实验室学习的本科生兰宇航、陈维伟、胡斌,华为成都研究所软件工程师徐新、华为深圳研究所软件工程师陈朱旭、百度软件研发工程师李天华、三星公司南京研究所软件研发工程席臣、微软苏州研究院林添、美团网研发工程师许斌、美国云控公司成都研发中心谢鑫、美国豪威公司上海研发中心周强等,他们在作者的引导下,从本科二年级开始学习嵌入式实时系统,并在本科期间围绕(ARM9 Mini2440+μC/OS-II+LWIP+μGUI+aCoral+Linux)平台上做过系列实验、课程设计、毕业设计,还在此平台上实现了智能家居及安防系统、智慧交通流量信息采集与显示系统、学习型遥控器、网络收音机、智能小车防撞系统、四轴飞行器等本科创新/实践项目(其中智能家居及安防系统获得了2010年电子科技大学“银杏黄”项目最佳奖,四轴飞行器获得全国一等奖),他们为aCoral代码分析及验证做了许多细节工作。

感谢在上海自主创业的申建晶先生,他与作者一起于2009年创建了开源嵌入式实时多核操作系统项目aCoral(www.aCoral.org),并为该项目做出了巨大贡献,同时为本科教育和研究生教育中付出了许多宝贵的时间。感谢在成都自主创业的刘坚、朱葛、郑亚斌,感谢完美世界的高攀、兰王靖辉、建设银行四川分行闫志强、美国美满电子(Marvell)上海研究所的陈勇明及成都研究所的魏守峰、程潜、任艳伟、淘宝杭州研发中心的张林江等曾在电子科技大学实时计算实验室学习过的同志们,他们在校期间陆续加入项目组,与作者共同探讨嵌入式操作系统相关的技术、教学改革、本科生学习及就业等问题,这为本书结构的拟定、撰写方法等提供了思路和素材。

特别感谢我的父母、妻子和儿子,他们在本书撰写过程中给予了极大鼓励和支持。

由于作者知识和水平有限,书中不足之处在所难免,恳求各位专家及读者赐正。

作 者

第1章 概论

20世纪60年代,以晶体管、磁芯存储为基础的计算机系统已开始应用于航空、航天、工业控制等领域,这些系统可看成嵌入式系统的雏形。第一台机载专用数字计算机是奥托内蒂克斯公司为美国海军舰载轰炸机研制的多功能数字分析仪,由几个体积庞大的黑匣子组成,能够进行中央集中处理,开始拥有数据总线雏形。

随后,嵌入式系统处理能力和功能则快速提升。例如,第一款微处理器Intel 4004于1971年诞生,被广泛应用于计算器和其他小型系统,此时的嵌入式系统已有外存和其他芯片的支持。到20世纪80年代中期,大多数外部系统芯片集成到一块芯片上作为处理器,称为微控制器(Microcontroller,MCU),也称为单片机,使得嵌入式的应用更为灵活。最早的单片机Intel 4084出现在1976年。20世纪80年代初,Intel公司开发出了著名的8051单片机,并一直沿用至今。同一时期,Motorola公司推出了68HC05,Zilog公司专门生产Z80单片机。这些处理器迅速渗透到家用电器、医疗仪器、仪器仪表、交通运输等领域,带动了嵌入式系统的快速发展。

为了实时处理数字信号,1982年诞生了首枚数字信号处理芯片(Data Signal Processor,DSP)。现今,已经发展成一类十分重要的多媒体处理芯片。1997年,来自美国嵌入式系统大会(EmbeddedSystemConference)的报告指出,未来5年(从1997年算起)仅基于嵌入式计算机系统的全数字电视产品,就将在美国产生一个每年1500亿美元的新市场。美国汽车大王福特公司的高级经理也曾宣称,“福特出售的‘计算能力’已超过了IBM”,由此可以想见嵌入式计算机工业的规模和广度。1998年在芝加哥举办的嵌入式系统会议上,与会专家一致认为,21世纪嵌入式系统将无所不在,它将为人类生产带来革命性的发展,实现“PCs Everywhere”的生活梦想。

美国嵌入式系统专业杂志RTC报道,21世纪最初的十年中,全球嵌入式系统市场需求量具有比PC市场需求量大10~100倍的商机。纵观嵌入式技术的发展过程,其出现至今已经有40多年的历史,大致经历以下五个阶段。

第一阶段大致在20世纪70年代之前,可看成嵌入式系统的萌芽阶段,是以单芯片为核心的可编程控制器形式的系统,具有与监测、伺服、指示设备相配合的功能。这类系统大部分应用于一些专业性强的工业控制系统中,一般没有操作系统的支持,通过汇编语言编程对系统进行直接控制。这一阶段系统的主要特点是:系统结构和功能相对单一,处理效率较低,存储容量较小,只有很少的用户接口。由于这种嵌入式系统使用简单、价格低,以前在国内外工业领域应用非常普遍。即使到现在,在简单、低成本的嵌入式应用领域依然大量使用,但已经远不能适应高效的、需要大容量存储的现代工业控制和新兴信息家电等领域的需求。

之后的十多年属于第二阶段,是以嵌入式处理器为基础、以简单操作系统为核心的嵌入式系统。在此阶段,大多数嵌入式系统使用8位处理器,不需要嵌入式操作系统支持,其主要特点是:处理器种类繁多,通用性比较弱;系统开销小,效率高;高端应用所需操作系统已达到一定的实时性、兼容性和扩展性;应用软件较专业化,用户界面不够友好。

第三阶段的时段大致是20世纪80年代末到90年代后期,是以嵌入式操作系统为标志的嵌入式系统,也是嵌入式应用开始普及的阶段。主要特点是:嵌入式操作系统内核小、效率高,具有高度的模块化和扩展性;能运行于各种不同类型的微处理器上,兼容性好;具备文件和目录管理、多任务、网络支持、图形窗口以及用户界面等功能;提供大量的应用程序接口API和集成开发环境,简化了应用程序开发;嵌入式应用软件丰富。在此阶段,嵌入式系统的软硬件技术加速发展,应用领域不断扩大。例如,日常生活中使用的手机、数码相机,网络设备中的路由器、交换机等,都是嵌入式系统;一辆豪华汽车中有数十个嵌入式处理器,分别控制发动机、传动装置、安全装置等;一个飞行器上可以有数百个乃至上千个微处理器;一个家庭中也有了几十个嵌入式系统。

第四个阶段从20世纪90年代末开始,是以网络化和Internet为标志的嵌入式系统。随着Internet的发展以及Internet技术与信息家电、工业控制、航空航天等技术结合日益密切,嵌入式设备与Internet的结合将代表嵌入式系统的未来。1998年11月在美国加州圣·何塞举行的嵌入式系统大会上,基于嵌入式实时操作系统的Embedded Internet成为一个新的技术热点。

最后一个阶段是21世纪初到现在,是以物联网、云计算和智能化为标志的嵌入式系统,也是多核芯片技术、无线技术、互联网发展与信息家电、工业控制、航空航天等技术结合的必然结果。从应用角度而言,移动互联网设备是嵌入式产品的热点,目前,具备网络互联功能的智能终端出货量将达到4亿部,比同时期笔记本电脑和台式计算机出货量的总和还多。无处不在的嵌入式系统(智能手机、无线传感器网络、RFID电子标签等)遍布在人们周围,为人们提供方便快捷的服务。

综上所述,嵌入式系统技术正在日益完善,高性能多核处理器已开始在该系统中占主导地位,嵌入式操作系统已从简单走向智能化,与互联网、云计算结合日益密切。因此,嵌入式系统应用日益广泛。

1.1 轮询系统(Polling Systems)

嵌入式系统发展初期,嵌入式软件的开发是基于汇编语言和C语言直接编程,不需要操作系统的支持,这样的系统也称为裸板嵌入式系统。

用过8051单片机的人都知道,8051单片机的程序从开始到结束基本上都是顺序的,最后必定有一个类似于while的死循环。这种方式必须不停地去轮询条件来查询要做什么事,因此这样的嵌入式系统被称为轮询系统,该方式虽然实现了宏观上执行多个事物的功能,但有以下几个明显的缺点。(1)轮询系统是一种顺序执行的系统,事物执行的顺序必须最开始就确定,缺乏动态性,减少了系统的灵活性,也增加系统设计的复杂度。(2)系统运行过程中无法接收和响应外部请求,无法处理紧急事情。(3)事物之间的耦合性太大,这主要是因为事物不可剥夺的原因,正因为不可剥夺,导致一个事物的任何错误都会使其他的任务的长久等待或错误。

1.2 前后台系统(Foreground Background Systems)

针对轮询系统的不足,工程师们提出了前后台系统:后台系统与轮询系统一样也是顺序执行的,只有一个main程序,程序功能的实现是依靠死循环来实现;但前台引入了中断机制,能处理外来请求。对于实时性要求比较高的事物,可以交给中断服务程序(ISR)进行处理,因为中断处理速度快,而对于非实时性的事物,可以交给后台顺序执行。

虽然前后台系统能对实时事物做出快速响应,增加了系统的动态性和灵活性,但存在如下不足:(1)事物不可剥夺,比如说某个事物在执行的过程中,其他事物不可能执行,也就是说事物没有优先级,这与实际的情况有很大出入,实际系统中事物是有优先级的,有些任务来了很紧急,必须先执行。(2)事物不可阻塞,也就是说事物没有暂停这一功能来阻塞自己,因为这种方式暂停当前的事物就意味着整个系统都暂停了,同时事物必须返回,因为只有这样其他的事物才能有机会执行。

1.3 嵌入式操作系统

由于前后台系统并不能很好地解决多任务并发执行的问题,尤其当系统要处理的事务和要响应的外部中断比较多时,系统的维护性就很差。更关键的是,随着嵌入式系统复杂性的增加,系统中需要管理的资源越来越多,如存储器、外设、网络协议栈、多任务、多处理器等。这时,仅用轮询系统或前后台系统实现的嵌入式系统已经很难满足用户对功能和性能的要求。因此,工程师们设计了嵌入式操作系统,以解决事务的不可剥夺、不可阻塞性,实现多任务的并发执行。由于嵌入式操作系统及其应用软件往往被嵌入到特定的控制设备或者仪器中,用于实时地响应并处理外部事件,所以嵌入式操作系统有时又称为实时操作系统(Real-time Operation System,RTOS);另一方面,由于RTOS也往往存在于嵌入式系统中。因此,本书约定:为了描述方便,下文提到的 RTOS 代表的就是实时操作系统或嵌入式操作系统,以下嵌入式实时操作系统。1.3.1 简单内核

RTOS可简单认为是功能强大的主控程序,系统复位后首先执行;它负责在硬件基础上为应用软件建立一个功能强大的运行环境,用户的应用程序都建立在RTOS之上。在这个意义上,RTOS的作用是为用户提供一台等价的扩展计算机,它比底层硬件更容易编程。一个简单的RTOS需要至少实现如下功能:(1)任务调度。有了操作系统,多个任务就能并发执行,但是系统中的CPU资源是有限的(如单核环境下只有一个CPU核),于是,需要特定的调度策略来决定哪个任务先执行?哪个任务后执行?哪个任务执行多长时间等?而要实现特定的调度策略、支持多任务并发执行,还必须有任务切换机制的支持。当前各种操作系统的任务切换本质上是为了解决任务的不可剥夺和不可抢占性,任务切换可分为以下两种。

① 被动切换:也就是被剥夺(对应上面的第一条),这主要是因为优先级高的任务来了,或者当前任务的执行时间完了。

② 主动切换:也就是当前任务调用相关函数主动放弃CPU,这对应上面的第二点,阻塞自己,让别人去使用CPU。(2)任务协调机制。要实现特定调度策略,除了任务切换机制外,还需任务协调机制的支持,即任务的互斥、同步、通信机制等。这个就是大家通常说的互斥量、信号量、邮箱等。互斥量分为普通互斥量、优先级继承的互斥量(解决了优先级反转)、天花板协议的互斥量(解决了死锁问题)。(3)内存管理机制。系统中多个任务并发执行,所有任务的执行代码和所需数据都是存储在内存中的,那各个任务及相关数据如何被分配到内存中的?这就需要 RTOS 提供内存管理机制。当然对于不同的应用需求,内存管理机制会不一样,对于PC等桌面应用,内存管理着重考虑的是如何有效利用内存空间,实时性不是特别重要;而对于嵌入式实时应用,内存管理的重点是内存分配和释放时间的确定性,因此RTOS中,内存管理的动态性就少许多。

RTOS的出现是随着嵌入式系统的发展的必然结果,RTOS的出现极大地推动了嵌入式系统的发展及应用,而嵌入式系统的发展,又促进了RTOS的不断完善和演化。据统计,到目前为止,世界各国数十家公司已成功推出200多种RTOS,其中包括WindRiver System公司的VxWorks、pSOS+,Mentor Graphics公司的VRTX,Microsoft公司支持Win32 API编程接口的Windows 8,Symbian公司的Symbian OS,苹果公司的IOS,Enea公司的OSE,Microware公司的OS-9,3COM公司的Palm OS,国产的DeltaOS,以及多种多样的嵌入式Linux等。1.3.2 RTOS结构

现有RTOS所采用的体系结构主要包括整体结构、层次结构、微内核结构和构件化结构等。

1.整体结构

这是最早出现并一直使用至今的RTOS体系结构。这种RTOS是一个整块,内部分为若干模块,模块之间直接相互调用,不分层次,形成网状调用模式。其工作模式分为系统模式和用户模式两类:用户模式下系统空间受到保护,并且有些操作受限制;而系统模式下可访问任何空间,可执行任何操作。

从某种角度上讲,当一个拥有强大功能的RTOS内核被完整地应用在嵌入式环境下,就会给嵌入式软件的开发提供非常完整的平台,最常见的应用是嵌入式Linux和Windows CE。对于简单的小系统而言,整体结构有几乎最高的系统效率和实时性保障。

但是,若将这种结构用于较复杂的嵌入式系统,需要大量昂贵的硬件资源;而由于内核的复杂性,使得系统的运行变得不可预测和不可靠。此外,随着嵌入式软件规模的扩大,由于模块间依赖严重,整体结构的RTOS在可剪裁性、可扩展性、可移植性、可重用性、可维护性等方面的缺陷越来越明显,严重制约了其应用。

2.层次结构

层次结构也是许多流行RTOS选择的体系结构。这种结构中,每一层对其上层而言好像是一个虚拟计算机(Virtual Machine),下层为上层提供服务,上层使用下层提供的服务。层与层之间定义良好的接口,上下层之间通过接口进行交互与通信,每层划分为一个或多个模块(又称为组件)。在实际应用中可根据需要配置个性化的RTOS。

内核位于 RTOS 的最底层,在某些简单的实时系统中,内核是唯一的层。内核最基本的工作是任务切换,此外,还提供了任务管理、定时器管理、中断管理、资源管理、消息管理、队列管理、信号管理等功能。RTOS的其他组件包括内存管理、I/O设备管理、嵌入式文件系统、嵌入式网络协议栈、嵌入式GUI等。

流行RTOS中,VxWorks、DeltaOS等在整体上都是这种模型的范例。

3.微内核结构

微内核结构也可称为客户机/服务器(Client/Server,C/S)结构,是目前的主流结构之一,最具有代表性的范例是QNX。

按最初的定义,微内核中只提供几种基本服务:任务调度、任务间通信、底层的网络通信和中断处理接口,以及实时时钟。整个内核非常小(可能只有几十KB),内核任务在独立的地址空间运行,速度极快。

传统操作系统提供的其他服务,如存储管理、文件管理、中断处理、网络通信等,都以内核上的协作任务的形式出现。每个协作任务可以看成是一个功能服务器。用户应用任务(客户任务)执行中若需要得到某种服务,则透过内核向服务器任务发出申请,由服务器任务完成相应的处理并将结果返还给客户任务(称为应答)。

随着时间的推移,微内核结构的定义已经有了显著变化。只要保持 C/S 结构,微内核中基本服务的个数不再受限,如加入基本存储管理。当然,微内核的大小尺度也有一定的放宽。在这种体系结构下,任务执行需要增加一定的开销(服务器与客户之间),与整体系统相比有一定的性能下降。但是,这种改变的好处也是十分明显的。

除基本内核外,C/S 结构的其他服务模块可以根据应用需求随意剪裁,十分符合 RTOS的发展要求;C/S结构可以更方便地扩展功能,可以更容易做到上层应用与下层系统的分离,便于系统移植,可以大大加强C/S结构服务模块的可重用性。

随着硬件性能的不断提高,内核处理速度在整个系统性能中的所占比例会越来越小,RTOS的可剪裁性、可扩展性、可移植性、可重用性越来越重要,再加上微内核结构本身的改进,其应用面将会越来越广。

4.构件化结构

随着构件化技术的广泛使用,如何将构件技术成功地应用到嵌入式操作系统中,受到人们越来越多的重视,这成为研究的热点之一。构件化RTOS内核由一组独立的构件和一个构件运行管理器构成,后者可以维护内核构件之间的协作关系。RTOS传统的各类服务,包括任务管理、调度算法、中断管理、时钟管理、存储管理等,可以是一个构件,也可由这些相互协作的构件构成,同时为上层应用软件开发提供统一的编程接口,支持应用软件的有效开发、运行和管理。

所有的RTOS抽象都由可加载的构件实现,配置灵活,裁减方便,能够很好地适应各种应用领域的不同需求。作为动态构件的任务,可以自动加载运行,不需要由用户去逐一启动。构件之间具有统一标准的交互式界面,既便于用户掌握,又方便应用程序开发。

一个典型的构件化RTOS是TinyOS,为无线传感器网络(Wireless Sensor Network,WSN)开发的构件化嵌入式操作系统,适用于内存资源和处理能力十分有限、电池供电的嵌入式系统。1.3.3 多核RTOS

随着嵌入式系统复杂度的提高,传统单核处理器及RTOS不能满足应用的需求。与此同时,近几年在MIT举行的High Performance Embedded Computing Workshop(HPEC)以及各处理器设计/制造商纷纷推出的多核处理器,标志了多核时代的到来。可以预料,在未来较长的一段时期内,多核计算将是计算机技术、嵌入式实时技术的一个重要发展方向。如何从传统的单核计算向多核计算过渡,成为了目前计算机及相关领域研究的热点。

操作系统作为运行在处理器上的最重要的基础软件,更成为了多核计算技术中受到普遍关注的焦点。尽管目前主流的操作系统已提供了对于桌面计算机多核处理器的支持,但是这种支持只是很浅薄的(如仅仅提供了简单的、以负载均衡为目的资源管理策略),与嵌入式实时系统对多核支持的要求相差甚远。此外,尽管一些商用嵌入式实时操作系统(如Vxworks、QNX等)提供了多核支持,但这种支持也是很浅薄的,并不能很好发挥多核处理器的优势和性能。因此,要让多核技术在嵌入式实时计算领域能有效应用,还有很长的路要走,这也成为当前学术界和工业界的研究热点。

1.4 从裸板开始

大家可能会认为上述介绍没什么意义,因为像这样的内容互联网上一大堆。是的,上述文字确实有些空洞,这里只是为了和大家一起梳理一下嵌入式系统软件开发及RTOS的演化。接下来,本书将以一款流行、易学的嵌入式开发平台ARM(Advanced Risk Machine)[1-2][37]Mini2440(CPU是三星ARM 9系列的ARM S3C2440)为例,通过具体代码实现,介绍如何从裸板入手设计简单的轮询系统、前后台系统,以及如何一步一步在ARM Mini2440上编写RTOS内核,到如何让RTOS内核支持多核嵌入式处理器。本书要求读者已掌握ARM 9处理器的基础知识,并且对ARM汇编、ADS编译器、Linux交叉开发环境的使用有足够了解(这部分内容不属于本书的范围,但却是本书的重要基础)。[1][3][4]

到地,该引入本书的主角aCoral了,aCoral是一个开源RTOS,本书将以它为例,介绍其设计与实现。具体而言,本书将以 aCoral 的设计为主线,详细剖析:ARM Mini2440是如何开始工作的?上电后运行的第一行代码是什么?各个外部设备如何驱动?aCoral 是如何启动 Mini2440?如何管理 Mini2440 的硬件设备?什么时候开始创建第一个任务?多个任务如何并发执行?如何切换并发执行的任务?调度算法如何在aCoral中实现等?

1.5 aCoral

aCoral 是一款由电子科技大学实时计算实验室于2009年创建的[1][3]开源的、支持多核(Symmetry Multiple Process,SMP)的RTOS[4][42-45]。aCoral(A small Coral),珊瑚的特性是aCoral追求的目标。aCoral具有高可配,高扩展性,可以在www.aCoral.org下载其源代码、文档及基于aCoral的应用开发实例,如JEPG的并行压缩、基于aCoral的网络收音机等。目前的aCoral包括五大模块:(1)内核:由电子科技大学实时计算实验室编写。(2)文件系统:在周立功文件系统上进行了优化而来。(3)轻型TCP/IP(LWIP):由LWIP移植而来。(4)GUI(TLGUI):来自开源嵌入式Linux图形系统LGUI。(5)简单应用(网页服务器、Telent服务、文件操作、GUI图形、测试等)。

aCoral支持多任务模式,其最小配置时,生成的代码为7KB左右,而配置文件系统,轻型TCP/IP,GUI后生成的代码仅有300KB左右。目前,aCoral支持各种ARM系列处理器:Cortex-m3、ARM7、ARM9、[1][6-7]ARM11,以及ARM11 MPCore四核平台。同时,为了方便没有开发板的用户体验aCoral,其模拟版本可以在运行Linux的PC中作为应用程序运行,这种模式可以在PC上体验aCoral的所有功能,包括内核、文件系统、GUI,该模式支持单核和多核。

实时计算实验室在多年的本科生教学[《嵌入式实时操作系统(ERTOS:Real-Time Operating System)》]、研究生教学(《嵌入式系统开发》、《实时计算》、《可信计算》)、留学生教学[《嵌入式操作系统及应用(Real-Time Operating System and application)》]、海外学生教学《Embedded System and Real-Time》)中发现,学生们在学习RTOS时,常常会有许多疑惑,并且很难有自己动手写RTOS的机会,这让大家难以融会贯通《计算机组成原理》、《C语言》、《汇编语言》、《操作系统》、《数据结构》、《嵌入式系统开发》的知识点,从而对计算机系统结构缺乏系统的、深入的理解。创建aCoral开源项目的目的是:希望能激发同学们自己编写操作系统的热情(写出操作系统不是目的,目的是让大家在写的过程中能真正思考和深度理解操作系统及相关知识点(编译、链接、加载等)的原理,从而提高分析问题、解决问题的能力,使计算机系统能力、工程能力上一个新台阶)。希望aCoral为对嵌入式实时操作系统有兴趣的同学或朋友们提供了一个较好的学习蓝本,aCoral 将应用在未来的本科教学和研究生教学中。

电子科技大学实时计算实验室在RTOS方面有着长期持续的研究,这里孕育了中国航空工业集团下属的科银京成技术有限公司。因此,aCoral的另一发展思路是:多核+强实时,为对性能有苛刻要求(Performance-critical)的嵌入式实时系统[如计算机密集型的嵌入式实时应用(高端控制系统、超声波无损检测与处理系统、精确导航与防撞系统)、航空电子系统等]提供一体化解决方案,充分发挥多核潜能,力求系统总体性能最佳。

对于多核,aCoral已支持同构多核(如ARM11 MPCore四核平

[39-41]台),对于异构多核的支持,项目组已在AMR+DSP构架下,实现了基本的异构通信、同步、共享内存等机制,对更高级别的支持[33-35][46](异构多核调度、对GPU的支持等)正在研究中。对于强实时而言,嵌入式操作系统一般都是实时的,但是如何做到强实时是一[17]个很棘手的问题,为强实时计算密集型应用(航空电子、舰载电子等)提供可靠运行支持是aCoral开发的强力主线。目前aCoral 提供了强实时内核机制(优先级位图法、优先级天花板协议、差分时间链、最短关中断时间等)。与此同时,aCoral还提供了强实时调度策略:单核和多核的RM调度算法,由于多核情况下的RM算法的复杂性,目前只支持简单环境下多核RM调度,RM调度算法在多核情况下的其他问题正在研究和解决中。此外,其他多核强实时确保策略也正在研究中。

aCoral会像珊瑚一样成长

1.6 本书结构

本书将介绍嵌入式系统的发展,早期嵌入式软件轮询系统的基本原理和缺陷,前后台系统的出现及不足,RTOS的诞生及发展。本书基于三星公司ARM9 Mini2440开发板逐步介绍轮询系统、前后台系统到RTOS是如何设计和实现的。

第1章:主要介绍RTOS的发展、主流结构及aCoral基本情况。

第2章:主要介绍轮询系统的基本原理,以及一个基于ARM9 Mini2440开发板的简单轮询系统的设计和实现。

第3章:在轮询系统基础上引入中断机制,介绍前后台系统的基本原理,然后重点描述裸板环境下中断发生、响应、处理的流程;在此基础上,详细介绍一个基于ARM Mini2440开发板的简单前后台系统的设计和实现。

第4章:介绍RTOS相关的基本概念,为aCoral在ARM Mini2440上的设计和实现做一个理论上的铺垫。

第5章:介绍aCoral的交叉开发环境,以及如何在Ubuntu下搭建其交叉开发工具链。

第6章:从用C语言描述一个线程开始,一步一步阐述aCoral内核的设计与实现,主要内容包括创建线程、调度线程、aCoral事务处理机制(中断与时钟管理)、内存管理机制、线程间的交互机制(通信、同步、互斥等)。

第7章:介绍aCoral是在ARM9 Mini2440上如何启动并开始执行的。

第8章:介绍aCoral硬件抽象层(HAL)相关代码,通过对这些代码的分析,大家可知道如何将aCoral从一个嵌入式平台移植到另一个嵌入式平台上,例如,从ARM9 s3c2440处理器移植到ARM s3c2410处理器。

第9章:基于aCoral工程文件,介绍如何在宿主机上编译aCoral,如何在ARM Mini2440上运行aCoral。

第10章:简单介绍RTOS的实时调度策略,实时系统运行过程中遇到的经典问题以及相应的解决办法。

第11章:以四核嵌入式处理器ARM11 MPCore为例,从操作系统引导和线程调度等方面介绍aCoral是如何支持多核处理器的。

习题

1.简述嵌入式系统的发展历程。

2.轮询系统的特点是什么?适用于哪些嵌入式应用?

3.前后台系统有什么优缺点?

4.嵌入式操作系统包括哪些结构?对比各种结构的特点。

5.嵌入式操作系统内核的协调机制有哪些?

第2章 轮询系统

第1章提到了嵌入式开发板ARM9 Mini2440,本章就首先介绍ARM Mini2440是如何一步一步启动的,然后介绍其裸板环境下一个最简单嵌入式软件系统:轮询系统的设计与实现。在此以前,先了解一下轮询系统的基础知识。

2.1 轮询系统概述

轮询系统也称为简单循环控制系统,是一种最简单的嵌入式实时软件体系结构模型。在单个微处理器情况下,系统功能由多个函数(子程序)完成,每个函数负责该系统的一部分功能;这些函数被循环调用执行,即它们按照一个执行顺序构成一个单向的有序环(称为轮询环),依次占用CPU,如图2.1所示。每个函数访问完成之后,才将CPU移交给下一个函数使用。对于某个函数而言,当它提出执行请求后,必须等到它被CPU接管后才能执行。图2.1 轮询过程注:Fi代表函数名Function(i=1,2,)图2.2 轮询程序框架2.1.1 程序框架

从程序实现上,基本轮询系统的结构如图2.2所示。在系统工作以前,首先进行系统初始化,然后系统进入无限循环状态;主程序依次对轮询环中的函数进行判断,若该函数要求占用CPU,则让其执行,否则就跳过该函数去执行提出请求的下一个函数,这种判定某个函数是否满足执行条件的过程,称为轮询。2.1.2 调度

根据程序结构特点,基本轮询系统具有以下工作特点:系统完成一个轮询的时间取决于轮询环中需要执行的函数个数(即满足执行条件的函数个数)。此外,轮询的次序是静态固定的,在运行时是不能进行动态调整的。

这种特点决定了轮询系统在诸如多路采样系统、实时监控系统等嵌入式应用中可以得到广泛使用,是最常用的软件结构之一。但同样也存在无法忽略的弱点:所有函数必须顺序执行,不区分函数的重要程度,系统也无法根据应用的实际需要灵活地调整对函数的使用粒度。

1.优先权调度图2.3 重要重复的轮询

克服以上缺陷的最简单办法就是允许优先级高的函数被多次重复调度,即在轮询环中增加重要函数(如图2.3所示的F2)的访问CPU的次数。这样,在每一次轮询中,相对重要的函数获得CPU的概率就比其他的函数大。

上述机制还可以通过一个指针表的形式加以改进,使得函数的优先级可以在允许时动态改变,如图2.4所示。图2.4 优先级可变的轮询

值得注意的是,这种基于优先权的轮询系统与不可抢占的多任务系统有明显的区别:后者是通过中断触发引起内核调度器进行多任务调度,而前者是通过对一张指针表查询实现的。

2.子轮询

当某些函数的执行时间相对较长时,可以将其分解成若干子函数,这些子函数也构成一个轮询,称为子轮询。例如,一个函数需要打印消息到一个慢速输出设备中,可以将其分解成为两部分:第一部分是打印消息处理(F2_1),另一部分为慢速设备忙时的等待处理(F2_2)。两部分的转换如图2.5所示。

显然,函数的两部分可以分别构成一个子轮询。更进一步,若F2_2中加入对更高优先权函数的执行条件的判断操作(图2.6),则在等待时间内有机会执行更高优先权的函数。图2.5 子轮询结构图2.6 子轮询F2_2程序结构

这种处理方式因为具有多任务系统的一些特征,也被称为伪多任务系统(Disguised Multitasking)。2.1.3 典型系统

许多工业现场网络中,由于需要控制的设备较多、相互距离又较远,且现场有较强的工业干扰,因此采用体积小、抗干扰能力强的单片机作为上位机与现场控制器一起组成分布式数据采集与控制系统,是一种较好的选择。

如图2.7所示,在一个多机通信系统中,只有一台单机(8051)作为主机,各台从机间不能相互通信,必须通过主机转发来交换信息。单片机间通过RS-485总线通信,主机通过点名方式向各从机发送命令,实现对系统的控制。同时,主机对从机不断地轮询,监视从机的状况,接收从机的请求或信息。图2.7 基于轮询结构的单片机通信网络

2.2 搭建开发环境

了解轮询系统基本概念后,如何付诸实践去实现一个具有轮询结构的嵌入式软件系统呢?毕竟“To learn by doing”[1]是最好的学习方法。在动手编码以前,需先了解一下开发环境。

第1章提到,本书以ARM9 Mini2440为例介绍轮询系统、前后台系统及 RTOS 的设计和实现[2]。ARM9 Mini2440是一款基于ARM 920T核心的开发板(图2.8),以下简称Mini2440,是一款容易入门、复杂程度适中的学习板,它采用三星SAMSUNG S3C2440为微处理器。电子科技大学计算机科学与工程学院、信息与软件工程学院的学生常基于该平台做《嵌入式系统及应用》、《嵌入式操作系统》的课程实验、课程设计,也基于该平台参加一些竞赛项目。图2.8 ARM9 Mini2440核心板

Mini2440的基本构成如下。(1)CPU:SAMSUNG S3C2440A,主频400MHz。(2)SDRAM:64MB,32位数据总线,时钟频率可达100MHz。(3)Flash:64M Nand Flash;2M Nor Flash(安装了启动代码FriendlyARM BIOS 2.0或者Supervivi)。(4)相关接口:电源接口(5V),3个串行口,1个10针JTAG 接口,4个LED灯,6个按键,1个USB主端接口和1个USB从端接口,1个100M以太网RJ-45 接口,1个SD卡存储接口,1路音频输出接口,21路麦克风接口,1个PWM控制蜂鸣器,1个IC总线AT24C08芯片,1个摄像头接口,系统时钟源12MHz无源晶振,1 个34 pin的GPIO 接口,1 个40 pin的系统总线接口等。

有了上述接口,大家可以自由发挥,将Mini2440设计成一个网络收音机、简单视频监控系统等,只要其计算能力和接口范围满足你的设计需求。

除了Mini2440外,还需一个仿真器J-LINK,J-LINK是为支持仿真ARM内核芯片推出的JTAG仿真器,能配合IAR EWARM、ADS、KEIL、WINARM、RealView等集成开发环境对所有ARM7/ARM9内核芯片进行仿真。如果大家已经编写好了代码,并且成功编译,那如何将编译好的可执行程序烧写在Mini2440上,让其在开发板上运行呢?又如何对下载执行程序进行调试呢?这就需要J-LINK的支持。

写过单片机程序的人都知道,开发人员的程序是在PC上编写的,PC是Intel的处理器、Windows的操作系统,而单片机可能是TI的8051、430等。Intel的处理器和单片机采用的是不同指令集,那在PC上写的程序能通过仿真器烧写到单片机上吗?如果能烧写,又是否能在单片机上运行呢?要回答这些问题,就必须先了解交叉开发(Cross [10][11][17]Developing)。

交叉开发是嵌入式软件系统开发的特殊方法,开发系统是建立在软硬件资源均比较丰富的PC 或工作站上,一般称为宿主机或Host,嵌入式软件的编辑、编译、链接等过程都是在宿主机上完成。嵌入式软件的最终运行平台却是和宿主机有很大差别的嵌入式设备,一般称为目标机或 Target,这里的目标机就是ARM9 Mini2440。宿主机与目标机通过串口、并口、网口或其他通信端口相连,嵌入式软件的调试和测试是由宿主机和目标机之间协作完成,如图2.9所示。图2.9 交叉开发环境示意图

宿主机与目标机的差别主要在于:(1)硬件的差别:最主要是两者的处理器不同。宿主机的CPU多数是Intel系列或与其兼容的其他处理器,而目标机的CPU则是ARM、MIPS、8051、TI 430等品种繁多的嵌入式处理器。因此,两者支持的指令集、地址空间都不同。其他的差别,如内存容量、外围设备等。(2)软件环境的差异:在宿主机上都有通用操作系统等系统软件提供软件开发支持,而目标机除了调试代理外几乎没有其他用于嵌入式软件开发的软件资源。现有的嵌入式操作系统仅可作为嵌入式软件运行时的支撑环境。

本章裸板轮询系统的交叉开发环境如图2.10所示。其中,ADS(ARM Development Suite)是Metrowerks公司开发的针对ARM处理器的集成开发环境,包含了代码编辑器、编译器(for ARM)、连接器、调试器。图中的宿主机与目标机的连接是通过J-LINK、串口连接的,其中,J-LINK主要是为了烧写和调试被调试程序(将要开发的轮询系统),而串口主要是为了回显调试信息。需要注意的是:为了让J-LINK能正常工作,需要在PC上安装驱动J-flashARM;此外,如果宿主机是没有串口的笔记本电脑,还需在笔记本的USB上外接一个USB转串口的工具,并安装相应驱动程序。这样,便可在PC上编写代码;然后用ADS将其编译、连接成具有ARM指令集的可执行程序,即被调试程序;再通过J-LINK将被调试程序烧写在Mini2440的NORFlash上(NORFlash的起始地址是0x00000000,开发板上电后PC将指向这里,从该地址存放的指令开始运行);最后,重新启动Mini2440,被调试程序便可在目标机上运行,并且通过串口回显运行信息。图2.10 交叉开发环境示意图

将PC、Mini2440和J-LINK连接好后,就可以在ADS下创建工程了,具体步骤如下。(1)新建一个ADS工程,并为其命名(这里将工程命名为“MINE”,也是本章的示例工程),然后新建file文件my_2440_init.s(“.s”表示该文件是由汇编语言编写,因为此时开发板尚未初始化,只支持汇编语言),在创建好后,就将该文件添加到刚建立的MINE工程中,并在 debug、release 和 debugrel 三个选项上打“√”,需要注意的是工程不能是中文名,路径不能包含中文。(2)设置“my_2440_init.s”文件编译连接后生成的可执行文件的格式。将ADS菜单“Edit”→“DebugRel Settings”→“Linker”→“ARM formELF”中的“output format”输出形式设定为“Plain binary”文件类型,后缀为“.bin”(而不是其他类型,此时的裸板程序还只能支持简单的二进制可执行文件,还不能支持像ELF这样的高级文件格式)。(3)在my_2440_init.s文件中输入将要编写的轮询系统汇编代码。如果代码编写完毕,并且编译成功,可以在MINE工程文件的MINE_data →DebugRel文件夹中发现一个生成了的MINE.bin的可执行文件,该文件类型为“Plain binary”。(4)生成bin文件后,就可通过J-LINK将该文件“MINE.bin”烧写到Mini2440的开发板中。此时,开发板跳线设置为“NORFlash”启动(NORFlash的起始地址为0x00000000),接上J-LINK后,插在底板的JTAG插座上,J-LINK另一头接PC的USB接口,如图2.10所示。(5)开发板上电。(6)打开之前在PC上安装的J-flashARM工具,打开步骤:“开始”→“所有程序”→“SEGGER”→“JLINK ARM V4.08”→“JLINK ARM”,该界面能将开发板上从地址0x00000000开始的内存数据显示出来,这里的地址0x00000000是第(4)步设置的NORFlash起始地址。(7)单击“File”→“open Project”,打开s3c2440a_embedclub.jflash,再在ADS的“Options”→“Project settings”→“Flash”下单击“Select flash device”,选中Mini2440开发板对应的NORFlash芯片型号“S29AL016Dxxxxxxx2”。(8)单击“Target”→“connect”,连接宿主机和目标机。(9)单击“File”→“open”,打开将要烧写的映像文件MINE.bin。(10)单击“Target”→“program”,烧写确认对话框,直接确认,J-LINK会先擦除NORFlash,再将MINE.bin烧写在其0x00000000开始的区域中。(11)烧写完成后断电,再取下J-LINK。(12)再重新上电,如果MINE.bin程序正确无误,Mini2440上将会有所显示,例如,LED灯被点亮,当然Mini2440的显示结果与开发人员的程序有关。再如,用户编写了一个裸板串口程序,并且希望通过Mini2440的串口是否正常工作来测试开发人员的程序,则需要在第(11)步之后,在PC和Mini2440之间通过串口UART连接(图2.10);如果程序正确无误,Mini2440将会通过串口回显信息到PC的串口工具(如超级终端);如果超级终端收到Mini2440的正确回显信息,程序开发成功;但如果超级终端没有回显信息或者收到了错误的回显信息,程序开发失败,重新查错、修改代码,再回到第(3)步。

2.3 启动Mini2440

交叉开发环境搭建好后,便可动手编码了,编码的首要工作是什么呢?答案是:用ARM汇编语言启动处理器S3C2440A。2.3.1 为什么需要启动

无论一个计算机系统由多少硬件设备组合而成,该系统能够运行的基础至少需要一个CPU与运行指令与数据的载体,该载体被称为主存。当系统上电后,CPU会在可以挂为主存的储存器上开始命令的执行,一般的CPU通常是从地址0x0处开始取指执行,Mini2440的S3C2440A芯片也是如此。当开发板上电后,CPU的PC寄存器的值通过硬件机制被初始化为0x0。

根据计算机组成原理的知识,一切指令与程序都只能在主存上运行。而主存价格较昂贵,并且开发人员的程序通常比较大,因此,开发人员的程序通常存储在外存中,而外存通常无法作为应用程序运行的载体。这样,当系统上电后,怎样通过一些机制将应用程序从其他存储设备复制到主存上是十分重要的。此外,不同的系统硬件设备不同,开机后所需要的硬件设备的配置也不同。所以,系统上电后,对各硬件控制器的设置也是十分重要的。这些设置其实就是“告诉”处理器CPU现在启动系统运行的基本硬件设备是怎样的,从而能正确地使用各种设备,这些都是启动代码的责任。

启动代码的作用可以随着需求的增加而进行扩充,上述描述只是确保系统能够基本运行启动代码的功能,其实,启动代码还可以包括实际开发板上各板级硬件和接口的驱动程序,这时的启动代码其实就具有了能够使应用程序使用开发板各资源的接口功能了,BootLoader(如FriendlyARM BIOS 2.0或者Supervivi)就是这样一类启动代码的很好诠释。2.3.2 启动流程

启动代码是与硬件设备密切相关的,其流程是与具体的硬件设备密不可分的。这一节将以Mini2440的S3C2440A处理器为例来讲述启动代码的流程,如图2.11所示,这里的启动代码只是一个能使CPU正常工作的一个最小系统,更为全面复杂的启动代码流程与所需要注意的细节会在后面章节加以描述。

Mini2440开发板有两种启动模式,一种是从NOR Flash启动,另一种是从NAND Flash启动,本节以从NAND Flash启动为例介绍。当Mini2440从NAND Flash启动时,因为NAND Flash无法作为程序运行的载体,所以S3C2440A芯片通过硬件机制将NAND Flash的开头4KB的内容自动复制到了S3C2440A芯片内部的4KB大小的SRAM上面,并且S3C2440A芯片会自动将这4KB大小的SRAM映射为自身内存的BANK0,将这4KB大小的内容映射到从0x00000000开始的地址上,然后处理器从0x00000000地址开始执行。

1.创建异常向量表

当程序在S3C2440A芯片上运行发生异常时,程序指针PC会自动跳转到主存最开始的地址(0x00000000),这里就是异常向量表的起始地址,然后会通过专门的硬件机制定位到相应的异常向量。ARM处理器内核一共定义了七种异常:复位异常、未定义指令异常、软中断异常、预取指终止异常、数据终止异常、IRQ中断异常、IRQ快速中断异常,具体描述如下。图2.11 启动程序流程(1)复位异常。当开发板复位时,S3C2440A的ARM920T核将当前正在运行程序的CPSR与PC存入管理模式下的SPSR与LR(R14)中。然后,强制将CPSR的M[4:0]位写为10011(管理模式),并将CPSR的I位与F位置1(屏蔽IRQ与FIQ),将CPSR的T位清0(进入ARM指令模式)。之后,强制将PC的值设为0x0,让CPU从0x0开始取指执行命令,这时CPU运行在ARM状态。(2)未定义指令异常。当ARM920T遇到一个无法处理的指令时,未定义指令异常发生。未定义异常发生后,当前运行程序的下一条指令的地址会被保存到相应模式下的LR(R14)中,CPSR被保存到相应的SPSR中,然后CPSR的M[4:0]被设置为相应的模式值,并且PC是被强制赋值为0x4(因为ARM 9是32位的指令集,每条指令占用4B的空间)。这时,CPSR的中断位可能会被置1,这里“可能”的意思是与异常的类型有关(如复位异常是一定要置1的),不同的异常将使S3C2440A芯片会采取不同的行为。如果在这些异常处理中允许中断嵌套,可以手动将I位清零,不可以的话就置1,以下各个异常均类似。(3)软中断异常。当软中断指令SWI被执行时,软中断异常发生。当软中断异常发生时,ARM920T采取与未定义指令异常类似的措施,只是相应的设置值变为软中断异常所需要的值,PC取值为0x8。软中断是用户模式切换到特权模式的唯一途径,软中断会将程序带到管理模式下,这样,程序就可以对更多的寄存器,特别是CPSR有了修改的权利。软中断通常用来实现特权模式下的系统调用功能。(4)预取指终止异常。当在一条指令的预取指片段执行失败(通常为内存读取错误)时,预取指终止异常发生,ARM920T对各寄存器的设置与上述异常类似,但PC取值为0xC。预取指终止异常只有当该指令进入了流水线时(也就是该指令被预取指时)发生,但是如果引发该异常的指令没有被执行的话,程序是不会终止去处理异常的,这是因为有可能在之前有跳转指令被执行从而跳过了该指令。(5)数据终止异常。当在读出数据时发生内存错误时,数据终止异常发生。ARM920T采取与上述异常类似的措施,但PC取值为0x10。当发生数据终止异常时,在异常处理函数中应注意发生变化

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载