微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > μC/OS-II的任务管理

μC/OS-II的任务管理

时间:10-08 来源:互联网 点击:

时候将任务挂起是很用的。挂起任务可通过调用OSTaskSuspend()函数来完成。被挂起的任务只能通过调用OSTaskResume()函数来恢复。任务挂起是一个附加功能。也就是说,如果任务在被挂起的同时也在等待延时的期满,那么,挂起操作需要被取消,而任务继续等待延时期满,并转入就绪状态。任务可以挂起自己或者其它任务。

OSTaskSuspend()函数的代码如程序清单L4.16所示。通常OSTaskSuspend()需要检验临界条件。首先,OSTaskSuspend()要确保用户的应用程序不是在挂起空闲任务[L4.16(1)],接着确认用户指定优先级是有效的[L4.16(2)]。记住最大的有效的优先级数(即最低的优先级)是OS_LOWEST_PRIO。注意,用户可以挂起统计任务(statistic) 。可能用户已经注意到了,第一个测试[L4.16(1)]在[L4.16(2)]中被重复了。笔者这样做是为了能与μC/OS兼容。

第一个测试能够被移除并可以节省一点程序处理的时间,但是,这样做的意义不大,所以笔者决定留下它。

接着, OSTaskSuspend()检验用户是否通过指定 OS_PRIO_SELF来挂起调用本函数的任务本身[L4.16(3)]。用户也可以通过指定优先级来挂起调用本函数的任务[L4.16(4)]。在这两种情况下,任务调度程序都需要被调用。这就是笔者为什么要定义局部变量self的原因,该变量在适当的情况下会被测试。如果用户没有挂起调用本函数的任务,OSTaskSuspend()就没有必要运行任务调度程序,因为正在挂起的是较低优先级的任务。

然后,OSTaskSuspend()检验要挂起的任务是否存在[L4.16(5)]。如果该任务存在的话,它就会从就绪表中被移除[L4.16(6)]。注意要被挂起的任务有可能没有在就绪表中,因为它有可能在等待事件的发生或延时的期满。在这种情况下,要被挂起的任务在OSRdyTbl[]中对应的位已被清除了(即为0)。再次清除该位,要比先检验该位是否被清除了再在它没被清除时清除它快得多,所以笔者没有检验该位而直接清除它。现在,OSTaskSuspend()就可以在任务的OS_TCB中设置OS_STAT_SUSPEND标志了,以表明任务正在被挂起[L4.16(7)]。最后,OSTaskSuspend()只有在被挂起的任务是调用本函数的任务本身的情况下才调用任务调度程序[L4.16(8)]。

程序清单 L4.16 OSTaskSuspend().

INT8UOSTaskSuspend(INT8Uprio)

{

BOOLEANself;

OS_TCB*ptcb;

if(prio==OS_IDLE_PRIO){(1)

return(OS_TASK_SUSPEND_IDLE);

}

if(prio>=OS_LOWEST_PRIOprio!=OS_PRIO_SELF){

(2)

return(OS_PRIO_INVALID);

}

OS_ENTER_CRITICAL();

if(prio==OS_PRIO_SELF){(3)

prio=OSTCBCur->OSTCBPrio;

self=TRUE;

}elseif(prio==OSTCBCur->OSTCBPrio){(4)

self=TRUE;

}else{

self=FALSE;

}

if((ptcb=OSTCBPrioTbl[prio])==(OS_TCB*)0){(5)

OS_EXIT_CRITICAL();

return(OS_TASK_SUSPEND_PRIO);

}else{

if((OSRdyTbl[ptcb->OSTCBY]=~ptcb->OSTCBBitX)==0){(6)

OSRdyGrp=~ptcb->OSTCBBitY;

}

ptcb->OSTCBStat|=OS_STAT_SUSPEND;(7)

OS_EXIT_CRITICAL();

if(self==TRUE){(8)

OSSched();

}

return(OS_NO_ERR);

}

}

4.8 恢复任务,OSTaskResume()

在上一节中曾提到过,被挂起的任务只有通过调用OSTaskResume()才能恢复。OSTaskResume()函数的代码如程序清单L4.17所示。 因为OSTaskSuspend()不能挂起空闲任务,所以必须得确认用户的应用程序不是在恢复空闲任务[L4.17(1)]。注意,这个测试也可以确保用户不是在恢复优先级为OS_PRIO_SELF的任务(OS_PRIO_SELF被定义为0xFF,它总是比OS_LOWEST_PRIO大)。

要恢复的任务必须是存在的,因为用户要需要操作它的任务控制块OS_TCB[L4.17(2)],并且该任务必须是被挂起的[L4.17(3)]。OSTaskResume()是通过清除OSTCBStat域中的OS_STAT_SUSPEND位来取消挂起的[L4.17(4)]。要使任务处于就绪状态,OS_TCBDly域必须为0[L4.17(5)],这是因为在OSTCBStat中没有任何标志表明任务正在等待延时的期满。只有当以上两个条件都满足的时候,任务才处于就绪状态[L4.17(6)]。最后,任务调度程序会检查被恢复的任务拥有的优先级是否比调用本函数的任务的优先级高[L4.17(7)]。

程序清单 L4.17 OSTaskResume().

INT8UOSTaskResume(INT8Uprio)

{

OS_TCB*ptcb;

If(prio>=OS_LOWEST_PRIO){(1)

return(OS_PRIO_INVALID);

}

OS_ENTER_CRITICAL();

If((ptcb=OSTCBPrioTbl[prio])==(OS_TCB*)0){(2)

OS_EXIT_CRITICAL();

return(OS_TASK_RESUME_PRIO);

}else{

if(ptcb->OSTCBStatOS_STAT_SUSPEND){(3)

if(((ptcb->OSTCBStat=~OS_STAT_SUSPEND)==OS_STAT_RDY)(4)

(ptcb->OSTCBDly==0)){(5)

OSRdyGrp|=ptcb->OSTCBBitY;(6

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top