μCOSII在基于51微控制器上的移植研究Word格式文档下载.docx
- 文档编号:22654187
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:39
- 大小:112.83KB
μCOSII在基于51微控制器上的移植研究Word格式文档下载.docx
《μCOSII在基于51微控制器上的移植研究Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《μCOSII在基于51微控制器上的移植研究Word格式文档下载.docx(39页珍藏版)》请在冰豆网上搜索。
5.3.1汇编文件头部定义23
5.3.2修改OSStartHighRdy()函数25
5.3.3修改OSCtxSW()函数25
5.3.4OSIntCtxSW()函数26
5.3.5OSTickISR()函数26
5.4定时器初始值设置27
第六章实验及其结果分析28
6.1实验的条件和指导思想28
6.2实验的过程和结果28
6.3对实验结果的分析和讨论29
参考文献30
致谢31
第一章绪论
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,微软公司的WindowsCE,QNX公司的QNXOS,在手持设备嵌入式操作系统中三分天下的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-II
2、μC/OS-II内核分析与系统分析
3、KeilCx51基础知识
4、μC/OS-II移植的基础知识
5、在51系列单片机上移植μC/OS-II
可行性分析:
1、μC/OS-II源码开放
2、KeilCx51编译器和51控制器满足μC/OS-II运行要求:
①处理器的C编译器能产生可重入型代码。
②用C语言就可以打开和关闭中断。
③处理器支持中断,并且能产生定时中断(频率通常在10至100Hz之间)。
④处理器能支持容纳一定量的数据存储硬件堆栈(可能是几千字节)。
⑤处理器有将堆栈指针和其他CPU寄存器的内容读出并存储到堆栈或内存中的指令。
第二章μC/OS-II简介
2.1μC/OS-II的产生背景
μC/OS-II是由JeanJ.Labrosse于1992年编写的一个嵌入式多任务实时操作系统。
最早这个系统叫做μC/OS,后来经过近10年的应用和修改,在1999年JeanJ.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语言编写的,只有极少部分和处理器密切相关的代码是用汇编语言编写的,所以用户只要做很少的工作就可以把它移植到各类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)。
可剪裁性是靠条件编译实现的,只要在用户的程序中(用#defineconstants语句)定义哪些μ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在一个航空项目中得到了美国联邦航空管理局对用于商用飞机的、符合RTCADO-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.C
OS_CORE.C
OS_SEM.C
OS_FLAG.COS_TASK.C
OS_MBOX.COS_TIME.C
OS_MEM.C
OS_MUTEX.C
μC/OS-II.H
μC/OS-II.C
μC/OS-II与应用程序相关的代码
OS_CHG.H
INCLUDES.H
μC/OS-II与处理器相关的代码
(移植时需要修改)
OS_CPU.H
OS_CPU_A.ASMOS_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任务的形式
voidYourTask(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,是按以下规则给出的:
当OSRdyTbl[0]中的任何一位是1时,OSRdyGrp的第0位置1,
当OSRdyTbl[1]中的任何一位是1时,OSRdyGrp的第1位置1,
当OSRdyTbl[2]中的任何一位是1时,OSRdyGrp的第2位置1,
当OSRdyTbl[3]中的任何一位是1时,OSRdyGrp的第3位置1,
当OSRdyTbl[4]中的任何一位是1时,OSRdyGrp的第4位置1,
当OSRdyTbl[5]中的任何一位是1时,OSRdyGrp的第5位置1,
当OSRdyTbl[6]中的任何一位是1时,OSRdyGrp的第6位置1,
当OSRdyTbl[7]中的任何一位是1时,OSRdyGrp的第7位置1,
图2-3μC/OS-II就绪表
4、任务调度
任务的调度属于实时操作系统的核心功能,在μC/OS-II中,通过调度器(Scheduler)确定哪个任务优先级最高,该哪个任务运行。
任务级的调度由函数OSSched()完成,中断级的调度由函数OSIntExit()完成。
OSSched()如程序清单2.2所示。
程序清单2.2任务调度器
voidOSSched(void)
#ifOS_CRITICAL_METHOD==3
OS_CPU_SRcpu_sr
#endif
INT8Uy;
OS_ENTER_CRITICAL();
if((OSLockNesting|OSIntNesting)==0){
y=OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy=(INT8U)((y<
<
3)+OSUnMapTbl[OSRdyTbl[y]]);
if(OSPrioHighRdy!
=OSPrioCur){
OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
OS_TASK_SW();
OS_EXIT_CRITICAL();
5、空闲任务
μC/OS-II会自动建立一个空闲任务,在没有其它任务进入就绪态时投入运行。
这个空闲任务OSTaskIdle()永远设为最低优先级,即OS_LOWEST_PRI0。
空闲任务由系统建立,也不可能被应用软件删除。
空闲任务会不停地给一个32位的名叫OSIdleCtr的计数器加1,用于确定空闲任务所消耗的CPU时间。
因为有的CPU完成加1需要多条指令,为了避免被高优先级任务或中断服务子程序打断,OSIdleCtr++按临界段代码处理。
完成加1后调用OSTaskIdleHook(),可以在这个函数中写入任何用户代码,例如使CPU进入省电模式。
因为空闲任务是永远处于就绪态的,所以不要在OSTaskIdleHook()中调用任何可以使得任务挂起的函数。
程序清单2.3是空闲任务的代码
程序清单2.3空闲任务
voidOSTaskIdle(void*pdata)
OS_CPU_SRcpu_sr
pdata=pdata;
OSIdleCtr++;
OS_EXIT_CRITICAL();
6、统计任务
μC/OS-II有一个提供运行时间统计的任务。
这个任务叫做OSTaskStat(),如果用户将系统定义常数OS_TASK_STAT_EN(见文件OS_CFG.H)设为1,这个任务就会建立。
一旦得到了允许,OSTaskStat()每秒钟运行一次(见文件OS_CORE.C),计算当前的CPU利用率。
换句话说,OSTaskStat()告诉用户应用程序使用了多少CPU时间,用百分比表示,这个值放在一个有符号8位整数OSCPUsage中,精读度是1个百分点。
如果用户应用程序打算使用统计任务,用户必须在初始化时建立一个唯一的任务,在这个任务中调用OSStatInit()。
换句话说,在调用系统启动函数OSStart()之前,用户初始代码必须先建立一个任务,在这个任务中调用系统统计初始化函数OSStatInit(),然后再建立应用程序中的其它任务。
2.3.3调度器上锁、开锁
调用函数OSSchedlock()可以给调度器上锁,禁止任务调度。
调用函数OSSchedUnlock()给调度器开锁,禁允许任务调度。
调用函数OSSchedlock()保持对CPU的控制权,不管是否有优先级更高的任务进入了就绪态。
知道该任务完成后调用开锁函数OSSchedUnlock()为止。
然而,此时中断是可以被识别的,中断服务也能得到。
函数OSSchedlock()和OSSchedUnlock()的使用要非常谨慎,因为它们影响μC/OS-II对任务的正常管理,OSSchedlock()和OSSchedUnlock()必须成对使用。
变量OSLockNesting跟踪OSSchedLock()函数被调用的次数,以允许嵌套的函数包含临界段代码,这段代码其它任务不得干预。
μC/OS-II允许嵌套深度达255层。
当OSLockNesting等于零时,调度重新得到允许,当OSLockNesting减到零的时候,OSSchedUnlock()调用OSSched()。
OSSchedUnlock()是被某任务调用的,在调度器上锁的期间,可能有什么事件发生了并使一个更高优先级的任务进入就绪态。
调度器上了锁后任何其它任务都不能运行。
所以调用OSSchedLock()以后,用户的应用程序不得使用任何能将现行任务挂起的系统调用,如OSMboxPend()、OSQPend()、OSSemPend()等,直到OSLockNesting回零为止。
当低优先级的任务要发消息给多任务的邮箱、消息队列、信号量时,用户不希望高优先级的任务在邮箱、队列和信号量没有得到消息之前就取得了CPU的控制权,此时,可以给调度器上锁。
2.3.4μC/OS-II中的中断与时钟节拍
1、μC/OS-II中断
在μC/OS-II中,中断服务子程序运行结束后,系统将会根据情况进行一次中断级的任务调度去运行优先级别最高的就绪任务,而并不一定要接续运行被中断的任务。
μC/OS-II的中断允许嵌套,用全局变量OSIntNesting来记录中断的嵌套数。
μC/OS-II的中断服务程序的工作通常是由中断激活的一个任务来完成的。
这样做的优点是可以使应用程序的设计更为灵活。
在任务中可以用设置临界区的方法来屏蔽中断。
设置临界区的宏有三种实现方法。
中断服务子程序的是一码如程序清单2.4所示。
程序清单2.4中断服务
保存全部CPU寄存器;
调用OSIntEnter()或OSIntNesting直接加1;
if(OSIntNesting==1){
OSTCBCur->
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()建立空闲任务idletask,这个任务总是处于就绪态的。
空闲任务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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- COSII 基于 51 控制器 移植 研究