os_task.c
上传用户:jingkewang
上传日期:2013-04-11
资源大小:917k
文件大小:48k
源码类别:

uCOS

开发平台:

Visual C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                            TASK MANAGEMENT
  6. *
  7. *                          (c) Copyright 1992-2005, Jean J. Labrosse, Weston, FL
  8. *                                           All Rights Reserved
  9. *
  10. * File    : OS_TASK.C
  11. * By      : Jean J. Labrosse
  12. * Version : V2.80
  13. *********************************************************************************************************
  14. */
  15. #ifndef  OS_MASTER_FILE
  16. #include <ucos_ii.h>
  17. #endif
  18. /*
  19. *********************************************************************************************************
  20. *                                        CHANGE PRIORITY OF A TASK
  21. *
  22. * Description: This function allows you to change the priority of a task dynamically.  Note that the new
  23. *              priority MUST be available.
  24. *
  25. * Arguments  : oldp     is the old priority
  26. *
  27. *              newp     is the new priority
  28. *
  29. * Returns    : OS_NO_ERR          is the call was successful
  30. *              OS_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
  31. *                                 (i.e. >= OS_LOWEST_PRIO)
  32. *              OS_PRIO_EXIST      if the new priority already exist.
  33. *              OS_PRIO_ERR        there is no task with the specified OLD priority (i.e. the OLD task does
  34. *                                 not exist.
  35. *              OS_TASK_NOT_EXIST  if the task is assigned to a Mutex PIP.
  36. *********************************************************************************************************
  37. */
  38. #if OS_TASK_CHANGE_PRIO_EN > 0
  39. INT8U  OSTaskChangePrio (INT8U oldprio, INT8U newprio)
  40. {
  41. #if OS_EVENT_EN
  42.     OS_EVENT    *pevent;
  43. #endif
  44.     OS_TCB      *ptcb;
  45.     INT8U        x;
  46.     INT8U        y;
  47. #if OS_LOWEST_PRIO <= 63
  48.     INT8U        bitx;
  49.     INT8U        bity;
  50. #else
  51.     INT16U       bitx;
  52.     INT16U       bity;
  53. #endif
  54.     INT8U        y_old;
  55. #if OS_CRITICAL_METHOD == 3
  56.     OS_CPU_SR    cpu_sr = 0;                                    /* Storage for CPU status register     */
  57. #endif
  58. #if OS_ARG_CHK_EN > 0
  59.     if (oldprio >= OS_LOWEST_PRIO) {
  60.     if (oldprio != OS_PRIO_SELF) {
  61.             return (OS_PRIO_INVALID);
  62. }
  63. }
  64.     if (newprio >= OS_LOWEST_PRIO) {
  65.         return (OS_PRIO_INVALID);
  66.     }
  67. #endif
  68.     OS_ENTER_CRITICAL();
  69.     if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) {                 /* New priority must not already exist */
  70.         OS_EXIT_CRITICAL();
  71.         return (OS_PRIO_EXIST);
  72.     }
  73.     if (oldprio == OS_PRIO_SELF) {                              /* See if changing self                */
  74.         oldprio = OSTCBCur->OSTCBPrio;                          /* Yes, get priority                   */
  75.     }
  76.     ptcb = OSTCBPrioTbl[oldprio];
  77.     if (ptcb == (OS_TCB *)0) {                                  /* Does task to change exist?          */
  78.         OS_EXIT_CRITICAL();                                     /* No, can't change its priority!      */
  79.         return (OS_PRIO_ERR);
  80.     }
  81.     if (ptcb == (OS_TCB *)1) {                                  /* Is task assigned to Mutex           */
  82.         OS_EXIT_CRITICAL();                                     /* No, can't change its priority!      */
  83.         return (OS_TASK_NOT_EXIST);
  84.     }
  85. #if OS_LOWEST_PRIO <= 63
  86.     y                     = newprio >> 3;                       /* Yes, compute new TCB fields         */
  87.     x                     = newprio & 0x07;
  88. #else
  89.     y                     = (newprio >> 4) & 0xFF;
  90.     x                     =  newprio & 0x0F;
  91. #endif
  92.     bity                  = 1 << y;
  93.     bitx                  = 1 << x;
  94.     OSTCBPrioTbl[oldprio] = (OS_TCB *)0;                        /* Remove TCB from old priority        */
  95.     OSTCBPrioTbl[newprio] = ptcb;                               /* Place pointer to TCB @ new priority */
  96.     y_old                 = ptcb->OSTCBY;
  97.     if ((OSRdyTbl[y_old] & ptcb->OSTCBBitX) != 0) {             /* If task is ready make it not        */
  98.         OSRdyTbl[y_old] &= ~ptcb->OSTCBBitX;
  99.         if (OSRdyTbl[y_old] == 0) {
  100.             OSRdyGrp &= ~ptcb->OSTCBBitY;
  101.         }
  102.         OSRdyGrp    |= bity;                                    /* Make new priority ready to run      */
  103.         OSRdyTbl[y] |= bitx;
  104. #if OS_EVENT_EN
  105.     } else {                                                    /* Task was not ready ...              */
  106.         pevent = ptcb->OSTCBEventPtr;
  107.         if (pevent != (OS_EVENT *)0) {                          /* ... remove from event wait list     */
  108.             pevent->OSEventTbl[y_old] &= ~ptcb->OSTCBBitX;
  109.             if (pevent->OSEventTbl[y_old] == 0) {
  110.                 pevent->OSEventGrp &= ~ptcb->OSTCBBitY;
  111.             }
  112.             pevent->OSEventGrp    |= bity;                      /* Add new priority to wait list       */
  113.             pevent->OSEventTbl[y] |= bitx;
  114.         }
  115. #endif
  116.     }
  117.     ptcb->OSTCBPrio = newprio;                                  /* Set new task priority               */
  118.     ptcb->OSTCBY    = y;
  119.     ptcb->OSTCBX    = x;
  120.     ptcb->OSTCBBitY = bity;
  121.     ptcb->OSTCBBitX = bitx;
  122.     OS_EXIT_CRITICAL();
  123.     OS_Sched();                                                 /* Run highest priority task ready     */
  124.     return (OS_NO_ERR);
  125. }
  126. #endif
  127. /*$PAGE*/
  128. /*
  129. *********************************************************************************************************
  130. *                                            CREATE A TASK
  131. *
  132. * Description: This function is used to have uC/OS-II manage the execution of a task.  Tasks can either
  133. *              be created prior to the start of multitasking or by a running task.  A task cannot be
  134. *              created by an ISR.
  135. *
  136. * Arguments  : task     is a pointer to the task's code
  137. *
  138. *              p_arg    is a pointer to an optional data area which can be used to pass parameters to
  139. *                       the task when the task first executes.  Where the task is concerned it thinks
  140. *                       it was invoked and passed the argument 'p_arg' as follows:
  141. *
  142. *                           void Task (void *p_arg)
  143. *                           {
  144. *                               for (;;) {
  145. *                                   Task code;
  146. *                               }
  147. *                           }
  148. *
  149. *              ptos     is a pointer to the task's top of stack.  If the configuration constant
  150. *                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  151. *                       memory to low memory).  'pstk' will thus point to the highest (valid) memory
  152. *                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pstk' will point to the
  153. *                       lowest memory location of the stack and the stack will grow with increasing
  154. *                       memory locations.
  155. *
  156. *              prio     is the task's priority.  A unique priority MUST be assigned to each task and the
  157. *                       lower the number, the higher the priority.
  158. *
  159. * Returns    : OS_NO_ERR               if the function was successful.
  160. *              OS_PRIO_EXIT            if the task priority already exist
  161. *                                      (each task MUST have a unique priority).
  162. *              OS_PRIO_INVALID         if the priority you specify is higher that the maximum allowed
  163. *                                      (i.e. >= OS_LOWEST_PRIO)
  164. *              OS_ERR_TASK_CREATE_ISR  if you tried to create a task from an ISR.
  165. *********************************************************************************************************
  166. */
  167. #if OS_TASK_CREATE_EN > 0
  168. INT8U  OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio)
  169. {
  170.     OS_STK    *psp;
  171.     INT8U      err;
  172. #if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */
  173.     OS_CPU_SR  cpu_sr = 0;
  174. #endif
  175. #if OS_ARG_CHK_EN > 0
  176.     if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */
  177.         return (OS_PRIO_INVALID);
  178.     }
  179. #endif
  180.     OS_ENTER_CRITICAL();
  181.     if (OSIntNesting > 0) {                  /* Make sure we don't create the task from within an ISR  */
  182.         OS_EXIT_CRITICAL();
  183.         return (OS_ERR_TASK_CREATE_ISR);
  184.     }
  185.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */
  186.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    /* Reserve the priority to prevent others from doing ...  */
  187.                                              /* ... the same thing until task is created.              */
  188.         OS_EXIT_CRITICAL();
  189.         psp = OSTaskStkInit(task, p_arg, ptos, 0);              /* Initialize the task's stack         */
  190.         err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
  191.         if (err == OS_NO_ERR) {
  192.             if (OSRunning == TRUE) {         /* Find highest priority task if multitasking has started */
  193.                 OS_Sched();
  194.             }
  195.         } else {
  196.             OS_ENTER_CRITICAL();
  197.             OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others                 */
  198.             OS_EXIT_CRITICAL();
  199.         }
  200.         return (err);
  201.     }
  202.     OS_EXIT_CRITICAL();
  203.     return (OS_PRIO_EXIST);
  204. }
  205. #endif
  206. /*$PAGE*/
  207. /*
  208. *********************************************************************************************************
  209. *                                     CREATE A TASK (Extended Version)
  210. *
  211. * Description: This function is used to have uC/OS-II manage the execution of a task.  Tasks can either
  212. *              be created prior to the start of multitasking or by a running task.  A task cannot be
  213. *              created by an ISR.  This function is similar to OSTaskCreate() except that it allows
  214. *              additional information about a task to be specified.
  215. *
  216. * Arguments  : task      is a pointer to the task's code
  217. *
  218. *              p_arg     is a pointer to an optional data area which can be used to pass parameters to
  219. *                        the task when the task first executes.  Where the task is concerned it thinks
  220. *                        it was invoked and passed the argument 'p_arg' as follows:
  221. *
  222. *                            void Task (void *p_arg)
  223. *                            {
  224. *                                for (;;) {
  225. *                                    Task code;
  226. *                                }
  227. *                            }
  228. *
  229. *              ptos      is a pointer to the task's top of stack.  If the configuration constant
  230. *                        OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  231. *                        memory to low memory).  'ptos' will thus point to the highest (valid) memory
  232. *                        location of the stack.  If OS_STK_GROWTH is set to 0, 'ptos' will point to the
  233. *                        lowest memory location of the stack and the stack will grow with increasing
  234. *                        memory locations.  'ptos' MUST point to a valid 'free' data item.
  235. *
  236. *              prio      is the task's priority.  A unique priority MUST be assigned to each task and the
  237. *                        lower the number, the higher the priority.
  238. *
  239. *              id        is the task's ID (0..65535)
  240. *
  241. *              pbos      is a pointer to the task's bottom of stack.  If the configuration constant
  242. *                        OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  243. *                        memory to low memory).  'pbos' will thus point to the LOWEST (valid) memory
  244. *                        location of the stack.  If OS_STK_GROWTH is set to 0, 'pbos' will point to the
  245. *                        HIGHEST memory location of the stack and the stack will grow with increasing
  246. *                        memory locations.  'pbos' MUST point to a valid 'free' data item.
  247. *
  248. *              stk_size  is the size of the stack in number of elements.  If OS_STK is set to INT8U,
  249. *                        'stk_size' corresponds to the number of bytes available.  If OS_STK is set to
  250. *                        INT16U, 'stk_size' contains the number of 16-bit entries available.  Finally, if
  251. *                        OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries
  252. *                        available on the stack.
  253. *
  254. *              pext      is a pointer to a user supplied memory location which is used as a TCB extension.
  255. *                        For example, this user memory can hold the contents of floating-point registers
  256. *                        during a context switch, the time each task takes to execute, the number of times
  257. *                        the task has been switched-in, etc.
  258. *
  259. *              opt       contains additional information (or options) about the behavior of the task.  The
  260. *                        LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application
  261. *                        specific.  See OS_TASK_OPT_??? in uCOS-II.H.  Current choices are:
  262. *
  263. *                        OS_TASK_OPT_STK_CHK      Stack checking to be allowed for the task
  264. *                        OS_TASK_OPT_STK_CLR      Clear the stack when the task is created
  265. *                        OS_TASK_OPT_SAVE_FP      If the CPU has floating-point registers, save them
  266. *                                                 during a context switch.
  267. *
  268. * Returns    : OS_NO_ERR               if the function was successful.
  269. *              OS_PRIO_EXIT            if the task priority already exist
  270. *                                      (each task MUST have a unique priority).
  271. *              OS_PRIO_INVALID         if the priority you specify is higher that the maximum allowed
  272. *                                      (i.e. > OS_LOWEST_PRIO)
  273. *              OS_ERR_TASK_CREATE_ISR  if you tried to create a task from an ISR.
  274. *********************************************************************************************************
  275. */
  276. /*$PAGE*/
  277. #if OS_TASK_CREATE_EXT_EN > 0
  278. INT8U  OSTaskCreateExt (void   (*task)(void *p_arg),
  279.                         void    *p_arg,
  280.                         OS_STK  *ptos,
  281.                         INT8U    prio,
  282.                         INT16U   id,
  283.                         OS_STK  *pbos,
  284.                         INT32U   stk_size,
  285.                         void    *pext,
  286.                         INT16U   opt)
  287. {
  288.     OS_STK    *psp;
  289.     INT8U      err;
  290. #if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */
  291.     OS_CPU_SR  cpu_sr = 0;
  292. #endif
  293. #if OS_ARG_CHK_EN > 0
  294.     if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */
  295.         return (OS_PRIO_INVALID);
  296.     }
  297. #endif
  298.     OS_ENTER_CRITICAL();
  299.     if (OSIntNesting > 0) {                  /* Make sure we don't create the task from within an ISR  */
  300.         OS_EXIT_CRITICAL();
  301.         return (OS_ERR_TASK_CREATE_ISR);
  302.     }
  303.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */
  304.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    /* Reserve the priority to prevent others from doing ...  */
  305.                                              /* ... the same thing until task is created.              */
  306.         OS_EXIT_CRITICAL();
  307.         OS_TaskStkClr(pbos, stk_size, opt);                    /* Clear the task stack (if needed)     */
  308.         psp = OSTaskStkInit(task, p_arg, ptos, opt);           /* Initialize the task's stack          */
  309.         err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);
  310.         if (err == OS_NO_ERR) {
  311.             if (OSRunning == TRUE) {                           /* Find HPT if multitasking has started */
  312.                 OS_Sched();
  313.             }
  314.         } else {
  315.             OS_ENTER_CRITICAL();
  316.             OSTCBPrioTbl[prio] = (OS_TCB *)0;                  /* Make this priority avail. to others  */
  317.             OS_EXIT_CRITICAL();
  318.         }
  319.         return (err);
  320.     }
  321.     OS_EXIT_CRITICAL();
  322.     return (OS_PRIO_EXIST);
  323. }
  324. #endif
  325. /*$PAGE*/
  326. /*
  327. *********************************************************************************************************
  328. *                                            DELETE A TASK
  329. *
  330. * Description: This function allows you to delete a task.  The calling task can delete itself by
  331. *              its own priority number.  The deleted task is returned to the dormant state and can be
  332. *              re-activated by creating the deleted task again.
  333. *
  334. * Arguments  : prio    is the priority of the task to delete.  Note that you can explicitely delete
  335. *                      the current task without knowing its priority level by setting 'prio' to
  336. *                      OS_PRIO_SELF.
  337. *
  338. * Returns    : OS_NO_ERR           if the call is successful
  339. *              OS_TASK_DEL_IDLE    if you attempted to delete uC/OS-II's idle task
  340. *              OS_PRIO_INVALID     if the priority you specify is higher that the maximum allowed
  341. *                                  (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  342. *              OS_TASK_DEL_ERR     if the task you want to delete does not exist.
  343. *              OS_TASK_NOT_EXIST   if the task is assigned to a Mutex PIP.
  344. *              OS_TASK_DEL_ISR     if you tried to delete a task from an ISR
  345. *
  346. * Notes      : 1) To reduce interrupt latency, OSTaskDel() 'disables' the task:
  347. *                    a) by making it not ready
  348. *                    b) by removing it from any wait lists
  349. *                    c) by preventing OSTimeTick() from making the task ready to run.
  350. *                 The task can then be 'unlinked' from the miscellaneous structures in uC/OS-II.
  351. *              2) The function OS_Dummy() is called after OS_EXIT_CRITICAL() because, on most processors,
  352. *                 the next instruction following the enable interrupt instruction is ignored.
  353. *              3) An ISR cannot delete a task.
  354. *              4) The lock nesting counter is incremented because, for a brief instant, if the current
  355. *                 task is being deleted, the current task would not be able to be rescheduled because it
  356. *                 is removed from the ready list.  Incrementing the nesting counter prevents another task
  357. *                 from being schedule.  This means that an ISR would return to the current task which is
  358. *                 being deleted.  The rest of the deletion would thus be able to be completed.
  359. *********************************************************************************************************
  360. */
  361. /*$PAGE*/
  362. #if OS_TASK_DEL_EN > 0
  363. INT8U  OSTaskDel (INT8U prio)
  364. {
  365. #if OS_EVENT_EN
  366.     OS_EVENT     *pevent;
  367. #endif
  368. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
  369.     OS_FLAG_NODE *pnode;
  370. #endif
  371.     OS_TCB       *ptcb;
  372. INT8U         y;
  373. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  374.     OS_CPU_SR     cpu_sr = 0;
  375. #endif
  376.     if (OSIntNesting > 0) {                                     /* See if trying to delete from ISR    */
  377.         return (OS_TASK_DEL_ISR);
  378.     }
  379. #if OS_ARG_CHK_EN > 0
  380.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to delete idle task     */
  381.         return (OS_TASK_DEL_IDLE);
  382.     }
  383.     if (prio >= OS_LOWEST_PRIO) {                               /* Task priority valid ?               */
  384.         if (prio != OS_PRIO_SELF) {
  385.             return (OS_PRIO_INVALID);
  386.         }
  387.     }
  388. #endif
  389.     OS_ENTER_CRITICAL();
  390.     if (prio == OS_PRIO_SELF) {                                 /* See if requesting to delete self    */
  391.         prio = OSTCBCur->OSTCBPrio;                             /* Set priority to delete to current   */
  392.     }
  393.     ptcb = OSTCBPrioTbl[prio];
  394.     if (ptcb == (OS_TCB *)0) {                                  /* Task to delete must exist           */
  395.         OS_EXIT_CRITICAL();
  396.         return (OS_TASK_DEL_ERR);
  397.     }
  398.     if (ptcb == (OS_TCB *)1) {                                  /* Must not be assigned to Mutex       */
  399.         OS_EXIT_CRITICAL();
  400.         return (OS_TASK_NOT_EXIST);
  401.     }
  402. y            =  ptcb->OSTCBY;
  403. OSRdyTbl[y] &= ~ptcb->OSTCBBitX;
  404.     if (OSRdyTbl[y] == 0) {                                     /* Make task not ready                 */
  405.         OSRdyGrp &= ~ptcb->OSTCBBitY;
  406.     }
  407. #if OS_EVENT_EN
  408.     pevent = ptcb->OSTCBEventPtr;
  409.     if (pevent != (OS_EVENT *)0) {                              /* If task is waiting on event         */
  410.     pevent->OSEventTbl[y] &= ~ptcb->OSTCBBitX;
  411.         if (pevent->OSEventTbl[y] == 0) {                       /* ... remove task from ...            */
  412.             pevent->OSEventGrp &= ~ptcb->OSTCBBitY;             /* ... event ctrl block                */
  413.         }
  414.     }
  415. #endif
  416. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
  417.     pnode = ptcb->OSTCBFlagNode;
  418.     if (pnode != (OS_FLAG_NODE *)0) {                           /* If task is waiting on event flag    */
  419.         OS_FlagUnlink(pnode);                                   /* Remove from wait list               */
  420.     }
  421. #endif
  422.     ptcb->OSTCBDly    = 0;                                      /* Prevent OSTimeTick() from updating  */
  423.     ptcb->OSTCBStat   = OS_STAT_RDY;                            /* Prevent task from being resumed     */
  424.     ptcb->OSTCBPendTO = FALSE;
  425. if (OSLockNesting < 255u) {                                 /* Make sure we don't context switch   */
  426.         OSLockNesting++;
  427. }
  428.     OS_EXIT_CRITICAL();                                         /* Enabling INT. ignores next instruc. */
  429.     OS_Dummy();                                                 /* ... Dummy ensures that INTs will be */
  430.     OS_ENTER_CRITICAL();                                        /* ... disabled HERE!                  */
  431. if (OSLockNesting > 0) {                                    /* Remove context switch lock          */
  432.         OSLockNesting--;
  433. }
  434.     OSTaskDelHook(ptcb);                                        /* Call user defined hook              */
  435.     OSTaskCtr--;                                                /* One less task being managed         */
  436.     OSTCBPrioTbl[prio] = (OS_TCB *)0;                           /* Clear old priority entry            */
  437.     if (ptcb->OSTCBPrev == (OS_TCB *)0) {                       /* Remove from TCB chain               */
  438.         ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
  439.         OSTCBList                  = ptcb->OSTCBNext;
  440.     } else {
  441.         ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
  442.         ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
  443.     }
  444.     ptcb->OSTCBNext   = OSTCBFreeList;                          /* Return TCB to free TCB list         */
  445.     OSTCBFreeList     = ptcb;
  446. #if OS_TASK_NAME_SIZE > 1
  447.     ptcb->OSTCBTaskName[0] = '?';                               /* Unknown name                        */
  448.     ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;
  449. #endif
  450.     OS_EXIT_CRITICAL();
  451.     OS_Sched();                                                 /* Find new highest priority task      */
  452.     return (OS_NO_ERR);
  453. }
  454. #endif
  455. /*$PAGE*/
  456. /*
  457. *********************************************************************************************************
  458. *                                    REQUEST THAT A TASK DELETE ITSELF
  459. *
  460. * Description: This function is used to:
  461. *                   a) notify a task to delete itself.
  462. *                   b) to see if a task requested that the current task delete itself.
  463. *              This function is a little tricky to understand.  Basically, you have a task that needs
  464. *              to be deleted however, this task has resources that it has allocated (memory buffers,
  465. *              semaphores, mailboxes, queues etc.).  The task cannot be deleted otherwise these
  466. *              resources would not be freed.  The requesting task calls OSTaskDelReq() to indicate that
  467. *              the task needs to be deleted.  Deleting of the task is however, deferred to the task to
  468. *              be deleted.  For example, suppose that task #10 needs to be deleted.  The requesting task
  469. *              example, task #5, would call OSTaskDelReq(10).  When task #10 gets to execute, it calls
  470. *              this function by specifying OS_PRIO_SELF and monitors the returned value.  If the return
  471. *              value is OS_TASK_DEL_REQ, another task requested a task delete.  Task #10 would look like
  472. *              this:
  473. *
  474. *                   void Task(void *p_arg)
  475. *                   {
  476. *                       .
  477. *                       .
  478. *                       while (1) {
  479. *                           OSTimeDly(1);
  480. *                           if (OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ) {
  481. *                               Release any owned resources;
  482. *                               De-allocate any dynamic memory;
  483. *                               OSTaskDel(OS_PRIO_SELF);
  484. *                           }
  485. *                       }
  486. *                   }
  487. *
  488. * Arguments  : prio    is the priority of the task to request the delete from
  489. *
  490. * Returns    : OS_NO_ERR          if the task exist and the request has been registered
  491. *              OS_TASK_NOT_EXIST  if the task has been deleted.  This allows the caller to know whether
  492. *                                 the request has been executed.
  493. *              OS_TASK_DEL_ERR    if the task is assigned to a Mutex.
  494. *              OS_TASK_DEL_IDLE   if you requested to delete uC/OS-II's idle task
  495. *              OS_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
  496. *                                 (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  497. *              OS_TASK_DEL_REQ    if a task (possibly another task) requested that the running task be
  498. *                                 deleted.
  499. *********************************************************************************************************
  500. */
  501. /*$PAGE*/
  502. #if OS_TASK_DEL_EN > 0
  503. INT8U  OSTaskDelReq (INT8U prio)
  504. {
  505.     INT8U      stat;
  506.     OS_TCB    *ptcb;
  507. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  508.     OS_CPU_SR  cpu_sr = 0;
  509. #endif
  510. #if OS_ARG_CHK_EN > 0
  511.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to delete idle task     */
  512.         return (OS_TASK_DEL_IDLE);
  513.     }
  514.     if (prio >= OS_LOWEST_PRIO) {         /* Task priority valid ?               */
  515.         if (prio != OS_PRIO_SELF) {
  516.             return (OS_PRIO_INVALID);
  517. }
  518.     }
  519. #endif
  520.     if (prio == OS_PRIO_SELF) {                                 /* See if a task is requesting to ...  */
  521.         OS_ENTER_CRITICAL();                                    /* ... this task to delete itself      */
  522.         stat = OSTCBCur->OSTCBDelReq;                           /* Return request status to caller     */
  523.         OS_EXIT_CRITICAL();
  524.         return (stat);
  525.     }
  526.     OS_ENTER_CRITICAL();
  527.     ptcb = OSTCBPrioTbl[prio];
  528.     if (ptcb == (OS_TCB *)0) {                                  /* Task to delete must exist           */
  529.         OS_EXIT_CRITICAL();
  530.         return (OS_TASK_NOT_EXIST);                             /* Task must already be deleted        */
  531.     }
  532.     if (ptcb == (OS_TCB *)1) {                                  /* Must NOT be assigned to a Mutex     */
  533.         OS_EXIT_CRITICAL();
  534.         return (OS_TASK_DEL_ERR);
  535.     }
  536.     ptcb->OSTCBDelReq = OS_TASK_DEL_REQ;                        /* Set flag indicating task to be DEL. */
  537.     OS_EXIT_CRITICAL();
  538.     return (OS_NO_ERR);
  539. }
  540. #endif
  541. /*$PAGE*/
  542. /*
  543. *********************************************************************************************************
  544. *                                        GET THE NAME OF A TASK
  545. *
  546. * Description: This function is called to obtain the name of a task.
  547. *
  548. * Arguments  : prio      is the priority of the task that you want to obtain the name from.
  549. *
  550. *              pname     is a pointer to an ASCII string that will receive the name of the task.  The
  551. *                        string must be able to hold at least OS_TASK_NAME_SIZE characters.
  552. *
  553. *              err       is a pointer to an error code that can contain one of the following values:
  554. *
  555. *                        OS_NO_ERR                  if the requested task is resumed
  556. *                        OS_TASK_NOT_EXIST          if the task has not been created or is assigned to a Mutex
  557. *                        OS_PRIO_INVALID            if you specified an invalid priority:
  558. *                                                   A higher value than the idle task or not OS_PRIO_SELF.
  559. *                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
  560. *
  561. * Returns    : The length of the string or 0 if the task does not exist.
  562. *********************************************************************************************************
  563. */
  564. #if OS_TASK_NAME_SIZE > 1
  565. INT8U  OSTaskNameGet (INT8U prio, INT8U *pname, INT8U *err)
  566. {
  567.     OS_TCB    *ptcb;
  568.     INT8U      len;
  569. #if OS_CRITICAL_METHOD == 3                              /* Allocate storage for CPU status register   */
  570.     OS_CPU_SR  cpu_sr = 0;
  571. #endif
  572. #if OS_ARG_CHK_EN > 0
  573.     if (err == (INT8U *)0) {                             /* Validate 'err'                             */
  574.         return (0);
  575.     }
  576.     if (prio > OS_LOWEST_PRIO) {                         /* Task priority valid ?                      */
  577.         if (prio != OS_PRIO_SELF) {
  578.             *err = OS_PRIO_INVALID;                      /* No                                         */
  579.             return (0);
  580.         }
  581.     }
  582.     if (pname == (INT8U *)0) {                             /* Is 'pname' a NULL pointer?                */
  583.         *err = OS_ERR_PNAME_NULL;   /* Yes                                       */
  584.         return (0);
  585.     }
  586. #endif
  587.     OS_ENTER_CRITICAL();
  588.     if (prio == OS_PRIO_SELF) {                           /* See if caller desires it's own name       */
  589.         prio = OSTCBCur->OSTCBPrio;
  590.     }
  591.     ptcb = OSTCBPrioTbl[prio];
  592.     if (ptcb == (OS_TCB *)0) {                            /* Does task exist?                          */
  593.         OS_EXIT_CRITICAL();                               /* No                                        */
  594.         *err = OS_TASK_NOT_EXIST;
  595.         return (0);
  596.     }
  597.     if (ptcb == (OS_TCB *)1) {                            /* Task assigned to a Mutex?                 */
  598.         OS_EXIT_CRITICAL();                               /* Yes                                       */
  599.         *err = OS_TASK_NOT_EXIST;
  600.         return (0);
  601.     }
  602.     len  = OS_StrCopy(pname, ptcb->OSTCBTaskName);        /* Yes, copy name from TCB                   */
  603.     OS_EXIT_CRITICAL();
  604.     *err = OS_NO_ERR;
  605.     return (len);
  606. }
  607. #endif
  608. /*$PAGE*/
  609. /*
  610. *********************************************************************************************************
  611. *                                        ASSIGN A NAME TO A TASK
  612. *
  613. * Description: This function is used to set the name of a task.
  614. *
  615. * Arguments  : prio      is the priority of the task that you want the assign a name to.
  616. *
  617. *              pname     is a pointer to an ASCII string that contains the name of the task.  The ASCII
  618. *                        string must be NUL terminated.
  619. *
  620. *              err       is a pointer to an error code that can contain one of the following values:
  621. *
  622. *                        OS_NO_ERR                  if the requested task is resumed
  623. *                        OS_TASK_NOT_EXIST          if the task has not been created or is assigned to a Mutex
  624. *                        OS_ERR_TASK_NAME_TOO_LONG  if the name you are giving to the task exceeds the
  625. *                                                   storage capacity of a task name as specified by
  626. *                                                   OS_TASK_NAME_SIZE.
  627. *                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
  628. *                        OS_PRIO_INVALID            if you specified an invalid priority:
  629. *                                                   A higher value than the idle task or not OS_PRIO_SELF.
  630. *
  631. * Returns    : None
  632. *********************************************************************************************************
  633. */
  634. #if OS_TASK_NAME_SIZE > 1
  635. void  OSTaskNameSet (INT8U prio, INT8U *pname, INT8U *err)
  636. {
  637.     INT8U      len;
  638.     OS_TCB    *ptcb;
  639. #if OS_CRITICAL_METHOD == 3                          /* Allocate storage for CPU status register       */
  640.     OS_CPU_SR  cpu_sr = 0;
  641. #endif
  642. #if OS_ARG_CHK_EN > 0
  643.     if (err == (INT8U *)0) {                         /* Validate 'err'                                 */
  644.         return;
  645.     }
  646.     if (prio > OS_LOWEST_PRIO) {                     /* Task priority valid ?                          */
  647.         if (prio != OS_PRIO_SELF) {
  648.             *err = OS_PRIO_INVALID;                  /* No                                             */
  649.             return;
  650.         }
  651.     }
  652.     if (pname == (INT8U *)0) {                        /* Is 'pname' a NULL pointer?                     */
  653.         *err = OS_ERR_PNAME_NULL;  /* Yes                                            */
  654.         return;
  655.     }
  656. #endif
  657.     OS_ENTER_CRITICAL();
  658.     if (prio == OS_PRIO_SELF) {                      /* See if caller desires to set it's own name     */
  659.         prio = OSTCBCur->OSTCBPrio;
  660.     }
  661.     ptcb = OSTCBPrioTbl[prio];
  662.     if (ptcb == (OS_TCB *)0) {                       /* Does task exist?                               */
  663.         OS_EXIT_CRITICAL();                          /* No                                             */
  664.         *err = OS_TASK_NOT_EXIST;
  665.         return;
  666.     }
  667.     if (ptcb == (OS_TCB *)1) {                       /* Task assigned to a Mutex?                      */
  668.         OS_EXIT_CRITICAL();                          /* Yes                                            */
  669.         *err = OS_TASK_NOT_EXIST;
  670.         return;
  671.     }
  672.     len = OS_StrLen(pname);                          /* Yes, Can we fit the string in the TCB?         */
  673.     if (len > (OS_TASK_NAME_SIZE - 1)) {             /*      No                                        */
  674.         OS_EXIT_CRITICAL();
  675.         *err = OS_ERR_TASK_NAME_TOO_LONG;
  676.         return;
  677.     }
  678.     (void)OS_StrCopy(ptcb->OSTCBTaskName, pname);    /*      Yes, copy to TCB                          */
  679.     OS_EXIT_CRITICAL();
  680.     *err = OS_NO_ERR;
  681. }
  682. #endif
  683. /*$PAGE*/
  684. /*
  685. *********************************************************************************************************
  686. *                                        RESUME A SUSPENDED TASK
  687. *
  688. * Description: This function is called to resume a previously suspended task.  This is the only call that
  689. *              will remove an explicit task suspension.
  690. *
  691. * Arguments  : prio     is the priority of the task to resume.
  692. *
  693. * Returns    : OS_NO_ERR                if the requested task is resumed
  694. *              OS_PRIO_INVALID          if the priority you specify is higher that the maximum allowed
  695. *                                       (i.e. >= OS_LOWEST_PRIO)
  696. *              OS_TASK_RESUME_PRIO      if the task to resume does not exist
  697. *              OS_TASK_NOT_EXIST        if the task is assigned to a Mutex PIP
  698. *              OS_TASK_NOT_SUSPENDED    if the task to resume has not been suspended
  699. *********************************************************************************************************
  700. */
  701. #if OS_TASK_SUSPEND_EN > 0
  702. INT8U  OSTaskResume (INT8U prio)
  703. {
  704.     OS_TCB    *ptcb;
  705. #if OS_CRITICAL_METHOD == 3                                   /* Storage for CPU status register       */
  706.     OS_CPU_SR  cpu_sr = 0;
  707. #endif
  708. #if OS_ARG_CHK_EN > 0
  709.     if (prio >= OS_LOWEST_PRIO) {                             /* Make sure task priority is valid      */
  710.         return (OS_PRIO_INVALID);
  711.     }
  712. #endif
  713.     OS_ENTER_CRITICAL();
  714.     ptcb = OSTCBPrioTbl[prio];
  715.     if (ptcb == (OS_TCB *)0) {                                /* Task to suspend must exist            */
  716.         OS_EXIT_CRITICAL();
  717.         return (OS_TASK_RESUME_PRIO);
  718.     }
  719.     if (ptcb == (OS_TCB *)1) {                                /* See if assigned to Mutex              */
  720.         OS_EXIT_CRITICAL();
  721.         return (OS_TASK_NOT_EXIST);
  722.     }
  723.     if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended                */
  724.         ptcb->OSTCBStat &= ~OS_STAT_SUSPEND;   /* Remove suspension                     */
  725.         if (ptcb->OSTCBStat == OS_STAT_RDY) {                 /* See if task is now ready              */
  726.             if (ptcb->OSTCBDly == 0) {
  727.                 OSRdyGrp               |= ptcb->OSTCBBitY;    /* Yes, Make task ready to run           */
  728.                 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  729.                 OS_EXIT_CRITICAL();
  730.                 OS_Sched();
  731.             } else {
  732.                 OS_EXIT_CRITICAL();
  733.             }
  734.         } else {                                              /* Must be pending on event              */
  735.     OS_EXIT_CRITICAL();
  736.         }
  737.         return (OS_NO_ERR);
  738.     }
  739.     OS_EXIT_CRITICAL();
  740.     return (OS_TASK_NOT_SUSPENDED);
  741. }
  742. #endif
  743. /*$PAGE*/
  744. /*
  745. *********************************************************************************************************
  746. *                                             STACK CHECKING
  747. *
  748. * Description: This function is called to check the amount of free memory left on the specified task's
  749. *              stack.
  750. *
  751. * Arguments  : prio          is the task priority
  752. *
  753. *              p_stk_data    is a pointer to a data structure of type OS_STK_DATA.
  754. *
  755. * Returns    : OS_NO_ERR           upon success
  756. *              OS_PRIO_INVALID     if the priority you specify is higher that the maximum allowed
  757. *                                  (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  758. *              OS_TASK_NOT_EXIST   if the desired task has not been created or is assigned to a Mutex PIP
  759. *              OS_TASK_OPT_ERR     if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created
  760. *              OS_ERR_PDATA_NULL   if 'p_stk_data' is a NULL pointer
  761. *********************************************************************************************************
  762. */
  763. #if OS_TASK_CREATE_EXT_EN > 0
  764. INT8U  OSTaskStkChk (INT8U prio, OS_STK_DATA *p_stk_data)
  765. {
  766.     OS_TCB    *ptcb;
  767.     OS_STK    *pchk;
  768.     INT32U     free;
  769.     INT32U     size;
  770. #if OS_CRITICAL_METHOD == 3                            /* Allocate storage for CPU status register     */
  771.     OS_CPU_SR  cpu_sr = 0;
  772. #endif
  773. #if OS_ARG_CHK_EN > 0
  774.     if (prio > OS_LOWEST_PRIO) {                       /* Make sure task priority is valid             */
  775.         if (prio != OS_PRIO_SELF) {
  776.             return (OS_PRIO_INVALID);
  777.         }
  778.     }
  779.     if (p_stk_data == (OS_STK_DATA *)0) {              /* Validate 'p_stk_data'                        */
  780.         return (OS_ERR_PDATA_NULL);
  781.     }
  782. #endif
  783.     p_stk_data->OSFree = 0;                            /* Assume failure, set to 0 size                */
  784.     p_stk_data->OSUsed = 0;
  785.     OS_ENTER_CRITICAL();
  786.     if (prio == OS_PRIO_SELF) {                        /* See if check for SELF                        */
  787.         prio = OSTCBCur->OSTCBPrio;
  788.     }
  789.     ptcb = OSTCBPrioTbl[prio];
  790.     if (ptcb == (OS_TCB *)0) {                         /* Make sure task exist                         */
  791.         OS_EXIT_CRITICAL();
  792.         return (OS_TASK_NOT_EXIST);
  793.     }
  794.     if (ptcb == (OS_TCB *)1) {
  795.         OS_EXIT_CRITICAL();
  796.         return (OS_TASK_NOT_EXIST);
  797.     }
  798.     if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0) { /* Make sure stack checking option is set       */
  799.         OS_EXIT_CRITICAL();
  800.         return (OS_TASK_OPT_ERR);
  801.     }
  802.     free = 0;
  803.     size = ptcb->OSTCBStkSize;
  804.     pchk = ptcb->OSTCBStkBottom;
  805.     OS_EXIT_CRITICAL();
  806. #if OS_STK_GROWTH == 1
  807.     while (*pchk++ == (OS_STK)0) {                    /* Compute the number of zero entries on the stk */
  808.         free++;
  809.     }
  810. #else
  811.     while (*pchk-- == (OS_STK)0) {
  812.         free++;
  813.     }
  814. #endif
  815.     p_stk_data->OSFree = free * sizeof(OS_STK);           /* Compute number of free bytes on the stack */
  816.     p_stk_data->OSUsed = (size - free) * sizeof(OS_STK);  /* Compute number of bytes used on the stack */
  817.     return (OS_NO_ERR);
  818. }
  819. #endif
  820. /*$PAGE*/
  821. /*
  822. *********************************************************************************************************
  823. *                                            SUSPEND A TASK
  824. *
  825. * Description: This function is called to suspend a task.  The task can be the calling task if the
  826. *              priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF.
  827. *
  828. * Arguments  : prio     is the priority of the task to suspend.  If you specify OS_PRIO_SELF, the
  829. *                       calling task will suspend itself and rescheduling will occur.
  830. *
  831. * Returns    : OS_NO_ERR                if the requested task is suspended
  832. *              OS_TASK_SUSPEND_IDLE     if you attempted to suspend the idle task which is not allowed.
  833. *              OS_PRIO_INVALID          if the priority you specify is higher that the maximum allowed
  834. *                                       (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  835. *              OS_TASK_SUSPEND_PRIO     if the task to suspend does not exist
  836. *              OS_TASK_NOT_EXITS        if the task is assigned to a Mutex PIP
  837. *
  838. * Note       : You should use this function with great care.  If you suspend a task that is waiting for
  839. *              an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from
  840. *              running when the event arrives.
  841. *********************************************************************************************************
  842. */
  843. #if OS_TASK_SUSPEND_EN > 0
  844. INT8U  OSTaskSuspend (INT8U prio)
  845. {
  846.     BOOLEAN    self;
  847.     OS_TCB    *ptcb;
  848. INT8U      y;
  849. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  850.     OS_CPU_SR  cpu_sr = 0;
  851. #endif
  852. #if OS_ARG_CHK_EN > 0
  853.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to suspend idle task    */
  854.         return (OS_TASK_SUSPEND_IDLE);
  855.     }
  856.     if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ?               */
  857.         if (prio != OS_PRIO_SELF) {
  858.             return (OS_PRIO_INVALID);
  859.         }
  860.     }
  861. #endif
  862.     OS_ENTER_CRITICAL();
  863.     if (prio == OS_PRIO_SELF) {                                 /* See if suspend SELF                 */
  864.         prio = OSTCBCur->OSTCBPrio;
  865.         self = TRUE;
  866.     } else if (prio == OSTCBCur->OSTCBPrio) {                   /* See if suspending self              */
  867.         self = TRUE;
  868.     } else {
  869.         self = FALSE;                                           /* No suspending another task          */
  870.     }
  871.     ptcb = OSTCBPrioTbl[prio];
  872.     if (ptcb == (OS_TCB *)0) {                                  /* Task to suspend must exist          */
  873.         OS_EXIT_CRITICAL();
  874.         return (OS_TASK_SUSPEND_PRIO);
  875.     }
  876.     if (ptcb == (OS_TCB *)1) {                                  /* See if assigned to Mutex            */
  877.         OS_EXIT_CRITICAL();
  878.         return (OS_TASK_NOT_EXIST);
  879.     }
  880. y            = ptcb->OSTCBY;
  881. OSRdyTbl[y] &= ~ptcb->OSTCBBitX; /* Make task not ready                 */
  882.     if (OSRdyTbl[y] == 0) {
  883.         OSRdyGrp &= ~ptcb->OSTCBBitY;
  884.     }
  885.     ptcb->OSTCBStat |= OS_STAT_SUSPEND;                         /* Status of task is 'SUSPENDED'       */
  886.     OS_EXIT_CRITICAL();
  887.     if (self == TRUE) {                                         /* Context switch only if SELF         */
  888.         OS_Sched();
  889.     }
  890.     return (OS_NO_ERR);
  891. }
  892. #endif
  893. /*$PAGE*/
  894. /*
  895. *********************************************************************************************************
  896. *                                            QUERY A TASK
  897. *
  898. * Description: This function is called to obtain a copy of the desired task's TCB.
  899. *
  900. * Arguments  : prio         is the priority of the task to obtain information from.
  901. *
  902. *              p_task_data  is a pointer to where the desired task's OS_TCB will be stored.
  903. *
  904. * Returns    : OS_NO_ERR          if the requested task is suspended
  905. *              OS_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
  906. *                                 (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  907. *              OS_PRIO_ERR        if the desired task has not been created
  908. *              OS_TASK_NOT_EXIST  if the task is assigned to a Mutex PIP
  909. *              OS_ERR_PDATA_NULL  if 'p_task_data' is a NULL pointer
  910. *********************************************************************************************************
  911. */
  912. #if OS_TASK_QUERY_EN > 0
  913. INT8U  OSTaskQuery (INT8U prio, OS_TCB *p_task_data)
  914. {
  915.     OS_TCB    *ptcb;
  916. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  917.     OS_CPU_SR  cpu_sr = 0;
  918. #endif
  919. #if OS_ARG_CHK_EN > 0
  920.     if (prio > OS_LOWEST_PRIO) {  /* Task priority valid ?                            */
  921.         if (prio != OS_PRIO_SELF) {
  922.             return (OS_PRIO_INVALID);
  923.         }
  924.     }
  925.     if (p_task_data == (OS_TCB *)0) {            /* Validate 'p_task_data'                             */
  926.         return (OS_ERR_PDATA_NULL);
  927.     }
  928. #endif
  929.     OS_ENTER_CRITICAL();
  930.     if (prio == OS_PRIO_SELF) {                  /* See if suspend SELF                                */
  931.         prio = OSTCBCur->OSTCBPrio;
  932.     }
  933.     ptcb = OSTCBPrioTbl[prio];
  934.     if (ptcb == (OS_TCB *)0) {                   /* Task to query must exist                           */
  935.         OS_EXIT_CRITICAL();
  936.         return (OS_PRIO_ERR);
  937.     }
  938.     if (ptcb == (OS_TCB *)1) {                   /* Task to query must not be assigned to a Mutex      */
  939.         OS_EXIT_CRITICAL();
  940.         return (OS_TASK_NOT_EXIST);
  941.     }
  942.                                                  /* Copy TCB into user storage area                    */
  943.     OS_MemCopy((INT8U *)p_task_data, (INT8U *)ptcb, sizeof(OS_TCB));
  944.     OS_EXIT_CRITICAL();
  945.     return (OS_NO_ERR);
  946. }
  947. #endif
  948. /*$PAGE*/
  949. /*
  950. *********************************************************************************************************
  951. *                                        CLEAR TASK STACK
  952. *
  953. * Description: This function is used to clear the stack of a task (i.e. write all zeros)
  954. *
  955. * Arguments  : pbos     is a pointer to the task's bottom of stack.  If the configuration constant
  956. *                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  957. *                       memory to low memory).  'pbos' will thus point to the lowest (valid) memory
  958. *                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pbos' will point to the
  959. *                       highest memory location of the stack and the stack will grow with increasing
  960. *                       memory locations.  'pbos' MUST point to a valid 'free' data item.
  961. *
  962. *              size     is the number of 'stack elements' to clear.
  963. *
  964. *              opt      contains additional information (or options) about the behavior of the task.  The
  965. *                       LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application
  966. *                       specific.  See OS_TASK_OPT_??? in uCOS-II.H.
  967. *
  968. * Returns    : none
  969. *********************************************************************************************************
  970. */
  971. #if OS_TASK_CREATE_EXT_EN > 0
  972. void  OS_TaskStkClr (OS_STK *pbos, INT32U size, INT16U opt)
  973. {
  974.     if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000) {       /* See if stack checking has been enabled       */
  975.         if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000) {   /* See if stack needs to be cleared             */
  976. #if OS_STK_GROWTH == 1
  977.             while (size > 0) {                         /* Stack grows from HIGH to LOW memory          */
  978.                 size--;
  979.                 *pbos++ = (OS_STK)0;                   /* Clear from bottom of stack and up!           */
  980.             }
  981. #else
  982.             while (size > 0) {                         /* Stack grows from LOW to HIGH memory          */
  983.                 size--;
  984.                 *pbos-- = (OS_STK)0;                   /* Clear from bottom of stack and down          */
  985.             }
  986. #endif
  987.         }
  988.     }
  989. }
  990. #endif