UCOSIII the tempo list update

Preface

On a blog I introduced to the microcontroller using a fixed-frequency interrupt timer bindings with the kernel, the corresponding interrupt ISR calls OSTimeTick (), OSTimeTick () uses OS_IntQPost to put into a queue IntQ Post will be called after a process of information, and then let OS_IntQTask ready to send a signal to the amount OS_TickTask, OS_TickTask receive the semaphore OS_TickListUpdate (). In this article we explore in detail about the implementation of internal processes OS_TickListUpdate

Source explanation

I hit the comment directly through the code step by step way to explore here during the execution of this function, there will be a final summary

void  OS_TickListUpdate (void)
{
    CPU_BOOLEAN        done;
    OS_TICK_SPOKE     *p_spoke;
    OS_TCB            *p_tcb;
    OS_TCB            *p_tcb_next;
    OS_TICK_SPOKE_IX   spoke;
    CPU_TS             ts_start;
    CPU_TS             ts_end;
    CPU_SR_ALLOC();


    //进入临界区
    OS_CRITICAL_ENTER();
    //获取时间戳,用来计算某段代码的执行时间,和最后的 ts_end = OS_TS_GET() - ts_start 配合使用
    ts_start = OS_TS_GET();
    //一个计数变量,用来统计UCOSIII从启动到现在一共经历了多少个时钟节拍
    OSTickCtr++;                                                       /* Keep track of the number of ticks           */
    //从节拍列表中取一个任务出来,具体如何取得,可以研究一下OSCfg_TickWheel这个结构体
    spoke    = (OS_TICK_SPOKE_IX)(OSTickCtr % OSCfg_TickWheelSize);
    p_spoke  = &OSCfg_TickWheel[spoke];
    //取出数组元素双向链表得第一个任务控制块
    p_tcb    = p_spoke->FirstPtr;
    done     = DEF_FALSE;
    while (done == DEF_FALSE) {
        if (p_tcb != (OS_TCB *)0) {
            p_tcb_next = p_tcb->TickNextPtr;                           /* Point to next TCB to update                 */
            //判断任务状态
            switch (p_tcb->TaskState) {
                //这些状态都是不可能得
                case OS_TASK_STATE_RDY:
                case OS_TASK_STATE_PEND:
                case OS_TASK_STATE_SUSPENDED:
                case OS_TASK_STATE_PEND_SUSPENDED:
                     break;
                //如果任务是单纯得延时状态
                case OS_TASK_STATE_DLY:
                    //这里可以使用全局搜索看一下TickCtrMatch是如何被初始化的,就可以理解这里了
                     p_tcb->TickRemain = p_tcb->TickCtrMatch           /* Compute time remaining of current TCB       */
                                       - OSTickCtr;
                     if (OSTickCtr == p_tcb->TickCtrMatch) {           /* Process each TCB that expires               */
                         p_tcb->TaskState = OS_TASK_STATE_RDY;
                         OS_TaskRdy(p_tcb);                            /* Make task ready to run                      */
                     } else {
                         done             = DEF_TRUE;                  /* Don't find a match, we're done!             */
                     }
                     break;
                //如果是因为带超时监测的阻塞而被延时
                case OS_TASK_STATE_PEND_TIMEOUT:
                     p_tcb->TickRemain = p_tcb->TickCtrMatch           /* Compute time remaining of current TCB       */
                                       - OSTickCtr;
                     if (OSTickCtr == p_tcb->TickCtrMatch) {           /* Process each TCB that expires               */
#if (OS_MSG_EN > 0u)
                         p_tcb->MsgPtr     = (void      *)0;
                         p_tcb->MsgSize    = (OS_MSG_SIZE)0u;
#endif
                         p_tcb->TS         = OS_TS_GET();
                         //将任务从阻塞列表中移除
                         OS_PendListRemove(p_tcb);                     /* Remove from wait list                       */
                         //将让任务就绪,其实这个函数包含两个步骤:将任务移除TickList,将任务插入就绪列表
                         OS_TaskRdy(p_tcb);
                         p_tcb->TaskState  = OS_TASK_STATE_RDY;
                         p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT;   /* Indicate pend timed out                     */
                         p_tcb->PendOn     = OS_TASK_PEND_ON_NOTHING;  /* Indicate no longer pending                  */
                     } else {
                         done              = DEF_TRUE;                 /* Don't find a match, we're done!             */
                     }
                     break;
               //如果任务延时而且被悬挂
                case OS_TASK_STATE_DLY_SUSPENDED:
                     p_tcb->TickRemain = p_tcb->TickCtrMatch           /* Compute time remaining of current TCB       */
                                       - OSTickCtr;
                     if (OSTickCtr == p_tcb->TickCtrMatch) {           /* Process each TCB that expires               */
                         p_tcb->TaskState  = OS_TASK_STATE_SUSPENDED;
                         //我们这里仅仅将任务从TickList中移除,并不让它就绪
                         OS_TickListRemove(p_tcb);                     /* Remove from current wheel spoke             */
                     } else {
                         done              = DEF_TRUE;                 /* Don't find a match, we're done!             */
                     }
                     break;
                    
               //如果任务是因为带超时监测的阻塞而延时,并且这个时候被悬挂起来了
                case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
                     p_tcb->TickRemain = p_tcb->TickCtrMatch           /* Compute time remaining of current TCB       */
                                       - OSTickCtr;
                     if (OSTickCtr == p_tcb->TickCtrMatch) {           /* Process each TCB that expires               */
#if (OS_MSG_EN > 0u)
                         p_tcb->MsgPtr     = (void      *)0;
                         p_tcb->MsgSize    = (OS_MSG_SIZE)0u;
#endif
                         p_tcb->TS         = OS_TS_GET();
                         //移出PendList
                         OS_PendListRemove(p_tcb);                     /* Remove from wait list                       */
                         //移出TickList
                         OS_TickListRemove(p_tcb);                     /* Remove from current wheel spoke             */
                         p_tcb->TaskState  = OS_TASK_STATE_SUSPENDED;
                         p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT;   /* Indicate pend timed out                     */
                         p_tcb->PendOn     = OS_TASK_PEND_ON_NOTHING;  /* Indicate no longer pending                  */
                     } else {
                         done              = DEF_TRUE;                 /* Don't find a match, we're done!             */
                     }
                     break;

                default:
                     break;
            }
            //更新p_tcb,准备检查下一个任务
            p_tcb = p_tcb_next;
        } else {
            done  = DEF_TRUE;
        }
    }
    //配合开头计算,执行上面这段代码所用的时间
    ts_end = OS_TS_GET() - ts_start;                                   /* Measure execution time of tick task         */
    if (OSTickTaskTimeMax < ts_end) {
        OSTickTaskTimeMax = ts_end;
    }
    OS_CRITICAL_EXIT();
}

to sum up

The entire code execution flow is this: whenever a beat comes, we calculated some way out of a position and remove an element from OSCfg_TickWheel According to this position, in fact, this element represents a doubly linked list, one by one we beat in this check this doubly linked list each of the above tasks, it will be time to move away from TickList in. The following is a schematic OSCfg_TickWheel

Guess you like

Origin www.cnblogs.com/YinShijia/p/11705006.html