UC/OS II时间片轮转法调度修改

时间:2021-12-05 21:13:14

**根据时间片轮转调度在同优先级任务中的应用,需要对
任务的TCB进行修改,增加4个属性项:**
1)OSTSLen(时间片初始值)。保存任务建立时给任务分
配时间片的个数。
2)OSTSCurLen(时间片剩余值)。记录了任务运行中还
剩余的时间片个数”-。
3)OSTSPrev(TCB双向链表前驱指针)。用作组成图2
所示的TCB循环链表。
4)OSTSNext(TCB双向链表后继指针)。用作组成图2
所示的TcB循环链表。
OSTimeTick代码部分修改:
void OSTimeTick(void)
{
OS_TCB *ptcb;
OS_TCB *temptcb;

if OS_TICK_STEP_EN > 0

BOOLEAN    step;

endif

if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */

OS_CPU_SR  cpu_sr = 0;

endif

if OS_TIME_TICK_HOOK_EN > 0

OSTimeTickHook();                                      /* Call user definable hook                     */

endif

if OS_TIME_GET_SET_EN > 0

OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter               */
OSTime++;
OS_EXIT_CRITICAL();

endif

if (OSRunning == OS_TRUE) {

if OS_TICK_STEP_EN > 0

    switch (OSTickStepState) {                         /* Determine whether we need to process a tick  */
    case OS_TICK_STEP_DIS:                         /* Yes, stepping is disabled                    */
        step = OS_TRUE;
        break;

    case OS_TICK_STEP_WAIT:                        /* No,  waiting for uC/OS-View to set ...       */
        step = OS_FALSE;                             /*      .. OSTickStepState to OS_TICK_STEP_ONCE */
        break;

    case OS_TICK_STEP_ONCE:                        /* Yes, process tick once and wait for next ... */
        step = OS_TRUE;                   /*      ... step command from uC/OS-View        */
        OSTickStepState = OS_TICK_STEP_WAIT;
        break;

    default:                                       /* Invalid case, correct situation              */
        step = OS_TRUE;
        OSTickStepState = OS_TICK_STEP_DIS;
        break;
    }
    if (step == OS_FALSE) {                               /* Return if waiting for step command           */
        return;
    }

endif

    ptcb = OSTCBList;                                  /* Point at first TCB in TCB list               */
    while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {          /* Go through all TCBs in TCB list              */
        OS_ENTER_CRITICAL();
        if (ptcb->OSTCBDly != 0) {                     /* No, Delayed or waiting for event with TO     */
            if (--ptcb->OSTCBDly == 0) {               /* Decrement nbr of ticks to end of delay       */
                /* Check for timeout                            */
                if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
                    ptcb->OSTCBStat &= ~OS_STAT_PEND_ANY;                /* Yes, Clear status flag   */
                    ptcb->OSTCBStatPend = OS_TRUE;                             /* Indicate PEND timeout    */
                }
                else {
                    ptcb->OSTCBStatPend = OS_FALSE;
                }

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

        if (ptcb == OSTCBCur){                                  /*找出处于运行态的任务*/
            if (ptcb->OSTCBPrio>OS_RT_PRIO&&ptcb->OSTCBPrio<OS_TASK_STAT_PRIO){                             /*分时任务*/
                if (ptcb->OSTCBCounter != 0){
                    if (--ptcb->OSTCBCounter == 0){                                                 /*时间片减1后为0*/
                        ptcb->OSTCBStat = OS_STAT_TS_USEUP;                                     /*设置为等待状态*/

                        if ((OSRdyTbl[ptcb->OSTCBPrio >> 3] &= ~OSMapTbl[ptcb->OSTCBPrio & 0x07]) == 0)   /*从就绪队列中取出*/
                            OSRdyGrp &= ~OSMapTbl[ptcb->OSTCBPrio >> 3];               /*对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时,才将相应位清零*/

                        OSTSSGrp |= ptcb->OSTCBBitY;                                    /*进入等待队列*/
                        OSTSSTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                        /*进行任务切换或重新分配时间片*/
                        if (((OSRdyGrp & 0x7f) == 0) && OSTSSGrp != 0){                                     /*就绪队列中无任务等待队列中有*/
                            temptcb = OSTCBList;                                                /*重新分配时间片*/
                            while (temptcb->OSTCBPrio != OS_TASK_IDLE_PRIO){
                                if (temptcb->OSTCBPrio>OS_RT_PRIO&&ptcb->OSTCBPrio<OS_TASK_STAT_PRIO){
                                    temptcb->OSTCBCounter = temptcb->OSTCBTimeSlice;
                                    temptcb->OSTCBStat = OS_STAT_RDY;
                                }
                                temptcb = temptcb->OSTCBNext;
                            }

                            OSRdyGrp |= OSTSSGrp;                                               /*将等待队列中任务转到就绪队列*/
                            OSRdyTbl[0] |= OSTSSTbl[0];
                            OSRdyTbl[1] |= OSTSSTbl[1];
                            OSRdyTbl[2] |= OSTSSTbl[2];
                            OSRdyTbl[3] |= OSTSSTbl[3];
                            OSRdyTbl[4] |= OSTSSTbl[4];
                            OSRdyTbl[5] |= OSTSSTbl[5];
                            OSRdyTbl[6] |= OSTSSTbl[6];
                            OSRdyTbl[7] |= OSTSSTbl[7];

                            OSTSSGrp = 0;                                                   /*清空等待队列*/
                            OSTSSTbl[0] = 0;
                            OSTSSTbl[1] = 0;
                            OSTSSTbl[2] = 0;
                            OSTSSTbl[3] = 0;
                            OSTSSTbl[4] = 0;
                            OSTSSTbl[5] = 0;
                            OSTSSTbl[6] = 0;
                            OSTSSTbl[7] = 0;

                        }
                        else if (((OSRdyGrp & 0x7f) == 0) && (OSRdyTbl[7] == 0xc0) && OSTSSGrp == 0){                                   /*系统无任务就绪或等待*/
                            //OSStart();    
                            //printf("I am coming\n");/*执行空闲任务*/
                        }
                        else
                            ;
                    }
                }
            }
        }

        ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list                */
        OS_EXIT_CRITICAL();
    }
}

}

OSTaskCreate内添加任务优先级创建:

if OS_ARG_CHK_EN > 0u

if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */
    return (OS_ERR_PRIO_INVALID);
}

endif

OS_ENTER_CRITICAL();
if (OSIntNesting > 0u) {                 /* Make sure we don't create the task from within an ISR  */
    OS_EXIT_CRITICAL();
    return (OS_ERR_TASK_CREATE_ISR);
}
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */
    OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ...  */
                                         /* ... the same thing until task is created.              */
    OS_EXIT_CRITICAL();
    psp = OSTaskStkInit(task, p_arg, ptos, 0u);             /* Initialize the task's stack         */
    err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u);
    if (err == OS_ERR_NONE) {
        if (OSRunning == OS_TRUE) {      /* Find highest priority task if multitasking has started */
            OS_Sched();
        }
    } else {
        OS_ENTER_CRITICAL();
        OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others                 */
        OS_EXIT_CRITICAL();
    }
    return (err);
}
else
{

}
OS_EXIT_CRITICAL();
return (OS_ERR_PRIO_EXIST);

}

OS_TCBInit增添初始化TCB时间片代码:
if (prio