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

下载本文档

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

文档简介

第四章

μC/OS-Ⅱ内核结构与运行流程本章要点μC/OS-Ⅱ内核结构及可裁剪性μC/OS-Ⅱ任务管理及表管理μC/OS-Ⅱ就绪表管理及算法分析μC/OS-Ⅱ任务调度及实现、任务调度的打开和关闭μC/OS-Ⅱ空闲任务及实现μC/OS-Ⅱ统计任务及实现μC/OS-Ⅱ任务的初始化μC/OS-Ⅱ中断处理μC/OS-Ⅱ时钟节拍μC/OS-Ⅱ内核的核心模块core.c1.操作系统服务嵌入式实时操作系统基本性质RTOS是一种能够响应时间约束控制以及事件控制过程的操作系统,这个控制过程具有预先设置的时限要求。RTOS是一种对任务、中断服务子程序有实时限制和截止时间要求的操作系统。实时操作系统软件提供的服务

任务管理、任务优先级、任务调度及算法、优先级继承系统预计时间属性:任务抖动即时限值最好情况和最坏情况的时间差。内存管理:应用程序任务能够在内核空间运行,访问内核代码、堆栈、数据的内存空间,将导致内核代码不可防护。采用定长内存块分配的内存分配方法,分配速度快。时钟管理:提供计时函数,完成时间分配和重置,以确保给定计时时限的有效性。任务同步机制:信号量、邮箱、消息队列等。2.基于RTOS嵌入式系统基本设计基本机制RTOS提供在内核空间运行用户线程的机制;RTOS提供中断、驱动、IST、任务或线程的处理;RTOS提供内存分配和释放函数;RTOS提供对零到多个任务的调度、运行和阻塞操作;RTOS提供简单操作,如I/O、文件、管道第等;RTOS提供对于CPU的多个状态、内部和外部设备的有效管理。RTOS支持下的嵌入式系统基本设计原则中断处理子程序ISR和任务的设计原则中断服务线程或任务的设计原则任务设计原则模块化设计原则坚持数据封装任务设计原则减少系统调用话费时间设计原则优先级设置策略和抢占式调度策略避免删除任务设计原则利用空闲的CPU时间执行系统内部函数任务内完成内存分配和回收的设计原则谨慎使用任务间共享资源和数据层次和限定范围优先级抢占调度任务的运行规律假设一个编码消息流到达一个嵌入式系统端口A,对每个消息进行解码,并传送到端口B。应用程序功能设计为5个任务运行,优先级大到小:任务B1:检测端口A是否有消息任务B2:读出端口A的消息任务B3:消息解码任务B4:消息编码任务B5:传送编码消息到端口B任务B1等待来自端口A的中断任务B2读出来自端口A的消息任务B3解码来自端口A的消息队列消息任务B4对消息再次编码任务B5向端口B写入编码消息运行上下文任务B1任务ISRB2任务B3任务B4任务B5保存上下文B3RunningB1RunningBlockedB3B2FinishRunningBlockedB3B3FinishFinishRunningB4FinishFinishFinishRunningB5FinishFinishFinishFinishRunningB1RunningBlockedB5B2FinishRunningBlockedB5B3FinishFinishRunningBlockedB5程序运行过程中各任务执行情况及上下文切换

操作系统µC/OS-II的内核模块结构核心杂项功能管理:os_core.c标志功能管理:os_flag.c消息邮箱管理:os_mbox.c内存块管理:os_mem.c互斥信号量管理:os_mutex消息队列管理:os_q.c计数信号量管理:os_sem.c任务管理:os_task.c时钟管理:os_time.c基于内核的应用软件编程当用户基于µC/OS-II内核,进行应用程序设计实现时,用户应用代码可以通过调用内核函数,并完成编译、链接等操作,用以形成可执行程序代码,实现具有实时特性的软件。3.uC/OS-II基本模块功能OSInit()OSIntEnter()OSIntExit()OSSchedLock()OSSchedUnlock()OSStart()OSStartInit()OSVersion()OSTimeTick()3.uC/OS-II基本模块功能OS_Dummy()OS_EventTaskRdy()OS_EventTaskWait()OS_EventTO()OS_EventWaitListInit()OS_InitEventList()OS_InitMisc()OS_InitRdyList()OS_InitTaskIdle()OS_EventTO()3.uC/OS-II基本模块功能OS_InitTaskStat()OS_InitTCBList()OS_Sched()OS_TaskIdle()OS_TaskStat()OS_TCBInit()OS_EventTO()核心杂项功能管理——os_core.c系统初始化函数:voidOSInit(void)OSinit()负责对μC/OS-Ⅱ操作系统进行初始化工作,完成杂项数据、任务就绪队列、空闲任务控制块、空闲事件控制块等数据结构的初始化工作。该函数功能为初始化核心数据,调用这个函数必须在调用OSStart()函数之前,OSStart()函数用于开始多任务应用系统运行,必须在创建所有μC/OS-Ⅱ任务之后调用。中断进入函数voidOSIntEnter(void)本函数告知μC/OS-Ⅱ内核,要开始执行一个中断处理子程序段,在该段程序执行期间,不能响应任何中断,程序员需要确保中断处理子程序的正确性、稳定性,以免程序瘫痪。μC/OS-Ⅱ可据此记录、跟踪中断嵌套的层数,确保只对最外层的中断处理子程序做出响应。OSIntEnter()函数和OSIntExit()函数成对使用,调用OSIntEnter()函数表示封中断开始,调用OSIntExit()函数表示封中断结束。中断退出函数voidOSIntExit(void)该函数告知μC/OS-Ⅱ内核,当前正在执行的中断服务子程序已执行完毕,μC/OS-Ⅱ可据此记录、跟踪中断嵌套的变化。当最后一层嵌套的中断处理子程序执行完毕后,也就是本程序可以响应中断的时候,由于实时内核采用可抢占式优先级调度进行任务调度。如果在执行中断处理子程序期间,有更高优先级的任务进入就绪态,μC/OS-Ⅱ会通过任务调度函数的执行,令中断返回到更高优先级的任务。而被中断执行的任务,要等待在就绪任务中,直到成为优先级最高时才能得到执行。系统任务调度关闭函数voidOSSchedLock(void)调用该函数允许应用程序禁止任务间的上下文切换,以确保当前任务能够执行,不被高优先级的就绪任务抢夺运行权。系统任务调度打开函数voidOSSchedUnlock(void)。调用该函数,表示应用程序此时解除了任务调度关闭状态,即允许上下文切换的发生。启动多任务函数voidOSStart(void)该函数用于启动多任务运行过程,令uC/OS-II内核管理已经创建好的任务。请注意,调用该函数之前,必须调用OSInit()函数,完成系统数据结构的初始化工作,并且,必须至少创建一个应用任务。系统统计数据初始化函数voidOSStatInit(void)应用代码调用该函数计算CPU利用率首先确定,在1秒钟内,如果没有其他任务执行的话,一个32位计数器能够完成的最大计数是多少CPU利用率可以由此这样确定:每秒钟,令一个低优先级任务跟踪这个32位计数器的计数值,该任务优先级高,可以执行。CPU利用率的计算公式如下:CPUUsage(%)=100*(1–OSIdleCtr/OSIdleCtrMax)

OSIdleCtr指在较低优先级任务执行过程中,计数器得到的计数值

OSIdleCtrMax指在没被中断情况下获取的计数器的值。表明,实时内核在并发执行实时任务时,具有的实际执行率,与单任务执行是不同的。系统版本函数INT16UOSVersion(void)。该函数用于返回uC/OS-II的版本号,返回值等于uC/OS-II版本号乘以100,也就是说,版本号2.00的返回值为200。系统时钟节拍函数voidOSTimeTick(void)该函数用于系统时钟嘀嗒发生时,向uC/OS-II内核发送信号。该函数一般由时钟嘀嗒中断处理程序调用,也可由更高优先级任务调用。等待事件发生,任务就绪函数:INT8UOS_EventTaskRdy(OS_EVENT*pevent,void*msg,INT8Umsk)该函数由其他uC/OS-II服务函数调用,用于当等待事件发生,一个任务由等待变为就绪。挂起等待事件的任务voidOS_EventTaskWait(OS_EVENT*pevent)

事件到来,任务就绪voidOS_EventTO(OS_EVENT*pevent)该函数由其他uC/OS-II服务函数调用,表明时间到时,一个任务就绪,可以运行。初始化事件控制块队列voidOS_EventWaitListInit(OS_EVENT*pevent)该函数由OSInit()调用,用于初始化事件控制块自由队列。初始化事件控制块自由队列函数voidOS_EventWaitListInit(OS_EVENT*pevent)该函数由OSInit()调用,用于初始化事件控制块自由队列。staticvoidOS_InitEventList(void)初始化杂项变量函数:staticvoidOS_InitMisc(void)该函数由OSInit()调用,用于初始化杂项数据变量。初始化就绪队列/初始化创建空闲任务staticvoidOS_InitRdyList(void)该函数由OSInit()调用,用于初始化就绪队列。staticvoidOS_InitTaskIdle(void)该函数用于创建空闲任务。创建统计任务staticvoidOS_InitTaskStat(void)

调用参数:无。返回值:无。初始化函数:staticvoidOS_InitTCBList(void)该函数用于初始化任务控制块自由队列。由OSInit()函数调用,初始化由OS_TCB构成的自由队列。调用参数:无。返回值:无。调度函数:voidOS_Sched(void)调用该函数,判定是否有一个新的更高优先级任务就绪,等待运行。该函数由任务级代码唤醒,不能用于中断处理子程序中重新调度任务。中断服务子程序的重新调度,调用系统函数OSIntExit()完成。调用说明: 1)该函数属于uC/OS-II的内部函数,应用代码不会调用。 2)当调度程序被锁定时,可以防止重新调度的发生。参见函数OS_SchedLock()的使用。闲逛任务函数voidOS_TaskIdle(void*pdata) 当没有其它高优先级任务执行时执行该任务,也许其它任务都在等待事件的发生。说明:系统函数OSTaskIdleHook()在临界区执行之后被调用。统计任务函数voidOS_TaskStat(void*pdata)用于计算多任务环境下的一些统计数据。OS_TaskStat()是专门用来计算CPU利用率。

OSCPUUsage=100*(1–OSIdleCtr/OSIdleCtrMax)调用说明:1)该任务的优先级高于闲逛任务的优先级。该任务运行的优先级为OS_IDLE_PRIO-1。2)可以通过设置配置参数不运行该任务,即定义#defineOS_TASK_STAT_EN为0。3)可以在初始状态下,延迟5秒钟,使系统到达一个稳定的状态,所有需要的任务创建完毕,才执行统计任务。初始化任务控制块函数创建任务时使用函数原型:INT8UOS_TCBInit(INT8Uprio,OS_STK*ptos,OS_STK*pbos,INT16Uid,INT32Ustk_size,void*pext,INT16Uopt)参考任务管理函数OSTaskCreate()和

OSTaskCreateExt()调用。4.µC/OS-II内核结构(1)µC/OS-II内核实现4层架构应用代码层:面向用户应用功能的程序设计代码,一般是基于内核进行的应用程序设计源代码。处理器无关代码层&与应用代码相关代码层:与处理器无关的内核功能代码,供应用代码层的源程序调用,以及面向应用代码的配置文件,对应用代码的参数等进行设置,也与处理器无关。与处理器相关代码层:内核功能只涉及三个文件与处理器相关,将移植的工作量降到最低。当嵌入式软件需要移植到另一个硬件平台时,需要按照目标机的机器指令修改该层文件中的功能实现。硬件层:嵌入式系统的硬件构成,包括系统时钟。这是嵌入式软件运行的平台。µC/OS-II内核的核心功能(OS_CORE.C)可裁减的如果用户应用程序不去调用该项内核功能,这部分功能代码就不用包含在应用软件中。不可裁减的分别实现了中断的关闭和打开,内核初始化,任务调度,中断ISR的入口函数和出口函数,任务调度的关闭和打开等。不可裁减的内核功能µC/OS-II内核功能函数OS_CFG.H中置1表示函数有效函数功能OS_ENTER_CRITICAL()必有关中断OS_EXIT_CRITICAL()必有开中断OSInit()必有内核初始化OSStart()必有任务调度OSIntEnter()必有中断进入OSIntExit()必有中断退出OSSchedLock()OS_SCHED_LOCK_EN置1任务调度加锁OSSchedUnlock()OS_SCHED_LOCK_EN置0任务调度解锁OSVersion()必有版本(2)任务任务函数的定义形式voidYourTask(void*pdata){for(;;){/*该任务应用代码*/ 调用uC/OS-II的某种系统服务,例如:

OSMboxPend();

OSQPend();

OSSemPend();

OSTaskDel(OS_PRIO_SELF);OSTaskSuspend(OS_PRIO_SELF);

OSTimeDly();

OSTimeDlyHMSM(); /*该任务用户代码*/}}任务的状态(3)任务控制块(TaskControlBlocks)typedef

struct

os_tcb{

OS_STK*OSTCBStkPtr;#ifOS_TASK_CREATE_EXT_EN/*如果使用扩展任务创建*/

Void*OSTCBExtPtr;

OS_STK*OSTCBStkBottom;

INT32UOSTCBStkSize;

INT16UOSTCBOpt;

INT16UOSTCBId;#endif

struct

os_tcb*OSTCBNext;

struct

os_tcb*OSTCBPrev;#if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_EN||OS_SEM_EN/*如果使用事件*/

OS_EVENT*OSTCBEventPtr;#endif#if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_EN/*如果使用消息*/

Void*OSTCBMsg;#endif

INT16UOSTCBDly;

INT8UOSTCBStat;

INT8UOSTCBPrio;

INT8UOSTCBX;

INT8UOSTCBY;

INT8UOSTCBBitX;

INT8UOSTCBBitY;#ifOS_TASK_DEL_EN/*如果允许删除任务*/

BOOLEANOSTCBDelReq;#endif}OS_TCB;空闲任务表μC/OS-Ⅱ初始化时,所有任务控制块OS_TCBs被链接成一个单向空闲任务表。任务建立时——空闲任务控制块指针OSTCBFreeList指向的任务控制块,便分配给该任务,OSTCBFreeList的值调整为指向下链表中下一个空闲的任务控制块。任务删除时——任务控制块就链入空闲任务表尾。(4)任务就绪表及其操作实现根据就绪表确定最高优先级任务进入运行态新就绪任务存入就绪表算法基础:就绪表的结构优先数分解为高三位和低三位,分别确定优先级高优先数小

根据优先级找到任务在就绪任务表中的位置就绪任务放入任务就绪表,就绪表用两个变量表示:OSRdyGrp、OSRdyTbl[]OSRdyGrp1207654300XXXYYY任务优先级2017654310891514131211181617232221201926242531302928273432333938373635424041474645444350484955545352515856576362616059[0][1][2][3][4][5][6][7]OSRdyTbl[8]XY优先级最低任务(空闲任务)优先级最高任务任务优先级号00001100001010011221为了找到就绪态优先级最高的任务,不需要从OSRdyTbl[0]开始扫描整个就绪任务表的各个元素值,算法设计查表,即优先级判定表OSUnMapTbl[],见文件OS_CORE.C中关于该数组表定义:INT8UconstOSUnMapTbl[]={0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x00to0x0F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x10to0x1F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x20to0x2F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x30to0x3F*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x40to0x4F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x50to0x5F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x60to0x6F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x70to0x7F*/7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x80to0x8F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x90to0x9F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xA0to0xAF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xB0to0xBF*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xC0to0xCF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xD0to0xDF*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xE0to0xEF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0/*0xF0to0xFF*/};1)采用查表法确定高优先级任务查表法具有确定时间,增加系统可预测性,C/OS–II所有系统调用时间确定。High3=OSUnMapTbl[OSRdyGrp];Low3=OSUnMapTbl[OSRdyTbl[High3]];Prio=(High3<<3)+Low3;OSRdyGrp0110100000XXXYYY任务优先级0000010000000010100001000000000000000000000000001000000000011000[0][1][2][3][4][5][6][7]OSRdyTbl[8]XY就绪表(ReadyList)结构

处于就绪态的任务将就绪态标志置于就绪表中。就绪表由变量OSRdyGrp和OSRdyTbl[]构成。如对应组中有就绪态任务,OSRdyGrp对应位置1。就绪表OSRdyTbl[]对应(Y,X)元素置1。就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PRIO的值,可在文件OS_CFG.H中定义。OS_LOWEST_PRIO值越小,占用RAM空间越少。为确定就绪任务优先级,内核调度程序总是先将OS_LOWEST_PRIO在就绪表相应位置1。Index(下标索引)BitMask(二进制位掩码)0000000011000000102000001003000010004000100005001000006010000007100000002、使任务进入就绪态:该算法中用到的二进制位映射查找表OSMapTbl[],定义在OS_CORE.C文件中,可确保算法执行时间的确定。该表数组值如下。使任务进入就绪态程序清单OSRdyGrp|=OSMapTbl[prio>>3];OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];使任务进入就绪态(修改OSRdyGrp)C语句OSRdyGrp|=OSMapTbl[prio>>3]:直接从TCB中取出OSTCBY的值(即priority>>3),该值表示该任务在就绪表中的逻辑行号,即Y值,以该值为下标索引,取得OSMapTbl[Y]的值,该值为对应就绪表中的逻辑行号的掩码值,行号所对应的二进制bit位是1。使用该掩码值与OSRdyGrp作按位或操作,将OSRdyGrp的对应就绪表中的逻辑行号的二进制位置1。使任务进入就绪态(修改OSRdyTbl[])C语句OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07]:直接从TCB中取出OSTCBY的值(即priority>>3),该值表示该任务在就绪表中的逻辑行号,即Y值,以该值为下标索引,取得OSRdyTbl[Y]变量,即该语句等号的右边。等式左边:直接从TCB中取出OSTCBX的值(即priority&0x07),该值表示该priority任务在就绪表中的某逻辑行号下的第几个任务,即X值,以该值为下标索引,取得OSMapTbl[X]变量,该值为对应就绪表中某逻辑行号下的序号的掩码值,该序号所对应的二进制bit位是1。使用该掩码值与OSRdyTbl[Y]作按或操作,达到将对应就绪表OSRdyTbl[]中的逻辑行号下的任务序号对应的二进制位置1的目的。OSRdyTbl[]表示优先级priority对应的就绪表中的逻辑行号及该行下的任务序号的二进制位,已置1,表明第Y行的第X个任务已就绪。附加说明:TCB表中有四个变量用来记录相关值。任务进入就绪态或进入等待事件发生状态算法使用。使得任务进入就绪表或进入等待表的时间是个常数,便于控制性能。避免在运行中去计算这些值。这些值在任务建立时确定,或在改变任务优先级时更新。

OSTCBY=priority>>3;OSTCBBitY=OSMapTbl[priority>>3];OSTCBX=priority&0x07;OSTCBBitX=OSMapTbl[priority&0x07];运用TCB成员算法代码:使任务进入就绪态程序清单OSRdyGrp|=OSMapTbl[priority>>3];OSRdyTbl[priority>>3]|=OSMapTbl[priority&0x07];使任务进入就绪态程序清单OSRdyGrp|=OSTCBBitY;OSRdyTbl[OSTCBY]|=OSTCBBitX;(5)任务调度(TaskScheduling)

μC/OS-Ⅱ内核总是运行就绪态任务中优先级最高的。前面算法已确定最高优先级任务。下面由调度程序(Scheduler)完成该任务运行。任务级调度由函数OSSched()完成中断级调度由函数OSIntExt()完成根据实时内核的设计需求,μC/OS-Ⅱ任务调度程序运行所花费时间是个常数,与应用程序中建立的任务数无关。

程序清单任务调度程序(TaskScheduler)voidOSSched(void){

INT8Uy;

OS_ENTER_CRITICAL();

if((OSLockNesting|OSIntNesting)==0){ (1)

Y=OSUnMapTbl[OSRdyGrp]; (2)

OSPrioHighRdy=(INT8U)((y<<3)+OSUnMapTbl[OSRdyTbl[y]]); (2)

if(OSPrioHighRdy!=OSPrioCur){ (3)

OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy]; (4)

OSCtxSwCtr++;(5)

OS_TASK_SW();(6)

}}

OS_EXIT_CRITICAL();}任务调度的关闭和打开调用任务调度关闭函数、任务调度打开函数实现1、调用任务调度关闭函数OSSchedLock()以后,不得使用任何能将现行任务挂起的系统调用,因为这些调用会导致该任务睡眠,使得任务调度程序无法重新打开。2、用户可以在低优先级任务在进行事件发送期间,调用任务调度关闭函数,禁止任务调度。确保事件发送过程不被中断。

程序清单:任务调度程序关闭VoidOSSchedLock(void){

if(OSRunning==TRUE){

OS_ENTER_CRITICAL();

OSLockNesting++;

OS_EXIT_CRITICAL();

}}程序清单:任务调度程序打开voidOSSchedUnlock(void){

If(OSRunning==TRUE){

OS_ENTER_CRITICAL();

if(OSLockNesting>0){

OSLockNesting--;

if((OSLockNesting|OSIntNesting)==0){

OS_EXIT_CRITICAL();

OSSched();

}else{

OS_EXIT_CRITICAL();

}

}else{

OS_EXIT_CRITICAL();

}

}}(6)空闲任务(IdleTask)为了更好地控制多个实时任务运行,μC/OS-Ⅱ内核总是建立一个空闲任务,这个任务在没有其它任务进入就绪态时运行。空闲任务对应的函数代码为OSTaskIdle(),空闲任务永远设为最低优先级,即OS_LOWEST_PRI0。空闲任务OSTaskIdle()的主要工作,只是在不断地给一个32位的变量OSIdleCtr计数器加1

μC/OS-Ⅱ的空闲任务代码VoidOSTaskIdle(void*pdata){

Pdata=pdata;

for(;;){

OS_ENTER_CRITICAL();

OSIdleCtr++;

OS_EXIT_CRITICAL();

}}在计数器OSIdleCtr加1时,中断关闭,加1完成后中断再打开。这是因为,完成8位和多数16位微处理器对一个32位变量加1操作,需要多条指令,要防止高优先级任务或中断服务子程序ISR中断这个加1的指令执行过程。统计任务

为了完成应用程序代码完成各种时间统计,μC/OS-Ⅱ内核提供一个统计任务,任务函数为OSTaskStat()。只当在文件OS_CFG.H中,将符号常量OS_TASK_STAT_EN设为1,这个任务才会创建。一旦创建成功,统计任务OSTaskStat()每秒钟运行一次,计算当前的CPU利用率。程序清单

4.12初始化统计任务Voidmain(void){

OSInit();/*1、初始化uC/OS-II*/

/*2、安装uC/OS-II的任务切换向量(略)*/

/*3、创建用户起始任务TaskStart()(略)*/

OSStart();/*4、开始多任务调度*/}VoidTaskStart(void*pdata){

/*5、安装并启动uC/OS-II的时钟节拍(略)*/

OSStatInit();/*6、初始化统计任务*/

/*7、创建用户应用程序任务(略)*/

for(;;){

/*8、任务函数TaskStart()的代码!*/

}}程序清单4.14统计任务VoidOSTaskStat(void*pdata){

INT32Urun;

INT8Susage;

pdata=pdata;

while(OSStatRdy==FALSE){ (1)

OSTimeDly(2*OS_TICKS_PER_SEC);

}}

for(;;){

OS_ENTER_CRITICAL();

OSIdleCtrRun=OSIdleCtr;

run=OSIdleCtr;

OSIdleCtr=0L;

OS_EXIT_CRITICAL();

if(OSIdleCtrMax>0L){

usage=(INT8S)(100L-100L*run/OSIdleCtrMax); (2)

if(usage>100){OSCPUUsage=100;

}elseif(usage<0){

OSCPUUsage=0;

}else{OSCPUUsage=usage;

}

}else{OSCPUUsage=0;

}

OSTaskStatHook(); (3)

OSTimeDly(OS_TICKS_PER_SEC);

}系统初始化期间创建的任务应用程序必须先建立一个起始任务,如TaskStart(),当应用程序运行到main()中调用uC/OS-II内核启动函数OSStart(),μC/OS-Ⅱ内核一般已创建3个任务:TaskStart()、OSTaskIdle()和OSTaskStat()。μC/OS-Ⅱ将空闲任务优先级设为最低,即OS_LOWEST_PRIO,统计任务优先级设为次低,即OS_LOWEST_PRIO-1。启动任务TaskStart()总是优先级最高的任务,比如,优先级为0。(7)μC/OS中的中断处理

中断技术及其实现是任何一种实时内核必须提供的应用机制。实时内核应该能够支持应用程序设计实现自身需要的中断及中断处理子程序。μC/OS内核中,中断服务子程序要用汇编语言来写。如果用户使用的C语言编译器支持内置汇编语言,用户可以直接将中断服务子程序代码放在C语言的程序文件中。程序清单

μC/OS-II中的中断服务子程序用户中断服务子程序:

保存全部CPU寄存器;(1)

调用OSIntEnter或OSIntNesting直接加1;

(2)

执行用户代码做中断服务;(3)

调用OSIntExit();

(4)

恢复所有CPU寄存器;

(5)

执行中断返回指令;

(6)程序清单4.16中断进入函数:通知μC/OS-Ⅱ内核,中断服务子程序开始执行voidOSIntEnter(void){OS_ENTER_CRITICAL();

OSIntNesting++;

OS_EXIT_CRITICAL();}程序清单

4.17中断退出函数:通知μC/OS-Ⅱ内核,中断服务子程序执行完毕voidOSIntExit(void)

{OS_ENTER_CRITICAL();(1)

If((--OSIntNesting|OSLockNesting)==0){(2)

OSIntExitY=OSUnMapTbl[OSRdyGrp];(3)

温馨提示

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

评论

0/150

提交评论