嵌入式实时操作系统内核分析解读_第1页
嵌入式实时操作系统内核分析解读_第2页
嵌入式实时操作系统内核分析解读_第3页
嵌入式实时操作系统内核分析解读_第4页
嵌入式实时操作系统内核分析解读_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

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

文档简介

1、关于对UC/OS-II嵌入式实时操作系统内核分析一、uc/os-n概述1、uc/os-n的基本概念UC/OS是源码公开的实时嵌入式操作系统,具有源代码开放、内核小、实时性好的突出优点,能够被移植到各种微处理器和微控制器上。我们今天所分析的HC/os-n实时操作系统内核正是建立在Uc/os的基础之上的。uc/os-n是典型的微内核实时操作系统。它提供了任务调度、任务管理、时间管理和任务间的通信等基本功能。与一般通用的操作系统相比,嵌入式实时操作系统既具有通用操作系统的基本特点,又具有系统实时性、硬件的相关依赖性、软件固态化以及应用的专用性等特点。嵌入式实时操作系统通常包括与硬件相关的底层驱动软件

2、、系统内核、设备驱动接口、通信协议、图形界面、标准化浏览器Browser等。评价嵌入式操作系统的重要指标有实时性、可裁剪性、可扩展性。2、uc/os-n的基本性能特点公开源代码、可移植性好、可固化、可裁剪、抢占式实时内核、多任务管理、函数调用和系统服务的执行时间是确定的、每个任务有自己单独的栈、提供多系统服务和中断请求可使正执行任务暂时挂起等多个优点。二、任务管理1、任务的工作状态任务是HC/OS-II中最重要的概念之一。它也被称作为一个线程为一个简单的程序,该程序可以认为CPU完全只属于该程序。每个任务都被赋予一定的优先级,有着自己的一套CPU寄存器和栈空间。如下图:一个任务通常是一个无限的

3、循环。uC/OS-n可以管理多达64个任务,但由于其两个任务被系统占用,并保留了优先级为0、1、2、3、()S_L0WEST_PRI0-3、0S_L0WEST_PRI0-2.()S_L()WEST_PRIO-1以及()S_LOWEST_PRI()这八个任务供将来使用。因此用户可以使用的有56个应用任务。每个任务都有不同的优先级,一般来说,任务的优先级号越低,任务的优先级越高。UC/OS-II总是先运行进入就绪态的优先级最高的任务。下图所示为任务所处的可能的5种状态。在任一时刻,任务的状态一定是这5种状态之一。如下图:等待消息挂起时间到收到消息2、任务调度任务调度是实时内核最重要的工作之一,uc

4、/os-n是抢占式实时多任务内核,采用基于优先级的任务调度。uc/os-n的任务调度包括任务级的任务调度和中断级的任务调度,所采用的调度算法是相同的。任务级的调度是函数()SSched()完成的,中断级的任务调度则由函数OSIntExt()完成。其中函数OSSched()的内容如下:VoidOSSched(void)(INT8Uy;OS_ENTER_CRITICAL();if(OSLockNestinglOSIntNesting)=0)(y=OSUnMapTblOSRdyGrp;OSPriolIighRdy=(INT8U)(y«3)+OSUnMapTblOSRdyTbly;if(OS

5、Priol!ighRdy!=0SPrioCur)(OSTCBl1ighRdy=()STCBPrioTb1OSPriolIighRdy;()SCtxSwCtr+;OS_TASK_SW();)OS_EXET_CRITICAL();)从上面的程序中可以了解到为了避免在调度过程中被中断,在OSSched()开始时,首先调用了OS_ENTER_CRITICAL()关中断,然后判断任务调度器是否上锁或调用是否来自中断服务子程序,如果不是,则开始任务调度。如下图所示:为一个任务就绪表。任务就绪表的示宣图态:任务就绪登记与注销00011101pno=29D7 De D5 D, D3 D D D0OSRdyGi

6、p I =OSMapTblpno»3;VXOSRdyTblpno»3| = OSMapTblpno&0x07;1OSRdyGrpOSRdyTbl3 Dr De D$ D4D3 D? D D0» De D$ Dq D3 D D D01下图便是一个相关例子,把prio为29的任务设置在任务就绪状把pno为29的任务置为就绪状态从任务就绪表中获取优先级别最高的就绪任务可用如下类似的代码:y=OSUnMapTalOSRdyGrp;/D5>D4、D3位x=OSUnMapTalOSRdyTblty;/D2,6、Do位prio=(y«3)+x;优先级别或

7、y=OSUnMapTblOSRdyGrp;prio=(INT8U)(y«3)+OSUnMapTblOSRdyTbly);3、uc/os-n的初始化uC/()S-n要求用户首先调用系统初始化函数OSIintO,对uc/os-n所有的变量和数据结构进行初始化,然后调用函数OSTaskCreate()或OSTaskCreateExt()建立用户任务,最后通过调用OSStartO函数启动多任务。Voidmain(void)(OSInitO;通过调用函数OSTaskCreate()或OSTaskCreateExt()创建至少一个任务;OSStart();/*开始调用调度!OSStart()永远

8、不会返回*/当调用OSStartO函数时,OSStartO函数从任务就绪表中找出用户建立的优先级最高任务的控制块。然后,OSStartO函数调用高优先级就绪任务启动函数OS先artHighRdyO。这个函数的任务是把任务栈中的任务状态参数值恢复到CPU寄存器中,然后执行一条中断返回指令,中断返回指令强制执行该任务代码。其代码如下:voidOSStart(void)(INT8Uy;INT8Ux;if(OSRunning=FALSE)(y=OSUnMapTblOSRdyGrp;x=OSUnMapTblOSRdyTbly;OSPrioIIighRdy=(INT8U)(y«3)+x);OSP

9、rioCur=OSPriollighRdy;OSTCBHighRdy=OSTCBPrioTblOSPrioIIighRdy;OSTCBCur=OSTCBHighRdy;OSStartllighRdy();4、任务的创建应用程序通过调用OSTaskCreate()函数来创建一个任务,OSTaskCreate()函数的原型如下:INT8UOSTaskCreate(void(*task)(void*pd),指向任务的指针void*pdata,传递给任务的参数OS_STK*ptos,指向任务堆栈栈顶的指针INT8Uprio任务的优先级)INT8UOSTaskCreate(void(*task)(voi

10、d*pd),void*pdata,OS_STK*ptos,INT8Uprio)(OS_STK*psp;初始化任务堆栈指针变量,返回新的栈顶指针INT8Uerr;定义(获得并定义初始化任务控制块)是否成功#if()S_ARG_C11K_EN>0所有参数必须在指定的参数内if(prio>OS_LOWEST_PRIO)检查任务优先级是否合法return(OS_PRIO_INVALID);参数指定的优先级大于OS_LOWEST_PRI()ttendifOS_ENTER_CRITICAL0;关闭中断if(OSTCBPrioTbltprio=(OS_TCB*)0)确认优先级未被使用,即就绪态为

11、oOSTCBPrioTbltprio=(0S_TCB*)1;保留这个优先级,将就绪态设为1OS_EXIT_CRITICAL();打开中断psp=(OS_STK*)OSTaskStklnit(task,pdata,ptos,0);/初始化任务堆栈err=OS_TCBInit(prio,psp,(0S_STK*)0,0,0,(void*)0,0);获得并初始化任务控制块if(err=()S_N0_ERR)任务控制初始化成功!OS_ENTER_CRITICAL0;关闭中断0STaskCtr+;任务计数器加1OS_EXIT_CRITICAL();打开中断if(OSRunning=TRUE)检查是否有(

12、某个)任务在运行(0S_Sched();任务调度,最高任务优先级运行)else否则,任务初始化失败OS_ENTER_CRITICAL0;关闭中断OSTCBPrioTbHprio=(0S_TCB*)0;放弃任务,设此任务就绪态为0OS_EXIT_CRITICAL();打开中断ireturn(err);返回(获得并定义初始化任务控制块是否成功)OS_EXIT_CRITICAL();打开中断return(0S_PRI0_EXIST);返回(具有该优先级的任务已经存在)三、中断和时间管理1、中断处理uc/os-n系统响应中断的过程为:系统接收到中断请求后,这时如果CPU处于中断允许状态(即中断是开放的

13、),系统就会中止正在运行的当前任务,而按照中断向量的指向转而去运行中断服务子程序,当中断服务子程序的运行结束后,系统将会根据情况返回到被中止的任务继续运行或者转向运行另一个具有更高优先级别的就绪任务。中断服务子程序运行结束之后,系统将会根据情况进行一次任务调度去运行优先级别最高的就绪任务,而并不是一定要接续运行被中断的任务的。中断嵌套层数计数器和锁定嵌套计数器OSLockNesting二者都必须是零,OSRdyTbl所需的检索值Y是保存在全程变量OSIntExitY中检查具有最高优先级别的就绪任务的优先级是否是正在运行的任务的优先级,将任务控制块优先级表保存到指向最高级优先级就绪任务控制块的指

14、针,上下文切换的次数统计任务计数器。做中断任务切换:voidOSIntEnter(void)if(OSRunning=TRUE)if(OSIntNesting<255)()SIntNesting+;中断嵌套层数计数器加一2、时间管理UC/OS-II需要用户提供周期性信号源,用于实现时间延时和确认超时。节拍率应在每秒10700次之间。时钟节拍率越高,系统的额外负荷就越重。时钟节拍是一种特殊的中断,UC/OS-II中的时钟节拍服务是在通过在中断服务子程序中调用OSTimeTickO函数实现的。时钟节拍的中断服务子程序如下所示:VoidOSTicklSR(void)(保存处理器寄存器的值;调用

15、OSIntEnter()或将OSIntNesting加1;调用OSTimeTickO;/*检查每个任务的时间延时*/调用OSIntExitO;恢复处理器寄存器的值;执行中断返回指令;)其中时钟节拍函数OSTimeTickO的主要工作是给每个任务控制块()S_TCB中的时间延时项OSTCBDly减1。当某任务的任务模块中的延时项OSTCBDly减为0,则该任务将进入就绪任务表。因此,OSTimeTickO的执行时间与应用程序中建立了多少任务有关。四、任务之间的通信与同步1、任务互斥和同步系统中的多个任务在运行时,经常需要互相无冲突地访问同一个共享资源,或者需要互相支持和依赖,甚至有时还要互相加以

16、必要的限制和制约,才保证任务的顺利运行。因此,操作系统必须具有对任务的运行进行协调的能力,从而使任务之间可以无冲突、流畅地同步运行,而不致导致灾难性的后果。与人们依靠通信来互相沟通,从而使人际关系和谐、工作顺利的做法一样,计算机系统是依靠任务之间的良好通信来保证任务与任务的同步的。有以下3种方法可以解决任务的互斥。(1)关闭中断法当一个任务进入临界区后,首先关中断,然后就可以去访问共享资源。当它从临界区推出后,再把中断打开。关闭中断法虽然简单有效,但也有明显的缺点。首先,中断关闭后,如果后面由于种种原因不能再及时打开,那么整个系统就有可能崩溃。其次,关闭中断后,所有的任务将被阻止,无法获得运行

17、的机会。因此,关闭中断法不能作为一种普遍使用的互斥实现方法。(2)繁忙等待法当一个任务进入临界区时,首先检查一下是否允许进入,若允许,就直接进入;若不允许,就在那里循环地等待。繁忙等待法的缺点是要不断地执行测试指令,会浪费大量的CPU时间。(3)信号量法信号量是一种约定机制,在多任务内核中将信号量用于:控制共享资源的使用权,标志某事件的发生,使两个任务的行为同步。信号量是由操作系统维护,任务不能直接修改它的值,只能通过初始化和两个标准原语来对它进行访问。2、任务间的通信任务间的同步依赖于任务间的通信。在UC/OS-II中,是使用信号量、邮箱(消息邮箱)和消息队列这些被称作事件的中间环节来实现任

18、务之间的通信的。把一个任务置于等待状态要调用()S_EventTaskWait()函数。该函数的原型为:voidOS_EventTaskWait()S_EVENT*Pevent事件控制块的指针);函数OS_EventTaskWait(),将在任务调用函数OSXXXPend()请求一个事件时,被()SXXXPend()所调用。如果一个正在等待的任务具备了可以运行的条件,那么就要使它进入就绪状态。这时要调用OS_EventTaskRdy()函数。该函数的作用就是把调用这个函数的任务在任务等待表中的位置清0(解除等待状态)后,再把任务在任务就绪表中对应的位置1,然后引发一次任务调度。OS_Event

19、TaskRdy()函数的原型为:INT8UOS_EventTaskRdy(OS_EVENT*Pevent,事件控制块的指针void*msg,未使用INT8Umsk清除TCB状态标志掩码);函数OS_EventTaskRdy()将在任务调用函数OSXXXPost()发送一个事件时,被函数OSXXXPost()所调用。如果一个正在等待事件的任务已经超过了等待的时间,却仍因为没有获取事件等原因而未具备可以运行的条件,却又要使它进入就绪状态,这时要调用()S_EventT()()函数。0S_EventT0()函数的原型为:void()S_EventT0(OS_EVENT*pevent事件控制块的指针)

20、;函数()S_EventT0()将在任务调用OSXXXPend()请求一个事件时,被函数OSXXXPend()所调用。3、信号量实例如下为一个信号量法控制任务之间调用的例子:在使用信号量之前,应用程序必须调用函数()SSemCreate()来创建一个信号量,OSSemCreat号)的原型为:OS_EVENT*()SSemCreate(INT16Uent信号量计数器初值);函数的返回值为已创建的信号量的指针。任务通过调用函数OSSemPend()请求信号量,函数OSSemPend()的原型如下:voidOSSemPend()S_EVENT*pevent,信号量的指针INT16Utimeout,等

21、待时限INT8U*err);错误信息参数pevent是被请求信号量的指针。为防止任务因得不到信号量而处于长期的等待状态,函数OSSemPend允许用参数timeout设置一个等待时间的限制,当任务等待的时间超过timeout时可以结束等待状态而进入就绪状态。如果参数timeout被设置为0,则表明任务的等待时间为无限长。任务获得信号量,并在访问共享资源结束以后,必须要释放信号量,释放信号量也叫做发送信号量,发送信号量需调用函数OSSemPost()oOSSemPost()函数在对信号量的计数器操作之前,首先要检查是否还有等待该信号量的任务。如果没有,就把信号量计数器OSEventCnt加一;如

22、果有,则调用调度器()S_Sched()去运行等待任务中优先级别最高的任务。函数OSSemPost()的原型为:INT8UOSSemPost()S_EVENT*pevent信号量的指针);调用函数成功后,函数返回值为()S_ON_ERR,否则会根据具体错误返回OS_ERR_EVENT_TYPE,0S_SEM_0VFo应用程序如果不需要某个信号量了,那么可以调用函数OSSemDel()来删除该信号量,这个函数的原型为:OS_EVENT*()SSemDel(OS_EVENT*pevent,信号量的指针INT8Uopt,删除条件选项INT8U*err错误信息任务3等待的事件痴监:丁一一一 一一一 一

23、一 一一|任务C使用共享资源任务A因优先级别 : 高于任务C而运行 !:任务B等待:L的事件来临;任务C因任务A获得 i CFU而等待21j在沏泅在络A等待 1信号量面继续运沅一r'lTTjA-Ertt 刘I E移放信号量而等待 1一一一一一一一I任务R因优先级别;高于任务C而运行;:任务C因任务E获得 :CPU而等待任务b (中)任务c (低)任务C获得信号量一,3CPU而运行任务C释放 信号量任务A (高)任务A申请 信号量、任务A因任务C置放 了信号员而运行任务A获得信号量任务优先级反4专示意图通过例子可以发现,使用信号量的任务是否能够运行是受任务的优先级别和是否占用信号量两个条

24、件约束的,而信号量的约束高于优先级别的约束。于是当出现低优先级别的任务与高优先级别的任务使用同一个信号量,而系统中还存有别的中等优先级别的任务时,如果低优先级别的任务先获得了信号量,就会使高级别的任务处于等待状态,而那些不使用该信号量的中等级别的任务却可以剥夺低优先级别的任务的CPU使用权而先于高优先级别的任务而运行了。我们可以使获得信号量任务的优先级别在使用共享资源期间暂时提升到所有任务最高优先级的高一个级别上,以使该任务不被其他的任务所打断,从而能尽快地使用完共享资源并释放信号量,然后在释放了信号量之后再恢复该任务原来的优先级别。4、邮箱创建邮箱需要调用函数OSMboxCreate(),这

25、个函数的原型为:OS_EVENT*OSMboxCreate(void*msg消息指针);函数中的参数msg为消息的指针,函数的返回值为消息邮箱的指针。调用函数OSMboxCreate()需先定义msg的初始值。在一般的情况下,这个初始值为NULL;但也可以事先定义一个邮箱,然后把这个邮箱的指针作为参数传递到函数OSMboxCreate()中,使之一开始就指向一个邮箱。任务可以通过调用函数OSMboxPost()向消息邮箱发送消息,这个函数的原型为:INT8UOSMboxPost(OS_EVENT*pevent,消息邮箱指针void *msg消息指针当一个任务请求邮箱时需要调用函数OSMboxP

26、end(),这个函数的主要作用就是查看邮箱指针OSEventPtr是否为NULL,如果不是NULL就把邮箱中的消息指针返回给调用函数的任务,同时用()S_NO_ERR通过函数的参数err通知任务获取消息成功;如果邮箱指针OSEventPtr是NULL,则使任务进入等待状态,并引发一次任务调度。函数OSMboxPend()的原型为:void*()SMboxPend(OS_EVENT*pevent,请求消息邮箱指针INT16Utimeout,等待时限INT8U*err错误信息);5、消息队列使用消息队列可以在任务之间传递多条消息。消息队列由三个部分组成:事件控制块、消息队列和消息。当把事件控制块成

27、员OSEventType的值置为()S_EVENT_TYPE_Q时,该事件控制块描述的就是一个消息队列。消息队列相当于一个共用一个任务等待列表的消息邮箱数组,事件控制块成员OSEventPtr指向了一个叫做队列控制块(OS_Q)的结构,该结构管理了一个数组MsgTbl,该数组中的元素都是一些指向消息的指针。创建一个消息队列首先需要定义一指针数组,然后把各个消息数据缓冲区的首地址存入这个数组中,然后再调用函数OSQCreate()来创建消息队列。创建消息队列函数OSQCreate()的原型为:()S_EVENTOSQCreate(void*start,指针数组的地址INT16Usize数组长度)

28、;请求消息队列的目的是为了从消息队列中获取消息。任务请求消息队列需要调用函数()SQPend(),该函数的原型为:void*OSQPend()S_EVENT*pevent,所请求的消息队列的指针INT16Utimeout,等待时限INT8U*err错误信息);任务需要通过调用函数OSQPost()或OSQPostFront()来向消息队列发送消息。函数OSQPost()以FIFO(先进先出)的方式组织消息队列,函数OSQPostFront。以LIFO(后进先出)的方式组织消息队列。这两个函数的原型分别为:INT8UOSQPost()S_EVENT*pevent,消息队列的指针消息指针void*

29、msg和INT8UOSQPost()S_EVENT*pevent,消息队列的指针void*msg消息指针);函数中的参数msg为待发消息的指针。五、RC/OS-II的移植分析1、移植所谓移植,是指一个操作系统可以在某个微处理器或者微控制器上运行。虽然uC/OS-II的大部分源代码是用C语言写成的,仍需要用C语言和汇编语言完成一些与处理器相关的代码。2、产生可重入代码可重入代码指的是一段代码可以被多个任务同时调用,而不必担心会破坏数据。也就是说,可重入型函数在任何时刻都可以被中断执行,过一段时间以后又可以继续运行,而不会因为在函数中断时被其它的任务重新调用,影响函数中的数据。如下为一个可重入型函

30、数Voidswap(int*x,int*y)Inttemp;temp=*x;*x=*y;*y=temp;)运用局部变量temp作为变量。C编译器把局部变量分配在栈中。多次调用同一个函数,可以保证每次的temp互不影响。Uc/os-II中进行任务调度时,会把当前任务的CPU寄存器存放到此任务的堆栈中,然后,再从另一个任务的堆栈中恢复原来的工作寄存器,继续运行另一个任务。所以寄存器的入栈和出栈是UC/OS-II中多任务调度的基础。3、设置与处理器和编译器相关的代码uC/OS-II定义了两个宏来禁止和允许中断:()S_ENTER_CRITICAL()和OS_EXT_CRITICAL()ouC/OS-

31、II需要先禁止中断,在访问代码的临界区,并在访问完毕后重新允许中断。如下:INTS_()FFmrsrO,cpsr;movrl,rO;orrrl,rl,#0xc0;msrCPSR,rl;andr0,r0,#0x80;movpcJr;INTS_ONmrsrO,cpsr;bicr0,r0,#0xc0;msrCPSR,rl;movpc,Ir;绝大多数的微处理器和微控制器的栈堆是从上往下增长的。4、与操作系统相关的函任务堆栈初始化函数OSTaskStklnit,用户传递任务的地址、pdata指针、任务的堆栈栈顶指针和任务的优先级给OSTaskCreateO函数和OSTaskCreateExt()函数。当

32、OSTaskCreateHook()函数被调用时,它会收到指向已建立任务的OSJFCB的指针,这样它就可以访问所有的结构成员了。当任务被删除时就会调用OSTaskDelHookO函数,OSTaskDelHookO函数可以检验TCB扩展是否被建立并进行一些清除操作。当任务切换时就会调用()STaskSwHook()函数,其期间中断一直都是被禁止的。OSTaskStatHook()函数每秒种都会被OSTaskStat()函数调用一次,用户可以用OSTaskStatHook。函数来扩展统计功能。OSTaskTickHookO函数在每个时钟节拍都会被OSTaskTick()函数调用,通知用户的移植实例

33、或应用程序之前被调用的。5、时钟节拍中断用户必须在多任务系统启动以后再开启时钟节拍器,也就是在调用OSStartO之后,在调用OSStartO之后做的第一件事是初始化定时器中断。6、移植测试为了使UC/OS-II可以正常运行,除了上述必须的移植工作外,硬件初始化和配置文件也是必须的。包括中断处理、时钟、串口通信等基本功能函数。以下为一个任务函数VoidTaskName(void*Id)!深入任务初始化语句For(;)!添入任务循环内容OSTimeDly(SusPendTime);六、总结通过上面我们对UC/OS-II操作系统内核的分析,我们初步了解了有关其特性和基本操作函数和组成,对其有了一个较为深入的了解。uc/os-n操作系统具有任务管理、调度和可移植性程序。一般情况下

温馨提示

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

评论

0/150

提交评论