zoukankan      html  css  js  c++  java
  • uC/OS-II 函数之任务相关函数

    获得更多资料欢迎进入我的网站或者 csdn或者博客园

    对于有热心的小伙伴在微博上私信我,说我的uC/OS-II 一些函数简介篇幅有些过于长应该分开介绍。应小伙伴的要求,特此将文章分开进行讲解。上文主要介绍了OSInit()初始化函数,本文介绍任务相关的函数:OSTaskCreate()任务创建函数1,OSTaskCreateExt任务创建函数2,OSTaskSuspend()任务挂起,OSTaskResume()唤醒任务

    OSTaskCreate()任务创建函数

    1、主要作用:建立一个新任务。任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立。中断处理程序中不能建立任务;注意,ISR中禁止建立任务,一个任务必须为无限循环结构。
    2、函数原型:INT8U OSTaskCreate(void (*task)(void *pd), void *pdata, OS_STK ptos, INT8U prio);
    3、参数说明:
    void (
    task)(void *pd):指向任务代码首地址的指针。
    void *pdata:指向一个数据结构,该结构用来在建立任务时向任务传递参数。
    OS_STK *ptos: 指向堆栈任务栈顶的指针
    INT8U prio:任务优先级
    4、返回值介绍:
    OS_NO_ERR:函数调用成功。

    OS_PRIO_EXIST:具有该优先级的任务已经存在。

    OS_PRIO_INVALID:参数指定的优先级大于OS_LOWEST_PRIO。

    OS_NO_MORE_TCB:系统中没有OS_TCB可以分配给任务了。

    5、函数主体在os_task.c中

    OSTaskCreateExt任务创建函数2

    1、主要作用:建立一个新任务。与OSTaskCreate()不同的是,OSTaskCreateExt()允许用户设置更多的细节内容。任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立,但中断处理程序中不能建立新任务。,且不
    2、函数原型:NT8U OSTaskCreateExt (void (*task)(void *pd),void *pdata, OS_STK *ptos,INT8U prio ,INT16U id, OS_STK *pbos,INT32U stk_size,void pext,INT16U opt)
    3、参数说明:
    void (
    task)(void *pd):指向任务代码首地址的指针。
    void *pdata:指向一个数据结构,该结构用来在建立任务时向任务传递参数。
    OS_STK *ptos: 指向堆栈任务栈顶的指针
    INT8U prio:任务优先级
    INT16U id: 任务ID,2.52版本,无实际作用,保留作为扩展用
    OS_STK *pbos: 指向堆栈底部的指针,用于OSTaskStkChk()函数
    INT32U stk_size:指定任务堆栈的大小,由OS_STK类型决定
    void *pext:定义数据结构的指针,作为TCB的扩展
    INT16U opt) :存放于任务操作相关的信息,详见uCOS-II.H
    4、返回值说明:
    OS_NO_ERR:函数调用成功。
    OS_PRIO_EXIST:具有该优先级的任务已经存在。
    OS_PRIO_INVALID:参数指定的优先级大于OS_LOWEST_PRIO。
    OS_NO_MORE_TCB:系统中没有OS_TCB可以分配给任务了。
    5、函数主体在os_task.c中

    OSTaskSuspend()任务挂起:

    1、主要作用: 无条件挂起一个任务。调用此函数的任务也可以传递参数 OS_PRIO_SELF,挂起调用任务本身。当前任务挂起后,只有其他任务才能唤醒被挂起的任务。任务挂起后,系统会重新进行任务调度,运行下一个优先级最高的就绪任务。唤醒挂起任务需要调用函数OSTaskResume()。任务的挂起是可以叠加到其他操作上的。例如,任务被挂起时正在进行延时操作,那么任务的唤醒就需要两个条件:延时的结束以及其他任务的唤醒操作。又如,任务被挂起时正在等待信号量,当任务从信号量的等待对列中清除后也不能立即运行,而必须等到被唤醒后。
    2、函数原型:INT8U OSTaskSuspend(INT8U prio);
    3、参数说明:prio为指定要获取挂起的任务优先级,也可以指定参数 OS_PRIO_SELF,挂起任务本身。此时,下一个优先级最高的就绪任务将运行。
    4、返回值说明:
    OS_NO_ERR:函数调用成功。
    OS_TASK_SUSPEND_IDLE:试图挂起μC/OS-II中的空闲任务(Idle task)。此为非法操作。
    OS_PRIO_INVALID:参数指定的优先级大于 OS_LOWEST_PRIO 或没有设定 OS_PRIO_SELF 的值。
    OS_TASK_SUSPEND_PRIO:要挂起的任务不存在。
    5、函数主体在os_task.c中

    OSTaskResume()唤醒任务

    1、主要作用: 唤醒一个用 OSTaskSuspend() 函数挂起的任务。OSTaskResume() 也是唯一能“解挂”挂起任务的函数。
    2、函数原型:INT8U OSTaskResume(INT8U prio);
    3、参数说明:prio指定要唤醒任务的优先级。
    4、返回值说明:
    OS_NO_ERR:函数调用成功。
    OS_TASK_RESUME_PRIO:要唤醒的任务不存在
    OS_TASK_NOT_SUSPENDED:要唤醒的任务不在挂起状态。
    OS_PRIO_INVALID:参数指定的优先级大于或等于OS_LOWEST_PRIO。
    5、函数主体在os_task.c中、

    附os_task.c代码:

    /*
    *********************************************************************************************************
    *                                                uC/OS-II
    *                                          The Real-Time Kernel
    *                                            TASK MANAGEMENT
    *
    *                              (c) Copyright 1992-2013, Micrium, Weston, FL
    *                                           All Rights Reserved
    *
    * File    : OS_TASK.C
    * By      : Jean J. Labrosse
    * Version : V2.92.08
    *
    * LICENSING TERMS:
    * ---------------
    *   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
    * If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
    * its use in your product. We provide ALL the source code for your convenience and to help you experience
    * uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
    * licensing fee.
    *********************************************************************************************************
    */
    
    #define  MICRIUM_SOURCE
    
    #ifndef  OS_MASTER_FILE
    #include <ucos_ii.h>
    #endif
    
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                      CHANGE PRIORITY OF A TASK
    *
    * Description: This function allows you to change the priority of a task dynamically.  Note that the new
    *              priority MUST be available.
    *
    * Arguments  : oldp     is the old priority
    *
    *              newp     is the new priority
    *
    * Returns    : OS_ERR_NONE            is the call was successful
    *              OS_ERR_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
    *                                     (i.e. >= OS_LOWEST_PRIO)
    *              OS_ERR_PRIO_EXIST      if the new priority already exist.
    *              OS_ERR_PRIO            there is no task with the specified OLD priority (i.e. the OLD task does
    *                                     not exist.
    *              OS_ERR_TASK_NOT_EXIST  if the task is assigned to a Mutex PIP.
    *********************************************************************************************************
    */
    
    #if OS_TASK_CHANGE_PRIO_EN > 0u
    INT8U  OSTaskChangePrio (INT8U  oldprio,
                             INT8U  newprio)
    {
    #if (OS_EVENT_EN)
        OS_EVENT  *pevent;
    #if (OS_EVENT_MULTI_EN > 0u)
        OS_EVENT **pevents;
    #endif
    #endif
        OS_TCB    *ptcb;
        INT8U      y_new;
        INT8U      x_new;
        INT8U      y_old;
        OS_PRIO    bity_new;
        OS_PRIO    bitx_new;
        OS_PRIO    bity_old;
        OS_PRIO    bitx_old;
    #if OS_CRITICAL_METHOD == 3u
        OS_CPU_SR  cpu_sr = 0u;                                 /* Storage for CPU status register         */
    #endif
    
    
    /*$PAGE*/
    #if OS_ARG_CHK_EN > 0u
        if (oldprio >= OS_LOWEST_PRIO) {
            if (oldprio != OS_PRIO_SELF) {
                return (OS_ERR_PRIO_INVALID);
            }
        }
        if (newprio >= OS_LOWEST_PRIO) {
            return (OS_ERR_PRIO_INVALID);
        }
    #endif
        OS_ENTER_CRITICAL();
        if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) {             /* New priority must not already exist     */
            OS_EXIT_CRITICAL();
            return (OS_ERR_PRIO_EXIST);
        }
        if (oldprio == OS_PRIO_SELF) {                          /* See if changing self                    */
            oldprio = OSTCBCur->OSTCBPrio;                      /* Yes, get priority                       */
        }
        ptcb = OSTCBPrioTbl[oldprio];
        if (ptcb == (OS_TCB *)0) {                              /* Does task to change exist?              */
            OS_EXIT_CRITICAL();                                 /* No, can't change its priority!          */
            return (OS_ERR_PRIO);
        }
        if (ptcb == OS_TCB_RESERVED) {                          /* Is task assigned to Mutex               */
            OS_EXIT_CRITICAL();                                 /* No, can't change its priority!          */
            return (OS_ERR_TASK_NOT_EXIST);
        }
    #if OS_LOWEST_PRIO <= 63u
        y_new                 = (INT8U)(newprio >> 3u);         /* Yes, compute new TCB fields             */
        x_new                 = (INT8U)(newprio & 0x07u);
    #else
        y_new                 = (INT8U)((INT8U)(newprio >> 4u) & 0x0Fu);
        x_new                 = (INT8U)(newprio & 0x0Fu);
    #endif
        bity_new              = (OS_PRIO)(1uL << y_new);
        bitx_new              = (OS_PRIO)(1uL << x_new);
    
        OSTCBPrioTbl[oldprio] = (OS_TCB *)0;                    /* Remove TCB from old priority            */
        OSTCBPrioTbl[newprio] =  ptcb;                          /* Place pointer to TCB @ new priority     */
        y_old                 =  ptcb->OSTCBY;
        bity_old              =  ptcb->OSTCBBitY;
        bitx_old              =  ptcb->OSTCBBitX;
        if ((OSRdyTbl[y_old] &   bitx_old) != 0u) {             /* If task is ready make it not            */
             OSRdyTbl[y_old] &= (OS_PRIO)~bitx_old;
             if (OSRdyTbl[y_old] == 0u) {
                 OSRdyGrp &= (OS_PRIO)~bity_old;
             }
             OSRdyGrp        |= bity_new;                       /* Make new priority ready to run          */
             OSRdyTbl[y_new] |= bitx_new;
        }
    
    #if (OS_EVENT_EN)
        pevent = ptcb->OSTCBEventPtr;
        if (pevent != (OS_EVENT *)0) {
            pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old;    /* Remove old task prio from wait list     */
            if (pevent->OSEventTbl[y_old] == 0u) {
                pevent->OSEventGrp    &= (OS_PRIO)~bity_old;
            }
            pevent->OSEventGrp        |= bity_new;              /* Add    new task prio to   wait list     */
            pevent->OSEventTbl[y_new] |= bitx_new;
        }
    #if (OS_EVENT_MULTI_EN > 0u)
        if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {
            pevents =  ptcb->OSTCBEventMultiPtr;
            pevent  = *pevents;
            while (pevent != (OS_EVENT *)0) {
                pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old;   /* Remove old task prio from wait lists */
                if (pevent->OSEventTbl[y_old] == 0u) {
                    pevent->OSEventGrp    &= (OS_PRIO)~bity_old;
                }
                pevent->OSEventGrp        |= bity_new;          /* Add    new task prio to   wait lists    */
                pevent->OSEventTbl[y_new] |= bitx_new;
                pevents++;
                pevent                     = *pevents;
            }
        }
    #endif
    #endif
    
        ptcb->OSTCBPrio = newprio;                              /* Set new task priority                   */
        ptcb->OSTCBY    = y_new;
        ptcb->OSTCBX    = x_new;
        ptcb->OSTCBBitY = bity_new;
        ptcb->OSTCBBitX = bitx_new;
        OS_EXIT_CRITICAL();
        if (OSRunning == OS_TRUE) {
            OS_Sched();                                         /* Find new highest priority task          */
        }
        return (OS_ERR_NONE);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                            CREATE A TASK
    *
    * Description: This function is used to have uC/OS-II manage the execution of a task.  Tasks can either
    *              be created prior to the start of multitasking or by a running task.  A task cannot be
    *              created by an ISR.
    *
    * Arguments  : task     is a pointer to the task's code
    *
    *              p_arg    is a pointer to an optional data area which can be used to pass parameters to
    *                       the task when the task first executes.  Where the task is concerned it thinks
    *                       it was invoked and passed the argument 'p_arg' as follows:
    *
    *                           void Task (void *p_arg)
    *                           {
    *                               for (;;) {
    *                                   Task code;
    *                               }
    *                           }
    *
    *              ptos     is a pointer to the task's top of stack.  If the configuration constant
    *                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
    *                       memory to low memory).  'pstk' will thus point to the highest (valid) memory
    *                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pstk' will point to the
    *                       lowest memory location of the stack and the stack will grow with increasing
    *                       memory locations.
    *
    *              prio     is the task's priority.  A unique priority MUST be assigned to each task and the
    *                       lower the number, the higher the priority.
    *
    * Returns    : OS_ERR_NONE                      if the function was successful.
    *              OS_ERR_PRIO_EXIST                if the task priority already exist
    *                                               (each task MUST have a unique priority).
    *              OS_ERR_PRIO_INVALID              if the priority you specify is higher that the maximum
    *                                               allowed (i.e. >= OS_LOWEST_PRIO)
    *              OS_ERR_TASK_CREATE_ISR           if you tried to create a task from an ISR.
    *              OS_ERR_ILLEGAL_CREATE_RUN_TIME   if you tried to create a task after safety critical
    *                                               operation started.
    *********************************************************************************************************
    */
    
    #if OS_TASK_CREATE_EN > 0u
    INT8U  OSTaskCreate (void   (*task)(void *p_arg),
                         void    *p_arg,
                         OS_STK  *ptos,
                         INT8U    prio)
    {
        OS_STK     *psp;
        INT8U       err;
    #if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */
        OS_CPU_SR   cpu_sr = 0u;
    #endif
    
    
    
    #ifdef OS_SAFETY_CRITICAL_IEC61508
        if (OSSafetyCriticalStartFlag == OS_TRUE) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);
        }
    #endif
    
    #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);
        }
        OS_EXIT_CRITICAL();
        return (OS_ERR_PRIO_EXIST);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                  CREATE A TASK (Extended Version)
    *
    * Description: This function is used to have uC/OS-II manage the execution of a task.  Tasks can either
    *              be created prior to the start of multitasking or by a running task.  A task cannot be
    *              created by an ISR.  This function is similar to OSTaskCreate() except that it allows
    *              additional information about a task to be specified.
    *
    * Arguments  : task      is a pointer to the task's code
    *
    *              p_arg     is a pointer to an optional data area which can be used to pass parameters to
    *                        the task when the task first executes.  Where the task is concerned it thinks
    *                        it was invoked and passed the argument 'p_arg' as follows:
    *
    *                            void Task (void *p_arg)
    *                            {
    *                                for (;;) {
    *                                    Task code;
    *                                }
    *                            }
    *
    *              ptos      is a pointer to the task's top of stack.  If the configuration constant
    *                        OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
    *                        memory to low memory).  'ptos' will thus point to the highest (valid) memory
    *                        location of the stack.  If OS_STK_GROWTH is set to 0, 'ptos' will point to the
    *                        lowest memory location of the stack and the stack will grow with increasing
    *                        memory locations.  'ptos' MUST point to a valid 'free' data item.
    *
    *              prio      is the task's priority.  A unique priority MUST be assigned to each task and the
    *                        lower the number, the higher the priority.
    *
    *              id        is the task's ID (0..65535)
    *
    *              pbos      is a pointer to the task's bottom of stack.  If the configuration constant
    *                        OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
    *                        memory to low memory).  'pbos' will thus point to the LOWEST (valid) memory
    *                        location of the stack.  If OS_STK_GROWTH is set to 0, 'pbos' will point to the
    *                        HIGHEST memory location of the stack and the stack will grow with increasing
    *                        memory locations.  'pbos' MUST point to a valid 'free' data item.
    *
    *              stk_size  is the size of the stack in number of elements.  If OS_STK is set to INT8U,
    *                        'stk_size' corresponds to the number of bytes available.  If OS_STK is set to
    *                        INT16U, 'stk_size' contains the number of 16-bit entries available.  Finally, if
    *                        OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries
    *                        available on the stack.
    *
    *              pext      is a pointer to a user supplied memory location which is used as a TCB extension.
    *                        For example, this user memory can hold the contents of floating-point registers
    *                        during a context switch, the time each task takes to execute, the number of times
    *                        the task has been switched-in, etc.
    *
    *              opt       contains additional information (or options) about the behavior of the task.  The
    *                        LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application
    *                        specific.  See OS_TASK_OPT_??? in uCOS-II.H.  Current choices are:
    *
    *                        OS_TASK_OPT_STK_CHK      Stack checking to be allowed for the task
    *                        OS_TASK_OPT_STK_CLR      Clear the stack when the task is created
    *                        OS_TASK_OPT_SAVE_FP      If the CPU has floating-point registers, save them
    *                                                 during a context switch.
    *
    * Returns    : OS_ERR_NONE                      if the function was successful.
    *              OS_ERR_PRIO_EXIST                if the task priority already exist
    *                                               (each task MUST have a unique priority).
    *              OS_ERR_PRIO_INVALID              if the priority you specify is higher that the maximum
    *                                               allowed (i.e. > OS_LOWEST_PRIO)
    *              OS_ERR_TASK_CREATE_ISR           if you tried to create a task from an ISR.
    *              OS_ERR_ILLEGAL_CREATE_RUN_TIME   if you tried to create a task after safety critical
    *                                               operation started.
    *********************************************************************************************************
    */
    /*$PAGE*/
    #if OS_TASK_CREATE_EXT_EN > 0u
    INT8U  OSTaskCreateExt (void   (*task)(void *p_arg),
                            void    *p_arg,
                            OS_STK  *ptos,
                            INT8U    prio,
                            INT16U   id,
                            OS_STK  *pbos,
                            INT32U   stk_size,
                            void    *pext,
                            INT16U   opt)
    {
        OS_STK     *psp;
        INT8U       err;
    #if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */
        OS_CPU_SR   cpu_sr = 0u;
    #endif
    
    
    
    #ifdef OS_SAFETY_CRITICAL_IEC61508
        if (OSSafetyCriticalStartFlag == OS_TRUE) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);
        }
    #endif
    
    #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();
    
    #if (OS_TASK_STAT_STK_CHK_EN > 0u)
            OS_TaskStkClr(pbos, stk_size, opt);                    /* Clear the task stack (if needed)     */
    #endif
    
            psp = OSTaskStkInit(task, p_arg, ptos, opt);           /* Initialize the task's stack          */
            err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);
            if (err == OS_ERR_NONE) {
                if (OSRunning == OS_TRUE) {                        /* Find HPT if multitasking has started */
                    OS_Sched();
                }
            } else {
                OS_ENTER_CRITICAL();
                OSTCBPrioTbl[prio] = (OS_TCB *)0;                  /* Make this priority avail. to others  */
                OS_EXIT_CRITICAL();
            }
            return (err);
        }
        OS_EXIT_CRITICAL();
        return (OS_ERR_PRIO_EXIST);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                            DELETE A TASK
    *
    * Description: This function allows you to delete a task.  The calling task can delete itself by
    *              its own priority number.  The deleted task is returned to the dormant state and can be
    *              re-activated by creating the deleted task again.
    *
    * Arguments  : prio    is the priority of the task to delete.  Note that you can explicitly delete
    *                      the current task without knowing its priority level by setting 'prio' to
    *                      OS_PRIO_SELF.
    *
    * Returns    : OS_ERR_NONE             if the call is successful
    *              OS_ERR_TASK_DEL_IDLE    if you attempted to delete uC/OS-II's idle task
    *              OS_ERR_PRIO_INVALID     if the priority you specify is higher that the maximum allowed
    *                                      (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
    *              OS_ERR_TASK_DEL         if the task is assigned to a Mutex PIP.
    *              OS_ERR_TASK_NOT_EXIST   if the task you want to delete does not exist.
    *              OS_ERR_TASK_DEL_ISR     if you tried to delete a task from an ISR
    *
    * Notes      : 1) To reduce interrupt latency, OSTaskDel() 'disables' the task:
    *                    a) by making it not ready
    *                    b) by removing it from any wait lists
    *                    c) by preventing OSTimeTick() from making the task ready to run.
    *                 The task can then be 'unlinked' from the miscellaneous structures in uC/OS-II.
    *              2) The function OS_Dummy() is called after OS_EXIT_CRITICAL() because, on most processors,
    *                 the next instruction following the enable interrupt instruction is ignored.
    *              3) An ISR cannot delete a task.
    *              4) The lock nesting counter is incremented because, for a brief instant, if the current
    *                 task is being deleted, the current task would not be able to be rescheduled because it
    *                 is removed from the ready list.  Incrementing the nesting counter prevents another task
    *                 from being schedule.  This means that an ISR would return to the current task which is
    *                 being deleted.  The rest of the deletion would thus be able to be completed.
    *********************************************************************************************************
    */
    
    #if OS_TASK_DEL_EN > 0u
    INT8U  OSTaskDel (INT8U prio)
    {
    #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
        OS_FLAG_NODE *pnode;
    #endif
        OS_TCB       *ptcb;
    #if OS_CRITICAL_METHOD == 3u                            /* Allocate storage for CPU status register    */
        OS_CPU_SR     cpu_sr = 0u;
    #endif
    
    
    
        if (OSIntNesting > 0u) {                            /* See if trying to delete from ISR            */
            return (OS_ERR_TASK_DEL_ISR);
        }
        if (prio == OS_TASK_IDLE_PRIO) {                    /* Not allowed to delete idle task             */
            return (OS_ERR_TASK_DEL_IDLE);
        }
    #if OS_ARG_CHK_EN > 0u
        if (prio >= OS_LOWEST_PRIO) {                       /* Task priority valid ?                       */
            if (prio != OS_PRIO_SELF) {
                return (OS_ERR_PRIO_INVALID);
            }
        }
    #endif
    
    /*$PAGE*/
        OS_ENTER_CRITICAL();
        if (prio == OS_PRIO_SELF) {                         /* See if requesting to delete self            */
            prio = OSTCBCur->OSTCBPrio;                     /* Set priority to delete to current           */
        }
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb == (OS_TCB *)0) {                          /* Task to delete must exist                   */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_NOT_EXIST);
        }
        if (ptcb == OS_TCB_RESERVED) {                      /* Must not be assigned to Mutex               */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_DEL);
        }
    
        OSRdyTbl[ptcb->OSTCBY] &= (OS_PRIO)~ptcb->OSTCBBitX;
        if (OSRdyTbl[ptcb->OSTCBY] == 0u) {                 /* Make task not ready                         */
            OSRdyGrp           &= (OS_PRIO)~ptcb->OSTCBBitY;
        }
    
    #if (OS_EVENT_EN)
        if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) {
            OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr);  /* Remove this task from any event   wait list */
        }
    #if (OS_EVENT_MULTI_EN > 0u)
        if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {   /* Remove this task from any events' wait lists*/
            OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
        }
    #endif
    #endif
    
    #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
        pnode = ptcb->OSTCBFlagNode;
        if (pnode != (OS_FLAG_NODE *)0) {                   /* If task is waiting on event flag            */
            OS_FlagUnlink(pnode);                           /* Remove from wait list                       */
        }
    #endif
    
        ptcb->OSTCBDly      = 0u;                           /* Prevent OSTimeTick() from updating          */
        ptcb->OSTCBStat     = OS_STAT_RDY;                  /* Prevent task from being resumed             */
        ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
        if (OSLockNesting < 255u) {                         /* Make sure we don't context switch           */
            OSLockNesting++;
        }
        OS_EXIT_CRITICAL();                                 /* Enabling INT. ignores next instruc.         */
        OS_Dummy();                                         /* ... Dummy ensures that INTs will be         */
        OS_ENTER_CRITICAL();                                /* ... disabled HERE!                          */
        if (OSLockNesting > 0u) {                           /* Remove context switch lock                  */
            OSLockNesting--;
        }
        OSTaskDelHook(ptcb);                                /* Call user defined hook                      */
    
    #if OS_TASK_CREATE_EXT_EN > 0u
    #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
        OS_TLS_TaskDel(ptcb);                               /* Call TLS hook                               */
    #endif
    #endif
    
        OSTaskCtr--;                                        /* One less task being managed                 */
        OSTCBPrioTbl[prio] = (OS_TCB *)0;                   /* Clear old priority entry                    */
        if (ptcb->OSTCBPrev == (OS_TCB *)0) {               /* Remove from TCB chain                       */
            ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
            OSTCBList                  = ptcb->OSTCBNext;
        } else {
            ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
            ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
        }
        ptcb->OSTCBNext     = OSTCBFreeList;                /* Return TCB to free TCB list                 */
        OSTCBFreeList       = ptcb;
    #if OS_TASK_NAME_EN > 0u
        ptcb->OSTCBTaskName = (INT8U *)(void *)"?";
    #endif
        OS_EXIT_CRITICAL();
        if (OSRunning == OS_TRUE) {
            OS_Sched();                                     /* Find new highest priority task              */
        }
        return (OS_ERR_NONE);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                  REQUEST THAT A TASK DELETE ITSELF
    *
    * Description: This function is used to:
    *                   a) notify a task to delete itself.
    *                   b) to see if a task requested that the current task delete itself.
    *              This function is a little tricky to understand.  Basically, you have a task that needs
    *              to be deleted however, this task has resources that it has allocated (memory buffers,
    *              semaphores, mailboxes, queues etc.).  The task cannot be deleted otherwise these
    *              resources would not be freed.  The requesting task calls OSTaskDelReq() to indicate that
    *              the task needs to be deleted.  Deleting of the task is however, deferred to the task to
    *              be deleted.  For example, suppose that task #10 needs to be deleted.  The requesting task
    *              example, task #5, would call OSTaskDelReq(10).  When task #10 gets to execute, it calls
    *              this function by specifying OS_PRIO_SELF and monitors the returned value.  If the return
    *              value is OS_ERR_TASK_DEL_REQ, another task requested a task delete.  Task #10 would look like
    *              this:
    *
    *                   void Task(void *p_arg)
    *                   {
    *                       .
    *                       .
    *                       while (1) {
    *                           OSTimeDly(1);
    *                           if (OSTaskDelReq(OS_PRIO_SELF) == OS_ERR_TASK_DEL_REQ) {
    *                               Release any owned resources;
    *                               De-allocate any dynamic memory;
    *                               OSTaskDel(OS_PRIO_SELF);
    *                           }
    *                       }
    *                   }
    *
    * Arguments  : prio    is the priority of the task to request the delete from
    *
    * Returns    : OS_ERR_NONE            if the task exist and the request has been registered
    *              OS_ERR_TASK_NOT_EXIST  if the task has been deleted.  This allows the caller to know whether
    *                                     the request has been executed.
    *              OS_ERR_TASK_DEL        if the task is assigned to a Mutex.
    *              OS_ERR_TASK_DEL_IDLE   if you requested to delete uC/OS-II's idle task
    *              OS_ERR_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
    *                                     (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
    *              OS_ERR_TASK_DEL_REQ    if a task (possibly another task) requested that the running task be
    *                                     deleted.
    *********************************************************************************************************
    */
    /*$PAGE*/
    #if OS_TASK_DEL_EN > 0u
    INT8U  OSTaskDelReq (INT8U prio)
    {
        INT8U      stat;
        OS_TCB    *ptcb;
    #if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
    
    
    
        if (prio == OS_TASK_IDLE_PRIO) {                            /* Not allowed to delete idle task     */
            return (OS_ERR_TASK_DEL_IDLE);
        }
    #if OS_ARG_CHK_EN > 0u
        if (prio >= OS_LOWEST_PRIO) {                               /* Task priority valid ?               */
            if (prio != OS_PRIO_SELF) {
                return (OS_ERR_PRIO_INVALID);
            }
        }
    #endif
        if (prio == OS_PRIO_SELF) {                                 /* See if a task is requesting to ...  */
            OS_ENTER_CRITICAL();                                    /* ... this task to delete itself      */
            stat = OSTCBCur->OSTCBDelReq;                           /* Return request status to caller     */
            OS_EXIT_CRITICAL();
            return (stat);
        }
        OS_ENTER_CRITICAL();
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb == (OS_TCB *)0) {                                  /* Task to delete must exist           */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_NOT_EXIST);                         /* Task must already be deleted        */
        }
        if (ptcb == OS_TCB_RESERVED) {                              /* Must NOT be assigned to a Mutex     */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_DEL);
        }
        ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ;                    /* Set flag indicating task to be DEL. */
        OS_EXIT_CRITICAL();
        return (OS_ERR_NONE);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                       GET THE NAME OF A TASK
    *
    * Description: This function is called to obtain the name of a task.
    *
    * Arguments  : prio      is the priority of the task that you want to obtain the name from.
    *
    *              pname     is a pointer to a pointer to an ASCII string that will receive the name of the task.
    *
    *              perr      is a pointer to an error code that can contain one of the following values:
    *
    *                        OS_ERR_NONE                if the requested task is resumed
    *                        OS_ERR_TASK_NOT_EXIST      if the task has not been created or is assigned to a Mutex
    *                        OS_ERR_PRIO_INVALID        if you specified an invalid priority:
    *                                                   A higher value than the idle task or not OS_PRIO_SELF.
    *                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
    *                        OS_ERR_NAME_GET_ISR        You called this function from an ISR
    *
    *
    * Returns    : The length of the string or 0 if the task does not exist.
    *********************************************************************************************************
    */
    
    #if OS_TASK_NAME_EN > 0u
    INT8U  OSTaskNameGet (INT8U    prio,
                          INT8U  **pname,
                          INT8U   *perr)
    {
        OS_TCB    *ptcb;
        INT8U      len;
    #if OS_CRITICAL_METHOD == 3u                             /* Allocate storage for CPU status register   */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (perr == (INT8U *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return (0u);
        }
    #endif
    
    #if OS_ARG_CHK_EN > 0u
        if (prio > OS_LOWEST_PRIO) {                         /* Task priority valid ?                      */
            if (prio != OS_PRIO_SELF) {
                *perr = OS_ERR_PRIO_INVALID;                 /* No                                         */
                return (0u);
            }
        }
        if (pname == (INT8U **)0) {                          /* Is 'pname' a NULL pointer?                 */
            *perr = OS_ERR_PNAME_NULL;                       /* Yes                                        */
            return (0u);
        }
    #endif
        if (OSIntNesting > 0u) {                              /* See if trying to call from an ISR          */
            *perr = OS_ERR_NAME_GET_ISR;
            return (0u);
        }
        OS_ENTER_CRITICAL();
        if (prio == OS_PRIO_SELF) {                          /* See if caller desires it's own name        */
            prio = OSTCBCur->OSTCBPrio;
        }
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb == (OS_TCB *)0) {                           /* Does task exist?                           */
            OS_EXIT_CRITICAL();                              /* No                                         */
            *perr = OS_ERR_TASK_NOT_EXIST;
            return (0u);
        }
        if (ptcb == OS_TCB_RESERVED) {                       /* Task assigned to a Mutex?                  */
            OS_EXIT_CRITICAL();                              /* Yes                                        */
            *perr = OS_ERR_TASK_NOT_EXIST;
            return (0u);
        }
        *pname = ptcb->OSTCBTaskName;
        len    = OS_StrLen(*pname);
        OS_EXIT_CRITICAL();
        *perr  = OS_ERR_NONE;
        return (len);
    }
    #endif
    
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                       ASSIGN A NAME TO A TASK
    *
    * Description: This function is used to set the name of a task.
    *
    * Arguments  : prio      is the priority of the task that you want the assign a name to.
    *
    *              pname     is a pointer to an ASCII string that contains the name of the task.
    *
    *              perr       is a pointer to an error code that can contain one of the following values:
    *
    *                        OS_ERR_NONE                if the requested task is resumed
    *                        OS_ERR_TASK_NOT_EXIST      if the task has not been created or is assigned to a Mutex
    *                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
    *                        OS_ERR_PRIO_INVALID        if you specified an invalid priority:
    *                                                   A higher value than the idle task or not OS_PRIO_SELF.
    *                        OS_ERR_NAME_SET_ISR        if you called this function from an ISR
    *
    * Returns    : None
    *********************************************************************************************************
    */
    #if OS_TASK_NAME_EN > 0u
    void  OSTaskNameSet (INT8U   prio,
                         INT8U  *pname,
                         INT8U  *perr)
    {
        OS_TCB    *ptcb;
    #if OS_CRITICAL_METHOD == 3u                         /* Allocate storage for CPU status register       */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (perr == (INT8U *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if OS_ARG_CHK_EN > 0u
        if (prio > OS_LOWEST_PRIO) {                     /* Task priority valid ?                          */
            if (prio != OS_PRIO_SELF) {
                *perr = OS_ERR_PRIO_INVALID;             /* No                                             */
                return;
            }
        }
        if (pname == (INT8U *)0) {                       /* Is 'pname' a NULL pointer?                     */
            *perr = OS_ERR_PNAME_NULL;                   /* Yes                                            */
            return;
        }
    #endif
        if (OSIntNesting > 0u) {                         /* See if trying to call from an ISR              */
            *perr = OS_ERR_NAME_SET_ISR;
            return;
        }
        OS_ENTER_CRITICAL();
        if (prio == OS_PRIO_SELF) {                      /* See if caller desires to set it's own name     */
            prio = OSTCBCur->OSTCBPrio;
        }
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb == (OS_TCB *)0) {                       /* Does task exist?                               */
            OS_EXIT_CRITICAL();                          /* No                                             */
            *perr = OS_ERR_TASK_NOT_EXIST;
            return;
        }
        if (ptcb == OS_TCB_RESERVED) {                   /* Task assigned to a Mutex?                      */
            OS_EXIT_CRITICAL();                          /* Yes                                            */
            *perr = OS_ERR_TASK_NOT_EXIST;
            return;
        }
        ptcb->OSTCBTaskName = pname;
        OS_EXIT_CRITICAL();
        *perr               = OS_ERR_NONE;
    }
    #endif
    
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                       RESUME A SUSPENDED TASK
    *
    * Description: This function is called to resume a previously suspended task.  This is the only call that
    *              will remove an explicit task suspension.
    *
    * Arguments  : prio     is the priority of the task to resume.
    *
    * Returns    : OS_ERR_NONE                if the requested task is resumed
    *              OS_ERR_PRIO_INVALID        if the priority you specify is higher that the maximum allowed
    *                                         (i.e. >= OS_LOWEST_PRIO)
    *              OS_ERR_TASK_RESUME_PRIO    if the task to resume does not exist
    *              OS_ERR_TASK_NOT_EXIST      if the task is assigned to a Mutex PIP
    *              OS_ERR_TASK_NOT_SUSPENDED  if the task to resume has not been suspended
    *********************************************************************************************************
    */
    
    #if OS_TASK_SUSPEND_EN > 0u
    INT8U  OSTaskResume (INT8U prio)
    {
        OS_TCB    *ptcb;
    #if OS_CRITICAL_METHOD == 3u                                  /* Storage for CPU status register       */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
    
    
    
    #if OS_ARG_CHK_EN > 0u
        if (prio >= OS_LOWEST_PRIO) {                             /* Make sure task priority is valid      */
            return (OS_ERR_PRIO_INVALID);
        }
    #endif
        OS_ENTER_CRITICAL();
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb == (OS_TCB *)0) {                                /* Task to suspend must exist            */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_RESUME_PRIO);
        }
        if (ptcb == OS_TCB_RESERVED) {                            /* See if assigned to Mutex              */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_NOT_EXIST);
        }
        if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended                */
            ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_SUSPEND;    /* Remove suspension                     */
            if (ptcb->OSTCBStat == OS_STAT_RDY) {                 /* See if task is now ready              */
                if (ptcb->OSTCBDly == 0u) {
                    OSRdyGrp               |= ptcb->OSTCBBitY;    /* Yes, Make task ready to run           */
                    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                    OS_EXIT_CRITICAL();
                    if (OSRunning == OS_TRUE) {
                        OS_Sched();                               /* Find new highest priority task        */
                    }
                } else {
                    OS_EXIT_CRITICAL();
                }
            } else {                                              /* Must be pending on event              */
                OS_EXIT_CRITICAL();
            }
            return (OS_ERR_NONE);
        }
        OS_EXIT_CRITICAL();
        return (OS_ERR_TASK_NOT_SUSPENDED);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                           STACK CHECKING
    *
    * Description: This function is called to check the amount of free memory left on the specified task's
    *              stack.
    *
    * Arguments  : prio          is the task priority
    *
    *              p_stk_data    is a pointer to a data structure of type OS_STK_DATA.
    *
    * Returns    : OS_ERR_NONE            upon success
    *              OS_ERR_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
    *                                     (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
    *              OS_ERR_TASK_NOT_EXIST  if the desired task has not been created or is assigned to a Mutex PIP
    *              OS_ERR_TASK_OPT        if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created
    *              OS_ERR_PDATA_NULL      if 'p_stk_data' is a NULL pointer
    *********************************************************************************************************
    */
    #if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
    INT8U  OSTaskStkChk (INT8U         prio,
                         OS_STK_DATA  *p_stk_data)
    {
        OS_TCB    *ptcb;
        OS_STK    *pchk;
        INT32U     nfree;
        INT32U     size;
    #if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
    
    
    
    #if OS_ARG_CHK_EN > 0u
        if (prio > OS_LOWEST_PRIO) {                       /* Make sure task priority is valid             */
            if (prio != OS_PRIO_SELF) {
                return (OS_ERR_PRIO_INVALID);
            }
        }
        if (p_stk_data == (OS_STK_DATA *)0) {              /* Validate 'p_stk_data'                        */
            return (OS_ERR_PDATA_NULL);
        }
    #endif
        p_stk_data->OSFree = 0u;                           /* Assume failure, set to 0 size                */
        p_stk_data->OSUsed = 0u;
        OS_ENTER_CRITICAL();
        if (prio == OS_PRIO_SELF) {                        /* See if check for SELF                        */
            prio = OSTCBCur->OSTCBPrio;
        }
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb == (OS_TCB *)0) {                         /* Make sure task exist                         */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_NOT_EXIST);
        }
        if (ptcb == OS_TCB_RESERVED) {
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_NOT_EXIST);
        }
        if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0u) { /* Make sure stack checking option is set      */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_OPT);
        }
        nfree = 0u;
        size  = ptcb->OSTCBStkSize;
        pchk  = ptcb->OSTCBStkBottom;
        OS_EXIT_CRITICAL();
    #if OS_STK_GROWTH == 1u
        while (*pchk++ == (OS_STK)0) {                    /* Compute the number of zero entries on the stk */
            nfree++;
        }
    #else
        while (*pchk-- == (OS_STK)0) {
            nfree++;
        }
    #endif
        p_stk_data->OSFree = nfree;                       /* Store   number of free entries on the stk     */
        p_stk_data->OSUsed = size - nfree;                /* Compute number of entries used on the stk     */
        return (OS_ERR_NONE);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                           SUSPEND A TASK
    *
    * Description: This function is called to suspend a task.  The task can be the calling task if the
    *              priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF.
    *
    * Arguments  : prio     is the priority of the task to suspend.  If you specify OS_PRIO_SELF, the
    *                       calling task will suspend itself and rescheduling will occur.
    *
    * Returns    : OS_ERR_NONE               if the requested task is suspended
    *              OS_ERR_TASK_SUSPEND_IDLE  if you attempted to suspend the idle task which is not allowed.
    *              OS_ERR_PRIO_INVALID       if the priority you specify is higher that the maximum allowed
    *                                        (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
    *              OS_ERR_TASK_SUSPEND_PRIO  if the task to suspend does not exist
    *              OS_ERR_TASK_NOT_EXITS     if the task is assigned to a Mutex PIP
    *
    * Note       : You should use this function with great care.  If you suspend a task that is waiting for
    *              an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from
    *              running when the event arrives.
    *********************************************************************************************************
    */
    
    #if OS_TASK_SUSPEND_EN > 0u
    INT8U  OSTaskSuspend (INT8U prio)
    {
        BOOLEAN    self;
        OS_TCB    *ptcb;
        INT8U      y;
    #if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
    
    
    
    #if OS_ARG_CHK_EN > 0u
        if (prio == OS_TASK_IDLE_PRIO) {                            /* Not allowed to suspend idle task    */
            return (OS_ERR_TASK_SUSPEND_IDLE);
        }
        if (prio >= OS_LOWEST_PRIO) {                               /* Task priority valid ?               */
            if (prio != OS_PRIO_SELF) {
                return (OS_ERR_PRIO_INVALID);
            }
        }
    #endif
        OS_ENTER_CRITICAL();
        if (prio == OS_PRIO_SELF) {                                 /* See if suspend SELF                 */
            prio = OSTCBCur->OSTCBPrio;
            self = OS_TRUE;
        } else if (prio == OSTCBCur->OSTCBPrio) {                   /* See if suspending self              */
            self = OS_TRUE;
        } else {
            self = OS_FALSE;                                        /* No suspending another task          */
        }
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb == (OS_TCB *)0) {                                  /* Task to suspend must exist          */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_SUSPEND_PRIO);
        }
        if (ptcb == OS_TCB_RESERVED) {                              /* See if assigned to Mutex            */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_NOT_EXIST);
        }
        y            = ptcb->OSTCBY;
        OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;                   /* Make task not ready                 */
        if (OSRdyTbl[y] == 0u) {
            OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
        }
        ptcb->OSTCBStat |= OS_STAT_SUSPEND;                         /* Status of task is 'SUSPENDED'       */
        OS_EXIT_CRITICAL();
        if (self == OS_TRUE) {                                      /* Context switch only if SELF         */
            OS_Sched();                                             /* Find new highest priority task      */
        }
        return (OS_ERR_NONE);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                            QUERY A TASK
    *
    * Description: This function is called to obtain a copy of the desired task's TCB.
    *
    * Arguments  : prio         is the priority of the task to obtain information from.
    *
    *              p_task_data  is a pointer to where the desired task's OS_TCB will be stored.
    *
    * Returns    : OS_ERR_NONE            if the requested task is suspended
    *              OS_ERR_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
    *                                     (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
    *              OS_ERR_PRIO            if the desired task has not been created
    *              OS_ERR_TASK_NOT_EXIST  if the task is assigned to a Mutex PIP
    *              OS_ERR_PDATA_NULL      if 'p_task_data' is a NULL pointer
    *********************************************************************************************************
    */
    
    #if OS_TASK_QUERY_EN > 0u
    INT8U  OSTaskQuery (INT8U    prio,
                        OS_TCB  *p_task_data)
    {
        OS_TCB    *ptcb;
    #if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
    
    
    
    #if OS_ARG_CHK_EN > 0u
        if (prio > OS_LOWEST_PRIO) {                 /* Task priority valid ?                              */
            if (prio != OS_PRIO_SELF) {
                return (OS_ERR_PRIO_INVALID);
            }
        }
        if (p_task_data == (OS_TCB *)0) {            /* Validate 'p_task_data'                             */
            return (OS_ERR_PDATA_NULL);
        }
    #endif
        OS_ENTER_CRITICAL();
        if (prio == OS_PRIO_SELF) {                  /* See if suspend SELF                                */
            prio = OSTCBCur->OSTCBPrio;
        }
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb == (OS_TCB *)0) {                   /* Task to query must exist                           */
            OS_EXIT_CRITICAL();
            return (OS_ERR_PRIO);
        }
        if (ptcb == OS_TCB_RESERVED) {               /* Task to query must not be assigned to a Mutex      */
            OS_EXIT_CRITICAL();
            return (OS_ERR_TASK_NOT_EXIST);
        }
                                                     /* Copy TCB into user storage area                    */
        OS_MemCopy((INT8U *)p_task_data, (INT8U *)ptcb, sizeof(OS_TCB));
        OS_EXIT_CRITICAL();
        return (OS_ERR_NONE);
    }
    #endif
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                              GET THE CURRENT VALUE OF A TASK REGISTER
    *
    * Description: This function is called to obtain the current value of a task register.  Task registers
    *              are application specific and can be used to store task specific values such as 'error
    *              numbers' (i.e. errno), statistics, etc.  Each task register can hold a 32-bit value.
    *
    * Arguments  : prio      is the priority of the task you want to get the task register from.  If you
    *                        specify OS_PRIO_SELF then the task register of the current task will be obtained.
    *
    *              id        is the 'id' of the desired task register.  Note that the 'id' must be less
    *                        than OS_TASK_REG_TBL_SIZE
    *
    *              perr      is a pointer to a variable that will hold an error code related to this call.
    *
    *                        OS_ERR_NONE            if the call was successful
    *                        OS_ERR_PRIO_INVALID    if you specified an invalid priority
    *                        OS_ERR_ID_INVALID      if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1
    *
    * Returns    : The current value of the task's register or 0 if an error is detected.
    *
    * Note(s)    : The maximum number of task variables is 254
    *********************************************************************************************************
    */
    
    #if OS_TASK_REG_TBL_SIZE > 0u
    INT32U  OSTaskRegGet (INT8U   prio,
                          INT8U   id,
                          INT8U  *perr)
    {
    #if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
        INT32U     value;
        OS_TCB    *ptcb;
    
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (perr == (INT8U *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return (0u);
        }
    #endif
    
    #if OS_ARG_CHK_EN > 0u
        if (prio >= OS_LOWEST_PRIO) {
            if (prio != OS_PRIO_SELF) {
                *perr = OS_ERR_PRIO_INVALID;
                return (0u);
            }
        }
        if (id >= OS_TASK_REG_TBL_SIZE) {
            *perr = OS_ERR_ID_INVALID;
            return (0u);
        }
    #endif
        OS_ENTER_CRITICAL();
        if (prio == OS_PRIO_SELF) {                  /* See if need to get register from current task      */
            ptcb = OSTCBCur;
        } else {
            ptcb = OSTCBPrioTbl[prio];
        }
        value = ptcb->OSTCBRegTbl[id];
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;
        return (value);
    }
    #endif
    
    /*$PAGE*/
    /*
    ************************************************************************************************************************
    *                                    ALLOCATE THE NEXT AVAILABLE TASK REGISTER ID
    *
    * Description: This function is called to obtain a task register ID.  This function thus allows task registers IDs to be
    *              allocated dynamically instead of statically.
    *
    * Arguments  : p_err       is a pointer to a variable that will hold an error code related to this call.
    *
    *                            OS_ERR_NONE               if the call was successful
    *                            OS_ERR_NO_MORE_ID_AVAIL   if you are attempting to assign more task register IDs than you 
    *                                                           have available through OS_TASK_REG_TBL_SIZE.
    *
    * Returns    : The next available task register 'id' or OS_TASK_REG_TBL_SIZE if an error is detected.
    ************************************************************************************************************************
    */
    
    #if OS_TASK_REG_TBL_SIZE > 0u
    INT8U  OSTaskRegGetID (INT8U  *perr)
    {
    #if OS_CRITICAL_METHOD == 3u                                    /* Allocate storage for CPU status register           */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
        INT8U      id;
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (perr == (INT8U *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return ((INT8U)OS_TASK_REG_TBL_SIZE);
        }
    #endif
    
        OS_ENTER_CRITICAL();
        if (OSTaskRegNextAvailID >= OS_TASK_REG_TBL_SIZE) {         /* See if we exceeded the number of IDs available     */
           *perr = OS_ERR_NO_MORE_ID_AVAIL;                         /* Yes, cannot allocate more task register IDs        */
            OS_EXIT_CRITICAL();
            return ((INT8U)OS_TASK_REG_TBL_SIZE);
        }
         
        id   = OSTaskRegNextAvailID;                                /* Assign the next available ID                       */
        OSTaskRegNextAvailID++;                                     /* Increment available ID for next request            */
        OS_EXIT_CRITICAL();
       *perr = OS_ERR_NONE;
        return (id);
    }
    #endif
    
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                              SET THE CURRENT VALUE OF A TASK VARIABLE
    *
    * Description: This function is called to change the current value of a task register.  Task registers
    *              are application specific and can be used to store task specific values such as 'error
    *              numbers' (i.e. errno), statistics, etc.  Each task register can hold a 32-bit value.
    *
    * Arguments  : prio      is the priority of the task you want to set the task register for.  If you
    *                        specify OS_PRIO_SELF then the task register of the current task will be obtained.
    *
    *              id        is the 'id' of the desired task register.  Note that the 'id' must be less
    *                        than OS_TASK_REG_TBL_SIZE
    *
    *              value     is the desired value for the task register.
    *
    *              perr      is a pointer to a variable that will hold an error code related to this call.
    *
    *                        OS_ERR_NONE            if the call was successful
    *                        OS_ERR_PRIO_INVALID    if you specified an invalid priority
    *                        OS_ERR_ID_INVALID      if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1
    *
    * Returns    : The current value of the task's variable or 0 if an error is detected.
    *
    * Note(s)    : The maximum number of task variables is 254
    *********************************************************************************************************
    */
    
    #if OS_TASK_REG_TBL_SIZE > 0u
    void  OSTaskRegSet (INT8U    prio,
                        INT8U    id,
                        INT32U   value,
                        INT8U   *perr)
    {
    #if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
        OS_CPU_SR  cpu_sr = 0u;
    #endif
        OS_TCB    *ptcb;
    
    
    #ifdef OS_SAFETY_CRITICAL
        if (perr == (INT8U *)0) {
            OS_SAFETY_CRITICAL_EXCEPTION();
            return;
        }
    #endif
    
    #if OS_ARG_CHK_EN > 0u
        if (prio >= OS_LOWEST_PRIO) {
            if (prio != OS_PRIO_SELF) {
                *perr = OS_ERR_PRIO_INVALID;
                return;
            }
        }
        if (id >= OS_TASK_REG_TBL_SIZE) {
            *perr = OS_ERR_ID_INVALID;
            return;
        }
    #endif
        OS_ENTER_CRITICAL();
        if (prio == OS_PRIO_SELF) {                  /* See if need to get register from current task      */
            ptcb = OSTCBCur;
        } else {
            ptcb = OSTCBPrioTbl[prio];
        }
        ptcb->OSTCBRegTbl[id] = value;
        OS_EXIT_CRITICAL();
        *perr                 = OS_ERR_NONE;
    }
    #endif
    
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                    CATCH ACCIDENTAL TASK RETURN
    *
    * Description: This function is called if a task accidentally returns without deleting itself.  In other
    *              words, a task should either be an infinite loop or delete itself if it's done.
    *
    * Arguments  : none
    *
    * Returns    : none
    *
    * Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
    *********************************************************************************************************
    */
    
    void  OS_TaskReturn (void)
    {
        OSTaskReturnHook(OSTCBCur);                   /* Call hook to let user decide on what to do        */
    
    #if OS_TASK_DEL_EN > 0u
        (void)OSTaskDel(OS_PRIO_SELF);                /* Delete task if it accidentally returns!           */
    #else
        for (;;) {
            OSTimeDly(OS_TICKS_PER_SEC);
        }
    #endif
    }
    
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                          CLEAR TASK STACK
    *
    * Description: This function is used to clear the stack of a task (i.e. write all zeros)
    *
    * Arguments  : pbos     is a pointer to the task's bottom of stack.  If the configuration constant
    *                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
    *                       memory to low memory).  'pbos' will thus point to the lowest (valid) memory
    *                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pbos' will point to the
    *                       highest memory location of the stack and the stack will grow with increasing
    *                       memory locations.  'pbos' MUST point to a valid 'free' data item.
    *
    *              size     is the number of 'stack elements' to clear.
    *
    *              opt      contains additional information (or options) about the behavior of the task.  The
    *                       LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application
    *                       specific.  See OS_TASK_OPT_??? in uCOS-II.H.
    *
    * Returns    : none
    *********************************************************************************************************
    */
    #if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
    void  OS_TaskStkClr (OS_STK  *pbos,
                         INT32U   size,
                         INT16U   opt)
    {
        if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000u) {      /* See if stack checking has been enabled       */
            if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000u) {  /* See if stack needs to be cleared             */
    #if OS_STK_GROWTH == 1u
                while (size > 0u) {                        /* Stack grows from HIGH to LOW memory          */
                    size--;
                    *pbos++ = (OS_STK)0;                   /* Clear from bottom of stack and up!           */
                }
    #else
                while (size > 0u) {                        /* Stack grows from LOW to HIGH memory          */
                    size--;
                    *pbos-- = (OS_STK)0;                   /* Clear from bottom of stack and down          */
                }
    #endif
            }
        }
    }
    
    #endif
    
  • 相关阅读:
    【移动端】300ms延迟以及点透事件原因以及解决方案
    javaScript drag对象进行拖拽使用详解
    js文件上传原理(form表单 ,FormData + XHR2 + FileReader + canvas)
    Linux常用bash命令
    一些好的关于网络知识的博客
    python 2 处理HTTP 请求的包
    python 3 处理HTTP 请求的包
    接口测试笔记
    接口测试资料
    PyH : python生成html
  • 原文地址:https://www.cnblogs.com/onepeace/p/4696862.html
Copyright © 2011-2022 走看看