打印

UCOSII 中的OSTaskResume 应用

[复制链接]
1829|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
醉心369|  楼主 | 2016-12-26 10:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
INT8U  OSTaskResume (INT8U prio)KCREENTRANT
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif
    OS_TCB    *ptcb;


#if OS_ARG_CHK_EN > 0
    if (prio >= OS_LOWEST_PRIO) {                               /* Make sure task priority is valid    */
        return (OS_PRIO_INVALID);
    }
#endif
    OS_ENTER_CRITICAL();
    if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) {           /* Task to suspend must exist          */
        OS_EXIT_CRITICAL();
        return (OS_TASK_RESUME_PRIO);
    }
    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != 0x00) {                     /* Task must be suspended   */
        if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) &&      /* Remove suspension        */
             (ptcb->OSTCBDly  == 0)) {                                     /* Must not be delayed      */
            OSRdyGrp               |= ptcb->OSTCBBitY;                     /* Make task ready to run   */
            OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
            OS_EXIT_CRITICAL();
            OS_Sched();
        } else {
            OS_EXIT_CRITICAL();
        }
        return (OS_NO_ERR);
    }
    OS_EXIT_CRITICAL();
    return (OS_TASK_NOT_SUSPENDED);
}
以上源码中,if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) && (ptcb->OSTCBDly  == 0)) 该判断条件需要判断ptcb->OSTCBDly为0,如果该任务在挂起之前,调用了OSTimeDly()相关函数,此时在调用OSTaskResume(),ptcb->OSTCBDly不为0,该函数怎么运行?大侠们给分析一下,我哪里分析错了

相关帖子

沙发
feelhyq| | 2016-12-26 10:42 | 只看该作者
调用()这个函数后,此时的Task已经被切换到别的Task去了, 也就不会执行OSTimeDly()后面的函数OSTaskResume()。当OSTimeDly()的延时时间到了以后,在切换到当前Task再去执行OSTaskResume()

使用特权

评论回复
板凳
醉心369|  楼主 | 2016-12-26 13:04 | 只看该作者
feelhyq 发表于 2016-12-26 10:42
调用()这个函数后,此时的Task已经被切换到别的Task去了, 也就不会执行OSTimeDly()后面的函数OSTaskResume( ...

如果该任务A调用了OSTimeDly()函数,此时任务B调用OSTaskSuspend(任务A的优先级),任务A的ptcb->OSTCBDly不为0,怎么用其他任务恢复任务A

使用特权

评论回复
地板
feelhyq| | 2016-12-26 13:25 | 只看该作者
明白你的意思了,任务B调用OSTaskSuspend(任务A的优先级)后,再执行OSTaskResume(任务A的优先级)。虽然A时间片还有,但是任务A状态已经从suspend标记为ready状态。
        while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {     /* Go through all TCBs in TCB list              */
            OS_ENTER_CRITICAL();
            if (ptcb->OSTCBDly != 0u) {                    /* No, Delayed or waiting for event with TO     */
                ptcb->OSTCBDly--;                          /* Decrement nbr of ticks to end of delay       */
                if (ptcb->OSTCBDly == 0u) {                /* Check for timeout                            */

                    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
                        ptcb->OSTCBStat  &= (INT8U)~(INT8U)OS_STAT_PEND_ANY;          /* Yes, Clear status flag   */
                        ptcb->OSTCBStatPend = OS_STAT_PEND_TO;                 /* Indicate PEND timeout    */
                    } else {
                        ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
                    }

                    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?       */
                        OSRdyGrp               |= ptcb->OSTCBBitY;             /* No,  Make ready          */
                        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                    }
                }
            }

这个是时间片的代码,可以看到当A任务的时间片用完了后,会将其放入OSRdyGrp ,OSRdyTbl 。然后再调用OSIntExit进行调度

使用特权

评论回复
5
醉心369|  楼主 | 2016-12-26 14:00 | 只看该作者
feelhyq 发表于 2016-12-26 13:25
明白你的意思了,任务B调用OSTaskSuspend(任务A的优先级)后,再执行OSTaskResume(任务A的优先级)。虽然 ...

咱们的版本应该不一样,你看看我这版本
oid  OSTimeTick (void)
{
#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif   
    OS_TCB    *ptcb;


    OSTimeTickHook();                                      /* Call user definable hook                 */
#if OS_TIME_GET_SET_EN > 0   
    OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter           */
    OSTime++;
    OS_EXIT_CRITICAL();
#endif   
    ptcb = OSTCBList;                                      /* Point at first TCB in TCB list           */
    while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {              /* Go through all TCBs in TCB list          */
        OS_ENTER_CRITICAL();
        if (ptcb->OSTCBDly != 0) {                         /* Delayed or waiting for event with TO     */
            if (--ptcb->OSTCBDly == 0) {                   /* Decrement nbr of ticks to end of delay   */
                if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == 0x00) {   /* Is task suspended?             */
                    OSRdyGrp               |= ptcb->OSTCBBitY; /* No,  Make task Rdy to Run (timed out)*/
                    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                } else {                                       /* Yes, Leave 1 tick to prevent ...     */
                    ptcb->OSTCBDly = 1;                        /* ... loosing the task when the ...    */
                }                                              /* ... suspension is removed.           */
            }
        }
        ptcb = ptcb->OSTCBNext;                                /* Point at next TCB in TCB list        */
        OS_EXIT_CRITICAL();
    }
}
这个版本ptcb->OSTCBDly = 1; 该值一直赋值为1,怎么恢复

使用特权

评论回复
6
feelhyq| | 2016-12-26 14:09 | 只看该作者
没有什么问题呀,你调用OSTaskResume函数后,任务A的状态就不是OS_STAT_SUSPEND状态了  所以 if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == 0x00)条件判断成立。

使用特权

评论回复
7
醉心369|  楼主 | 2016-12-26 14:31 | 只看该作者
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != 0x00) {                     /* Task must be suspended   */
        if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) &&      /* Remove suspension        */
             (ptcb->OSTCBDly  == 0)) {                                     /* Must not be delayed      */
            OSRdyGrp               |= ptcb->OSTCBBitY;                     /* Make task ready to run   */
            OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
            OS_EXIT_CRITICAL();
            OS_Sched();
        } else {
            OS_EXIT_CRITICAL();
        }
        return (OS_NO_ERR);
    }
恢复挂起函数中,下面这个判断要
if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) &&    (ptcb->OSTCBDly  == 0))
中ptcb->OSTCBDly  == 0第一次判断此时肯定不成立,因为时间片中把该值总赋值为1(当挂起状态)。

使用特权

评论回复
8
feelhyq| | 2016-12-26 14:46 | 只看该作者
挂起恢复函数仅仅是消除任务A的 OS_STAT_SUSPEND状态,任务A时间片消耗完后,再systick中断函数里面会执行
          OSRdyGrp               |= ptcb->OSTCBBitY;                    
          OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;


不分析代码了,建议把重点放在OS状态机这块

使用特权

评论回复
9
ticomi| | 2016-12-27 08:27 | 只看该作者
一般情况下不要使用Suspend和Resume函数,带来很多隐患。需要任务暂停执行的方式很多且很安全,比如信号量,消息等等。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

60

主题

283

帖子

2

粉丝