本帖最后由 eehome 于 2013-1-5 09:57 编辑
实例:应用程序的 2 个任务使用了延时函数 OStimeDly () 进行延时,在任务 MyTask 中还调用了函数 OSTimeDlyResume () 取消了任务 YourTask 的延时(为了观察任务YourTask 的延时时间的变化,在钩子函数 OSTimeTickHook () 输出了任务 YourTask在延时时间到时的时钟节拍数)。 OSTimeTickHook钩子函数程序如下
- #if OS_CPU_HOOKS_EN > 0
- INT8U d=0;
- INT8U l=0;
- INT8U n=0;
- INT8U m=0;
-
- INT16U tt=1; //时钟计数器
- char s[5];
- void OSTimeTickHook (void)
- {
- if(OSTCBPrioTbl[2]->OSTCBDly == 1)
- {
- sprintf(s,"%5d",tt);
- PC_DispStr(d,l+4,s,DISP_BGND_BLACK+DISP_FGND_WHITE );
- d+=6;
- }
- /*
- if(OSTCBPrioTbl[2]->OSTCBDly == 0)
- {
- sprintf(s,"%5d",tt);
- PC_DispStr(d,l+6,s,DISP_BGND_BLACK+DISP_FGND_WHITE );
- d+=6;
- }
- */
- tt+=1;
- }
- #endif
复制代码
经过我调试发现当(OSTCBPrioTbl[2]->OSTCBDly == 1) 时,正常显示节拍数,当(OSTCBPrioTbl[2]->OSTCBDly == 0) 时,则不显示节拍数。所以显然,在OSTimeTickHook函数中OSTCBPrioTbl[2]->OSTCBDly不为0。但是仔细一想在OSTimeDlyResume () 中
- INT8U OSTimeDlyResume (INT8U prio )
- {
- if ( prio >= OS_LOWEST_PRIO)
- {
- return (OS_PRIO_INVALID);
- }
- OS_ENTER_CRITICAL();
- ptcb = (OS_TCB * ) OSTCBPrioTbl[prio ];
- if ( ptcb != (OS_TCB * )0)
- {
- if ( ptcb -> OSTCBDly != 0)
- {
- ptcb -> OSTCBDly = 0;
- if (( ptcb -> OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY)
- {
- OSRdyGrp |= ptcb -> OSTCBBitY ;
- OSRdyTbl[ptcb ->OSTCBY] |= ptcb -> OSTCBBitX ;
- OS_EXIT_CRITICAL();
- OS_Sched ();
- }
- else
- {
- OS_EXIT_CRITICAL();
- }
- return (OS_NO_ERR);
- }
- else
- {
- OS_EXIT_CRITICAL();
- return (OS_TIME_NOT_DLY);
- }
- }
- OS_EXIT_CRITICAL();
- return (OS_TASK_NOT_EXIST);
- }
复制代码
可以看出在OSTCBPrioTbl[prio]->OSTCBDly 被赋值为0,且进行了一次任务调度,那为什么上面的结果又不对了。那就得看void OSTimeTick (void)
- 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;
- OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
- }
- else
- {
- ptcb->OSTCBDly = 1;
- }
- }
- }
- ptcb = ptcb->OSTCBNext; //下一个任务控制块
- //OS_EXIT_CRITICAL();
- }
- //OS_ENTER_CRITICAL();
- OSTime++; //节拍计数器+1
- //OS_EXIT_CRITICAL();
- }
复制代码
可见当OSTCBPrioTbl[prio]->OSTCBDly=1时 在OSTimeTick函数中就已经赋值为0了,且将任务放入就绪表。分析 当使用OSTimeDlyResume ()将任务中OSTCBPrioTbl[prio]->OSTCBDly强制变为0,在进行任务调度,进入优先级高的任务后,任务中肯要使用延时函数,延时一段节拍,进行任务调度,这时候OSTCBPrioTbl[prio]->OSTCBDly就不为0了,所以再进入OSTimeTick函数时,使用(OSTCBPrioTbl[2]->OSTCBDly == 0) 的判断就不对了。所以就为出现上面调试的结果。
0
|
|
|
|
学习了 我刚学 不是很懂
|
|
|
|
|
好像很复杂的样子.................
|
|
|
|
|