os_task.c
上传用户:zbk8730
上传日期:2017-08-10
资源大小:12168k
文件大小:48k
源码类别:

uCOS

开发平台:

C/C++

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