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

下载本文档

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

文档简介

嵌入式系统(EmbeddedSystem)实时操作系统C/OS-Ⅱ分析华北电力大学电气与电子工程学院本节提要13254C/OS-Ⅱ简介C/OS-Ⅱ内核结构C/OS-Ⅱ任务通信与同步C/OS-Ⅱ任务管理C/OS-Ⅱ时间管理常见的嵌入式操作系统实时嵌入式操作系统的种类繁多,大体上可分为两种,商用型和免费型。商用型的实操作系统功能稳定、可靠,有完善的技术支持和售后服务,但往往价格昂贵,如Vxworks、QNX、WinCE、PalmOS等。免费型的实时操作系统在价格方面具有优势,目前主要有Linux和μC/OS,稳定性与服务性存在挑战。RTOS在嵌入式系统中的位置嵌入式硬件平台BSPKERNELFSTCP/IP设备驱动设备I/O调试工具其它组件应用RTOSC/C++RTOS是32位的嵌入式CPU的软件基础RTOS内核提供CPU的管理硬件初时化,MMU,定时器,中断RTOS内核提供任务,内存管理RTOS提供设备管理,文件和网络的支持RTOS提供C/C++,JAVA,图形模块等编程接口C/OS简介

1、C/OS——MicroControllerOS,微控制器操作系统2、C/OS简介美国人JeanLabrosse1992年完成应用面覆盖了诸多领域,如照相机、医疗器械、音响设备、发动机控制、高速公路电话系统、自动提款机等1998年C/OS-II,目前的版本C/OS-IIV2.61,2.722000年,得到美国航空管理局(FAA)的认证,可以用于飞行器中网站www.ucos-II.com()公开源代码可移植性(Portable)

绝大部分

C/OS-II的源码是用移植性很强的ANSIC写的。和微处理器硬件相关的那部分是用汇编语言写的。汇编语言写的部分已经压到最低限度,使得

C/OS-II便于移植到其他微处理器上。

C/OS-II可以在绝大多数8位、16位、32位以至64位微处理器、微控制器、数字信号处理器(DSP)上运行。可固化(ROMable)

C/OS-II是为嵌入式应用而设计的,这就意味着,只要读者有固化手段(C编译、连接、下载和固化),

C/OS-II可以嵌入到读者的产品中成为产品的一部分。可裁剪(Scalable)

可以只使用

C/OS-II中应用程序需要的那些系统服务。也就是说某产品可以只使用很少几个

C/OS-II调用,而另一个产品则使用了几乎所有

C/OS-II的功能,这样可以减少产品中的

C/OS-II所需的存储器空间(RAM和ROM)。这种可剪裁性是靠条件编译实现的。C/OS的性能特点(一)占先式(Preemptive)多任务

C/OS-II可以管理64个任务,然而,目前这一版本保留8个给系统。应用程序最多可以有56个任务可确定性

全部

C/OS-II的函数调用与服务的执行时间具有可确定性。任务栈

每个任务有自己单独的栈,

C/OS-II允许每个任务有不同的栈空间,以便压低应用程序对RAM的需求。系统服务

C/OS-II提供很多系统服务,例如邮箱、消息队列、信号量、块大小固定的内存的申请与释放、时间相关函数等。中断管理

中断可以使正在执行的任务暂时挂起,如果优先级更高的任务被该中断唤醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可达255层。稳定性与可靠性C/OS的性能特点(二)µC/OS-II图书描述了µC/OS-II内部的工作原理随书的CD中包含了源代码工业界最清晰的源代码除英文版外,有中文和韩文版ChineseKoreanEnglishISBN1-57820-103-9美国CMPBOOKISBN7-81077-290-2北京航空航天大学出版社ISBN89-951540-5-5µC/OS-II的各种商业应用全世界有数百种产品在应用:AvionicsMedicalCellphonesRoutersandswitchesHigh-endaudioequipmentWashingmachinesanddryersUPS(UninterruptiblePowerSupplies)IndustrialcontrollersGPSNavigationSystemsMicrowaveRadiosInstrumentationPoint-of-saleterminals更多µC/OS-II提供的系统服务信号量(Semaphore)

信号量是E.W.Dijkstra在1965年提出的一种方法,在他的建议中引入一个新的变量类型,称作信号量。信号量是进程间通讯(IPC)的一种形式——是一个进程给另一个进程发送信息的方法。但是信息不可能很多——一个信号量不可能携带详细的信息,即使是传送者的身份也不能被传递;唯一能够确定的事实是信号量的确被发送了。Dijkstra建议设两种操作:DOWN和UP(分别为推广后的SLEEP和WAKEUP)。对一信号量执行DOWN操作是检查其值是否大于0。若是则将其值减1(即用掉一个保存的唤醒信号)并继续。若值为0,则进程将睡眠,而且此时DOWN操作并未结束。检查数值、改变数值、以及可能发生的睡眠操作均作为一个单一的、不可分割的原子操作(atomicaction)完成。即保证一旦一个信号量操作开始,则在操作完成或阻塞之前别的进程均不允许访问该信号量。这也就是二进制信号量。二进制信号量有两中用途:互斥和同步。µC/OS-II提供的系统服务带互斥机制的信号量减少优先级倒置的问题事件标志消息信箱消息队列内存管理时钟管理任务管理µC/GUIandµC/FSµC/GUI嵌入式的用户界面用ANSIC书写支持任何8,16,32-bitsCPU彩色,灰、度,等级或黑白显示代码尺寸小µC/FS嵌入式的文件系统WritteninANSIC用ANSIC书写支持任何8,16,32-bitsCPU支持SMC,MMC,SD,CF,IDE,Flash,RAM其他介质本节提要13254C/OS-Ⅱ简介C/OS-Ⅱ内核结构C/OS-Ⅱ任务通信与同步C/OS-Ⅱ任务管理C/OS-Ⅱ时间管理C/OS-II的文件结构内核结构

五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信

任务管理时间管理任务之间通信与同步

C/OS的移植C/OS-II的内核结构当处理临界段代码时,需要关中断,处理完毕后,再开中断;关中断时间是实时内核最重要的指标之一;在实际应用中,关中断的时间很大程度中取决于微处理器的结构和编译器生成的代码质量;C/OS-II定义两个宏开关中断:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL();C/OS-II中开关中断的方法OS_CRITICAL_METHOD==1用处理器指令关中断,执行OS_ENTER_CRITICAL(),开中断执行OS_EXIT_CRITICAL();OS_CRITICAL_METHOD==2实现OS_ENTER_CRITICAL()时,先在堆栈中保存中断的开/关状态,然后再关中断;实现OS_EXIT_CRITICAL()时,从堆栈中弹出原来中断的开/关状态;OS_CRITICAL_METHOD==3把当前处理器的状态字保存在局部变量中(如OS_CPU_SR,关中断时保存,开中断时恢复C/OS-II中采用了3种开关中断的方法任务task典型的任务一个无限循环。voidmytask(void*pdata){for(;;){dosomething;waiting;dosomething;}}C/OS–II2.5版本支持64个任务,每个任务一个特定的优先级。优先级越高,数字越小。系统占用了8个任务,保留优先级为0、1、2、3、OS_LOWEST_PRIO-3、OS_LOWEST_PRIO-2、OS_LOWEST_PRIO-1、OS_LOWEST_PRIO-0。TaskStructurevoidYourTask(void*pdata) (1){for(;;){ (2)/*用户代码*/

调用uC/OS-II的某种系统服务:OSMboxPend();OSQPend();OSSemPend();OSTaskDel(OS_PRIO_SELF);OSTaskSuspend(OS_PRIO_SELF);OSTimeDly();OSTimeDlyHMSM();/*用户代码*/}}AlternateStructurevoidYourTask(void*pdata){/*用户代码*/OSTaskDel(OS_PRIO_SELF);}任务状态任务控制块(TCB)任务控制块OS_TCB是一个数据结构,保存该任务的相关参数,包括任务堆栈指针,状态,优先级,任务表位置,任务链表指针等。所有的任务控制块分为两条链表,空闲链表和使用链表。µC/OS-II任务控制块.typedefstructos_tcb{OS_STK*OSTCBStkPtr;#ifOS_TASK_CREATE_EXT_EN>0void*OSTCBExtPtr;OS_STK*OSTCBStkBottom;INT32UOSTCBStkSize;INT16UOSTCBOpt;INT16UOSTCBId;#endifstructos_tcb*OSTCBNext;structos_tcb*OSTCBPrev;#if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_EN||OS_SEM_ENOS_EVENT*OSTCBEventPtr;#endif#if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_ENvoid*OSTCBMsg;#endifINT16UOSTCBDly;INT8UOSTCBStat;INT8UOSTCBPrio;INT8UOSTCBX;INT8UOSTCBY;INT8UOSTCBBitX;INT8UOSTCBBitY;#ifOS_TASK_DEL_ENBOOLEANOSTCBDelReq;#endif}OS_TCB; 任务控制块OS_TCB中几个成员的算法OSTCBY=priority>>3;OSTCBBitY=OSMapTbl[priority>>3];OSTCBX=priority&0x07;OSTCBBitX=OSMapTbl[priority&0x07];空任务列表所有的任务控制块都被放置在任务控制块列表数组OSTCBTbl[]中,系统初始化时,所有任务控制块被链接成空任务控制块的单向链表,任务建立后,空任务控制块指针OSTCBFreeList指向的任务控制块就赋给了该任务,然后OSTCBFreeList的值调整为指向链表中的下一个空任务控制块。任务控制块初始化函数INT8UOS_TCBInit(INT8Uprio,OS_STK*ptos,OS_STK*pbos,INT16Uid,INT32Ustk_size,void*pext,INT16Uopt){……}任务级的任务调度--OSSched

C/OS是占先式实时多任务内核,优先级最高的任务一旦准备就绪,则拥有CPU的所有权开始投入运行。

C/OS中不支持时间片轮转法,每个任务的优先级要求不一样且是唯一的,所以任务调度的工作就是:查找准备就绪的最高优先级的任务并进行上下文切换。

C/OS任务调度所花的时间为常数,与应用程序中建立的任务数无关。根据就绪表确定最高优先级两个关键:优先级数分解为高三位和低三位分别确定;高优先级有着小的优先级号;根据优先级找到任务在就绪任务表中的位置每个就绪的任务都放入就绪表中(readylist)中,就绪表有两个变量:OSRdyGrp、OSRdyTbl[]OSRdyGrp1207654300XXXYYY任务优先级2017654310891514131211181617232221201926242531302928273432333938373635424041474645444350484955545352515856576362616059[0][1][2][3][4][5][6][7]OSRdyTbl[7]XY优先级最低任务(空闲任务)优先级最高任务任务优先级号根据优先级确定就绪表(1)假设优先级为12的任务进入就绪状态,12=1100b,则OSRdyTbl[1]的第4位置1,且OSRdyGrp的第1位置1,相应的数学表达式为:

OSRdyGrp|=00000010=0x02;

OSRdyTbl[1]|=00010000=0x10;而优先级为21的任务就绪21=10101b,则OSRdyTbl[2]的第5位置1,且OSRdyGrp的第2位置1,相应的数学表达式为:

OSRdyGrp|=00000100=0x04;

OSRdyTbl[2]|=00100000=0x20;根据优先级确定就绪表(2)从上面的计算我们可以得到:若OSRdyGrp及OSRdyBbl[]的第n位置1,则应该把OSRdyGrp及OSRdyBbl[]的值与2n相或。uC/OS中,把2n的n=0-7的8个值先计算好存在数组OSMapTbl[]中,也就是:

OSMapTbl[0]=20=0x01(00000001)OSMapTbl[1]=21=0x02(00000010)

……OSMapTbl[7]=27=0x80(10000000)使任务进入就绪态如果prio(00yyyxxx)是任务的优先级,也是任务的识别号,则将任务放入就绪表,即使任务进入就绪态的方法是:OSRdyGrp|=OSMapTbl[prio>>3];OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];假设优先级为12——1100bOSRdyGrp|=OSMapTbl[1](00000010);OSRdyTbl[1]|=OSMapTbl[4](00010000);使任务脱离就绪态将任务就绪表OSRdyTbl[prio>>3]相应元素的相应位清零,而且当OSRdyTbl[prio>>3]中的所有位都为零时,即全组任务中没有一个进入就绪态时,OSRdyGrp的相应位才为零。If((OSRdyTbl[prio>>3]&=

OSMapTbl[prio&0x07])==0);OSRdyGrp&=

OSMapTbl[prio>>3];采用查表法确定高优先级任务查表法具有确定的时间,增加了系统的可预测性,uC/OS中所有的系统调用时间都是确定的High3=OSUnMapTbl[OSRdyGrp];Low3=OSUnMapTbl[OSRdyTbl[High3]];Prio=(High3<<3)+Low3;OSRdyGrp1207654300XXXYYY任务优先级2017654310891514131211181617232221201926242531302928273432333938373635424041474645444350484955545352515856576362616059[0][1][2][3][4][5][6][7]OSRdyTbl[7]XYINT8UconstOSUnMapTbl[]={0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};优先级判定表OSUnMapTbl[256]举例:

如OSRdyGrp的值为01101000B,即0X68,则查得OSUnMapTbl[OSRdyGrp]的值是3,它相应于OSRdyGrp中的第3位置1;如OSRdyTbl[3]的值是11100100B,即0XE4,则查OSUnMapTbl[OSRdyTbl[3]]的值是2,则进入就绪态的最高任务优先级Prio=3*8+2=26

TaskschedulervoidOSSched(void){INT8Uy;OS_ENTER_CRITICAL();if((OSLockNesting=0)&&(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();}voidOSSchedLock(void){if(OSRunning==TRUE){OS_ENTER_CRITICAL();if(OSLockNesting<255){OSLockNesting++;}OS_EXIT_CRITICAL();}}给调度器上锁给调度器开锁voidOSSchedUnlock(void){if(OSRunning==TRUE){OS_ENTER_CRITICAL();if(OSLockNesting>0){OSLockNesting--;if((OSLockNesting==0)&&(OSIntNesting==0)){OS_EXIT_CRITICAL();OSSched(); }else{OS_EXIT_CRITICAL();}}else{OS_EXIT_CRITICAL();}}}任务切换将被挂起的任务寄存器入栈将较高优先级任务的寄存器出栈任务级的任务切换OS_TASK_SW()OS_TASK_SW()是宏调用,含有微处理器的软中断指令OS_TASK_SW()将处理器相关的软件中断机制封装起来,便于操作系统移植调用OS_TASK_SW()前的数据结构低优先级任务OS_TCBOSTCBCur(1)存贮器低地址存贮器高地址堆栈方向SPR1R2R3R4PCPSW存贮器低地址存贮器高地址高优先级任务OS_TCBOSTCBHighRdy(3)(2)CPU(4)(5)PSWPCR1R2R3R4保存当前CPU寄存器的值低优先级任务OS_TCBOSTCBCurPSWPCR1R2R3R4存贮器低地址存贮器高地址堆栈方向SPR1R2R3R4PCPSWPSWPCR1R2R3R4存贮器低地址存贮器高地址高优先级任务OS_TCBOSTCBHighRdy(2)CPU(1)(3)重新装入要运行的任务低优先级任务OS_TCBOSTCBCurPSWPCR1R2R3R4存贮器低地址存贮器高地址堆栈方向SPR1R2R3R4PCPSWPSWPCR1R2R3R4存贮器低地址存贮器高地址高优先级任务OS_TCBOSTCBHighRdyOSTCBCur(1)(2)CPU(4)(4)(1)(3)(3)(4)任务切换OS_TASK_SW()的代码VoidOSCtxSw(void){将R1,R2,R3及R4推入当前堆栈;OSTCBCurOSTCBStkPtr=SP;OSTCBCur=OSTCBHighRdy;SP=OSTCBHighRdyOSTCBSTKPtr;将R4,R3,R2及R1从新堆栈中弹出;执行中断返回指令;}C/OS-II中的中断中断:由于某种事件的发生,而导致程序流程的改变。产生中断的事件称为中断源。CPU响应中断的条件:至少有一个中断源向CPU发出中断信号;系统允许中断,且对此中断信号未予屏蔽中断类型:硬件中断外部中断陷井中断现场控制量的中断C/OS-II中的中断服务子程序用户中断服务子程序:保存全部CPU寄存器;调用OSIntEnter()或OSIntNesting直接加1;if(OSIntNesting==1){OSTCBCur->OSTCBStkPtr=SP;}清中断源;重新开中断;执行用户代码做中断服务;调用OSIntExit();恢复所有CPU寄存器;执行中断返回指令;中断服务Searchforhighestpriority–similartoschedulerHalfcontextswitchisdonebyinterruptresponse–i.e.registerssaved中断与时钟节拍时钟节拍(时钟滴答)Tick,是一种定时器中断,可通过编程方式实现时钟节拍是一种特殊的中断,操作系统的心脏。首先32位的整数OSTime加一。对任务列表进行扫描,判断是否有延时任务应该处于准备就绪状态,最后进行上下文切换。时钟节拍中断服务子程序VoidOSTickISR(void){保存处理器寄存器的值;调用OSIntEnter(),或是将OSIntNesting加1if(OSIntNesting==1){OSTCBCur->OSTCBStkPtr=SP;}调用OSTimeTick();清发出中断设备的中断;重新允许中断(可选用)调用OSIntExit();恢复处理器寄存器的值;执行中断返回指令;}voidOSTimeTick(void){OS_TCB*ptcb;OSTimeTickHook(); (1)ptcb=OSTCBList; (2)while(ptcb->OSTCBPrio!=OS_IDLE_PRIO){ (3)OS_ENTER_CRITICAL();if(ptcb->OSTCBDly!=0){if(--ptcb->OSTCBDly==0){if(!(ptcb->OSTCBStat&OS_STAT_SUSPEND)){ (4)OSRdyGrp|=ptcb->OSTCBBitY; (5)OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;}else{ptcb->OSTCBDly=1;}}}ptcb=ptcb->OSTCBNext;OS_EXIT_CRITICAL();}OS_ENTER_CRITICAL(); (6)OSTime++; (7)OS_EXIT_CRITICAL();}时钟节拍函数OSTimTick()voidOSTaskIdle(void*pdata){pdata=pdata;for(;;){OS_ENTER_CRITICAL();OSIdleCtr++;OS_EXIT_CRITICAL();}}空闲任务OSTaskIdle()初始化统计任务voidmain(void){OSInit();/*初始化uC/OS-II (1)*//*安装uC/OS-II的任务切换向量 *//*创建用户起始任务(以TaskStart()作为起始任务)(2)*/OSStart();/*开始多任务调度 (3)*/}voidTaskStart(void*pdata){/*安装并启动uC/OS-II的时钟节拍 (4)*/OSStatInit();/*初始化统计任务 (5)*//*创建用户应用程序任务 */for(;;){/*这里是TaskStart()的代码! */}}统计任务初始化C/OS-II初始化首先调用系统初始化函数OSIint()。OSIint()初始化μC/OS-Ⅱ所有的变量和数据结构(见OS_CORE.C)。OSInit()建立空闲任务idletask,这个任务总是处于就绪态的。空闲任务OSTaskIdle()的优先级总是设成最低,即OS_LOWEST_PRIO。如果统计任务允许OS_TASK_STAT_EN和任务建立扩展允许都设为1,则OSInit()还得建立统计任务OSTaskStat()并且让其进入就绪态。OSTaskStat的优先级总是设为OS_LOWEST_PRIO-1空闲和统计任务的任务控制块(OS_TCBs)是用双向链表链接在一起的。OSTCBList指向这个链表的起始处。当建立一个任务时,这个任务总是被放在这个链表的起始处。调用OSInit()之后的数据结构空闲缓冲区μC/OS-Ⅱ的启动voidmain(void){OSInit();/*初始化uC/OS-II*/..通过调用OSTaskCreate()或OSTaskCreateExt()创建至少一个任务;..OSStart();/*开始多任务调度!OSStart()永远不会返回*/}启动多任务voidOSStart(void){INT8Uy;INT8Ux;if(OSRunning==FALSE){y=OSUnMapTbl[OSRdyGrp];x=OSUnMapTbl[OSRdyTbl[y]];OSPrioHighRdy=(INT8U)((y<<3)+x);OSPrioCur=OSPrioHighRdy;OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy]; OSTCBCur=OSTCBHighRdy;OSStartHighRdy(); }}关于OSStartHighRdy

voidOSStartHighRdy(void){CalluserdefinableOSTaskSwHook();Getthestackpointerofthetasktoresume:Stackpointer=OSTCBHigh

温馨提示

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

评论

0/150

提交评论