zoukankan      html  css  js  c++  java
  • 任务管理

      要使用 uC/OS 的任务必须先声明任务控制块和创建任务,调用 OSTaskCreate () 函数可以创建一个任务。OSTaskCreate () 函数的信息如下表所示。

      OSTaskCreate () 函数的定义位于“os_task.c”:

    void  OSTaskCreate (OS_TCB        *p_tcb,
                        CPU_CHAR      *p_name,
                        OS_TASK_PTR    p_task,
                        void          *p_arg,
                        OS_PRIO        prio,
                        CPU_STK       *p_stk_base,
                        CPU_STK_SIZE   stk_limit,
                        CPU_STK_SIZE   stk_size,
                        OS_MSG_QTY     q_size,
                        OS_TICK        time_quanta,
                        void          *p_ext,
                        OS_OPT         opt,
                        OS_ERR        *p_err)
    {
        CPU_STK_SIZE   i;
    #if OS_CFG_TASK_REG_TBL_SIZE > 0u
        OS_REG_ID      reg_nbr;
    #endif
    #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
        OS_TLS_ID      id;
    #endif
    
        CPU_STK       *p_sp;
        CPU_STK       *p_stk_limit;
        CPU_SR_ALLOC();
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #ifdef OS_SAFETY_CRITICAL_IEC61508
        if (OSSafetyCriticalStartFlag == DEF_TRUE) {
           *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
            return;
        }
    #endif
    
    #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* ---------- CANNOT CREATE A TASK FROM AN ISR ---------- */
           *p_err = OS_ERR_TASK_CREATE_ISR;
            return;
        }
    #endif
    
    #if OS_CFG_ARG_CHK_EN > 0u                                  /* ---------------- VALIDATE ARGUMENTS ------------------ */
        if (p_tcb == (OS_TCB *)0) {                             /* User must supply a valid OS_TCB                        */
           *p_err = OS_ERR_TCB_INVALID;
            return;
        }
        if (p_task == (OS_TASK_PTR)0) {                         /* User must supply a valid task                          */
           *p_err = OS_ERR_TASK_INVALID;
            return;
        }
        if (p_stk_base == (CPU_STK *)0) {                       /* User must supply a valid stack base address            */
           *p_err = OS_ERR_STK_INVALID;
            return;
        }
        if (stk_size < OSCfg_StkSizeMin) {                      /* User must supply a valid minimum stack size            */
           *p_err = OS_ERR_STK_SIZE_INVALID;
            return;
        }
        if (stk_limit >= stk_size) {                            /* User must supply a valid stack limit                   */
           *p_err = OS_ERR_STK_LIMIT_INVALID;
            return;
        }
        if (prio >= OS_CFG_PRIO_MAX) {                          /* Priority must be within 0 and OS_CFG_PRIO_MAX-1        */
           *p_err = OS_ERR_PRIO_INVALID;
            return;
        }
    #endif
    
    #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
        if (prio == (OS_PRIO)0) {
            if (p_tcb != &OSIntQTaskTCB) {
               *p_err = OS_ERR_PRIO_INVALID;                    /* Not allowed to use priority 0                          */
                return;
            }
        }
    #endif
    
        if (prio == (OS_CFG_PRIO_MAX - 1u)) {
            if (p_tcb != &OSIdleTaskTCB) {
               *p_err = OS_ERR_PRIO_INVALID;                    /* Not allowed to use same priority as idle task          */
                return;
            }
        }
    
        OS_TaskInitTCB(p_tcb);                                  /* Initialize the TCB to default values                   */
    
       *p_err = OS_ERR_NONE;
                                                                /* --------------- CLEAR THE TASK'S STACK --------------- */
        if ((opt & OS_OPT_TASK_STK_CHK) != (OS_OPT)0) {         /* See if stack checking has been enabled                 */
            if ((opt & OS_OPT_TASK_STK_CLR) != (OS_OPT)0) {     /* See if stack needs to be cleared                       */
                p_sp = p_stk_base;
                for (i = 0u; i < stk_size; i++) {               /* Stack grows from HIGH to LOW memory                    */
                   *p_sp = (CPU_STK)0;                          /* Clear from bottom of stack and up!                     */
                    p_sp++;
                }
            }
        }
                                                                /* ------- INITIALIZE THE STACK FRAME OF THE TASK ------- */
    #if (CPU_CFG_STK_GROWTH == CPU_STK_GROWTH_HI_TO_LO)
        p_stk_limit = p_stk_base + stk_limit;
    #else
        p_stk_limit = p_stk_base + (stk_size - 1u) - stk_limit;
    #endif
    
        p_sp = OSTaskStkInit(p_task,
                             p_arg,
                             p_stk_base,
                             p_stk_limit,
                             stk_size,
                             opt);
    
                                                                /* -------------- INITIALIZE THE TCB FIELDS ------------- */
        p_tcb->TaskEntryAddr = p_task;                          /* Save task entry point address                          */
        p_tcb->TaskEntryArg  = p_arg;                           /* Save task entry argument                               */
    
        p_tcb->NamePtr       = p_name;                          /* Save task name                                         */
    
        p_tcb->Prio          = prio;                            /* Save the task's priority                               */
    
        p_tcb->StkPtr        = p_sp;                            /* Save the new top-of-stack pointer                      */
        p_tcb->StkLimitPtr   = p_stk_limit;                     /* Save the stack limit pointer                           */
    
        p_tcb->TimeQuanta    = time_quanta;                     /* Save the #ticks for time slice (0 means not sliced)    */
    #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
        if (time_quanta == (OS_TICK)0) {
            p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta;
        } else {
            p_tcb->TimeQuantaCtr = time_quanta;
        }
    #endif
        p_tcb->ExtPtr        = p_ext;                           /* Save pointer to TCB extension                          */
        p_tcb->StkBasePtr    = p_stk_base;                      /* Save pointer to the base address of the stack          */
        p_tcb->StkSize       = stk_size;                        /* Save the stack size (in number of CPU_STK elements)    */
        p_tcb->Opt           = opt;                             /* Save task options                                      */
    
    #if OS_CFG_TASK_REG_TBL_SIZE > 0u
        for (reg_nbr = 0u; reg_nbr < OS_CFG_TASK_REG_TBL_SIZE; reg_nbr++) {
            p_tcb->RegTbl[reg_nbr] = (OS_REG)0;
        }
    #endif
    
    #if OS_CFG_TASK_Q_EN > 0u
        OS_MsgQInit(&p_tcb->MsgQ,                               /* Initialize the task's message queue                    */
                    q_size);
    #else
        (void)&q_size;
    #endif
    
        OSTaskCreateHook(p_tcb);                                /* Call user defined hook                                 */
    
    #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
        for (id = 0u; id < OS_CFG_TLS_TBL_SIZE; id++) {
            p_tcb->TLS_Tbl[id] = (OS_TLS)0;
        }
        OS_TLS_TaskCreate(p_tcb);                               /* Call TLS hook                                          */
    #endif
                                                                /* --------------- ADD TASK TO READY LIST --------------- */
        OS_CRITICAL_ENTER();
        OS_PrioInsert(p_tcb->Prio);
        OS_RdyListInsertTail(p_tcb);
    
    #if OS_CFG_DBG_EN > 0u
        OS_TaskDbgListAdd(p_tcb);
    #endif
    
        OSTaskQty++;                                            /* Increment the #tasks counter                           */
    
        if (OSRunning != OS_STATE_OS_RUNNING) {                 /* Return if multitasking has not started                 */
            OS_CRITICAL_EXIT();
            return;
        }
    
        OS_CRITICAL_EXIT_NO_SCHED();
    
        OSSched();
    }
    OSTaskCreate()

      如果使能了 OS_CFG_DBG_EN(位于“os_cfg.h”),创建任务时还会调用 OS_TaskDbgListAdd() 函数将该任务插入到一个任务调试双向列表,是为方便调试所设。

      OS_TaskDbgListAdd () 函数的定义位于“os_task.c”:

    #if OS_CFG_DBG_EN > 0u
    void  OS_TaskDbgListAdd (OS_TCB  *p_tcb)
    {
        p_tcb->DbgPrevPtr                = (OS_TCB *)0;
        if (OSTaskDbgListPtr == (OS_TCB *)0) {
            p_tcb->DbgNextPtr            = (OS_TCB *)0;
        } else {
            p_tcb->DbgNextPtr            =  OSTaskDbgListPtr;
            OSTaskDbgListPtr->DbgPrevPtr =  p_tcb;
        }
        OSTaskDbgListPtr                 =  p_tcb;
    }
    OS_TaskDbgListAdd()

    OSTaskSuspend ()

      OSTaskSuspend () 函数用于挂起一个任务,令任务暂停运行。任务可以多次调用OSTaskSuspend() 对任务进行挂起操作,即一个任务被挂起是可以嵌套的,但是想要将任务脱离挂起状态需要调用相应次数的 OSTaskResume() 函数。除空闲任务和延迟提交任务之外,任务可以挂起任何任务。OSTaskSuspend () 函数的信息如下表所示。

      OSTaskSuspend () 函数的定义也位于“os_task.c :

    #if OS_CFG_TASK_SUSPEND_EN > 0u
    void   OSTaskSuspend (OS_TCB  *p_tcb,
                          OS_ERR  *p_err)
    {
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if (OS_CFG_ISR_POST_DEFERRED_EN   == 0u) && 
        (OS_CFG_CALLED_FROM_ISR_CHK_EN >  0u)
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* Not allowed to call from an ISR                        */
           *p_err = OS_ERR_TASK_SUSPEND_ISR;
            return;
        }
    #endif
    
        if (p_tcb == &OSIdleTaskTCB) {                          /* Make sure not suspending the idle task                 */
           *p_err = OS_ERR_TASK_SUSPEND_IDLE;
            return;
        }
    
    #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
        if (p_tcb == &OSIntQTaskTCB) {                          /* Not allowed to suspend the ISR handler task            */
           *p_err = OS_ERR_TASK_SUSPEND_INT_HANDLER;
            return;
        }
    
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* See if called from an ISR                              */
            OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_SUSPEND,  /* Post to ISR queue                                      */
                        (void      *)p_tcb,
                        (void      *)0,
                        (OS_MSG_SIZE)0,
                        (OS_FLAGS   )0,
                        (OS_OPT     )0,
                        (CPU_TS     )0,
                        (OS_ERR    *)p_err);
            return;
        }
    #endif
    
        OS_TaskSuspend(p_tcb, p_err);
    }
    #endif
    OSTaskSuspend()

      其实,不管是否使能了中断延迟发布,最终都是调用 OS_TaskSuspend () 函数挂起任务。只是使能了中断延迟发布的挂起过程会比较曲折,中间会有许多插曲,这是中断管理范畴的内容,留到后面再作介绍。

      OS_TaskSuspend () 函数的定义位于“os_task.c”:

    #if OS_CFG_TASK_SUSPEND_EN > 0u
    void   OS_TaskSuspend (OS_TCB  *p_tcb,
                           OS_ERR  *p_err)
    {
        CPU_SR_ALLOC();
    
    
    
        CPU_CRITICAL_ENTER();
        if (p_tcb == (OS_TCB *)0) {                             /* See if specified to suspend self                       */
            p_tcb = OSTCBCurPtr;
        }
    
        if (p_tcb == OSTCBCurPtr) {
            if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) {    /* Can't suspend when the scheduler is locked             */
                CPU_CRITICAL_EXIT();
               *p_err = OS_ERR_SCHED_LOCKED;
                return;
            }
        }
    
       *p_err = OS_ERR_NONE;
        switch (p_tcb->TaskState) {
            case OS_TASK_STATE_RDY:
                 OS_CRITICAL_ENTER_CPU_EXIT();
                 p_tcb->TaskState  =  OS_TASK_STATE_SUSPENDED;
                 p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
                 OS_RdyListRemove(p_tcb);
                 OS_CRITICAL_EXIT_NO_SCHED();
                 break;
    
            case OS_TASK_STATE_DLY:
                 p_tcb->TaskState  = OS_TASK_STATE_DLY_SUSPENDED;
                 p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
                 CPU_CRITICAL_EXIT();
                 break;
    
            case OS_TASK_STATE_PEND:
                 p_tcb->TaskState  = OS_TASK_STATE_PEND_SUSPENDED;
                 p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
                 CPU_CRITICAL_EXIT();
                 break;
    
            case OS_TASK_STATE_PEND_TIMEOUT:
                 p_tcb->TaskState  = OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED;
                 p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
                 CPU_CRITICAL_EXIT();
                 break;
    
            case OS_TASK_STATE_SUSPENDED:
            case OS_TASK_STATE_DLY_SUSPENDED:
            case OS_TASK_STATE_PEND_SUSPENDED:
            case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
                 p_tcb->SuspendCtr++;
                 CPU_CRITICAL_EXIT();
                 break;
    
            default:
                 CPU_CRITICAL_EXIT();
                *p_err = OS_ERR_STATE_INVALID;
                 return;
        }
    
        OSSched();
    }
    #endif
    OS_TaskSuspend()

    OSTaskResume ()

      OSTaskSuspend () 函数相对应,被挂起的任务如果要恢复被挂起前的任务状态,就必须调用 OSTaskResume () 函数解嵌该任务。如果解嵌后任务挂起前套数为 0,就可以恢复被挂起前的任务状态。

      OSTaskResume () 函数的定义也位于“os_task.c 

    #if OS_CFG_TASK_SUSPEND_EN > 0u
    void  OSTaskResume (OS_TCB  *p_tcb,
                        OS_ERR  *p_err)
    {
        CPU_SR_ALLOC();
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if (OS_CFG_ISR_POST_DEFERRED_EN   == 0u) && 
        (OS_CFG_CALLED_FROM_ISR_CHK_EN >  0u)
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* Not allowed to call from an ISR                        */
           *p_err = OS_ERR_TASK_RESUME_ISR;
            return;
        }
    #endif
    
    
        CPU_CRITICAL_ENTER();
    #if OS_CFG_ARG_CHK_EN > 0u
        if ((p_tcb == (OS_TCB *)0) ||                           /* We cannot resume 'self'                                */
            (p_tcb == OSTCBCurPtr)) {
            CPU_CRITICAL_EXIT();
           *p_err  = OS_ERR_TASK_RESUME_SELF;
            return;
        }
    #endif
        CPU_CRITICAL_EXIT();
    
    #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* See if called from an ISR                              */
            OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_RESUME,   /* Post to ISR queue                                      */
                        (void      *)p_tcb,
                        (void      *)0,
                        (OS_MSG_SIZE)0,
                        (OS_FLAGS   )0,
                        (OS_OPT     )0,
                        (CPU_TS     )0,
                        (OS_ERR    *)p_err);
            return;
        }
    #endif
    
        OS_TaskResume(p_tcb, p_err);
    }
    #endif
    OSTaskResume()

          其实,不管是否使能了中断延迟发布,最终都是调用 OS_TaskResume () 函数恢复任务。只是使能了中断延迟发布的挂起过程会比较曲折,中间会有许多插曲,这是中断管理范畴的内容,留到后面再作介绍。

      OS_TaskResume () 函数的定义位于“os_task.c”:

    #if OS_CFG_TASK_SUSPEND_EN > 0u
    void  OS_TaskResume (OS_TCB  *p_tcb,
                         OS_ERR  *p_err)
    {
        CPU_SR_ALLOC();
    
    
        CPU_CRITICAL_ENTER();
       *p_err  = OS_ERR_NONE;
        switch (p_tcb->TaskState) {
            case OS_TASK_STATE_RDY:
            case OS_TASK_STATE_DLY:
            case OS_TASK_STATE_PEND:
            case OS_TASK_STATE_PEND_TIMEOUT:
                 CPU_CRITICAL_EXIT();
                *p_err = OS_ERR_TASK_NOT_SUSPENDED;
                 break;
    
            case OS_TASK_STATE_SUSPENDED:
                 OS_CRITICAL_ENTER_CPU_EXIT();
                 p_tcb->SuspendCtr--;
                 if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
                     p_tcb->TaskState = OS_TASK_STATE_RDY;
                     OS_TaskRdy(p_tcb);
                 }
                 OS_CRITICAL_EXIT_NO_SCHED();
                 break;
    
            case OS_TASK_STATE_DLY_SUSPENDED:
                 p_tcb->SuspendCtr--;
                 if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
                     p_tcb->TaskState = OS_TASK_STATE_DLY;
                 }
                 CPU_CRITICAL_EXIT();
                 break;
    
            case OS_TASK_STATE_PEND_SUSPENDED:
                 p_tcb->SuspendCtr--;
                 if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
                     p_tcb->TaskState = OS_TASK_STATE_PEND;
                 }
                 CPU_CRITICAL_EXIT();
                 break;
    
            case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
                 p_tcb->SuspendCtr--;
                 if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
                     p_tcb->TaskState = OS_TASK_STATE_PEND_TIMEOUT;
                 }
                 CPU_CRITICAL_EXIT();
                 break;
    
            default:
                 CPU_CRITICAL_EXIT();
                *p_err = OS_ERR_STATE_INVALID;
                 return;
        }
    
        OSSched();
    }
    #endif
    OS_TaskResume()

    OSTaskChangePrio ()
      在创建任务的时候,可以通过设置参数 prio 来设置任务的优先级。在创建完任务后,还可以通过 OSTaskChangePrio () 函数调整任务的优先级。要使用 OSTaskChangePrio () 函数,还得事先使能 OS_CFG_TASK_CHANGE_PRIO_EN(位于“os_cfg.h”),如下所示。

    #define OS_CFG_TASK_CHANGE_PRIO_EN      1u   //使能/禁用函数 OSTaskChangePrio()     

      OSTaskChangePrio () 函数的信息如下所示

      OSTaskChangePrio () 函数的定义也位于“os_task.c :

    #if OS_CFG_TASK_CHANGE_PRIO_EN > 0u
    void  OSTaskChangePrio (OS_TCB   *p_tcb,
                            OS_PRIO   prio_new,
                            OS_ERR   *p_err)
    {
        CPU_BOOLEAN   self;
        CPU_SR_ALLOC();
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* ---------- CANNOT CREATE A TASK FROM AN ISR ---------- */
           *p_err = OS_ERR_TASK_CHANGE_PRIO_ISR;
            return;
        }
    #endif
    
    #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
        if (prio_new == 0) {                                    /* Cannot set to IntQueue Task priority                   */
           *p_err = OS_ERR_PRIO_INVALID;
            return;
        }
    #endif
    
        if (prio_new >= (OS_CFG_PRIO_MAX - 1u)) {               /* Cannot set to Idle Task priority                       */
           *p_err = OS_ERR_PRIO_INVALID;
            return;
        }
    
        if (p_tcb == (OS_TCB *)0) {                             /* See if want to change priority of 'self'               */
            CPU_CRITICAL_ENTER();
            p_tcb = OSTCBCurPtr;
            CPU_CRITICAL_EXIT();
            self  = DEF_TRUE;
        } else {
            self  = DEF_FALSE;
        }
    
        OS_CRITICAL_ENTER();
        switch (p_tcb->TaskState) {
            case OS_TASK_STATE_RDY:
                 OS_RdyListRemove(p_tcb);                       /* Remove from current priority                           */
                 p_tcb->Prio = prio_new;                        /* Set new task priority                                  */
                 OS_PrioInsert(p_tcb->Prio);
                 if (self == DEF_TRUE) {
                     OS_RdyListInsertHead(p_tcb);
                 } else {
                     OS_RdyListInsertTail(p_tcb);
                 }
                 break;
    
            case OS_TASK_STATE_DLY:                             /* Nothing to do except change the priority in the OS_TCB */
            case OS_TASK_STATE_SUSPENDED:
            case OS_TASK_STATE_DLY_SUSPENDED:
                 p_tcb->Prio = prio_new;                        /* Set new task priority                                  */
                 break;
    
            case OS_TASK_STATE_PEND:
            case OS_TASK_STATE_PEND_TIMEOUT:
            case OS_TASK_STATE_PEND_SUSPENDED:
            case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
                 switch (p_tcb->PendOn) {                       /* What to do depends on what we are pending on           */
                     case OS_TASK_PEND_ON_TASK_Q:               /* Nothing to do except change the priority in the OS_TCB */
                     case OS_TASK_PEND_ON_TASK_SEM:
                     case OS_TASK_PEND_ON_FLAG:
                          p_tcb->Prio = prio_new;               /* Set new task priority                                  */
                          break;
    
                     case OS_TASK_PEND_ON_MUTEX:
                     case OS_TASK_PEND_ON_MULTI:
                     case OS_TASK_PEND_ON_Q:
                     case OS_TASK_PEND_ON_SEM:
                          OS_PendListChangePrio(p_tcb,
                                                prio_new);
                          break;
    
                     default:
                          break;
                }
                 break;
    
            default:
                 OS_CRITICAL_EXIT();
                *p_err = OS_ERR_STATE_INVALID;
                 return;
        }
    
        OS_CRITICAL_EXIT_NO_SCHED();
    
        OSSched();                                              /* Run highest priority task ready                        */
    
       *p_err = OS_ERR_NONE;
    }
    #endif
    OSTaskChangePrio()

    OSTaskDel ()
      当任务不再使用时,可以调用 OSTaskDel() 函数删除任务。要使用 OSTaskDel() 函数,还得事先使能 OS_CFG_TASK_SEM_PEND_ABORT_EN(位于“os_cfg.h”)

    #define OS_CFG_TASK_DEL_EN              1u   //使能/禁用函数 OSTaskDel()        

      OSTaskDel() 函数的信息如下所示。

      OSTaskDel () 函数的定义也位于“os_task.c

    #if OS_CFG_TASK_DEL_EN > 0u
    void  OSTaskDel (OS_TCB  *p_tcb,
                     OS_ERR  *p_err)
    {
        CPU_SR_ALLOC();
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* See if trying to delete from ISR                       */
           *p_err = OS_ERR_TASK_DEL_ISR;
            return;
        }
    #endif
    
        if (p_tcb == &OSIdleTaskTCB) {                          /* Not allowed to delete the idle task                    */
           *p_err = OS_ERR_TASK_DEL_IDLE;
            return;
        }
    
    #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
        if (p_tcb == &OSIntQTaskTCB) {                          /* Cannot delete the ISR handler task                     */
           *p_err = OS_ERR_TASK_DEL_INVALID;
            return;
        }
    #endif
    
        if (p_tcb == (OS_TCB *)0) {                             /* Delete 'Self'?                                         */
            CPU_CRITICAL_ENTER();
            p_tcb  = OSTCBCurPtr;                               /* Yes.                                                   */
            CPU_CRITICAL_EXIT();
        }
    
        OS_CRITICAL_ENTER();
        switch (p_tcb->TaskState) {
            case OS_TASK_STATE_RDY:
                 OS_RdyListRemove(p_tcb);
                 break;
    
            case OS_TASK_STATE_SUSPENDED:
                 break;
    
            case OS_TASK_STATE_DLY:                             /* Task is only delayed, not on any wait list             */
            case OS_TASK_STATE_DLY_SUSPENDED:
                 OS_TickListRemove(p_tcb);
                 break;
    
            case OS_TASK_STATE_PEND:
            case OS_TASK_STATE_PEND_SUSPENDED:
            case OS_TASK_STATE_PEND_TIMEOUT:
            case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
                 OS_TickListRemove(p_tcb);
                 switch (p_tcb->PendOn) {                       /* See what we are pending on                             */
                     case OS_TASK_PEND_ON_NOTHING:
                     case OS_TASK_PEND_ON_TASK_Q:               /* There is no wait list for these two                    */
                     case OS_TASK_PEND_ON_TASK_SEM:
                          break;
    
                     case OS_TASK_PEND_ON_FLAG:                 /* Remove from wait list                                  */
                     case OS_TASK_PEND_ON_MULTI:
                     case OS_TASK_PEND_ON_MUTEX:
                     case OS_TASK_PEND_ON_Q:
                     case OS_TASK_PEND_ON_SEM:
                          OS_PendListRemove(p_tcb);
                          break;
    
                     default:
                          break;
                 }
                 break;
    
            default:
                OS_CRITICAL_EXIT();
               *p_err = OS_ERR_STATE_INVALID;
                return;
        }
    
    #if OS_CFG_TASK_Q_EN > 0u
        (void)OS_MsgQFreeAll(&p_tcb->MsgQ);                     /* Free task's message queue messages                     */
    #endif
    
        OSTaskDelHook(p_tcb);                                   /* Call user defined hook                                 */
    
    #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
        OS_TLS_TaskDel(p_tcb);                                  /* Call TLS hook                                          */
    #endif
    
    #if OS_CFG_DBG_EN > 0u
        OS_TaskDbgListRemove(p_tcb);
    #endif
        OSTaskQty--;                                            /* One less task being managed                            */
    
        OS_TaskInitTCB(p_tcb);                                  /* Initialize the TCB to default values                   */
        p_tcb->TaskState = (OS_STATE)OS_TASK_STATE_DEL;         /* Indicate that the task was deleted                     */
    
        OS_CRITICAL_EXIT_NO_SCHED();
    
       *p_err = OS_ERR_NONE;                                    /* See Note #1.                                           */
    
        OSSched();                                              /* Find new highest priority task                         */
    }
    #endif
    OSTaskDel()

    OSSchedRoundRobinCfg ()
      当有任务使用相同的优先级的时候,一般需要使用时间片轮转调度。当具有相同优先级的多个任务就绪时,系统会根据分配给它们的时间片轮流调度各个任务运行。要使用时间片轮转调度功能,除了要先使能 OS_CFG_SCHED_ROUND_ROBIN_EN(位于“os_cfg.h”)外,还需调用 OSSchedRoundRobinCfg() 函数使能时间片轮转调度和配置相关指标。OS_CFG_SCHED_ROUND_ROBIN_EN 位于“os_cfg.h

    #define OS_CFG_SCHED_ROUND_ROBIN_EN     1u   //使能/禁用时间片轮转调度

      OSSchedRoundRobinCfg() 函数的信息如下表所示 

      OSSchedRoundRobinCfg() 函数的定义位于“os_core.c

    #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
    void  OSSchedRoundRobinCfg (CPU_BOOLEAN   en,
                                OS_TICK       dflt_time_quanta,
                                OS_ERR       *p_err)
    {
        CPU_SR_ALLOC();
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
        CPU_CRITICAL_ENTER();
        if (en != DEF_ENABLED) {
            OSSchedRoundRobinEn = DEF_DISABLED;
        } else {
            OSSchedRoundRobinEn = DEF_ENABLED;
        }
    
        if (dflt_time_quanta > (OS_TICK)0) {
            OSSchedRoundRobinDfltTimeQuanta = dflt_time_quanta;
        } else {
            OSSchedRoundRobinDfltTimeQuanta = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10);
        }
        CPU_CRITICAL_EXIT();
       *p_err = OS_ERR_NONE;
    }
    #endif
    OSSchedRoundRobinCfg()

    OSSchedRoundRobinYield ()
      一个任务也可以主动放弃时间片,当一个任务已经完成要执行的事情后,也可以主动放弃时间片,提前退出运行,让就绪列表(处于就绪状态的同一优先级任务)的下一个任务提前运行。但是,如果就绪列表中只有一个任务,该任务无法放弃时间片。一个任务放弃时间片使用 OSSchedRoundRobinYield () 函数,OSSchedRoundRobinYield () 函数的信息如下表所示

      OSSchedRoundRobinYield () 函数的定义位于“os_core.c :

    #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
    void  OSSchedRoundRobinYield (OS_ERR  *p_err)
    {
        OS_RDY_LIST  *p_rdy_list;
        OS_TCB       *p_tcb;
        CPU_SR_ALLOC();
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* Can't call this function from an ISR                   */
           *p_err = OS_ERR_YIELD_ISR;
            return;
        }
    #endif
    
        if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) {        /* Can't yield if the scheduler is locked                 */
           *p_err = OS_ERR_SCHED_LOCKED;
            return;
        }
    
        if (OSSchedRoundRobinEn != DEF_TRUE) {                  /* Make sure round-robin has been enabled                 */
           *p_err = OS_ERR_ROUND_ROBIN_DISABLED;
            return;
        }
    
        CPU_CRITICAL_ENTER();
        p_rdy_list = &OSRdyList[OSPrioCur];                     /* Can't yield if it's the only task at that priority     */
        if (p_rdy_list->NbrEntries < (OS_OBJ_QTY)2) {
            CPU_CRITICAL_EXIT();
           *p_err = OS_ERR_ROUND_ROBIN_1;
            return;
        }
    
        OS_RdyListMoveHeadToTail(p_rdy_list);                   /* Move current OS_TCB to the end of the list             */
        p_tcb = p_rdy_list->HeadPtr;                            /* Point to new OS_TCB at head of the list                */
        if (p_tcb->TimeQuanta == (OS_TICK)0) {                  /* See if we need to use the default time slice           */
            p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta;
        } else {
            p_tcb->TimeQuantaCtr = p_tcb->TimeQuanta;           /* Load time slice counter with new time                  */
        }
    
        CPU_CRITICAL_EXIT();
    
        OSSched();                                              /* Run new task                                           */
       *p_err = OS_ERR_NONE;
    }
    #endif
    OSSchedRoundRobinYield()

    OSTaskTimeQuantaSet ()
      在创建任务的时候,可以通过设置参数 time_quanta 来设置任务的时间片。在创建完任务后,还可以通过 OSTaskTimeQuantaSet () 函数调整任务的时间片。OSTaskTimeQuantaSet ()函数的信息如下所示

      OSTaskTimeQuantaSet () 函数的定义位于“os_task.c”:

    #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
    void  OSTaskTimeQuantaSet (OS_TCB   *p_tcb,
                               OS_TICK   time_quanta,
                               OS_ERR   *p_err)
    {
        CPU_SR_ALLOC();
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
        if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* Can't call this function from an ISR                   */
           *p_err = OS_ERR_SET_ISR;
            return;
        }
    #endif
    
        CPU_CRITICAL_ENTER();
        if (p_tcb == (OS_TCB *)0) {
            p_tcb = OSTCBCurPtr;
        }
    
        if (time_quanta == 0u) {
            p_tcb->TimeQuanta    = OSSchedRoundRobinDfltTimeQuanta;
        } else {
            p_tcb->TimeQuanta    = time_quanta;
        }
        if (p_tcb->TimeQuanta > p_tcb->TimeQuantaCtr) {
            p_tcb->TimeQuantaCtr = p_tcb->TimeQuanta;
        }
        CPU_CRITICAL_EXIT();
       *p_err = OS_ERR_NONE;
    }
    #endif
    OSTaskTimeQuantaSet()

    OSTaskRegSet ()

      UC/OS-III 允许任务拥有给用户自己使用的任务寄存器。所谓任务寄存器,其实就是在任务的任务控制块里增加一个无符号 32 位整型的数组,用来给用户存放一些任务相关的数据。在 创 建 任 务 时 , 会 将 任 务 寄 存 器 全 部 置 0 。 要 使 用 任 务 寄 存 器 , 还 得 事 先 通 过OS_CFG_TASK_REG_TBL_SIZE(位于“os_cfg.h”)定义任务的任务寄存器数目,如下所示

    #define OS_CFG_TASK_REG_TBL_SIZE        1u   //定义任务指定的寄存器数目     

      通过 OSTaskRegSet () 函数可以设置一个任务的任务寄存器的值。OSTaskRegSet () 函数的信息如下所示。

      OSTaskRegSet () 函数的定义位于“os_task.c”:

    #if OS_CFG_TASK_REG_TBL_SIZE > 0u
    void  OSTaskRegSet (OS_TCB     *p_tcb,
                        OS_REG_ID   id,
                        OS_REG      value,
                        OS_ERR     *p_err)
    {
        CPU_SR_ALLOC();
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (p_err == (OS_ERR *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if OS_CFG_ARG_CHK_EN > 0u
        if (id >= OS_CFG_TASK_REG_TBL_SIZE) {
           *p_err = OS_ERR_REG_ID_INVALID;
            return;
        }
    #endif
    
        CPU_CRITICAL_ENTER();
        if (p_tcb == (OS_TCB *)0) {
            p_tcb = OSTCBCurPtr;
        }
        p_tcb->RegTbl[id] = value;
        CPU_CRITICAL_EXIT();
       *p_err             = OS_ERR_NONE;
    }
    #endif
    OSTaskRegSet()

     

     

  • 相关阅读:
    java读取properties文件的几种方法
    mysql中的一些操作
    Threalocal的使用及其原理
    ResourceBundle和properties 读取配置文件区别
    (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
    mysql中的unique
    JSP标签 <meta> 的作用
    面向对象、匿名内部类
    Katalon Studio 安装 配置 简单使用
    Sonar 规则
  • 原文地址:https://www.cnblogs.com/tianxxl/p/10390803.html
Copyright © 2011-2022 走看看