os_task.c
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:51k
源码类别:

uCOS

开发平台:

C/C++

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