收藏 分销(赏)

chap03-内核结构.ppt

上传人:pc****0 文档编号:10391267 上传时间:2025-05-26 格式:PPT 页数:80 大小:1.07MB
下载 相关 举报
chap03-内核结构.ppt_第1页
第1页 / 共80页
chap03-内核结构.ppt_第2页
第2页 / 共80页
点击查看更多>>
资源描述
西安邮电学院,计算机系,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,page,1,2025/5/26 周一,嵌入式实时操作系统,C,/OS-II,2025/5/26 周一,2,第,3,章 内核结构,3,2025/5/26 周一,本章给出C/OS-的主要结构概貌。内容,如下:,C/OS-是怎样处理临界段代码的;,什么是任务,怎样把用户的任务交给C/OS-;,任务是怎样调度的;,应用程序CPU的利用率是多少,C/OS-是怎样知道的;,怎样写中断服务子程序;,什么是时钟节拍,C/OS-是怎样处理时钟节拍的;,C/OS-是怎样初始化的,怎样启动多任务;,本章还描述以下函数,这些服务于应用程序:,OS_ENTER_CRITICAL(),和,OS_EXIT_CRITICAL(),OSInit,(),OSStart,(),OSIntEnter,(),和,OSIntExit,(),OSSchedLock,(),和,OSSchedUnlock,(),以及,OSVersion,().,4,3.0,临界段,(Critical Sections),C,/OS-,为了处理临界段代码需要,关中断,,处理完毕后再,开中断,。这使得,C,/OS-,能够避免同时有其它任务或中断服务进入临界段代码。,关中断的时间,是实时内核开发商应提供的最重要的指标之一,因为这个指标影响用户系统对实时事件的响应性。,5,C,/OS-,定义两个宏,(macros),来关中断和开中断,,以便避开不同,C,编译器厂商选择不同的方法来处理关中断和开中断。,C,/OS-,中的这两个宏调用分别是:,OS_ENTER_CRITICAL(),和,OS_EXIT_CRITICAL(),。因为这两个宏的定义取决于所用的微处理器,故在文件,OS_CPU.H,中可以找到相应宏定义。每种微处理器都有自己的,OS_CPU.H,文件。,6,3.1,任务,一个任务通常是一个无限的循环。,任务返回参数必须定义成,void,。,7,程序清单,L3.1,任务是一个无限循环,void,YourTask,(void*,pdata,),for(;),/*,用户代码*,/,调用,uC,/OS-II,的某种系统服务,:,OSMboxPend,();,OSQPend,();,OSSemPend,();,OSTaskDel(OS_PRIO_SELF,);,OSTaskSuspend(OS_PRIO_SELF,);,OSTimeDly,();,OSTimeDlyHMSM,();,/*,用户代码*,/,形式参数变量是由用户代码在第一次执行的时候带入的。请注意,该变量的类型是一个指向,void,的指针。这是为了允许用户应用程序传递任何类型的数据给任务。,亦可用,while(1),8,当任务完成以后,,任务可以自我删除,。注意任务代码并非真的删除了,,C,/OS-,只是简单地不再理会这个任务了,这个任务的代码也不会再运行,如果任务调用了,OSTaskDel,(),,这个任务绝不会返回什么。,void,YourTask,(void*,pdata,),/*,用户代码*,/,OSTaskDel(OS_PRIO_SELF,);,9,可以建立许多,相同的任务,,所有任务都使用同一个函数(或者说是同一个任务代码程序)。,例如,,用户可以将四个串行口安排成每个串行口都是一个单独的任务,而每个任务的代码实际上是相同的。并不需要将代码复制四次,用户可以建立一个任务,向这个任务传入一个指向某数据结构的指针变量,这个数据结构定义串行口的参数(波特率、,I/O,口地址、中断向量号等)。,10,C,/OS-,可以管理多达,64,个任务。,系统占用优先级:,0,、,1,、,2,、,3,、,OS_LOWEST_PRIO-3,、,OS_LOWEST_PRIO-2,,,OS_LOWEST_PRIO-1,以及,OS_LOWEST_PRIO,。,OS_LOWEST_PRIO,是作为定义的常数在,OS_CFG.H,文件中用定义常数语句,#define constant,定义的。,11,用户应用程序的一般结构,“用户任务”代码形式上很像,C,函数,但他不是函数!,“任务”不能被主函数,main(),或其他函数调用,只能被主函数或已激活任务,创建,。,任务的运行由操作系统调度管理。,void,MyTask1,(void*,pdata,),void,MyTask2,(void*,pdata,),void main(),OSInit,();,OSTaskCreate,(MyTask1,);,OSTaskCreate,(MyTask2,);,OSStart,();,12,3.2,任务状态,图,3.1,是,C,/OS-,控制下的任务状态转换图。在任一给定的时刻,任务的状态一定是在这五种状态之一。,睡眠态(,DORMANT,),指任务驻留在程序空间之中,还没有交给,C,/OS-,管理。把任务交给,C,/OS-,是通过调用下述两个函数之一:,OSTaskCreate,(),或,OSTaskCreateExt,(),。当任务一旦建立,这个任务就进入就绪态准备运行。,13,任务的状态及其转换,正在运行的任务,需要等待一段时间或需要等待一个事件发生再运行时,该任务就会把,CPU,的使用权让给别的任务而使任务进入等待状态,。,任务在没有被配备任务控制块或被剥夺了任务控制块时的状态叫做任务的睡眠状态,系统为任务配备了任务控制块且在任务就绪表中进行了就绪登记,这时任务的状态叫做就绪状态。,处于就绪状态的任务如果经调度器判断获得了,CPU,的使用权,,则任务就进入运行状态,一个正在运行的任务一旦响应中断申请就会中止运行而去执行中断服务程序,这时任务的状态叫做中断服务状态,14,15,3.3,任务控制块(,Task Control Blocks,OS_TCBs,),一旦任务建立了,任务控制块,OS_TCB,将被赋值(程序清单,3.3,)。任务控制块是一个数据结构,当任务的,CPU,使用权被剥夺时,,C,/OS-,用它来保存该任务的状态。当任务重新得到,CPU,使用权时,任务控制块能确保任务从当时被中断的那一点丝毫不差地继续执行,OS_TCB,全部驻留在,RAM,中。,16,typedef,struct,os_tcb,OS_STK *,OSTCBStkPtr,;,#if OS_TASK_CREATE_EXT_EN 0,void *,OSTCBExtPtr,;,OS_STK *,OSTCBStkBottom,;,INT32U,OSTCBStkSize,;,INT16U,OSTCBOpt,;,INT16U,OSTCBId,;,#,endif,struct,os_tcb,*,OSTCBNext,;,struct,os_tcb,*,OSTCBPrev,;,#if(OS_Q_EN 0)&(OS_MAX_QS 0)|(OS_MBOX_EN 0)|(OS_SEM_EN 0)|(OS_MUTEX_EN 0),OS_EVENT *,OSTCBEventPtr,;,#,endif,是指向当前任务栈顶的指针。,C,/OS-,允许每个任务有自己的栈,每个任务的栈的容量可以是任意的。,OSTCBStkPtr,是,OS_TCB,数据结构中唯一的一个能用汇编语言来处置的变量。,指向用户定义的任务控制块扩展。用户可以扩展任务控制块而不必修改,C,/OS-,的源代码。例如用户可以建立一个数据结构,这个数据结构包含每个任务的名字,或跟踪某个任务的执行时间,或者跟踪切换到某个任务的次数。,是指向任务栈底的指针。如果微处理器的栈指针是递减的,即栈存储器从高地址向低地址方向分配,则,OSTCBStkBottom,指向任务使用的栈空间的最低地址。反之亦然。可在任务运行时检验栈空间的使用情况。,存有栈中可容纳的指针元数目而不是用字节(,Byte,)表示的栈容量总数。,把“选择项”传给,OSTaskCreateExt,(),。,取值含义:,OS_TASK_OTP_STK_CHK,:用于告知,TaskCreateExt,(),,在任务建立的时候任务栈检验功能得到了允许。,OS_TASK_OPT_STK_CLR,:表示任务建立的时候任务栈要清零。只有在用户需要有栈检验功能时,才需要将栈清零。,OS_TASK_OPT_SAVE_FP,:通知,TaskCreateExt,(),,任务要做浮点运算。如果微处理器有硬件的浮点协处理器,则所建立的任务在做任务调度切换时,浮点寄存器的内容要保存。,OSTCBId,用于存储任务的识别码。,用于任务控制块,OS_TCBs,的双重链接,该链表在时钟节拍函数,OSTimeTick,(),中使用,用于刷新各个任务的任务延迟变量。,指向事件控制块的指针。,17,#if(OS_Q_EN 0)&(OS_MAX_QS 0)|(OS_MBOX_EN 0),void *,OSTCBMsg,;,#,endif,#if(OS_VERSION=251)&(OS_FLAG_EN 0)&(OS_MAX_FLAGS 0),#if OS_TASK_DEL_EN 0,OS_FLAG_NODE *,OSTCBFlagNode,;,#,endif,OS_FLAGS,OSTCBFlagsRdy,;,#,endif,指向传给任务的消息的指针。,Message received from,OSMboxPost,()or,OSQPost,(),指向事件标志节点,(flag node),的指针。,当任务等待事件标志组时,,OSTCBFlagsRdy,是使任务进入就绪态的事件标志。,18,INT16U,OSTCBDly,;,INT8U,OSTCBStat,;,INT8U,OSTCBPrio,;,INT8U OSTCBX;,INT8U OSTCBY;,INT8U,OSTCBBitX,;,INT8U,OSTCBBitY,;,#if OS_TASK_DEL_EN 0,BOOLEAN,OSTCBDelReq,;,#,endif,OS_TCB;,当需要把任务延时若干时钟节拍时要用到这个变量,或者需要把任务挂起一段时,间以等待某事件的发生,这种等待是有超时限制的。,值为,0,时含义?,是任务的状态字。当,.,OSTCBStat,为,0,,任务进入就绪态。可以,.,OSTCBStat,赋其它的值,在文件,uCOS_II.H,中有关于这个值的描述。,是任务优先级。高优先级任务的,.,OSTCBPrio,值小。也就是说,这个值越小,任务的优先级越高。,(0=highest,63=lowest),用于加速任务进入就绪态的过程或进入等待事件发生状态的过程(避免在运行中去计算这些值)。这些值是在任务建立时算好的,或者是在改变任务优先级时算出的。,是一个布尔量,用于表示该任务是否需要删除。,19,OS_MAX_TASKS,-,应用程序中可以有的最多任务数,,是在文件,OS_CFG.H,中定义的。这个最多任务数也是,C,/OS-,分配给用户程序的最多任务控制块,OS_TCB,的数目。将,OS_MAX_TASKS,的数目设置为用户应用程序实际需要的任务数可以减小,RAM,的需求量。,所有的任务控制块,OS_TCBs,都是放在任务控制块列表数组,OSTCBTbl,中的。,所有任务控制块,OS_TCBs,被链接成,单向空任务链表,。任务的建立与删除操作(见图)。,20,-1,21,任务控制块及任务控制块链表,任务控制块链表,空任务块链表是在,uC,/OS-II,初始化(,OSInit,(),)时系统自建的,用户可依据目标系统的实际需求,设定其链表长度。,OS_CFG.H,文件中的宏常数,OS_MAX_TASKS-,用于定义最大用户任务数。,UCOS_II.H,文件中的宏常数,OS_N_SYS_TASKS-,用于约定系统任务数,其值固定为,2,。,当应用程序调用函数,OSTaskCreate,(),创建一个任务时,这个函数会调用系统函数,OSTCBInit,(),来为任务控制块进行初始化。这个函数首先为被创建任务从空任务控制块链表获取一个任务控制块,然后用任务的属性对任务控制块各个成员进行赋值,最后再把这个任务控制块链入到任务控制块链表的头部。,当进行系统初始化时,初始化函数会按用户提供的任务数为系统创建具有相应数量的任务控制块并把它们链接为一个链表。,由于这些任务控制块还没有对应的任务,故这个链表叫做,空任务块链表,。即相当于是一些空白的身份证。,22,任务控制块链表,空任务控制块链表,23,uC,/OS-II,中提供了系统函数,OSTaskDel,(),,用于删除一个任务,-,实质就是将该任务的,TCB,从,“,任务控制块列表,”,移到了,“,空任务控制块列表,”,。,任务控制块及任务控制块链表,任务控制块,就相当于是一个任务的身份证,没有任务控制块的任务是不能被系统承认和管理。,任务控制块链表,24,任务控制块及任务控制块链表,任务控制块链表其他相关系统管理变量,OSTCBPrioTbl,:,OS_TCB*,数据类型的数组,以,Prio,为下标存放已使能的,TCB,指针。用于加速,TCB,的访问。,OSTCBCur,:全局系统变量,指向当前正在运行的任务的,TCB,。,OSTCBFreeList,、,OSTCBList,OSTCBTbl,-,OSInit,(),建立的任务控制块数组,OSTCBPrioTbl,-,任务控制块优先级数组,OSTCBCur,25,3.4,就绪表,每个任务被赋予不同的优先级等级,,从,0,级到最低优先级,OS_LOWEST_PRIO,,包括,0,和,OS_LOWEST_PR1O,在内(见文件,OS_CFG.H,)。,当,C,/OS-,初始化的时候,最低优先级,OS_LOWEST_PRIO,总是被赋给空闲任务,idle,task,。,最多任务数目,OS_MAX_TASKS,和,最低优先级数,是没有关系的,。,26,每个任务的就绪态标志都放入就绪表中的,就绪表中有两个变量,OSRedyGrp,和,OSRdyTbl,。,在,OSRdyGrp,中,任务按优先级分组,,8,个任务为一组。,OSRdyGrp,中的每一位表示,8,组任务中每一组中是否有进入就绪态的任务。,任务进入就绪态时,就绪表,OSRdyTbl,中的相应元素的相应位也置位。,就绪表,OSRdyTbl,数组的大小取决于,OS_LOWEST_PRIO,。当用户的应用程序中任务数目比较少时,减少,S_LOWEST_PRIO,的值可以降低,C,/OS-,对,RAM,(数据空间)的需求量。,27,为确定下次该哪个优先级的任务运行了,内核调度器总是将,OS_LOWEST_PRIO,在就绪表中相应字节的相应位置,1,。,OSRdyGrp,和,OSRdyTbl,之间的关系见图,3.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,。,28,29,使任务进入就绪态(,Prio,是任务的优先级,),OSRdyGrp,|=,OSMapTblprio,3;,OSRdyTblprio,3|=,OSMapTblprio,OSMapTbl,的值,Index Bit Mask(Binary),0 00000001,1 00000010,2 00000100,3 00001000,4 00010000,5 00100000,6 01000000,7 10000000,30,任务优先级的,低三位,用于确定任务在总就绪表,OSRdyTbl,中的所在位。,接下去的三位,用于确定是在,OSRdyTbl,数组的第几个元素。,OSMapTbl,是在,ROM,中的屏蔽字,用于限制,OSRdyTbl,数组的元素下标在,0,到,7,之间。,31,如果一个任务被,删除,了,则用下述程序清单中的代码做,求反处理,。,程序清单,从就绪表中删除一个任务,if(,OSRdyTblprio,3&=,OSMapTblprio,&0 x07)=0),OSRdyGrp,&=,OSMapTblprio,3;,以上代码将就绪任务表数组,OSRdyTbl,中,相应元素的相应位清零,,而对于,OSRdyGrp,,,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时,才将相应位清零,。,32,为了找到那个,进入就绪态的优先级最高的任务,,并不需要从,OSRdyTbl0,开始扫描整个就绪任务表,只需要查另外一张表,即优先级判定表,OSUnMapTbl(256)(,见文件,OS_CORE.C),。,OSRdyTbl,中每个字节的,8,位代表这一组的,8,个任务哪些进入就绪态了,低位的优先级高于高位。,利用这个字节为下标来查,OSUnMapTbl,这张表,,返回的字节就是该组任务中就绪态任务中优先级最高的那个任务所在的位置,。这个返回值在,0,到,7,之间。,33,程序清单,找出进入就绪态的优先级最高的任务,y=,OSUnMapTblOSRdyGrp,;,x=,OSUnMapTblOSRdyTbly,;,prio,=(y 3)+x;,34,例如,如果,OSRdyGrp,的值为二进制,01101000(0 x68),,查,OSUnMapTblOSRdyGrp,得到的值是,3,,它相应于,OSRdyGrp,中的第,3,位,bit3,,这里假设最右边的一位是第,0,位,bit0,。类似地,如果,OSRdyTbl3,的值是二进制,11100100(0 xE4),则,OSUnMapTblOSRdyTbc3,的值是,2,,即第,2,位。于是任务的优先级,Prio,就等于,26,(,3*8+2,)。利用这个优先级的值。查任务控制块优先级表,OSTCBPrioTbl,,得到指向相应任务的任务控制块,OS_TCB,的工作就完成了。,35,36,3.5,任务调度,C,/OS-,总是运行进入就绪态任务中优先级最高的那一个,。确定哪个任务优先级最高,下面该哪个任务运行了的工作是由调度器(,Scheduler,)完成的。任务级的调度是由函数,OSSched,(),完成的。中断级的调度是由另一个函数,OSIntExt,(),完成的。,37,程序清单,L3.8,任务调度器(,the Task Scheduler,),void,OSSched,(void),INT8U y;,OS_ENTER_CRITICAL();,if(,OSLockNesting,|,OSIntNesting,)=0),y=,OSUnMapTblOSRdyGrp,;,OSPrioHighRdy,=(INT8U)(y,OSTCBStkPtr,=SP;,OSTCBCur,=,OSTCBHighRdy,;,SP =,OSTCBHighRdy,-,OSTCBStkPtr,;,将,R4,R3,R2,及,R1,从新堆栈中弹出,;,执行中断返回指令,;,任务切换宏,OS_TASK_SW(),依次完成的,7,项工作:,被中止,Task,的断点指针(,PC,)入栈保护,被中止,Task,通用寄存器入栈保护,被中止,Task,系统管理,SP,该,TCB-,OSTCBStkPtr,获得待运行任务,TCB,获得待运行任务,TCB-,OSTCBStkPtr,恢复待运行任务,CPU,现场(不包含,PC,),切换,CPU.PC,,使,CPU,接续运行待运行,Task,断点。,备注:,Step1-,中断方式保护;,Step7-IRET,指令恢复,PC,;汇编语言编程,OS_TASK_SW()-,直接操作寄存器,3.7,给调度器上锁和开锁,(Locking and,UnLocking,the Scheduler),给调度器,上锁函数,OSSchedlock,(),(用于禁止任务调度,直到任务完成后调用给调度器,开锁函数,OSSchedUnlock,(),为止。,OSSchedlock,(),和,OSSchedUnlock,(),必须成对使用。,变量,OSLockNesting,跟踪,OSSchedLock,(),函数被调用的次数,以允许嵌套的函数包含临界段代码,这段代码其它任务不得干预。,C,/OS-,允许嵌套深度达,255,层。当,OSLockNesting,等于零时,调度重新得到允许。,46,程序清单 给调度器上锁,void,OSSchedLock,(void),#if OS_CRITICAL_METHOD=3,OS_CPU_SR,cpu_sr,;,#,endif,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();,48,调用,OSSchedLock,(),以后,用户的应用程序不得使用任何能将现行任务挂起的系统调用,。也就是说,用户程序,不得调用,OSMboxPend,(),、,OSQPend,(),、,OSSemPend,(),、,OSTaskSuspend(OS_PR1O_SELF),、,OSTimeDly,(),或,OSTimeDlyHMSM,(),直到,OSLockNesting,回零为止。因为调度器上了锁,用户就锁住了系统,任何其它任务都不能运行。,当低优先级的任务要发消息给多任务的邮箱、消息队列、信号量时,用户不希望高优先级的任务在邮箱、队列和信号量没有得到消息之前就取得了,CPU,的控制权,此时,用户可以使用禁止调度器函数。,49,3.8,空闲任务,(Idle Task),C,/OS-,总是建立一个,空闲任务,,这个任务在没有其它任务进入就绪态时投入运行。,这个空闲任务,OSTaskIdle,(),永远设为,最低优先级,,即,OS_LOWEST_PRIO,。,空闲任务,OSTaskIdle,(),什么也不做,只是在不停地给一个,32,位的名叫,OSIdleCtr,的计数器,加,1,,,统计任务使用这个计数器以确定现行应用软件实际消耗的,CPU,时间,。,50,程序清单,L3.11,C,/OS-,的空闲任务,void,OSTaskIdle,(void*,pdata,),#if OS_CRITICAL_METHOD=3,OS_CPU_SR,cpu_sr,;,#,endif,pdata,=,pdata,;,for(;),OS_ENTER_CRITICAL();,OSIdleCtr,+;,OS_EXIT_CRITICAL();,OSTaskIdleHook,();,51,计数器加,1,在某些处理器中需要多条指令。,可在此函数中写入任何用户代码。如使,CPU,执行,STOP,指令。,3.9,统计任务,OSTaskStat,(),-,运行时间统计的任务。如果用户将系统定义常数,S_TASK_STAT_EN,(见文件,OS_CFG.H,)设为,1,,这个任务就会建立。,OSTaskStat,(),每秒钟运行一次,(见文件,OS_CORE.C,),,计算当前的,CPU,利用率,。告诉用户应用程序使用了多少,CPU,时间,用百分比表示。,如果用户应用程序打算使用统计任务,,用户必须在初始化时建立一个唯一的任务,,在这个任务中调用,OSStatInit,(),。,52,程序清单,L3.12,初始化统计任务,.,void main(void),OSInit,();/*,初始化,uC,/OS-II*/,/*,安装,uC,/OS-II,的任务切换向量*,/,/*,创建用户起始任务,(,为了方便讨论,这里以,TaskStart,(),作为起始任务,)*/,OSStart,();/*,开始多任务调度,*/,void,TaskStart,(void*,pdata,),/*,安装并启动,uC,/OS-II,的时钟节拍,(4)*/,OSStatInit,();/*,初始化统计任务,(5)*/,/*,创建用户应用程序任务*,/,for(;),/*,这里是,TaskStart,(),的代码,!*/,53,程序清单,L3.13,统计任务的初始化,.,void,OSStatInit,(void),#if OS_CRITICAL_METHOD=3,OS_CPU_SR,cpu_sr,;,#,endif,OSTimeDly(2);,OS_ENTER_CRITICAL();,OSIdleCtr,=0L;,OS_EXIT_CRITICAL();,OSTimeDly(OS_TICKS_PER_SEC,);,OS_ENTER_CRITICAL();,OSIdleCtrMax,=,OSIdleCtr,;,OSStatRdy,=TRUE;,OS_EXIT_CRITICAL();,55,程序清单,L3.14,统计任务,void,OSTaskStat,(void*,pdata,),INT32U run;,INT8S usage;,pdata,=,pdata,;,while(,OSStatRdy,=FALSE)(1),OSTimeDly(2*OS_TICKS_PER_SEC);,56,max=OSIdleCtrMax/100L;,for(;),OS_ENTER_CRITICAL();,OSIdleCtrRun,=,OSIdleCtr,;,run=,OSIdleCtr,;,OSIdleCtr,=0L;,OS_EXIT_CRITICAL();,if(max 0L),usage=(INT8S)(100L-run/max);,if(usage=0),OSCPUUsage,=usage;,else,OSCPUUsage,=0;,else,OSCPUUsage,=0;,max =,OSIdleCtrMax,/100L;,OSTaskStatHook,();,OSTimeDly(OS_TICKS_PER_SEC,);,57,可由用户定义的函数,能使统计任务得到扩展。,58,3.10,C,/OS,中的中断处理,C,/OS,中,中断服务子程序要用汇编语言来写。然而,如果用户使用的,C,语言编译器支持在线汇编语言的话,用户可以直接将中断服务子程序代码放在,C,语言的程序文件中。,59,程序清单,L3.15,C,/OS-II,中的中断服务子程序,.,用户中断服务子程序,:,保存全部,CPU,寄存器,;,调用,OSIntEnter,或,OSIntNesting,直接加,1,;,if(,OSIntNesting,=1),OSTCBCur,-,OSTCBStkPtr,=SP;,清中断源,;,重新开中断,;,执行用户代码做中断服务,;,调用,OSIntExit,(),;,恢复所有,CPU,寄存器;,执行中断返回指令;,60,跳转到相应的中断向量,程序清单 通知,C,/OS-,,中断服务子程序开始了,.,void,OSIntEnter,(void),if(,OSRuning,=TRUE),if(,OSIntNesting,0),OSIntNesting,-;,63,if(,OSIntNesting,=0)&(,OSLockNesting,=0),OSIntExitY,=,OSUnMapTblOSRdyGrp,;,OSPrioHighRdy,=(INT8U)(OSIntExitY,OSTCBStkPtr,=SP;,调用,OSTimeTick,();,清发出中断设备的中断,;,重新允许中断,;(,可选,),调用,OSIntExit,();,恢复处理器寄存器的值,;,执行中断返回指令,;,68,程序清单,时钟节拍函数,OSTimtick,(),的一个节拍服务,void,OSTimeTick,(void),OS_TCB*,ptcb,;,OSTimeTickHook,();,ptcb,=,OSTCBList,;,while(,ptcb,-,OSTCBPrio,!=OS_IDLE_PRIO),OS_ENTER_CRITICAL();,if(,ptcb,-,OSTCBDly,!=0),if(-,ptcb,-,OSTCBDly,=0),if(!(,ptcb,-,OSTCBStat,&OS_STAT_SUSPEND),OSRdyGrp,|=,ptcb,-,OSTCBBitY,;,OSRdyTblptcb,-OSTCBY|=,ptcb,-,OSTCBBitX,;,else,ptcb,-,OSTCBDly,=1;,ptcb,=,ptcb,-,OSTCBNext,;,OS_EXIT_CRITICAL();,OS_ENTER_CRITICAL();,OSTime,+;,OS_EXIT_CRITICAL();,69,时钟节拍中断服务一开始给用户做工作,从,OSTCBList,开始,沿着,OS_TCB,链表做,一直做到空闲任务。,当某任务的任务控制块中的时间延时项,OSTCBDly,减到,了零,这个任务就进入了就绪态。,确切被任务挂起的函数,OSTaskSuspend,(),挂起的任务则不会进入就绪态。,过调用,OSTime,(),累加从开机以来的时间,用的是一个无符号,32,位变量。,可以从,任务级调用,OSTimeTick,(),。,程序清单,时钟节拍任务,TickTask,(),作时钟节拍服务,.,void,TickTask,(void*,pdata,),pdata,=,pdata,;,for(;),OSMboxPend,(.);/*,等待从时钟节拍中断服务程序发来的信号*,/,OSTimeTick,();,OS_Sched,();,70,程序清单 时钟节拍中断服务函数,OSTickISR,(),做节拍服务。,void,OSTickISR(void,),保存处理器寄存器的值;,调用,OSIntEnter,(),或是将,OSIntNesting,加,1;,if(,OSIntNesting,=1),OSTCBCur,-,OSTCBStkPtr,=SP;,发送一个空消息,(,例如,,(void*)1),到时钟节拍的邮箱,;,调用,OSIntExit,();,恢复处理器寄存器的值,;,执行中断返回指令,;,71,INT16U d=0;,INT16U d1=0;,void,OSTimeTickHook,(void),char*s0=“500”;,char*s1=“,每”,;,char*s2=“,次中断的调度次数”,;,char s8;,if(d,=500),PC_DispStr(14,4,s1,DISP_BGND_BLACK+DISP_FGND_WHITE);,PC_DispStr(18,4,s0,DISP_BGND_BLACK+DISP_FGND_WHITE);,PC_DispStr(24,4,s2,DISP_BGND_BLACK+DISP_FGND_WHITE);,sprintf(s,”%d”,OSCtxSwCtr,);,PC_DispStr(20,d1+5,s,DISP_BGND_BLACK+DISP_FGND_WHITE);,d=0;,d1+=1;,d+=1;,OSTimeTickHook,(),是系统调用的函数,为了方便应用程序设计人员能在系统调用的函数中插入一些自己的工作。,3.13,C,/OS-,初始化,在调用,C,/OS-,的任何其它服务之前,,C,/OS-,要求用户首先调用系统初始化函数,OSInit,(),。,OSInit,(),初始化,C,/OS-,所有的变量和数据结构(见,OS_CORE.C,)。,OSInit,(),建立空闲任务,idle,task,,这个任务总是处于就绪态的。空闲任务,OSTaskIdle,()的优先级总是设成最低,即,OS_LOWEST_PRIO,。,如果统计任务允许,OS_TASK_STAT_EN,和任务建立扩展允许都设为,1,,则,OSInit,(),还得建立统计任务,OSTaskStat,(),并且让其进入就绪态。,OSTaskStat,的优先级总是设为,OS_LOWEST_PRIO-1,。,73,下图表示调用,OSInit,(),之后,一些,C,/OS-,变量和数据结构之间的关系。其解释是基于以下假设的:,在文件,OS_CFG.H,中,,OS_TASK_STAT_EN,是设为,1,的。,在文件,OS_CFG.H,中,,OS_LOWEST_PRIO,是设为,63,的。,在文件,OS_CFG.H,中,最多任务数,OS_MAX_TASKS,是设成大于,2,的。,74,空任务控制块,空事件表,空队列表,空存储区,缓冲区的容量在,OS_CFG.H,中定义,3.13,C,/OS-,的启动,多任务的启动是用户通过调用,OSStart,(),实现的。启动,C,/OS-,之前,用户至少要建立一个应用任务。,程序清单,初始化和启动,C,/OS-,void main(void),OSInit,();/*,初始化,uC,/OS-II*/,.,.,通过调用,OSTaskCreate,(),或,OSTaskCreateExt,(),创建至少一个任务,;,.,.,OSStart,();/*,开始多任务调度,!,OSStart,(),永远不会返回*,/,程序清单 启动多任务,.,void,OSStart,(void),INT8U y;,INT8U x;,if(,OSRunning,=FALSE),y=,OSUnMapTblOSRdyGrp,;,x=,OSUnMapTblOSRdyTbly,;,OSPrioHighRdy,=(INT8U)(y 3)+x);,OSPrioCur,=,OSPrioHighRdy,;,OSTCBHighRdy,=,OSTCBPrioTblOSPrioHighRdy,;,OSTCBCur,=,OSTCBHighRdy,;,OSStartHighRdy,();,见汇编语言文件,OS_CPU_A.ASM),,这个文件与选择的微处理器有关。将任务栈中保存的值弹回到,CPU,寄存器中,然后执行一条中断返回指令,中断返回指令强制执行该任务代码。,3.14,获取当前,C,/OS-,的版本号,应用程序调用,OSVersion,,可以得到当前,C,/OS-,的版本号。,OSVersion,(),函数返回版本号值乘以,100,。换言之,,200,表示版本号,2.00,。,程序清单,得到,C,/OS-,当前版本号,INT16U,OSVersion,(void),return(OS_VERSION);,,
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手

当前位置:首页 > 百科休闲 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服