uc ocii在x86平台上的移植研究_第1页
uc ocii在x86平台上的移植研究_第2页
uc ocii在x86平台上的移植研究_第3页
uc ocii在x86平台上的移植研究_第4页
uc ocii在x86平台上的移植研究_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 毕业论文本科生题 目: UC/OS-II在X86平台上的移植研究英文题目: The study of UC/OS-II ported in the X86姓名:孙某某班级:2021137导师:戴某某 专业:计算机科学与技术 2021年六月摘 要嵌入系统广泛应用于控制领域,信息家电,工业,农业,商业,效劳业等各行业,已成为现在电子设计的一大领域与方向。而嵌入式操作系统是嵌入系统的灵魂,已成为操作系统研究的一个重要分支,本课题的目的就是为了在基于80X86核心的微处理器的硬件环境下搭建嵌入式的UC/OS软件平台。本论文通过分析具有一定实时性的、源代码公开的嵌入式操作系统UC/OS,了解其内核原理

2、,如:任务管理、内存管理、时钟管理以及任务间的通讯与同步机制,同时研究以80X86为内核的微处理器的体系结构及编程特点,对操作系统UC/OS进行改良,使用Borland C的编译器,将此实时嵌入式操作系统移植到PC机上,并编写测试程序来测试该系统的成功移植,从而实现对嵌入式系统的理解以及对操作系统与硬件的如何结合的理解,为今后扩展到ARM平台上打下一定的根底。关键词: 嵌入式操作系统 实时 UC/OS 任务 移植AbstractEmbedded System Design is a trend in the development of modern electronic technology

3、 .It has been used in every walk of life, such as communications and the field of controlling. At the same time, Embedded Operation System plays the most important role in Embedded System .So the writer intends to port an embedded operation system to the hardware platform based on 80X86 embedded mic

4、ro-processor, and build a whole embedded system.This thesis will introduce the real-time embedded operation system UC/OS and analyze its kernel, such as tasks management, memory management. At the same time study the architecture and the character of the 80X86 micro-processor, Use complier Borland C

5、 to write some new program to improve UC/OS-II and to port its to the hardware platform of the personal computer, and focus on the problem during the work and how to resolve them, Afterwards write a small program to test whether the operation successfully port. At last bring forward the scheme for i

6、mproving this system performance.Keywords: Embedded; Operation; System;Real-time;UC/OS;Task;Port目 录第1章 绪论1.1 嵌入系统的开展与展望当今世界以计算机技术、芯片技术和软件技术为核心的数字化技术取得了迅猛开展,不仅广泛的渗透到社会、经济、军事、交通、通信等相关行业,而且深入到家电、娱乐、艺术、社会文化等各个领域,掀起了一场数字化技术革命。现代控制技术、多媒体技术与Internet的应用与普及,促使消费电子、计算机、通信一体化3G趋势步伐加快,嵌入式技术再度成为一个研究的热点。嵌入式系统是以应用

7、为中心和以计算机技术为根底的,并且软硬件是可裁剪的,能满足应用系统对功能、可靠性、本钱、体积、功耗等指标的严格要求的专用计算机系统,它通常由嵌入式处理器、嵌入式外围设备、嵌入式操作系统和嵌入式应用软件等几大局部组成,是软硬件于一体的可独立工作的器件。纵观嵌入式技术的开展,大致可分为3各阶段:分别是第一阶段以功能简单的专用计算机或单片机为核心的可编程控制器形式存在的嵌入技术的早期阶段;第二阶段是嵌入式和嵌入式操作系统为标志的嵌入式系统;第三阶段是以芯片技术和Internet技术为标志的嵌入式系统。信息时代、数字时代使得嵌入式产品获得了巨大的开展机遇,为嵌入式市场展现了美好的前景,同时也对嵌入式生

8、产厂商提出了新的挑战。从中可以看出未来嵌入式系统的几大开展趋势:嵌入式开发使一项系统工程,因此要求嵌入式系统厂商不仅要提供嵌入式软硬件系统本身,同时还需要提供强大的硬件开发工具和软件包支持。比方三星在推广ARM7芯片的同时还提供开发板和板级支持包BSP。网络化、信息化的要求随着Internet技术成熟,带宽的加大而日益提高,使得以往单一功能的设备如 、 、冰箱等功能不在单一,结构更加复杂。网络互联成为必然趋势。精简系统内核、算法、降低功耗和软硬件本钱。提供友好的多媒体人机界面。1.2 实时操作系统RTOS的概述实时操作系统是由实时内核、实时网络组件,文件系统和图形接口等组成,具有实时性,能支持

9、实时控制系统工作的操作系统,其首要任务是调动一切可利用的资源完成实时控制任务,其次才着眼于提高计算机系统的使用效率;其最重要的特点是能满足对时间的限制与要求,与一般的操作系统有一定的差异,IEEE的UNIX委员会规定了实时操作系统必须具有以下几个特点:支持异步的事件响应中断和调度任务的优先级机制支持强占式调度确定任务切换时间和中断延迟时间内存锁定功能连续文件支持支持同步1.3 开发平台的选择进行嵌入式系统开发时,开发平台是不可缺少的。我选用的PC机上的80X86体系的CPU和UC/OSII作为开发平台,这是因为PC机价格低廉,处理速度快,而且80X86体系结构开展到现在已经很成熟稳定,加上我们

10、在校学习过80X86的指令系统和它的组成原理,再者,他应用的非常普遍,对一个嵌入式系统的初学者来讲,PC机无疑是最好的选择。至于UC/OS-II,它与其它实时操作系统相比,有明显的优点:结构的简单:它采用的是C语言和汇编语言编写,其中绝大局部用C语言,结构非常简洁非常好的移植性:好的移植性易于移植到微处理器上,用户在移植过程中只需做少量的工作即可。公开的源代码:他的源代码是公开的而且免费,任何人都可以到它的官方网站下载,对于毫无收入的学生来讲是最好的选择。高性能:它具备了实时操作系统的全部性能,非常适合初次接触嵌入式技术的初学者学习嵌入式技术的使用1.4 课题的提出及意义在嵌入应用中使用实时操

11、作系统RTOS已成为当前嵌入式应用的一个特点、一种时尚。 一个好的实时操作系统能够大大提高控制产品的研制效率,缩短开发时间,更有利于多人的分工协作。商业的实时操作系统具有强大的功能、良好的接口,但其昂贵的价格限制了它在为数众多的低端低本钱嵌入式场合的应用。并且对这些场合来讲,一个包含网络协议栈、文件管理、完整的内存管理的操作系统实在是显得过于庞大和强大了,它们需要的仅仅是一个稳定的、包含任务管理和进程调度的实时内核。UC/OS是一个开放源代码的、精简的实时内核,它功能强大,提供了任务管理、进程调度、任务间通信、内存管理等功能。它具有如下 特点:可移植性Portable 绝大局部UC/OS的源代

12、码是用移植性很强的ANSIC写的,和微处理器硬件相关的那局部使用汇编语言写的。而汇编语言写的局部已经压到最低限制,使得UC/OS便于移植到其他处理器上。可固化ROMable UC/OS是为了嵌入式应用而设计的。这就意味着只要有固化手段C编译、连接、下载和固化,UC/OS可以嵌入到用户产品中成为产品的一局部。可裁减Scalable 这种可裁减性是靠条件编译实现的。只要是用户的应用程序中用#define constants语句定义那些UC/OS中的功能是应用程序需要的就可以了,这样可以减少产品中所需要的存储空间ROM和RAM。占先式Preemptive UC/OS是基于优先级的、抢占式的实时内核。

13、它总是运行就绪条件下优先级最高的任务。大多数商业内核也是占先式的,UC/OS在性能上和它们类似。多任务 UC/OS可以管理64个任务,然而,目前这一版本保存了8个给系统。应用程序最多可达有56个。可确定性 全部UC/OS函数的调用与效劳的执行时间具有其可确定性。也就是说,全部UC/OS的函数调用与效劳的执行时间是可知的,UC/OS 系统效劳的执行时间不依赖于应用任务的多少。任务栈 每个任务都有自己独立的栈,UC/OS允许每个任务有不同的栈空间,以压低应用程序对RAM的需求。系统效劳 UC/OS提供很多的系统效劳,如消息队列、邮箱、块大小固定的内存的申请与释放、时间相关函数等。中断管理 中断可以

14、使正在执行的任务暂时挂起。如果优先级更高的任务被该中断唤醒,那么高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可达255层稳定性和可靠性UC/OS已经成功的应用到几百个嵌入式的商业应用中,被证明是一个成熟稳定的实时内核。我们的课题就是以在80X86为内核的PC机上移植UC/OS,为将来扩展到ARM上奠定根底。第2章 UC/OS-II内核原理 2.1 任务管理任务现在成为操作系统和并发程序设计中的一个非常重要的概念。一般认为程序是存储在磁盘上包含可执行机器指令和数据的静态实体,而任务是具有一定功能的程序关于一个数据集合的一次运行活动,是处于活动状态的计算机程序。在多处理操作系统中,任务

15、是具有独立的权限和职责。如果系统中某个任务崩溃,不会影响到其余的任务。每个任务运行在各自的地址空间中,通过一定的通讯机制,它们间才发生联系。UC/OS-II控制下的任务在其生存期内可能处于5种根本状态,如图21所示: 休眠态 :任务驻留在程序空间中,还没有交给UC/OS管理就绪态 :任务本身具有运行能条件,等待CPU运行态 :任务占有CPU,正在运行等待态 :等待除CPU之外的其他资源或条件如信号量,不能运行中断态 :正在运行的任务被中断,进入中断在任一时刻,任务的状态一定是这五种状态之一。 图表21 任务状态转换图在UC/OS中对任务的管理与调度主要包括建立任务、删除任务、改变任务的优先级、

16、挂起和恢复任务以及获得有关任务的信息,它是通过任务控制块和任务就绪表来实现的。任务控制块是一个数据结构,它与任务是一一对应的,在操作系统初始化OSINIT时,系统申请一块RAM空间来存储空闲任务控制块。一旦任务建立,系统就会分配一个任务控制块OS-TCB给任务。当任务的CPU使用权被剥夺时,UC/OS用它来保存该任务的状态。当任务重新得到CPU使用权时,任务控制块能确保任务从被中断的那一点继续执行下去。OS-TCB全部驻留在RAM中,在任务建立的时候,OS-TCB被初始化。在UC/OS初始化的时候,所有的任务控制块就被链接成任务控制块单向链表,通过链表指针来管理任务,然而,UC/OS实现任务管

17、理还需另一个数据结构就绪表。即每个任务被赋予不同的优先级等级,从0级到最低优先级OS_LOWEST_PR1O,包括0和OS_LOWEST_PR1O在内见文件OS_CFG.H。当C/OS-初始化的时候,最低优先级OS_LOWEST_PR1O总是被赋给空闲任务idle task,每个任务的就绪态标志都放入就绪表中的,就绪表中有两个变量OSRedyGrp和OSRdyTbl。在OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组中是否有进入就绪态的任务。任务进入就绪态时,就绪表OSRdyTbl中的相应元素的相应位也置位。就绪表OSRdyTbl数组的大小取

18、决于OS_LOWEST_PR1O(见文件OS_CFG.H)。当用户的应用程序中任务数目比拟少时,减少OS_LOWEST_PR1O的值可以降低C/OS-对RAM数据空间的需求量。为确定下次该哪个优先级的任务运行了,内核调度器总是将OS_LOWEST_PR1O在就绪表中相应字节的相应位置1,为了找到那个进入就绪态的优先级最高的任务,并不需要从OSRdyTbl0开始扫描整个就绪任务表,只需要查另外一张表,即优先级判定表OSUnMapTbl(256)(见文件OS_CORE.C)。OSRdyTbl中每个字节的8位代表这一组的8个任务哪些进入就绪态了,低位的优先级高于高位。利用这个字节为下标来查OSUnM

19、apTbl这张表,返回的字节就是该组任务中就绪态任务中优先级最高的那个任务所在的位置。这个返回值在0到7之间。为了运行就绪任务中优先级最高的任务,UC/OS-II是通过任务调度函数OSSched()来实现任务间的切换。为实现任务切换,OSTCBHighRdy必须指向优先级最高的那个任务控制块OS_TCB,这是通过将以OSPrioHighRdy为下标的OSTCBPrioTbl数组中的那个元素赋给OSTCBHighRdy来实现的L3.8(4)。接着,统计计数器OSCtxSwCtr加1,以跟踪任务切换次数L3.8(5)。最后宏调用OS_TASK_SW()来完成实际上的任务切换L3.8(6)。任务切换

20、很简单,由以下两步完成,将被挂起任务的微处理器存放器推入堆栈,然后将较高优先级的任务的存放器值从栈中恢复到存放器中。在C/OS-中,就绪任务的栈结构总是看起来跟刚刚发生过中断一样,所有微处理器的存放器都保存在栈中。换句话说,C/OS-运行就绪态的任务所要做的一切,只是恢复所有的CPU存放器并运行中断返回指令。为了做任务切换,运行OS_TASK_SW(),人为模仿了一次中断。多数微处理器有软中断指令或者陷阱指令TRAP来实现上述操作。2.2 时间管理UC/OS和其他的操作系统一样,要求用户提供定时中断来实现延时与超时控制等功能。这个定时中断叫做时间节拍。时钟节拍是特定的周期性中断。这个中断可以看

21、作是系统心脏的脉动,中断之间的时间间隔取决于不同的应用,一般在10ms和200ms之间,时钟节拍式的中断使得内核可以将任务延时假设干个整数时钟节拍,以及当任务等待事件发生时,提供等待超时的依据。注意:用户必须在多任务系统启动后再启动时钟节拍源计时,也就是在调用OSStart()之后。换句话说,在调用OSStart()后第一件事是初始化定时器中断。通常容易犯的错误是将允许时钟节拍器中断放在系统初始化函数OSInit()之后,在调用多任务系统启动函数OSStart()之前。这样做潜在的危险是:时钟节拍中断可能在UC/OS启动第一个任务之前发生,此时UC/OS是处在一种不确定的状态中,用户程序有可能

22、崩溃。µC/OS-提供了这样一个系统效劳:申请该效劳的任务可以延时一段时间,这段时间的长短是用时钟节拍的数目来确定的。实现这个系统效劳的函数叫做OSTimeDly(),当然当用户需要知道延时时间对应的时钟节拍的数目,可定义使用全局常数OS-TICKS-PER-SEC将时间转换为时钟段,用OSTimeDlyHMSM()代替OSTimeDly()。调用该函数会使µC/OS-进行一次任务调度,并且执行下一个优先级最高的就绪态任务。任务调用OSTimeDly()后,一旦规定的时间期满或者有其它的任务通过调用OSTimeDlyResume()取消了延时,它就会马上进入就绪状态。注意,

23、只有当该任务在所有就绪任务中具有最高的优先级时,它才会立即运行。2.3 任务间的通信与同步对一个实时多任务操作系统来讲,有时很需要任务间的中断效劳与任务间的信息传递;这种消息传递被称为任务间的通信而另一方面,有时某一任务的继续执行是以另一个任务或中断效劳子程序的执行为条件的,只有等所需的时间都发生生了,该任务才会继续执行这种互为条件的等待发生被称为任务间的同步。所以UC/OS中进程间的通信和同步是必不可少的。在UC/OS提供了三种进程同步方式:信号量、消息信箱和消息队列。图22介绍了任务和中断效劳子程序之间是如何通信的,第一种情况表示一个进程等待另一个进程或ISR的信号。第二种表示多个进程等待

24、另一个进程或ISR的信号。在多个进程中只有优先级最高的进程才获取信号。第三种情况是信号量特有的。 图22 UC/OSII的任务切换一个任务或者中断效劳子程序可以通过事件控制块ECBEvent Control Blocks来向另外的任务发信号。这里,所有的信号都被看成是事件Event。这也说明为什么上面把用于通讯的数据结构叫做事件控制块。一个任务还可以等待另一个任务或中断效劳子程序给它发送信号。这里要注意的是,只有任务可以等待事件发生,中断效劳子程序是不能这样做的。对于处于等待状态的任务,还可以给它指定一个最长等待时间,以此来防止因为等待的事件没有发生而无限期地等下去。多个任务可以同时等待同一个

25、事件的发生F6.1B。在这种情况下,当该事件发生后,所有等待该事件的任务中,优先级最高的任务得到了该事件并进入就绪状态,准备执行。上面讲到的事件,可以是信号量、邮箱或者消息队列等。当事件控制块是一个信号量时,任务可以等待它,也可以给它发送消息。2.4 内存管理在µC/OS-II中,操作系统把连续的大块内存按分区来管理。每个分区中包含有整数个大小相同的内存块,如同图F7.1。利用这种机制,µC/OS-II 对malloc()和free()函数进行了改良,使得它们可以分配和释放固定大小的内存块。这样一来,malloc()和free()函数的执行时间也是固定的了。在一个系统中可以

26、有多个内存分区。这样,用户的应用程序就可以从不同的内存分区中得到不同大小的内存块。但是,特定的内存块在释放时必须重新放回它以前所属于的内存分区。显然,采用这样的内存管理算法,上面的内存碎片问题就得到了解决。为了便于内存的管理,在µC/OS-II中使用内存控制块memory control blocks的数据结构来跟踪每一个内存分区,系统中的每个内存分区都有它自己的内存控制块. 在使用一个内存分区之前,必须先建立该内存分区。这个操作可以通过调用OSMemCreate()函数来完成,每个内存块至少为一个指针的大小,因为同一个分区内的所有空闲块是由指针链接起来的。在UCOS系统中提供了以下

27、几个内存管理效劳建立一个内存分区,OSMemCreateo。该函数共有4个参数:内存分区的起始地址、分区内的内存块总数、每个内存块的字节数和一个指向错误信息代码的指针该函数负责从系统中的空闲内存控制块链表中取得个内存控制块,所要建立的内存分区内的所有内存块被链接成一个单向的链表,然后。在对应的内存控制块中填写相应的信息,最后返回指向该内存块的指针。分配一个内存块,OSMemG威。该函数唯一的参数是指向特定内存分区的指针,该指针在建立内存分区时;由OSMemCreate函数返回。OSMemG创亩先检查内存分【中是否有空闲的内存块,如果有,从空闲内存块链表中删除第一个内存块,并对空闲内存块链表做相

28、应的修改。这包括将链表头指针后移一个元素和空闲内存块数减1。最后,返回指向被分配内存块的指针。注意:应用程序必须知道内存块的大小,并且在使用时不能超过该容量。释放一个内存块,OSMemGut()。该函数需要2个参数:指向内存控制块的指针也即内存块属干的内存分区和要释放的内存块的指针。注意:在释放内存块时,应确保该内存块属于对应的内存分区,否那么有可能使系统崩渍。OSMemP帆0首先检查内存分区是否己满、如果己满,说明系统在分配和释放内存时出现了错误。如果未满,要释放的内存块被插入到该分区的空闲内存块链表中。最后,将分区中空闲内存块总数加l。查询一个内存分区的状态,OSMemQuery()。通过

29、该函数可以知道特定内存分区中内存块的人小、可用内存块数和正在使用的内存块数等信息。所有这些信息都放在OSMEMDATA的数据结构中。注意:在使用该函数复制内存分区信息前,必须先禁止外部中断,防止启动过程中某些变量值被修改。 有时候,在内存分区暂时没有可用的空闲内存块的倩况下,让一个申请内存块的任务等待也是有用的。但是,UCOS本身内存管理上并不支持这项功能。如果确实需要,那么可以通过为特定内存分区增加信号量的方法未实现这种功能。应用程序为了申请分配内存块,首先耍获得一个相应的信号量,然后才能调用OSMemGet、注意:信号量的初始值必须等于内存分区中总的内存块数。2.5 UC/OS-II的初始

30、化在调用UC/OS的其他效劳之前,UC/OS要求用户首先调用操作系统 初始化函数OSInit()。该函数负责初始化UC/OS所有的变量和数据结构,还建立一些必须的任务。OSInit建立空闲任务,这个任务总是处于就绪态的。空闲任务OSTaskIdle的优先级总是设成最低,既OS-LOWEST-PRIO。如果统计任务允许OS-TASK-STAT-EN和建立扩展允许都设为1,那么OSInit()还得建立统计任务OSTaskStat()并且让其进入就绪态。统计任务OSTaskStat的优先级总是设为OS-LOWEST-PRIO-1。这两个任务的任务控制块OS-TCB是用双向链表链接在一起的。OS-TC

31、BList指向这个链表的起始处。换句话说,OSTCBList总是指向最后建立的那个任务,链的终点指向空字符NULL。除此以外,UC/OS还初始化4个空数据结构缓冲区:空闲任务控制块链表OSTCBFreeList、空闲事件控制块OSEventFreeList、空闲队列控制块链表OSQFreeList、空闲内存控制块链表OSMemFreeList,每个缓冲区都是单向链表,允许UC/OS从缓冲区迅速得到或释放一个其中元素。2.6 UC/OS启动在UC/OS系统中多任务的启动是用户通过调用OSStart()实现的。然而,启动UC/OS之前,用户至少要建立一个应用任务。程序清单表2-1:void mai

32、n (void) OSInit(); /* 初始化uC/OS-II */ . . 通过调用OSTaskCreate()或OSTaskCreateExt()创立至少一个任务; . . OSStart(); /* 开始多任务调度!OSStart()永远不会返回 */表21 UC/OSII的启动示意程序当调用OSStart()时,OSStart()负责从任务就绪表中找出那个用户建立的优先级最高的任务的任务控制块,然后OSStart()调用高优先级就绪任务启动函数OSStartHighRdy(),这个函数与选择的微处理器有关,实质上,函数OSStartHighRdy()是将任务栈中保存的值弹回到CPU

33、存放器中,然后执行一条中断返回指令,中断返回指令强制执行该任务代码,使系统进入用户应用程序的运行,开始多任务的调度。第三章 UC/OS-II的移植3.1 80X86体系结构说明现代个人PC机是根本上是32位的微处理器,但体系结构和80X86的是同样的原理,我们80X86为例来介绍他的体系结构。80X86 是一个高级的 16 位微处理器,专门用于多任务的操作系统,并为需要高性能的应用所设计。16位的存放器和数据通道支持 16 位的寻址方式和数据类型,处理器使用一种特殊的机制,寻址最高可达1GB 的地址空间,计算方法是:段地址存放器的内容的左移4位乘以16,再加上偏移量存放器其他6个存放器中的一个

34、,AX,BP,SP,SI,DI或IP的内容,产生了可寻址1MB的20位物理地址,图3-1说明了存放器如何组成的。段存放器可以指向一个内存块,称为一个段。一个16位的段存放器可以表示65536个不同的段,因此可以寻址1048576字节。由于偏移量存放器也是16位的,所以单个字段不能超过64k。实际操作中,应用程序是由许多小于64K的段组成。代码存放器CS指向当前程序运行的代码起始,堆栈段存放器SS指向程序堆栈段的其始,数据段存放器指向程序数据区的起始,附加段存放器ES)指向一个附加数据存储区。每次CPU寻址的时候,段存放器中的某一个会自动选用,加上偏移量存放器的内容作为物理地址。 图3-1 80

35、X86实模式内部存放器图中断和异常:04Hz),我们将时钟节拍频率设为200Hz,PC时钟节拍的中断向量为0X08,UC/OS-II将此向量截取,指向了UC/OS-II的中断效劳函数OSTickISR(),而原先的中断向量保存在104(0X81)中,为满足DOS的需要,原先的中断效劳还是每隔54.39ms(实际上还要短些),图3-2为安装UC/OS-II前后的中断向量表. 图3-2 PC中断向量表 3.2 UC/OS操作系统的文件介绍 在用户移植工作开始之前,用户必须熟悉UC/OS的结构以及它与硬件之间的关系如图3-3所示:图33 UC/OSII硬件和软件体系结构UC/OS操作系统包括以下文件

36、:OS-CORE.C:内核文件,包含系统调度OSSched()、系统初始化OSInit()、多任务启动OSStart()、时钟节拍OSTimeTick()等函数.:邮箱效劳文件,提供使用邮箱的所有函数OS-MEM.C:内存管理文件OS-Q.C:消息队列效劳文件OS-SEM.C:信号量效劳文件OS-TASK.C:任务管理文件UCOS-II.CUCOS-II.H:定义与处理器无关的常量、数据结构和全局变量OS-CFG.H:UC/OS的配置文件,与应用程序相关INCLUDES.H:统一的头文件OS-CPU.H:定义与处理器相关的常量、宏和类型OS-CPU-A.ASM:与处理器相关的代码,定义了高优先

37、级就绪任务启动函数OSStartHighRdy()、任务级切换函数OSCtxSW()、中断级切换函数OSIntCtxSw()、定时中断处理函数OSTickISR()OS-CPU-C.C:与处理器相关的代码,定义了任务堆栈初始化函数OSTaskSkInit()、和一些扩展函数OSTaskStkInit()、OSTaskCreateHook()、OSTaskDelHook()、OSTaskSwHook()、OSTaskStatHook()、OSTimeTickHook()3.3 开发工具移植UC/OS需要一个编译器,并且是针对用户用的CPU的。因为µC/OS-是一个可剥夺型内核,用户只有

38、通过C编译器来产生可重入代码;C编译器还要支持汇编语言程序。绝大局部的C编译器都是为嵌入式系统设计的,它包括汇编器、连接器和定位器。连接器用来将不同的模块(编译过和汇编过的文件)连接成目标文件。定位器那么允许用户将代码和数据放置在目标处理器的指定内存映射空间中。所用的C编译器还必须提供一个机制来从C中翻开和关闭中断。一些编译器允许用户在C源代码中插入汇编语言。这就使得插入适宜的处理器指令来允许和禁止中断变得非常容易了。还有一些编译器实际上包括了语言扩展功能,可以直接从C中允许和禁止中断,我们采用的的处理器是80X86体系结构的CPU,所以开发工具选用Borland公司的,利用此工具可以开发、编

39、译和调试C程序和汇编程序。BC编译器主要包含以下几个主要文件:bc.exe IDE bcc.exe c make.exe maketlink.exe 连接tasm.exe 汇编tasm2msg.exe 汇编touch 修改日期3.4 PC机上的 UC/OSII移植本节将介绍如何将UC/OSII移植到80X86体系的PC机上,虽然UC/OSII的大局部源代码是用C语言写成的,但是还需要用C语言和汇编语言完成一些与处理器相关的代码。因为UC/OS-II的设计时充分考虑了可移植性,所以UC/OSII的移植还是比拟容易的,但要使它可以正常工作,处理器必须满足如下要求:处理器的C编译器能产生可重入代码:

40、可重入代码指的是一段代码可以被多个任务同时调用,而不必担忧会破坏数据。所以代码的可重入性是保证完成多任务的根底,除了在C程序中使用局部变量外,还需C编译器的支持。PC机上的80X86体系的CPU是可以产生可重入代码的。在程序中可以翻开或关闭中断。根据本章第一节的介绍我们知道80X86体系结构可以设置相应的存放器来翻开或关闭中断。处理器支持中断并且能产生定时中断,UC/OS-II是通过处理器产生的定时中断来实现多任务之间的调度的。80X86体系结构的CPU是可以产生定时中断的。处理器支持能够容纳一定数量的硬件堆栈。处理器有将堆栈指针和其它CPU存放器存储和读出到堆栈或者内存的指令。 移植UC/O

41、S操作系统时,需要修改的系统文件就是以下三个文件。下面将详细介绍对80X86体系的CPU如何移植这三个文件。1OS-CPU.H主要包括四局部内容:与编译器相关的数据类型:因为不同的微处理器有不同的字长,所以µC/OS-的移植包括了一系列的类型定义以确保其可移植性。尤其是,µC/OS-代码从不使用C的short,int和long等数据类型,因为它们是与编译器相关的,不可移植。相反的,我定义的整型数据结构既是可移植的又是直观,例如,INT16U数据类型总是代表16位的无符号整数。将µC/OS-移植到32位的处理器上也就意味着INT16U实际被声明为无符号短整型数据结构

42、而不是无符号整型数据结构。但是,µC/OS-所处理的仍然是INT16U。用户必须将任务堆栈的数据类型告诉给µC/OS-。这个过程是通过为OS_STK声明正确的C数据类型来完成的。如果用户的处理器上的堆栈成员是32位的,并且用户的编译文件指定整型为32位数,那么就应该将OS_STK声明位无符号整型数据类型。所有的任务堆栈都必须用OS_STK来声明数据类型。用户所必须要做的就是查看编译器手册,并找到对应于µC/OS-的标准C数据类型。OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL():与所有的实时内核一样,µC/OS-需要先禁止中断

43、再访问代码的临界段,并且在访问完毕后重新允许中断。这就使得µC/OS-能够保护临界段代码免受多任务或中断效劳例程(ISR)的破坏。中断禁止时间是商业实时内核公司提供的重要指标之一,因为它将影响到用户的系统对实时事件的响应能力。虽然µC/OS-尽量使中断禁止时间到达最短,但是µC/OS-的中断禁止时间还主要依赖于处理器结构和编译器产生的代码的质量。通常每个处理器都会提供一定的指令来禁止/允许中断,在80X86体系的CPU中提供了CLI和STI来翻开和关闭中断。µC/OS-定义了两个宏来禁止和允许中断:OS_ENTER_CRITICAL()和OS_EXIT_

44、CRITICAL()。OS_STK_GROWTH:堆栈的方向。绝大多数的微处理器和微控制器的堆栈是从上往下长的。但是某些处理器是用另外一种方式工作的。对于80X86体系的CPU,它的堆栈是从从上往下的,所以置OS_STK_GROWTH为1。置OS_STK_GROWTH为0表示堆栈从下往上长OS_TASK_SW():定义宏,指向任务切换函数OS_TASK_SW(),该函数总是在任务级代码中被调用的。另一个函数OSIntExit()被用来在ISR使得更高优先级任务处于就绪状态时,执行任务切换功能。任务切换只是简单的将处理器存放器保存到将被挂起的任务的堆栈中,并且将更高优先级的任务从堆栈中恢复出来。

45、2OS-CPU-A.S文件中定义了四个汇编语言函数:这些函数都要处理CPU的内部存放器,用汇编语言来实现比拟方便。OSStartHighRdy():该函数假设OSTCBHighRdy指向的是优先级最高的任务的任务控制块。要想运行最高优先级任务,用户所要做的是将所有处理器存放器按顺序从任务堆栈中恢复出来,并且执行中断的返回。该函数是在OSStart()中调用的,启动多任务的完成。示意程序如表31所示:void OSStartHighRdy (void) Call user definable OSTaskSwHook(); Get the stack pointer of the task to

46、 resume: Stack pointer = OSTCBHighRdy->OSTCBStkPtr; OSRunning = TRUE; Restore all processor registers from the new task's stack; Execute a return from interrupt instruction; 表31 OSCtxSw():任务切换函数。任务级的切换问题是通过发软中断命令或依靠处理器执行陷阱指令来完成的。中断效劳例程,陷阱或异常处理例程的向量地址必须指向OSCtxSw()。注意在OSCtxSw()和用户定义的函数OSTaskSwH

47、ook()的执行过程中,中断是禁止的。OSCtxSw()的示意程序如表32所示:void OSCtxSw(void)保存处理器存放器;将当前任务的堆栈指针保存到当前任务的OS_TCB中:OSTCBCur->OSTCBStkPtr = Stack pointer;调用用户定义的OSTaskSwHook();OSTCBCur = OSTCBHighRdy;OSPrioCur = OSPrioHighRdy;得到需要恢复的任务的堆栈指针:Stack pointer = OSTCBHighRdy->OSTCBStkPtr;将所有处理器存放器从新任务的堆栈中恢复出来;执行中断返回指令;

48、60;表32 任务切换程序示意表OSIntCtxSw():中断级任务切换函数。由于调用该函数前已经发生中断了,该函数将默认CPU存放器已经保存在被中断任务的堆栈中,所以,它的代码大局部与OSCtxSw()相同,不同之处是:第一,此处不需要再CPU内容;第二,该函数需要调整堆栈指针,去掉堆栈中一些不需要的内容,以使堆栈中只包含任务的运行环境。该函数的示意程序如33所下:void OSIntCtxSw(void)调整堆栈指针来去掉在调用:OSIntExit(),OSIntCtxSw()过程中压入堆栈的多余内容;将当前任务堆栈指针保存到当前任务的OS_TCB中:OSTCBCur->OSTCBS

49、tkPtr = 堆栈指针;调用用户定义的OSTaskSwHook();OSTCBCur = OSTCBHighRdy;OSPrioCur = OSPrioHighRdy;得到需要恢复的任务的堆栈指针:堆栈指针 = OSTCBHighRdy->OSTCBStkPtr;将所有处理器存放器从新任务的堆栈中恢复出来;执行中断返回指令; 表33OSTickISR()时钟节拍处理函数。µC/OS-要求用户提供一个时钟资源来实现时间的延时和期满功能。所以用户必须在开始多任务调度后(即调用OSStart()后)允许时钟节拍中断。通常所犯的错误是在调用OSInit()和OSStart()之间允许

50、时钟节拍中断。示意程序如34所示:void OSTickISR(void)保存处理器存放器;调用OSIntEnter()或者直接将 OSIntNesting加1;调用OSTimeTick();调用OSIntExit();恢复处理器存放器;执行中断返回指令;表343最后需要修改的系统文件OS_CPU_C.C:移植UC/OS-II需要用户编写6个简单的C函数:OSTaskStkInit():任务堆栈初始化函数。该函数在OSTaskCreate()和OSTaskCreateExt()中。用户在建立任务时,用户会传递任务的地址、pdata指针、任务的堆栈栈顶和任务的优先级给OSTaskCreate()

51、和OSTaskCreateExt(),然后开始OSTaskStkInt()堆栈初始化。该函数将任务起始地址、处理器状态字、中断返回地址、处理器存放器的值依次压入任务堆栈,并返回堆栈栈顶指针。OSTaskCreate()和OSTaskCreateExt()会获得该地址并将它保存到任务控制块(OS_TCB)中。OSTaskCreateHook()OSTaskDelHook()OSTaskSwHook()OSTaskStatHook()OSTimeTickHook()第四章 测试与总结41 测试在完成处理器的初始化,外围设备的初始化与驱动之后,系统将进入操作系统的初始化和多任务的启动,启动程序是嵌入

52、式程序的开头局部,与应用程序一起固化在ROM中,并首先在系统上运行,他应包含各模块中可能出现的所有段类,并合理安排它们的次序。写好启动程序是设计好嵌入式程序的关键,系统启动程序所知行的操作依赖于正在开发其软件的系统,一般流程如下: 设置中断向量。初始化堆栈和存放器:系统堆栈初始化取决于用户使用了哪些中断,以及系统需要处理哪些错误类型。初始化存储系统:有些芯片可通过存放器编程初始化存储器系统,而对于复杂的系统通常集成有MMU来管理内存空间。如有必要改变处理器模式、状态:如果系统应用程序是运行在用户模式下,可在此处将系统改为用户模式并初始化用户堆栈指针。设置入口指针:启动程序首先必须定义入口指针,

53、而且整个应用程序只有一个入口指针初始化C语言所需的存储器空间。为很好的测试本系统的成功移植,我用了它的测试程序源代码做本次测试程序,如表41,42,43所示该程序实现了多任务的切换,测试CPU的使用情况与UC/OS的性能。其中共有13个任务包括UC/OS的空闲任务,UC/OS增加了两个内部任务:空闲任务和一个计算CPU利用率的任务。在操作系统启动之前建立一个任务TaskSart(),t它的功能是建立其它10个任务,并且向串口发送如下显示信息:每秒钟的任务切换次数CPU利用的百分率存放器切换次数目前日期和时间UC/OS的版本号图表41是该测试程序的主程序,main函数实际上就是程序流程中讲到的设

54、置入口指针。Void main (viod)PC_DispClrScr(DISP_FGND_WHITE+DISP_BGND_BLACK);OSInit();PC_DOSSaveREturn();PC_VectSet(Ucos,OSCtxSw);RandomSem=OSSemCreate(1);OSTaskCreate(TaskStart,(void*)0,(void*)&TaskStartStkTASK_STK_SIZE-1,0); OSStart();表 41注意,在启动多任务之前,用户必须先建立一个任务,该任务的优先级必须高于空闲任务和统计任务,使得多任务的启动之后,系统能进入用户

55、应用程序,同时由于在系统初始化时系统并没有设置时钟中断,做嵌入应用时,用户必须在第一个任务翻开时钟节拍中断。其示意程序如图表42所示。void TaskStart (void *data) Prevent compiler warning by assigning data to itself; Display banner identifying this as EXAMPLE #1; (1)OS_ENTER_CRITICAL(); PC_VectSet(0x08, OSTickISR); (2) PC_SetTickRate(200); (3) OS_EXIT_CRITICAL();  Initialize the statistic task

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论