创建好了任务之后,就已经初步跨进了ucosii的编程了,随着进一步的编程,发现学会创建了任务还是不够的,创建任务1用于串口1发送数据,
任务2用于串口1接收数据,程序本身的意图是发送完数据后,接着就串口1接收反馈回来的信息,但是不能正常通信,原因就是当任务1在发送数据过程
CPU时不是会跑到任务2去接收数据,这样就会接收自己的发送的数据,在任务1执行的时候,任务2不执行,当任务1执行完,任务2才执行,相同地,
当任务2执行完,任务1才执行,档案是肯定的,ucos提供了任务挂起恢复两种操作。
挂起任务需要使用OSTaskSuspend函数,任务可以挂起自己或者其他的任务,OSTaskSuspend只需要一个参数,就是需要挂起的任务的优先级
INT8U OSTaskSuspend(INT8U prio)
{
BOOLEAN self;
OS_TCB *ptcb;
if(prio==OS_IDLE_PRIO) (1)
return (OS_TASK_SUSPEND_IDLE);
if(prio>=OS_LOWEST_PRIO&&prio!=OS_PRIO_SELF) (2)
return(OS_PRIO_INVALID);
OS_ENTER_CRITICAL();
if(prio==OS_PRIO_SELF) (3)
{
prio=OSTCBCur->OSTCBPrio;
self=TRUE;
}
else if(prio==OSTCBCur->OSTCBPrio) (4)
{
self=TRUE;
}
else
{
self=FALSE;
}
if((ptcb==OSTCBPrioTbl[prio])==(OS_TCB*)0) (5)
{
OS_EIX_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_CRITCIAL();
if(self==TRUE) (8)
{
OSSched();
}
return (OS_NO_ERR);
}
}
首先理解挂起的实现过程。
1.首先,OSTaskSuspend要确保用户的应用程序不是在挂起空闲任务(1).接着用户指定优先级是有效的(2),记住最大的有效的优先级是
OS_LOWEST_PRIO,注意,用户可以挂起统计任务,可能用户已经注意到了,
2.接着,OSTaskSuspend()检验用户是否通过指定OS_RPIO_SEFL来挂起本函数的任务本身(3),用户也可以通过指定优先级来挂起调用本函数的任务
(4),在这两种情况下,任务调度程序需要被调用,这就是笔者为什么要定义局部变量self的原因,该变量在适当情况下会被测试。如果用户没有
挂起调用本函数的任务,OSTaskSuspend就没有必要运行任务调度了,因为挂起的是较低优先级的任务.
3.然后,OSTaskSuspend()挂起的任务是否存在(5).如果该任务存在的话,它就会从就绪表中移除,在我理解,这是任务挂起函数最关键的地方,所谓任务挂起,
简单点来说,就是把任务从就绪表中删除,因为CPU下一次执行的任务是就绪表中优先级最高的任务,当任务不在就绪表中,也不有可能这个任务还会被执行。下面理解
下它的实现过程,每个任务的就绪表标志都存放在就绪标志中,就绪标志有两个变量OSRdyGrp和OSRdyTbl[],在OSRdyGrp中,任务按优先级分组,8个任务为一组,OSRdyGrp中的每一个表示8组任务中每一组是否进入就绪态的任务,任务进入就绪态时,就绪表OSRdyTbl中的相应元素的相应位也职位,比如说我要把优先级为5的任务从就绪表删除,我需要的操作时把OSRdyTbl[0]第五位清零,同时把OSRdyGrp第零为清零。
注意要被挂起的任务有可能没有在就绪表中,因为他有可鞥等待时间的发送或延时期满,在这种情况下,要被挂起的任务在OSRdyTbl中对于的位仪表清除,再次清除该位,要比先检查该位是否被清除了 在他没被请查收清除它快得多,所以笔者没有检查该位而直接清除它,现在OSTaskSuspend就可以再该任务的OS_TCB中设置OS_STAT_SUSPEND标志,以表明任务正在被挂起,最后OSTaskSuspend()只有在被挂起的任务是调用本函数的任务本身的情况下次啊调用任务调度程序(8)。