第2章 μCOS与μCOS-II的任务part2_第1页
第2章 μCOS与μCOS-II的任务part2_第2页
第2章 μCOS与μCOS-II的任务part2_第3页
第2章 μCOS与μCOS-II的任务part2_第4页
第2章 μCOS与μCOS-II的任务part2_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

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

文档简介

1、1v 多任务操作系统的核心:任务调度。v 调度定义:就是通过一个算法在多个任务中确定哪个任务来运行。做这项工作的就是调度器。v 任务调度的思想:总是让优先级最高的就绪任务处于运行状态。v uC/OS-II进行任务调度的依据:任务就续表。2.2.9 就绪任务表及任务调度为了能使系统清楚地知道系统中哪些任务已经就绪,哪些还没有就绪,UC/OS-II在RAM中设立了一个记录表,系统中的每个任务都在这个表占据一个位置,并用这个位置的状态(1或者0)来表示任务是否处于就绪状态。这个表就叫做任务就绪表。2每个就绪的任务都放入就绪表中,就绪表有两个变量:OSRdyGrp、OSRdyTblINT8U OSRd

2、yGrp1207654300XXXYYY任务优先级201765431089151413121118161723222120192624253130292827343233393837363542404147464544435048495554535251585657636261605901234567XY优先级最低任务优先级最高任务任务优先级号(idle task)2.2.9.1 任务就绪表的结构图2-10 就绪表的结构由于每个任务的就绪状态只占一位,因此OSRdyTbl数组的一个元素可表达8个任务的就绪状态。即每一个数组元素描述了8个任务的就绪状态,于是这8个任务就可以看成一个任务组。为了便

3、于就绪表的查找,UC/OS-II又定义了一个数据类型为INT8U的变量OSRdyGrp,该变量的每一个位都对应OSRdyTbl的一个任务组(即数组的一个元素)。INT8U OSRdyTbl832.2.9.1 任务就绪表的结构(续)如何根据任务的优先级别查找任务在就绪表的位置呢例:已知某一个已经就绪的任务优先级别为prio=30,试判断应该在就绪表的哪一位置上置1。分析:由于优先级别是一个单字节的数字,而且最大值不会超过63,即二进制00111111,因此,可以把优先级别看成是一个6位的二进制数,这样就可以用高3位(D5、D4、D3)来指明变量OSRdyGrp的具体数据位,并用来确定就绪表数组元

4、素的下标;用低3位(D2、D1、D0)来指明该数组元素的具体数据位。答:30的二进制形式为00011110,其低6位为011110,于是可知应该在OSRdyTbl3的D6位上置1,同时要把变量OSRdyGrp的D3位置1。42.2.9.2 对任务就绪表的操作在程序中,可用类似于下面的代码把优先级为prio的任务置为就绪态。OSRdyGrp | = OSMapTblprio3;OSRdyTblprio3 | = OSMapTblprio & 0 x07;其中,OSMapTbl是uC/OS-II为加快运算速度定义的一个数组,各元素为: OSMapTbl0 = 0000 0001B OSMa

5、pTbl1 = 0000 0010B OSMapTbl2 = 0000 0100B OSMapTbl3 = 0000 1000B OSMapTbl4 = 0001 0000B OSMapTbl5 = 0010 0000B OSMapTbl6 = 0100 0000B OSMapTbl7 = 1000 0000B如果要使一个优先级为prio的任务脱离就绪态,则可使用如下代码: If(OSRdyTblprio3 &= OSMapTblprio & 0 x07)=0) OSRdyGrp &= OSMapTblprio3;脱离就绪态:将任务就绪表OSRdyTblprio3相应元

6、素的相应位清零,而且当OSRdyTblprio3中的所有位都为零时,即全组任务中没有一个进入就绪态时,OSRdyGrp的相应位才为零。52.2.9.2 对任务就绪表的操作(续)例:欲使优先级为12的任务进入就绪态,设置就绪表。答:优先级为12,即00001100B。OSRdyGrp | = OSMapTblprio3 ; (OSMapTbl1 = 0000 0010)OSRdyTbl1 | = OSMapTblprio &0 x07 ; (OSMapTbl4 = 0001 0000)例:欲使优先级为12的任务脱离就绪态,设置就绪表。答:优先级为12,即00001100B。OSMapTb

7、lprio & 0 x07 = OSMapTbl4 = 11101111OSMapTblprio3 = OSMapTbl1 = 11111101如果OSRdyTblprio3 &= OSMapTblprio & 0 x07 = 0 (该行所有任务都是非就绪态)则OSRdyGrp = OSRdyGrp & OSMapTblprio3 = 06从任务就绪表中获取优先级别最高的就绪任务可用如下代码:2.2.9.3 采用查表法确定高优先级任务Y = OSUnMapTblOSRdyGrp;/获得优先级别的D5、D4、D3位X = OSUnMapTblOSRdyTblY;

8、/获得优先级别的D2、D1、D0位Prio =(Y3)+X; /获得就绪任务的优先级别其中,OSUnMapTbl同样是uC/OS-II为加快运算速度定义的一个数组,共有256个元素:INT8U const OSUnMapTbl16*16 = 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,

9、 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,

10、 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;举例:如已知OSRdyG

11、rp的值为01101000B,即104,则查得OSUnMapTblOSRdyGrp的值是3。如已知OSRdyTbl3的值是11100100B,即228,则查OSUnMapTblOSRdyTbl3的值是2。则进入就绪态的最高任务优先级。 Prio=3*8+2=26 UC/OS-II经常使用类似于就绪表的形式来记录任务的某种状态,因此一定要熟悉这种表的结构以及对这种表的基本操作。7p任务切换:在多任务系统中,令CPU中止当前正在运行的任务而去运行另一个任务的工作。p任务调度:按某种规则进行任务切换的工作。p调度的发生条件:系统或用户任务调用系统函数或者执行中断服务程序结束时。p任务调度由任务调度器

12、完成,调度器主要工作: 1. 在任务就绪表中查找具有最高优先级别的就绪任务。 2. 实现任务切换。uC/OS-II有两种调度器: 任务级调度器(由OSSched()实现)、中断级调度器(由OSIntExt()实现)。任务切换的两个步骤:1. 获得待运行任务的TCB指针。2. 进行断点数据的切换。2.2.9.4 任务的调度82.2.9.4 任务的调度(续)1. 获得待运行任务的TCB指针void OSSched (void) INT8U y; OS_ENTER_CRITICAL(); if (OSLockNesting | OSIntNesting) = 0) / 未被上锁且不是中断服务程序调用

13、 y = OSUnMapTblOSRdyGrp; OSPrioHighRdy = (INT8U)(y OSTCBStkPtr = SP; /把SP保存在中止任务控制块中OSTCBCur = OSTCBHighRdy; /使系统获得待运行任务控制块SP = OSTCBHighRdy - OSTCBStkPtr; /把待运行任务堆栈指针赋给SP用出栈指令把R1、R2.弹入CPU的通用寄存器;112.2.9.4 任务的调度(续)2. 任务切换宏OS_TASK_SW()-续,保存或者重置PC完成第1项、第7项工作的示意性代码段如下:void OSCtxSw(void) 用压栈指令把CPU通用寄存器R1

14、、R2.压入堆栈; OSTCBCur - OSTCBStkPtr = SP; /在中止任务控制块中保存SP. OSTCBCur = OSTCBHighRdy; /任务控制块的切换 SP = OSTCBHighRdy - OSTCBStkPtr; /使SP指向待运行任务堆栈 用出栈指令把R1、R2.弹入CPU的通用寄存器; IRET; /中断返回;使PC指向待运行任务只有使程序指针PC寄存器获得新任务的地址,才会使CPU运行新的任务。L 遗憾的是,目前的处理器一般没有对程序指针寄存器PC的出栈和入栈指令。想办法引发一次中断(或调用),让中断向量指向OSCtxSw(),利用系统在跳转到中断服务程序

15、时会自动把断点指针压入堆栈的功能。而利用中断返回指令IRET把断点指针推入CPU的PC寄存器,恢复待运行任务的断点,这样就可以实现断点的保存和恢复了。其实这个函数就是中断服务程序那么由什么来引发中断呢?可在OS_TASK_SW()这个宏中封装一个软中断指令或调用指令122.2.9.5 任务切换过程获得待运行任务的任务控制块恢复待运行任务的运行环境处理器的PC=任务堆栈中的断点地址处理器的SP=任务块中保存的SP如何获得待运行任务的任务控制块?根据就绪表获得待运行任务的任务控制块指针其实,调度器在进行调度时,在这个位置还要进行一下判断:究竟待运行任务是否为当前任务,如果是,则不切换;如果不是才切

16、换,而且还要保存被中止任务的运行环境。132.2.10 任务的创建 uC/OS-II是通过任务控制块来管理任务的。 uC/OS-II有两个用来创建任务的函数:TaskCreate()、OSTaskCreateExt() OSTaskCreate()向下兼容,OSTaskCreateExt()是前一函数的扩展,提供 了一些附加功能。 任务可以在多任务调度开始前建立,也可以在其他任务执行过程中建立。 任务不能由中断服务程序建立。142.2.10.1 用函数OSTaskCreate()创建任务应用程序通过调用函数OSTaskCreate()来创建一个任务,函数OSTaskCreate()源代码如下:

17、INT8U OSTaskCreate ( void (*task)(void *pd), / 指向任务的指针 void *pdata, / 传递给任务的参数 OS_STK *ptos, / 指向任务堆栈栈顶的指针 INT8U prio / 任务的优先级 ) void *psp; INT8U err; if (prio OS_LOWEST_PRIO) / 检测任务的优先级是否合法 return (OS_PRIO_INVALID); OS_ENTER_CRITICAL(); if (OSTCBPrioTblprio = (OS_TCB *)0) / 确认优先级未被使用 OSTCBPrioTblpr

18、io = (OS_TCB *)1; / 保留优先级 OS_EXIT_CRITICAL(); psp = (void *)OSTaskStkInit(task, pdata, ptos, 0); / 初始化任务堆栈 err = OS_TCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); / 获得并初始化任务控制块 if (err = OS_NO_ERR) OS_ENTER_CRITICAL(); OSTaskCtr+; / 任务计数器加1 OS_EXIT_CRITICAL();任务的优先级必须在0到OS_LOWEST_PRIO之间建立任务的堆栈,返

19、回新的堆栈栈顶,注意堆栈增长方向从空闲的OS_TCB池中获得并初始化一个OS_TCB152.2.10.1 用函数OSTaskCreate()创建任务(续)应用程序通过调用函数OSTaskCreate()来创建一个任务,函数OSTaskCreate()源代码如下: if (OSRunning) OSSched(); / 任务调度 else OS_ENTER_CRITICAL(); OSTCBPrioTblprio = (OS_TCB *)0; / 放弃任务 OS_EXIT_CRITICAL(); return (err); else OS_EXIT_CRITICAL(); return (OS_

20、PRIO_EXIST); 如果OSTaskCreate()函数是在某个任务的执行过程中被调用(OSRunning=1),则任务调度函数会被调用来判断是否新建立的任务比原来的任务有更高的优先级。如果新任务的优先级更高,内核会进行一次任务切换。从OSTCBInit()返回后,要检验返回代码,如果成功,就增加OSTaskCtr,OSTaskCtr用于保存产生的任务数目。如果OSTCBInit()返回失败,就置OSTCBPrioTblprio的入口为0以放弃该任务的优先级。162.2.10.2 用函数OSTaskCreateExt()创建任务应用程序还可以通过调用函数OSTaskCreateExt()

21、来创建一个任务,用此函数创建任务将更加灵活,但也会增加开销,函数OSTaskCreateExt()源代码如下:INT8U OSTaskCreateExt( void (*task)(void *pd), / 指向任务的指针 void *pdata, / 传递给任务的参数 OS_STK *ptos, / 指向任务堆栈栈顶的指针 INT8U prio, / 任务的优先级 INT16U id,/ 任务的标示 OS_STK *pbos,/ 任务堆栈栈底的指针 INT32U stk_size,/ 任务堆栈的容量 void *pext,/ 指向附加数据域的指针INT16U opt/ 用于设置操作选项);1

22、72.2.10.3 创建任务的一般方法v 可在调用函数OSStart()启动任务调度之前来创建。v 在任务中来创建。v uC/OS-II的规定:在OSStart()启动任务调度之前必须创建至少一个用户任务。 这样,在OSStart()之前先创建一个任务,并赋予它最高的优先级,从而使它 成为起始任务,然后在这个起始任务中,再创建其它各任务。 如果要使用系统提供的统计任务,则统计任务的初始化函数必须在这个起始任务中来调用。v uC/OS-II不允许在中断服务程序中创建任务182.2.10.3 创建任务的一般方法/*主函数*/void main(void)OSInit();/ 对uC/OS-II初始

23、化OSTaskCreate(TaskStart,);/ 创建起始任务OSStart();/ 开始多任务调度/*起始任务*/void TaskStart(void *pdata)/ 在这个位置安装并启动uC/OS-II时钟OSStatInit();/ 初始化统计任务/ 在这个位置创建其它任务For(;)起始任务的代码19例程2-1:设计一个只有一个任务Task1,当程序运行后任务的工作就是每秒在显示器上显示一个字符“M”。练习2-1:在例2-1应用程序的任务myTask中再创建一个任务yourTask 。当程序运行后,任务myTask的工作在显示器上显示一个字符“M”;yourTask 则是在显

24、示器上显示字符 “Y”,两个任务延时同样的时间1s。202.2.11 任务的挂起和恢复 所谓挂起一个任务,就是停止这个任务的运行。 在uC/OS-II中,用户任务可通过调用系统提供的函数OSTaskSuspend(INT8U prio)来挂起自身或者除空闲任务之外的其他任务。用函数OSTaskSuspend(INT8U prio)挂起的任务,只能在其它任务中通过调用恢复函数OSTaskResume(INT8U prio)使其恢复为就绪状态。等待状态就绪状态运行状态OS_TASK_SW()OSTaskResume(prio)OSTaskSuspend(prio) 任务的CPU使用权被剥夺图2-1

25、2 任务的挂起和恢复212.2.11.1 任务的挂起挂起任务函数OSTaskSuspend()的原型如下:INT8U OSTaskSuspend ( INT8U prio ); 图2-13 函数OSTaskSuspend()流程图进入Prio是空闲任务?Prio是合法优先级? Prio=0 xFF? 标志self=TRUE并取任务TCB的指针取消任务的就绪状态并在控制块中记录 标志self=TRUE? 调用任务调度器OS_Sched()返回OS_NO_ERR 返回OS_TASK_SUSPEND_IDLE 返回OS_PRIO_INVALID 标志self=FALSE并取任务TCB的指针 指针非空

26、? 返回OS_TASK_SUSPEND_PRIOYESYESYESYESYESYESNONONONONOPrio为待挂起任务的优先级。如果调用函数OSTaskSuspend()的任务要挂起自身,则参数为自身优先级或者常数OS_PRIO_SELF(该常数在文件uCOS_II.H中被定义为0 xFF)。如果是任务本身,则必须删除任务在就绪表中的就绪标志,并在任务控制块成员OSTCBStat中做了挂起记录之后,引发一次任务调度,以使CPU去运行就绪的其他任务。否则删除任务就绪表中被挂起任务的就绪标志,并将状态迁移。222.2.11.2 任务的恢复恢复任务函数OSTaskResume()的原型如下:

27、INT8U OSTaskResume ( INT8U prio ); 图2-14 函数OSTaskResume()流程图进入Prio是合法优先级? 取任务TCB的指针取消任务在控制块中的挂起记录使之就绪 调用任务调度器OS_Sched()返回OS_NO_ERR 返回OS_PRIO_INVALID 指针非空? 返回OS_TASK_SUSPEND_PRIOYESYESNONO 返回 OS_TASK_NOT_SUSPENDNO 任务存在&被 挂起的&延时时间 为0?YES任务确实是一个已存在的挂起任务,同时它又不是一个延时任务(任务控制块成员OSTCBDly = 0)。232.2.1

28、2 调度器的上锁和开锁给调度器上锁函数OSSchedlock()用于禁止任务的调度,直到调用给调度器开锁函数OSSchedUnlock()为止。调用OSSchedlock()的任务保持对CPU的使用权,尽管有优先级更高的任务进入了就绪态。但此时中断让然可以识别,中断服务也能得到处理(假设中断打开)。 注意:OSSchedlock()和OSSchedUnlock()必须成对使用,这两个函数之间的代码,其它任务不能干预;函数OSSchedlock()和OSSchedUnlock()的使用要非常谨慎,因为它们影响uC/OS-II对任务的正常管理。void OSSchedlock (void) /给调

29、度器上锁函数void OSSchedUnlock (void) /给调度器解锁函数调度器上锁和解锁函数原型如下: 242. 改造练习2-1的任务MyTask,当任务MyTask运行5次时,用函数OSSchedLock()对调度器进行加锁;而当任务MyTask运行到第20次时,再用函数OSSchedUnlock()对调度器进行解锁,并运行该程序。 练习2-2:1. 修改练习2-1应用程序的任务YourTask 。要求任务YourTask运行10次后,挂起任务MyTask;任务YourTask运行20次后,恢复任务MyTask。提示:1、查看OS_corc.c 中OSSched()(什么时候进行任

30、务切换?)/OSTimeTick()(时钟节拍函数,负责将延时的任务每来一个时钟节拍延时数减一)Time.c OSTimeDly() OSTimeDlyHMSM() 函数2、任务等待状态:挂起(由suspend引起)、延时等待(OSTCBDly)3、复习常用数据结构252.2.13 改变任务优先级在用户建立任务的时候会分配给任务一个优先级。在程序运行期间,用户可以通过调用OSTaskChangePrio()来改变任务的优先级。换句话说,就是C/OS-允许用户动态的改变任务的优先级。如果优先级修改成功则函数返回OS_NO_ERR;如果newprio已经存在则函数返回OS_PRIO_EXIST。函

31、数OSTaskChangePrio()的原型如下: INT8U OSTaskChangePrio( INT8U oldprio, / 任务现在的优先级 INT8U newprio / 要修改的优先级 ); 262.2.14 任务的删除 删除任务,就是把该任务处于休眠状态。 并不是说任务的代码真的被删除了,只是任务的代码不再被操作系统调用。 通过调用OSTaskDel()就可以完成删除任务自身或除了空闲任务之外的其他任务。 函数OSTaskDel()的原型如下: #if OS_TASK_DEL_ENINT8U OSTaskDel ( INT8U prio / 要删除任务的优先级 ); 如果任务删

32、除自己,则应在调用函数时令函数的参数prio为OS_PRIO_SELF。 删除任务具体做法是,把被删除任务的任务控制块从任务控制块链表中删除,并归还给空任务控制块链表,然后在任务就绪表中把该任务的就绪状态位置0,于是该任务就不能再被调度器调用了。272.2.14.1请求删除任务请求删除任务函数OSTaskDelReq()的原型如下: INT8U OSTaskDelReq ( INT8U prio / 要删除任务的优先级 ); 如果任务请求删除自己,则应在调用函数时令函数的参数prio为OS_PRIO_SELF。 进入Prio是空闲任务? 返回OS_TASK_NOT_EXIST 返回OS_TAS

33、K_IDLE_PRIO返回被删除任务TCB的成员OSTCBDelReq的值NOYESYESYES 返回 OS_NO_ERRNOPrio是合法优先级? 返回OS_PRIO_INVALIDNOPrio=OS_PRIO_SELF?Prio任务的TCB不存在?NOYES图2-15 函数OSTaskDelReq()流程图提出删除请求任务的执行路径被删除任务的执行路径(删除自身)有时任务会占用一些动态分配的资源,这时如果有其他任务把这个任务删除了,那么被删除任务所占用的一些资源就会因为没有被释放而丢失,这是任何系统都无法接受的。具体办法是:提出删除任务请求的任务只是提出删除任提出删除任务请求的任务只是提出

34、删除任务的请求,而真正删除工作则由被删除任务自务的请求,而真正删除工作则由被删除任务自己来完成己来完成。这样,被删除任务就可以根据自身的具体情况来决定何时删除自身,同时也有机会在删除自身之前把占用的资源释放掉。282.2.14.2 请求删除自身任务 被删除任务方一定要用OS_PRIO_SELF作为参数来调用函数OSTaskDelReq(),返回任务TCB的OSTCBDelReq的值,看是否等于OS_TASK_DEL_REQ。如 果 等 于 则 意 味 有 其 他 任 务 发 出 了 删 除 任 务 请 求 , 则 调 用 函 数 OSTaskDel(OS_PRIO_SELF)删除自己。if (

35、 OSTaskDelReq (OS_PRIO_SELF) = = OS_TASK_DEL_REQ ) 释放资源和动态内存的代码; OSTaskDel(OS_PRIO_SELF);else其它应用代码;Mytask为被删除任务方,调用函数OSTaskDelReq()的代码如下: Yourtask为请求删除任务方,调用函数OSTaskDelReq()的代码如下: while ( OSTaskDelReq (prio) != OS_TASK_NOT_EXIST )OSTimeDly(1); / 延时等待,直到被删除任务已被删除29练习2-3:修改练习2-1的应用程序,使任务myTask能删除任务yo

36、urTask。 302.2.15 查询任务的信息INT8U OSTaskQuery(INT8U prio,/ 待查询任务的优先级OS_TCB *pdata/ 存储任务信息的结构);函数OSTaskQuery()的原型如下: 有时,在应用程序运行中需要了解一个任务的指针、堆栈等信息,这时可通过调用函数OSTaskQuery()来获取选定的任务的信息。 若调用函数OSTaskQuery()查询成功,则返回OS_NO_ERR,并把查询得到的任务信息存放在结构OS_TCB类型的变量中。31系统首先调用初始化函数OSInit()。OSInit()初始化C/OS-所有的变量和数据结构。OSInit()建立

37、空闲任务idle task,这个任务总是处于就绪态的。空闲任务OSTaskIdle()的优先级总是设成最低,即OS_LOWEST_PRIO。如果统计任务允许OS_TASK_STAT_EN和任务建立扩展允许都设为1,则OSInit()还得建立统计任务OSTaskStat()并且让其进入就绪态。OSTaskStat的优先级总是设为OS_LOWEST_PRIO-1。 初始化时主要是创建包括空任务控制块链表在内的5个空数据缓冲区,及按任务优先级存放的任务控制块指针的数组OSTCBPrioTblOS_LOWEST_PRIO+1。2.2.16 uC/OS-II初始化后的数据结构322.2.16.1 uC/

38、OS-II初始化后的数据结构000000000000000000000000000000000000000000000000000000001100000000000001图2-16 uC/OS-II初始化后的数据结构任务就绪表 OSRdyGrp任务就绪表OSRdyTbl OS_LOWEST_PRIO-1OS_LOWEST_PRIO OSTCBPrioTbl012 空任务控制块 空任务控制块 空任务控制块OSTCBStkBottomOSTCBStkPtrOSTCBStkBottomOSTCBStkPtr统计任务的控制块空闲任务的控制块OSTCBFreeList 任务控制块链表OSTCBList

39、 统计任务 堆 栈 空闲任务 堆 栈 其余4个链表332.2.16.2 初始化后的全局变量变量值变量的说明OSPrioCur0类型为INT8U,正在运行的任务的优先级OSprioHighRdy0类型为INT8U,具有最高优先级的就绪任务的优先级OSTCBCurNULL类型为OS_TCB*,指向正在运行任务控制块的指针OSTCBHighRdyNULL类型为OS_TCB*,指向最高优先级就绪任务控制块的指针OSTime0类型为INT32U,表示系统当前时间(节拍数)OSIntNesting0类型为INT32U,存放中断嵌套的层数(0255)OSLockNesting0类型为INT8U,调用了OSS

40、chededLock的嵌套层数OSCtxSwCtr0类型为INT32U,上下文切换的次数OSTaskCtr2类型为INT8U,已经建立的任务数OSRunningFALSE类型为BOOLEAN,uC/OS-II核是否正在运行的标志OSCPUUsage0类型为INT8S,存放CPU的利用率的变量OSIdleCtrMax0类型为INT32U,表示每秒空闲任务计数的最大值OSIdleCtrRun0类型为INT32U,表示空闲任务计数器每秒的计数量OSIdleCtr0类型为INT32U,空闲任务的计数器OSStatRdyFALSE类型为BOOLEAN,统计任务是否就绪的标志OSIntExity0类型为I

41、NT8U,用于函数OSInitExt()表2-2 初始化的全局变量342.2.17 uC/OS-II的启动uC/OS-II进行的任务管理是从调用启动函数OSStart()开始的。当然,其前提条件是在调用该函数之前至少创建了一个用户任务。 函数OSStart()的源代码如下:void OSStart (void) INT8U y; INT8U x; if (OSRunning = FALSE) y = OSUnMapTblOSRdyGrp; x = OSUnMapTblOSRdyTbly; OSPrioHighRdy = (INT8U)(y 3) + x); OSPrioCur = OSPrio

42、HighRdy; OSTCBHighRdy = OSTCBPrioTblOSPrioHighRdy; OSTCBCur = OSTCBHighRdy; OSStartHighRdy(); CPU相关函数,代码在OS_CPU_A.ASM。实现的功能是,设置系统运行标志位OSRunning=TRUE,将就绪表中最高优先级任务的指针加载到SP中,并强制中断返回。这样就绪的最高优先级任务就如同从中断里返回到运行态一样,使得整个系统得以运转 。注意,OSStartHighRdy()将永远不返回到OSStart()。35#include “includes.h”#define MY_TASK_STK_SI

43、ZE512/ 定义堆栈容量void main (void)OSInit(); /初始化uC/OS-II通过调用OSTaskCreate(MyTask, (void*)0, &MyTaskStkMY_TASK_STK_SIZE-1,6); OSStart(); /开始多任务调度!OSStart()永远不会返回 2.2.17.1 启动后的数据结构010000000000000000000000000000000000000000000000000000001100000010000001任务就绪表 OSRdyGrp任务就绪表OSRdyTbl OS_LOWEST_PRIO-1OS_LOWEST_PRIO OSTCBPrioTbl012 空任务控制块 空任务控制块OSTCBStkBottomOSTCBStkPtrOSTCBStkBottomOSTCBStkPtr统计任务的控制块空闲任务的控制块OSTCBFreeList 任务控制块链表 统计任务 堆栈 空闲任务 堆栈456OSTCBStkBottomOSTCBStkPtr MyTask 任务堆栈OSTCBList图2-

温馨提示

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

评论

0/150

提交评论