毕业设计(论文)-μCOS-II在基于51微控制器上的移植研究.doc_第1页
毕业设计(论文)-μCOS-II在基于51微控制器上的移植研究.doc_第2页
毕业设计(论文)-μCOS-II在基于51微控制器上的移植研究.doc_第3页
毕业设计(论文)-μCOS-II在基于51微控制器上的移植研究.doc_第4页
毕业设计(论文)-μCOS-II在基于51微控制器上的移植研究.doc_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

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

文档简介

C/OS-II在基于51微控制器上的移植研究第一章 绪论11.1 背景和选题依据11.2 国内外的研究现状及发展趋势11.3 本文的研究内容1第二章 C/OS-II简介32.1 C/OS-II的产生背景32.2 C/OS-II的特点32.3 C/OS-II内核结构42.3.1 宏OS_ENTER_CRITICAL( )和OS_EXIT_CRITICAL( )52.3.2 任务52.3.3 调度器上锁、开锁92.3.4 C/OS-II中的中断与时钟节拍92.3.5 C/OS-II初始化与启动10第三章 Keil Cx51基础知识123.1 Cx51程序设计基础123.1.1 标识符与关键字123.1.2 基本语法及语句123.2 函数133.2.1 函数定义与调用143.2.2 函数的递归调用与再入函数15第四章 C/OS-II移植基础知识174.1 C/OS-II源文件移植174.2 硬件平台构成与编译器的选择194.3 C/OS-II移植的一般性问题20第五章 C/OS-II在51单片机上的移植215.1 头文件处理215.2 修改OS_CPU.H文件215.3 修改OS_CPU_C.C文件215.3 OS_CPU_AASM文件235.3.1 汇编文件头部定义235.3.2 修改OSStartHighRdy( )函数255.3.3 修改OSCtxSW( )函数255.3.4 OSIntCtxSW( )函数265.3.5 OSTickISR( )函数265.4 定时器初始值设置27第六章 实验及其结果分析286.1 实验的条件和指导思想286.2 实验的过程和结果286.3 对实验结果的分析和讨论29参考文献30致 谢31I第一章 绪论1.1 背景和选题依据随着各种应用电子系统的复杂化和系统实时性需求的提高,并伴随应用软件朝着系统化方向发展的加速,在16位/32位单片机中广泛使用了嵌入式实时操作系统。然而实际使用中却存在着大量8位单片机,很长时间都采用前后台系统软件设计模式:主程序为一个无限循环,单任务顺序执行,通过设置一个或多个中断来处理异步事件。这种系统对于简单的应用是可以的,但对于实时性要求比较高的、处理任务较多的应用,就会暴露出实时性差、系统可靠性低、稳定性差等缺点。本课题研究嵌入式实时操作系统C/OS-II在51微控制器上的移植,对C/OS-II的移植具有普遍的指导意义,可以为51平台更高层次的开发和拓展打下了基础。从学习操作系统角度看,通过C/OS-II在VRS51上的移植,可以掌握移植和测试C/OS-II的实质内容,很容易将其移植到其它的CPU平台上。1.2 国内外的研究现状及发展趋势目前比较常见的嵌入式操作系统有WindRiver公司的VxWorks、pSOS,微软公司的Windows CE,QNX公司的QNX OS,在手持设备嵌入式操作系统中三分天下的Plam、WinCE、EPOS等,但是使用这些商业操作系统是需要高昂的费用。面对这种情况,一些组织和个人也开发了一些免费的、源码开放的操作系统,在互联网发布,其中比较有名的是CLinux和C/OS-II。C/OS-II具有足够的稳定性和安全性,而且C/OS-II的构思巧妙,结构简洁精练,可读性很强,具备了实时操作系统的全部功能。C/OS-II是用C语言和汇编语言编写的。其中绝大部分代码都是用C语言编写的,只有极少部分与处理器密切相关的代码是用汇编语言编写的,所以用户只要做很少的工作就可以把它移植到各类8位、16位和32位嵌入式处理器上。随着硬件技术、应用需求和开发需求的变化,嵌入操作系统也需要支持面向对象和可重用等技术。这也要求未来嵌入式操作系统的开发要注意以下几个方面:通过自动化配置提高系统移植的效率,即尽量将操作系统的移植工作让开发工具自动完成;系统性能向信息化、网络化、智能化发展;面向构件的体系结构,即将操作系统的功能模块构件化,建立标准统一的网络通信协议,并在嵌入式操作系统构件化基础之上实现应用程序的智能化。1.3 本文的研究内容根据收集到的嵌入式实时操作系统C/OS-II一些相关资料,使用Keil Vision2开发工具对C/OS-II进行移植,直到仿真通过为止。基本内容: 1、了解嵌入式实时操作系统C/OS-II2、C/OS-II内核分析与系统分析3、Keil Cx51基础知识4、C/OS-II移植的基础知识5、在51系列单片机上移植C/OS-II可行性分析:1、C/OS-II源码开放2、Keil Cx51编译器和51控制器满足C/OS-II运行要求:处理器的C编译器能产生可重入型代码。用C语言就可以打开和关闭中断。处理器支持中断,并且能产生定时中断(频率通常在10至100Hz之间)。处理器能支持容纳一定量的数据存储硬件堆栈(可能是几千字节)。处理器有将堆栈指针和其他CPU寄存器的内容读出并存储到堆栈或内存中的指令。第二章 C/OS-II简介2.1 C/OS-II的产生背景C/OS-II是由Jean J.Labrosse于1992年编写的一个嵌入式多任务实时操作系统。最早这个系统叫做C/OS,后来经过近10年的应用和修改,在1999年Jean J.Labrosse推出了C/OS-II。C/OS-II是一个完整的、可移植、可固化、可裁剪的占先式实时多任务内核。C/OS-II包括任务调度、时间管理、内存管理、资源管理(信号量、邮箱、消息队列)四大部分,没有文件系统、网络接口、输入输出界面。它的移植只与4个文件相关:汇编文件(OS_CPU_A.ASM)、处理器相关C文件(OS_CPU.H、OS_CPU_C.C)和配置文件(OS_CFG.H)。有64个优先级,系统占用8个,用户可创建56个任务,不支持时间片轮转。它的基本思路就是 “近似地每时每刻总是让优先级最高的就绪任务处于运行状态” 。为了保证这一点,它在调用系统API函数、中断结束、定时中断结束时总是执行调度算法。原作者通过事先计算好数据,简化了运算量,通过精心设计就绪表结构,使得延时可预知。任务的切换是通过模拟一次中断实现的。由于C/OS-II的构思巧妙,结构简洁精练,可读性很强,同时又具备了实时操作系统的全部功能,所以虽然它只是一个内核,但非常适合初次接触嵌入式实时操作系统的学生、嵌入式系统开发人员和爱好者学习,并且通过适当地扩展之后,还可以应用到实际系统中去。2.2 C/OS-II的特点可移植性:C/OS-II是用C语言和汇编语言编写的。其中绝大部分代码都是用C语言编写的,只有极少部分和处理器密切相关的代码是用汇编语言编写的,所以用户只要做很少的工作就可以把它移植到各类8位、16位和32位嵌入式处理器上。C/OS-II已在超过40种不同架构上的微处理器上运行。C/OS-II已经在世界范围内得到广泛应用,包括很多领域, 如手机、路由器、集线器、不间断电源、飞行器、医疗设备及工业控制上。可固化:C/OS-II是为嵌入式应用而设计的,这就意味着,只要具备合适的系列软件工具(C编译、会变、链接及下载/固化),实际上就可以将C/OS-II嵌入到产品中作为产品的一部分。可剪裁:可以只使用C/OS-II中应用程序需要的系统服务。也就是说,某产品可以只使用很少几个C/OS-II调用,而列一个产品则可能使用了几乎所有C/OS-II的功能,这样可以减少产品中C/OS-II所需的存储器空间(RAM和ROM)。可剪裁性是靠条件编译实现的,只要在用户的程序中(用#define constants语句)定义哪些C/OS-II中的功能是应用程序需要的就可以了。可剥夺性:C/OS-II是完全可剥夺型的实时内核,即C/OS-II总是运行就绪条件下优先级最高的任务。大多数商业内核也是可剥夺型的,C/OS-II在性能上与它们类似。可确定性:绝大多数C/OS-II的函数调用和服务的执行时间具有可确定性。也就是说,用户总是能知道C/OS-II的函数调用与服务执行了多长时间。进而可以说,除了函数OSTimeTick()和某些事件标志服务,C/OS-II系统服务的执行时间不依赖于用户应用程序任务数目的多少。多任务:C/OS-II可以管理64个任务;然而建议用户保留8个给C/OS-II。留给用户的应用程序最多可有56个任务。赋予每个任务的优先级必须是不同的,这意味着C/OS-II不支持时间片轮转调度法。该调度法适用于调度优先级平等的任务。任务栈:每个任务都有自己单独的栈。C/OS-II允许每个任务有不同的栈空间,以便压低应用程序对RAM的需求。使用C/OS-II的栈空间校验函数,可以确定每个任务到底需要多少栈空间。系统服务:C/OS-II提供很多系统服务,例如信号量、互斥型信号量、事件标志、消息邮箱、消息队列、信号量、块儿大小固定的内存的申请与释放及事件管理函数等。中断管理:中断可以使正在执行的任务暂时挂起。如果优先级更高的任务被该中断唤醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可达255层。稳定性与可靠性:C/OS-II是基于C/OS的,C/OS自1992年以来已经有数百个商业应用。C/OS-II与C/OS的内核是一样的,只是提供了更多的功能。另外,2000年7月,C/OS-II在一个航空项目中得到了美国联邦航空管理局对用于商用飞机的、符合RTCA DO-178B标准的认证,该标准对用于航空设备方面的软件提出了要求。为了符合这一标准,必须尽可能地通过文件描述和测试,展示软件在稳定性和安全性这两方面都符合要求。这一结论对于操作系统来说特别重要,因为这一结论表明,该操作系统的质量得到了认证,可以在任何应用中使用。为了表明C/OS-II具有足够的安全性与稳定性,能应用于人性命攸关的、安全性条件极为苛刻的系统,C/OS-II的每一种功能、每一个函数及每一行代码都经过了考验和测试。2.3 C/OS-II内核结构C/OS-II文件结构如图2-1所示,分为4个部分,应用软件层位于最顶端,由用户自行编写。与处理器无关代码即是内核部分,包括了所有的内核代码和系统功能代码。C/OS-II配置定义了所有与内核裁剪有关的宏定义及主头文件。C/OS-II移植包含了与处理器相关的代码。用户应用程序 C/OS-II与处理器无关的代码 OS_Q.COS_CORE.COS_SEM.COS_FLAG.C OS_TASK.COS_MBOX.C OS_TIME.COS_MEM.COS_MUTEX.CC/OS-II.HC/OS-II.CC/OS-II与应用程序相关的代码 OS_CHG.HINCLUDES.HC/OS-II与处理器相关的代码 (移植时需要修改)OS_CPU.H OS_CPU_A.ASM OS_CPU_C.C图2-1 C/OS-II文件结构2.3.1 宏OS_ENTER_CRITICAL( )和OS_EXIT_CRITICAL( )为了处理临界段代码,需要关中断,处理完毕后,再打开中断。关中断使得C/OS-II能够避免同时有其他任务或中断服务进入临界段代码。就C/OS-II而言,关中断的时间很大程度上取决于微处理器的结构以及编译器所产生的代码质量。在C/OS-II与处理器无关的代码中,为了避免不同的方法处理关中断和开中断,同时减少移植的难度,同样需要处理临界段。定义两个宏处理关中断和开中断。分别是OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。2.3.2 任务1、任务及其状态C/OS-II中的任务和普通C函数一样,有函数返回类型,有形式参数变量。但这并不意味着任务就是函数,内核也不会调用这个“函数”。换句话说,C/OS-II不过是借用了C语言中函数的形式来完成任务的划分。因为任务永远不被调用,也绝不会返回。所以返回参数必须定义成void型。如程序清单2.1所示。程序清单 2.1 任务的形式void YourTask (void *pdata) for (;) /* 用户代码 */ /*调用uC/OS-II的某种系统服务*/ /* 用户代码 */ 任务通常是一个无限循环,可以使用for(;),也可以使用while(1).当任务完成以后,任务可以调用OSTaskDel()函数自我删除。在C/OS-II中,任务的状态一定是睡眠态、就绪态、运行态、挂起态和被中断态这五个状态中的一种。2、任务控制块OS_TCB任务一旦建立,任务控制块OS_TCB就会被赋值。任务控制块是一个结构体,用来保存该任务的状态。任务控制块OS_TCB全部驻留在数据存储器中。C/OS-II初始化的时候,所有任务控制块OS_TCB被链接成单向空任务链表。任务一旦建立,空任务控制块指针OSTCBFreeList指向的任务控制块便赋给了该任务,然后OSTCBFreeList指向链表中下一个空的任务控制块。一旦任务被删除,任务控制块就还给空任务链表,如图2-2所示。图2-2 空任务列表3、就绪表每个任务的就绪态标志都放入就绪表中的,就绪表中有两个变量OSRedyGrp和OSRdyTbl。在OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组中是否有进入就绪态的任务。任务进入就绪态时,就绪表OSRdyTbl中的相应元素的相应位也置位。就绪表OSRdyTbl数组的大小取决于OS_LOWEST_PR1O(见文件OS_CFG.H)。当用户的应用程序中任务数目比较少时,减少OS_LOWEST_PR1O的值可以降低C/OS-对数据存储器的需求。为确定下次该哪个优先级的任务运行了,内核调度器总是将OS_LOWEST_PR1O在就绪表中相应字节的相应位置1。OSRdyGrp和OSRdyTbl之间的关系见图2-3,是按以下规则给出的:当OSRdyTbl0中的任何一位是1时,OSRdyGrp的第0位置1, 当OSRdyTbl1中的任何一位是1时,OSRdyGrp的第1位置1,当OSRdyTbl2中的任何一位是1时,OSRdyGrp的第2位置1,当OSRdyTbl3中的任何一位是1时,OSRdyGrp的第3位置1,当OSRdyTbl4中的任何一位是1时,OSRdyGrp的第4位置1, 当OSRdyTbl5中的任何一位是1时,OSRdyGrp的第5位置1,当OSRdyTbl6中的任何一位是1时,OSRdyGrp的第6位置1, 当OSRdyTbl7中的任何一位是1时,OSRdyGrp的第7位置1,图2-3 C/OS-II就绪表4、任务调度任务的调度属于实时操作系统的核心功能,在C/OS-II中,通过调度器(Scheduler)确定哪个任务优先级最高,该哪个任务运行。任务级的调度由函数OSSched()完成,中断级的调度由函数OSIntExit()完成。OSSched()如程序清单2.2所示。程序清单 2.2任务调度器void OSSched (void)#if OS_CRITICAL_METHOD = 3 OS_CPU_SR cpu_sr#endif INT8U y; OS_ENTER_CRITICAL(); if (OSLockNesting | OSIntNesting) = 0) y = OSUnMapTblOSRdyGrp; OSPrioHighRdy = (INT8U)(y OSTCBStkptr = SP;/清中断源;/重开中断源;/执行用户代码做中断服务;/调用OSIntExit();/恢复所有CPU寄存器;/执行中断返回指令;2、时钟节拍C/OS-II需要用户提供周期性信号源,用于实现时间延时和确认超时。节拍率应在每秒10次到100次之间,或者说10到100Hz。时钟节拍率越高,系统的额外负荷就越重。时钟节拍的实际频率取决于用户应用程序的精度。时钟节拍源可以是专门的硬件定时器,也可以是来自50/60Hz交流电源的信号。用户必须在多任务系统启动以后再开启时钟节拍器,也就是在调用OSStart()之后。换句话说,在调用OSStart()之后做的第一件事是初始化定时器中断。通常,容易犯的错误是将允许时钟节拍器中断放在系统初始化函数OSInit()之后,在调启动多任务系统启动函数OSStart()之前。这里潜在地危险是,时钟节拍中断有可能在C/OS-II启动第一个任务之前发生,此时C/OS-II是处在一种不确定的状态之中,用户应用程序有可能会崩溃。C/OS-II中的时钟节拍服务是通过在中断服务子程序中调用OSTimeTick()实现的。2.3.5 C/OS-II初始化与启动1、C/OS-II初始化在调用C/OS-II的任何其它服务之前,C/OS-II要求用户首先调用系统初始化函数OSIint()。OSIint()初始化C/OS-II所有的变量和数据结构。OSInit()建立空闲任务idle task,这个任务总是处于就绪态的。空闲任务OSTaskIdle()的优先级总是设成最低,即OS_LOWEST_PRIO。如果统计任务允许OS_TASK_STAT_EN和任务建立扩展允许都设为1,则OSInit()还得建立统计任务OSTaskStat()并且让其进入就绪态。OSTaskStat的优先级总是设为OS_LOWEST_PRIO-1。C/OS-II还初始化了5个空数据结构缓冲区。每个缓冲区都是单向链表,允许C/OS-II从缓冲区中迅速得到或释放一个缓冲区中的元素。调用OSInit()以后,任务控制块缓冲池中有OS_MAX_TASKS个任务控制块,事件控制块缓冲池中有OS_MAX_EVENTS个事件控制块,消息队列缓冲池OS_Q中有OS_MAX_QS个消息队列控制块,OS_FLAG_GRP缓冲池中有OS_MAX_FLAGS个标志控制块,最后。OS_MEM缓冲池中有OS_MAX_MEM_PART个存储控制块。每个空闲缓冲池以空指针结束。当然,如果所有列表中的指针全部指向NULL,缓冲池全空。缓冲池的容量在OS_CFG.H中定义。2、C/OS-II的启动多任务的启动是用户通过调用OSStart()实现的。然而,启动C/OS-之前,用户至少要建立一个应用任务,否则系统将直接进入空闲任务,或者在启动了统计任务的情况下进入统计任务,无法执行用户的应用程序。如清单2.5所示。程序清单 2.5 启动C/OS-IIvoid main (void) OSInit(); /* 初始化uC/OS-II */ . . 通过调用OSTaskCreate()或OSTaskCreateExt()创建至少一个任务; . . OSStart(); /* 开始多任务调度!OSStart()永远不会返回 */第三章 Keil Cx51基础知识3.1 Cx51程序设计基础3.1.1 标识符与关键字标识符用来标识源程序中某个对象的名字,可以是函数、变量、常量、数组、数据类型、存储方式或语句等。标识符由字符串、数字和下划线组成,第一个字符必须是字母或下划线。关键字是一类具有固定名称和特定含义的特殊标识符,又称为保留字。在编写程序时一般不允许将关键字另做他用。为了利用51单片机的许多特性,Cx51编译器增加了许多新的关键字,如表3-1所示。表3-1 Cx51增加的关键字atfarsbitalienidatasfrbdatainterruptsfr16bitlargesmallcodepdatataskcompactpriorityusingdatareentrantxdata3.1.2 基本语法及语句1、数据类型Cx51编译器不仅提供一些基本的数据类型,还支持标准C数据类型和51单片机平台独特的数据类型,如表3-2所示。表3-2 可用的数据类型数据类型位字节值范围bit101signed char81-128+127usigned char810255enum8/161/2-128+127或-32768+32767signed short162-32768+32767usigned short162065535signed int162-32768+32767usigned int162065535usigned long324-2147483648+2147483647unsigned long32404294967295float3241.175494E-383.402823E+38sbit 101sfr、sfr168/161、20255、0655352、常量常量在程序的执行过程中不能改变。常量的数据类型有: 整形常量 浮点型常量 字符型常量 字符串型常量3、变量及其存储模式在使用变量前,必须对其进行定义,用一个标识符作为变量名并指出它的数据类型和存储类型,以便编译系统为它分配相应的存储单元。在Cx51中,对变量进行定义的格式如下:存储种类 数据类型 存储器类型 变量名表:变量的存储种类有4种:自动型、外部型、静态型和寄存器型。定义变量时如果省略存储种类选项,则变量会是自动型变量。定义变量时除了需要说明其数据类型之外,Keil Cx51编译器还允许说明变量的存储器类型。在Cx51编译器命令行中使用SMALL、COMPACT和LARGE控制命令指定存储模式。4、用typedef重新定义数据类型在C语言程序中用户可以根据需要重新定义数据类型。重新定义是需使用关键字typedef,定义方法如下:typedef 已有的数据类型 新的数据类型名其中,“已有的数据类型”是指C语言中所有的数据类型,包括结构、指针和数组等,“新的数据类型名”可按用户自己的习惯或根据任务需要而定。关键字typedef的作用只是将C语言中已有的数据类型进行置换,因此可用置换后的新数据类型名定义变量。3.2 函数函数是C语言中的一种基本模块,实际上,C语言程序就是由若干个模块化的函数所构成的。在进行程序设计的过程中,如果所设计的程序较大,一般应将其分成若干个子程序模块,每个模块完成一种特定的功能。在C语言中,子程序是用函数来实现的。对于一些需要经常使用的子程序可以设计成一个专门的函数库,以供反复调用。此外,Keil Cx51编译器还提供了丰富的运行库函数,用户可以根据需要随时调用。这种模块化的程序设计方法,可以大大提升编程效率和速度。3.2.1 函数定义与调用1、函数定义从用户的角度来看,有两种函数标准库函数和用户自定义函数。标准库函数是Keil Cx51编译器提供的,不需要用户进行定义,可以直接调用。用户自定义函数是用户根据需要编写的能实现特定功能的函数,必须先进行定义,以后才能调用。函数的一般定义如下: 函数类型 函数名 (形式参数表) 形参说明 局部变量定义 函数体语句 “函数类型”说明了自定义函数返回值的类型。“函数名”是用标识符表示的自定义函数名字。“形式参数表”中列出的是在调用函数与被调用函数之间传递数据的形式参数,形式参数的类型必须加以说明。ANSI C标准允许在形式参数表中对形式参数的类型进行说明。如果定义的是无参函数,可以没有形式参数表,但圆括号不能省略。“局部变量定义”是对在函数内部使用的局部变量进行定义。“函数体语句”是为完成该函数的特定功能而设置的各种语句。如果定义函数时只给出一对花括号而不给出其局部变量和函数体语句,则该函数为“空函数”,这种函数也是合法的。进行C语言模块化程序设计时,各模块的功能可通过函数来实现。开始时只设计最基本的模块,其他作为扩充功能在以后需要时再加上。编写程序时可在将来准备扩充的地方写上一个空函数,这样可使程序的结构清晰,可读性好,而且容易扩充。2、函数调用(1)函数的调用形式所谓函数调用就是在一个函数体中引用另外一个已经定义了的函数,前者称为主调函数,后者称为被调函数。函数调用的一般形式为:函数名 (实际参数表)“函数名”指出被调用的函数。“实际参数表”中可以包含多哥实际参数,各个参数之间用逗号隔开。实际参数的作用是将它的值传递给被调函数中的形式参数。可以采用3种方式完成函数的调用。函数语句。在主调函数中将函数调用作为一条语句,它不要求被调用函数返回一个确定的值,只要求它完成一定的操作。函数表达式。在主调函数中将函数调用作为一个运算对象直接出现在表达式中,这种表达式称为函数表达式。这种函数调用方式要求被调函数返回一个确定的值。函数参数。在主调函数中将函数调用作为另一个函数调用的实际参数。以其返回值作为另一个函数调用的实际参数。这种在调用一个函数的过程中又调用了另外一个函数的方式,称为嵌套函数调用。在输出一个函数的值时经常采用这种方法。(2)对被调用函数的说明在调用函数之前(包括标准库函数),必须对该函数的类型进行说明,即“先说明,后调用”。如果调用的是库函数,一般应在程序的开始出用预处理命令#include将有关函数说明的头文件包含进来。如果调用的是用户自定义函数,而且该函数与调用它的主调函数在同一个文件中,一般应该在主调函数中对被调用函数的类型进行说明。函数说明的一般形式为: 类型标识符 被调用的函数名(形式参数表)其中,“类型标识符”说明了函数返回值的类型。“形式参数表”中说明了各个形式参数的类型。C语言程序中不允许在函数定义的内部包括另一个函数的定义,即不允许嵌套函数定义。但是,C语言允许在调用函数的过程中包含另一个函数调用。(3)函数的参数和函数的返回值通常在进行函数调用时,主调函数与被调函数之间具有数据传递关系。这种数据传递是通过函数的参数来实现的。在定义一个函数时,位于函数名后面圆括号中的变量称为“形式参数”。而在调用函数时,函数名后面括号中的表达式称为“实际参数”。形式参数在未发生函数调用之前,不占用内存单元,因而也是没有值的。只有在发生函数调用时它才被分配内存单元,同时获得从主调函数中传递过来的实际参数值。函数调用结束后,它所占用的内存单元也被释放。(4)实际参数的传递方式在进行函数调用时,必须用主调函数中的实际参数来替换被调函数中的形式参数,这就是所谓的参数传递。在C语言中,对于不同类型的实际参数,有3种不同的参数传递方式: 基本类型的实际参数传递 数组类型的实际参数传递 指针类型的实际参数传递3.2.2 函数的递归调用与再入函数在调用一个函数的过程中,间接或直接地调用该函数本身称为函数的递归调用。再入函数是一种可以在函数体内直接或间接调用其自身的函数,显然再入函数是可以进行递归调用的。Keil中的函数递归调用可分为两种情况,一种是普通函数递归,调用时,新调用函数的程序储存空间覆盖原来的相同函数调用的程序储存空间,使得原来的局部变量消失了;还有一种是再入函数(用reentrant说明)的递归,每次递归,Keil为再入函数生成一个模拟栈,再入函数参数和局部变量被放在这模拟栈中,这样使得原来调用函数的局部变量就没有消失了,而新的调用函数参数和局部变量又可以继续。Keil Cx51编译器采用扩展关键字reentrant作为定义函数时的选项,要将函数定义为再入函数,只要在函数后面加上关键字reentrant即可。如下所示: 函数类型 函数名 (形式参数表) reentrant再入函数可被递归调用,无论何时,包括中断服务函数在内的任何函数都可调用再入函数。与非再入函数的参数递归和局部变量的存储分配方法不同,Cx51编译器为再入函数生成一个模拟战,通过这个模拟栈来完成参数传递和存放局部变量。模拟栈所在的存储空间根据载入函数存储器模式不同,可以是DATA、PDATA或XDATA存储器空间。当程序中包含有多种存储器模式的再入函数时,Cx51编译器为每种模式单独建立一个模拟栈并独立管理各自的栈指针。使用再入函数注意事项: 再入函数不能传送bit类型的参数,函数内部也不能定义局部位变量,不能有位操作。总之与位有关的定义和操作在再入函数中都不能实现。同一程序中可以有不同储存模式的再入函数,但是注意,任意模式的再入函数不能调用不同储存模式的再入函数,但可以调用不同储存模式的非再入函数。参数传递上,实际参数可以传递给间接调用的再入函数;非再入函数不能包含调用参数,因为那样会覆盖了原来的参数;但是,可以用全局变量来进行参数传递。第四章 C/OS-II移植基础知识移植就是使C/OS-II能在VRS51上运行。为了方便移植,大部分的C/OS-II的代码是用C语言编写的;但是仍需要用C语言和汇编语言编写一些处理器硬件相关的代码,这是因为C/OS-II在读/写处理器寄存器时,只能通过汇编语言来实现。由于C/OS-II在设计时就已经充分考虑了可移植性,所以C/OS-II的移植相对来说是比较容易的。4.1 C/OS-II源文件移植在了解了P89V51RD2微处理器和Keil C51 编译器的技术细节的基础上,就可以开始C/OS-II源文件移植的工作了。真正编写移植代码的工作就相对比较简单了。要使C/OS-II正常运行,必须满足一下要求:(1)处理器的C编译器能产生可重入型代码。(2)用C语言就可以打开和关闭中断。(3)处理器支持中断,并且能产生定时中断(通常频率在10至100Hz之间)。(4)处理器能支持容纳一定量的数据存储硬件堆栈(可能是几千字节)。(5)处理器有将堆栈指针和其他CPU寄存器的内容读出并存储到堆栈或内存中的指令。MCS-51与KeilCx51编译器可以满足以上条件,可以将C/OS-II移植到MCS-51系列处理器。需要说明一点,目前C/OS-II的版本较多,但基本都一致,兼容性也很好,本例采用的是C/OS-II V2.52版。C/OS-II的移植包括以下几个部分:1、设置与编译器有关的代码OS_CPU.H在差异的处理器中有差异的字长,所以必须界说一系列数据范例以确保移植的准确性。另外,在C/OS-II中,不使用C的short、int和long等数据范例,这些都是和编译器相干的。下面即是C/OS-II界说的一部分数据范例:typedef unsigned char BOOLEAN;typedef unsigned char INT8U; /*无标志8位整数 */typedef signed char INT8S; /*有标志8位整数 */typedef unsigned int INT16U; /*无标志16位整数 */typedef signed int INT16S; /*有标志16位整数 */typedef unsigned long INT32U; /*无标志32位整数 */typedef signed long INT32S; /*有标志32位整数 */typedef float FP32; /*单精度浮点数 */typedef double FP64; /*双精度浮点数 */首先来看对临界段的处理,就是关中断,处理完毕后在开中断。C/OS-II提供了3种方法来处理,针对MCS-51单片机,可以使用方法1来处理临界段。在MCS-51系列单片机中,中断允许寄存器IE的第7位EA为中断允许控制为,EA=0屏蔽所有中断、EA=1允许所有中断。MCS-51堆栈从低地址往高地址增长(1=向下,0=向上),因此将OS_STK_GROWTH定义为0。OS_TASK_SW()是一个宏,在C/OS-II从低优先级任务切换到高优先级任务是被调用。C/OS-II假定任务切换时靠中断级代码完成的,或者说C/OS-II的任务切换时靠模仿中断动作来完成的。C/OS-II需要一条处理器指令,使其行为就像是硬件中断。MCS-51没有软中断指令,在这种情况下,需要将堆栈结构设置成与中断堆栈结构一样,在用函数调用的方式来实现任务切换,也就是说,通过函数来模仿软中断指令。#defineOS_TASK_SW()OSCtxSw()2、用C语言编写6个与操作体系有关的函数OS_CPU_C.C这10个函数是:OSTaskStkInit( )、OSTaskCreatHook( )、OSTaskDelHook( )、OSTaskSwHook( )、OSTaskStatHook( )、OSTaskIdleHook( )、OSTimeTickHook( )、OSInitHookBegin( )、OSInitHookEnd( )和OSTCBInitHook( )。这10个函数只对OSTaskStkInit( )编写代码,后9个函数必须声明,但是内部并没有代码。在对堆栈设计时需要考虑一下因素: 传统的8051处理器在中断来临时只将程序计数器PC的值压入堆栈。 按照C/OS-II的要求,保存全部寄存器,MCS-51的寄存器有PSW、ACC、B、DPL、DPH、R0-R7和SP。 Cx51编译器允许用CPU寄存器传递3个参数。 堆栈从低地址向高地址增长。 堆栈指针指向上次入栈地址。 MCS-51存在系统栈。 系统栈深度为256字节。因为需要进行任务栈与系统栈的复制,获得系统栈的起始地址,所以需要对系统进行一些定义。首先,堆栈起点由Keil决定,只关心大小,然后通过OSStack获得keil分配的SP起点。下面的代码就是相关的汇编代码,可以放在启动代码中,也可以放在相关的文件中。?STACKSEGMENTIDATARSEG?STACKOSStack: DS 40H OSStkStart IDATA OSStack-1系统堆栈存储空间大小=SP-OSStkSart,便可以得到长度。任务切换时可以计算出得出,所以不必保存SP的内容。为了函数重入,形参和局部变量必须保存在堆栈里。MCS-51硬件堆栈太小,Keil将根据内存模式在相应内存空间仿真堆栈,增长方向由上向下,与硬件栈相反。对于大模式编译,函数返回地址保存在硬件堆栈里,形参和局部变量放在仿真堆栈中,仿真堆栈指针为?C_XBP,对MCS-51要使用大模式编译。3、编写4个汇编语言函数OS_CPU_A.SC/OS-II的移植实例要求用户编写4个简略的汇编语言函数:OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()、OSTickISR()。4.2 硬件平台构成与编译器的选择由于VRS51是一款80C51微控制器,片内包含了64KB的FLASH程序存储器,并且支持串行在线编程(ISP)。使它在ROM 空间上很适合做C/OS-II的移植。由于C/OS-II绝大部分代码是用标准的C语言编写的,所以C语言开发工具对于C/OS-II是必不可少的。由于C/OS-II是一个可剥夺行的占先式内核,所以要求C编译器可以产生可重入型代码。所以选择Keil C51集成开发环境作为开发工具。该开发工

温馨提示

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

评论

0/150

提交评论