OS_TASK.c
上传用户:jinguanrq
上传日期:2022-06-04
资源大小:724k
文件大小:35k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                            TASK MANAGEMENT
  6. *
  7. *                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
  8. *                                           All Rights Reserved
  9. *
  10. *                                                  V2.00
  11. *
  12. * File : OS_TASK.C
  13. * By   : Jean J. Labrosse
  14. *********************************************************************************************************
  15. */
  16. #ifndef  OS_MASTER_FILE
  17. #include "includes.h"
  18. #endif
  19. /*
  20. *********************************************************************************************************
  21. *                                        LOCAL FUNCTION PROTOTYPES
  22. *********************************************************************************************************
  23. */
  24. static  void  OSDummy(void);
  25. /*
  26. *********************************************************************************************************
  27. *                                            DUMMY FUNCTION
  28. *
  29. * Description: This function doesn't do anything.  It is called by OSTaskDel() to ensure that interrupts
  30. *              are disabled immediately after they are enabled.
  31. *
  32. * Arguments  : none
  33. *
  34. * Returns    : none
  35. *********************************************************************************************************
  36. */
  37. static void  OSDummy (void)
  38. {
  39. }
  40. /*$PAGE*/
  41. /*
  42. *********************************************************************************************************
  43. *                                        CHANGE PRIORITY OF A TASK
  44. *
  45. * Description: This function allows you to change the priority of a task dynamically.  Note that the new
  46. *              priority MUST be available.
  47. *
  48. * Arguments  : oldp     is the old priority
  49. *
  50. *              newp     is the new priority
  51. *
  52. * Returns    : OS_NO_ERR        is the call was successful
  53. *              OS_PRIO_INVALID  if the priority you specify is higher that the maximum allowed 
  54. *                               (i.e. >= OS_LOWEST_PRIO)
  55. *              OS_PRIO_EXIST    if the new priority already exist.
  56. *              OS_PRIO_ERR      there is no task with the specified OLD priority (i.e. the OLD task does
  57. *                               not exist.
  58. *********************************************************************************************************
  59. */
  60. #if OS_TASK_CHANGE_PRIO_EN
  61. INT8U OSTaskChangePrio (INT8U oldprio, INT8U newprio)
  62. {
  63.     OS_TCB   *ptcb;
  64.     OS_EVENT *pevent;
  65.     INT8U     x;
  66.     INT8U     y;
  67.     INT8U     bitx;
  68.     INT8U     bity;
  69.     if ((oldprio >= OS_LOWEST_PRIO && oldprio != OS_PRIO_SELF)  || 
  70.          newprio >= OS_LOWEST_PRIO) {
  71.         return (OS_PRIO_INVALID);
  72.     }
  73.     OS_ENTER_CRITICAL();
  74.     if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) {                 /* New priority must not already exist */
  75.         OS_EXIT_CRITICAL();
  76.         return (OS_PRIO_EXIST);
  77.     } else {
  78.         OSTCBPrioTbl[newprio] = (OS_TCB *)1;                    /* Reserve the entry to prevent others */
  79.         OS_EXIT_CRITICAL();
  80.         y    = newprio >> 3;                                    /* Precompute to reduce INT. latency   */
  81.         bity = OSMapTbl[y];
  82.         x    = newprio & 0x07;
  83.         bitx = OSMapTbl[x];
  84.         OS_ENTER_CRITICAL();
  85.         if (oldprio == OS_PRIO_SELF) {                          /* See if changing self                */
  86.             oldprio = OSTCBCur->OSTCBPrio;                      /* Yes, get priority                   */
  87.         }
  88.         if ((ptcb = OSTCBPrioTbl[oldprio]) != (OS_TCB *)0) {    /* Task to change must exist           */
  89.             OSTCBPrioTbl[oldprio] = (OS_TCB *)0;                /* Remove TCB from old priority        */
  90.             if (OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) {     /* If task is ready make it not ready  */
  91.                 if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
  92.                     OSRdyGrp &= ~ptcb->OSTCBBitY;
  93.                 }
  94.                 OSRdyGrp    |= bity;                            /* Make new priority ready to run      */
  95.                 OSRdyTbl[y] |= bitx;
  96.             } else {
  97.                 if ((pevent = ptcb->OSTCBEventPtr) != (OS_EVENT *)0) { /* Remove from event wait list  */
  98.                     if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
  99.                         pevent->OSEventGrp &= ~ptcb->OSTCBBitY;
  100.                     }
  101.                     pevent->OSEventGrp    |= bity;              /* Add new priority to wait list       */
  102.                     pevent->OSEventTbl[y] |= bitx;
  103.                 }
  104.             }
  105.             OSTCBPrioTbl[newprio] = ptcb;                       /* Place pointer to TCB @ new priority */
  106.             ptcb->OSTCBPrio       = newprio;                    /* Set new task priority               */
  107.             ptcb->OSTCBY          = y;
  108.             ptcb->OSTCBX          = x;
  109.             ptcb->OSTCBBitY       = bity;
  110.             ptcb->OSTCBBitX       = bitx;
  111.             OS_EXIT_CRITICAL();
  112.             OSSched();                                          /* Run highest priority task ready     */
  113.             return (OS_NO_ERR);
  114.         } else {
  115.             OSTCBPrioTbl[newprio] = (OS_TCB *)0;                /* Release the reserved prio.          */
  116.             OS_EXIT_CRITICAL();
  117.             return (OS_PRIO_ERR);                               /* Task to change didn't exist         */
  118.         }
  119.     }
  120. }
  121. #endif
  122. /*$PAGE*/
  123. /*
  124. *********************************************************************************************************
  125. *                                            CREATE A TASK
  126. *
  127. * Description: This function is used to have uC/OS-II manage the execution of a task.  Tasks can either
  128. *              be created prior to the start of multitasking or by a running task.  A task cannot be
  129. *              created by an ISR.
  130. *
  131. * Arguments  : task     is a pointer to the task's code
  132. *
  133. *              pdata    is a pointer to an optional data area which can be used to pass parameters to
  134. *                       the task when the task first executes.  Where the task is concerned it thinks
  135. *                       it was invoked and passed the argument 'pdata' as follows:
  136. *
  137. *                           void Task (void *pdata)
  138. *                           {
  139. *                               for (;;) {
  140. *                                   Task code;
  141. *                               }
  142. *                           }
  143. *
  144. *              ptos     is a pointer to the task's top of stack.  If the configuration constant 
  145. *                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  146. *                       memory to low memory).  'pstk' will thus point to the highest (valid) memory 
  147. *                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pstk' will point to the 
  148. *                       lowest memory location of the stack and the stack will grow with increasing
  149. *                       memory locations.
  150. *
  151. *              prio     is the task's priority.  A unique priority MUST be assigned to each task and the
  152. *                       lower the number, the higher the priority.
  153. *
  154. * Returns    : OS_NO_ERR        if the function was successful.
  155. *              OS_PRIO_EXIT     if the task priority already exist 
  156. *                               (each task MUST have a unique priority).
  157. *              OS_PRIO_INVALID  if the priority you specify is higher that the maximum allowed 
  158. *                               (i.e. >= OS_LOWEST_PRIO)
  159. *********************************************************************************************************
  160. */
  161. #if OS_TASK_CREATE_EN
  162. INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
  163. {
  164.     void   *psp;
  165.     INT8U   err;
  166.     if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */
  167.         return (OS_PRIO_INVALID);
  168.     }
  169.     OS_ENTER_CRITICAL();
  170.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */
  171.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    /* Reserve the priority to prevent others from doing ...  */
  172.                                              /* ... the same thing until task is created.              */
  173.         OS_EXIT_CRITICAL();
  174.         psp = (void *)OSTaskStkInit(task, pdata, ptos, 0); /* Initialize the task's stack              */
  175.         err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0);         
  176.         if (err == OS_NO_ERR) {
  177.             OS_ENTER_CRITICAL();
  178.             OSTaskCtr++;                                   /* Increment the #tasks counter             */
  179.             OSTaskCreateHook(OSTCBPrioTbl[prio]);          /* Call user defined hook                   */
  180.             OS_EXIT_CRITICAL();
  181.             if (OSRunning) {                 /* Find highest priority task if multitasking has started */
  182.                 OSSched();
  183.             }
  184.         } else {
  185.             OS_ENTER_CRITICAL();
  186.             OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others                 */
  187.             OS_EXIT_CRITICAL();
  188.         }
  189.         return (err);
  190.     } else {
  191.         OS_EXIT_CRITICAL();
  192.         return (OS_PRIO_EXIST);
  193.     }
  194. }
  195. #endif
  196. /*$PAGE*/
  197. /*
  198. *********************************************************************************************************
  199. *                                     CREATE A TASK (Extended Version)
  200. *
  201. * Description: This function is used to have uC/OS-II manage the execution of a task.  Tasks can either
  202. *              be created prior to the start of multitasking or by a running task.  A task cannot be
  203. *              created by an ISR.  This function is similar to OSTaskCreate() except that it allows
  204. *              additional information about a task to be specified.
  205. *
  206. * Arguments  : task     is a pointer to the task's code
  207. *
  208. *              pdata    is a pointer to an optional data area which can be used to pass parameters to
  209. *                       the task when the task first executes.  Where the task is concerned it thinks
  210. *                       it was invoked and passed the argument 'pdata' as follows:
  211. *
  212. *                           void Task (void *pdata)
  213. *                           {
  214. *                               for (;;) {
  215. *                                   Task code;
  216. *                               }
  217. *                           }
  218. *
  219. *              ptos     is a pointer to the task's top of stack.  If the configuration constant 
  220. *                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  221. *                       memory to low memory).  'pstk' will thus point to the highest (valid) memory 
  222. *                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pstk' will point to the 
  223. *                       lowest memory location of the stack and the stack will grow with increasing
  224. *                       memory locations.  'pstk' MUST point to a valid 'free' data item.
  225. *
  226. *              prio     is the task's priority.  A unique priority MUST be assigned to each task and the
  227. *                       lower the number, the higher the priority.
  228. *
  229. *              id       is the task's ID (0..65535)
  230. *
  231. *              pbos     is a pointer to the task's bottom of stack.  If the configuration constant 
  232. *                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  233. *                       memory to low memory).  'pbos' will thus point to the LOWEST (valid) memory 
  234. *                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pbos' will point to the 
  235. *                       HIGHEST memory location of the stack and the stack will grow with increasing
  236. *                       memory locations.  'pbos' MUST point to a valid 'free' data item.
  237. *
  238. *              stk_size is the size of the stack in number of elements.  If OS_STK is set to INT8U,
  239. *                       'stk_size' corresponds to the number of bytes available.  If OS_STK is set to
  240. *                       INT16U, 'stk_size' contains the number of 16-bit entries available.  Finally, if
  241. *                       OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries
  242. *                       available on the stack.
  243. *
  244. *              pext     is a pointer to a user supplied memory location which is used as a TCB extension.
  245. *                       For example, this user memory can hold the contents of floating-point registers
  246. *                       during a context switch, the time each task takes to execute, the number of times
  247. *                       the task has been switched-in, etc. 
  248. *
  249. *              opt      contains additional information (or options) about the behavior of the task.  The 
  250. *                       LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application 
  251. *                       specific.  See OS_TASK_OPT_??? in uCOS-II.H.
  252. *
  253. * Returns    : OS_NO_ERR        if the function was successful.
  254. *              OS_PRIO_EXIT     if the task priority already exist 
  255. *                               (each task MUST have a unique priority).
  256. *              OS_PRIO_INVALID  if the priority you specify is higher that the maximum allowed 
  257. *                               (i.e. > OS_LOWEST_PRIO)
  258. *********************************************************************************************************
  259. */
  260. /*$PAGE*/
  261. #if   OS_TASK_CREATE_EXT_EN    
  262. INT8U OSTaskCreateExt (void   (*task)(void *pd), 
  263.                        void    *pdata, 
  264.                        OS_STK  *ptos, 
  265.                        INT8U    prio,
  266.                        INT16U   id,
  267.                        OS_STK  *pbos,
  268.                        INT32U   stk_size,
  269.                        void    *pext,
  270.                        INT16U   opt)
  271. {
  272.     void    *psp;
  273.     INT8U    err;
  274.     INT16U   i;
  275.     OS_STK  *pfill;
  276.     if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */
  277.         return (OS_PRIO_INVALID);
  278.     }
  279.     OS_ENTER_CRITICAL();
  280.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */
  281.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    /* Reserve the priority to prevent others from doing ...  */
  282.                                              /* ... the same thing until task is created.              */
  283.         OS_EXIT_CRITICAL();
  284.         
  285.         if (opt & OS_TASK_OPT_STK_CHK) {     /* See if stack checking has been enabled                 */
  286.             if (opt & OS_TASK_OPT_STK_CLR) { /* See if stack needs to be cleared                       */
  287.                 pfill = pbos;                /* Yes, fill the stack with zeros                         */
  288.                 for (i = 0; i < stk_size; i++) {
  289.                     #if OS_STK_GROWTH == 1
  290.                     *pfill++ = (OS_STK)0;
  291.                     #else
  292.                     *pfill-- = (OS_STK)0;
  293.                     #endif
  294.                 }
  295.             }
  296.         }
  297.         
  298.         psp = (void *)OSTaskStkInit(task, pdata, ptos, opt); /* Initialize the task's stack            */
  299.         err = OSTCBInit(prio, psp, pbos, id, stk_size, pext, opt);         
  300.         if (err == OS_NO_ERR) {
  301.             OS_ENTER_CRITICAL();
  302.             OSTaskCtr++;                                     /* Increment the #tasks counter           */
  303.             OSTaskCreateHook(OSTCBPrioTbl[prio]);            /* Call user defined hook                 */
  304.             OS_EXIT_CRITICAL();
  305.             if (OSRunning) {                 /* Find highest priority task if multitasking has started */
  306.                 OSSched();
  307.             }
  308.         } else {
  309.             OS_ENTER_CRITICAL();
  310.             OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others                 */
  311.             OS_EXIT_CRITICAL();
  312.         }
  313.         return (err);
  314.     } else {
  315.         OS_EXIT_CRITICAL();
  316.         return (OS_PRIO_EXIST);
  317.     }
  318. }
  319. #endif
  320. /*$PAGE*/
  321. /*
  322. *********************************************************************************************************
  323. *                                            DELETE A TASK
  324. *
  325. * Description: This function allows you to delete a task.  The calling task can delete itself by 
  326. *              its own priority number.  The deleted task is returned to the dormant state and can be
  327. *              re-activated by creating the deleted task again.
  328. *
  329. * Arguments  : prio    is the priority of the task to delete.  Note that you can explicitely delete
  330. *                      the current task without knowing its priority level by setting 'prio' to
  331. *                      OS_PRIO_SELF.
  332. *
  333. * Returns    : OS_NO_ERR           if the call is successful
  334. *              OS_TASK_DEL_IDLE    if you attempted to delete uC/OS-II's idle task
  335. *              OS_PRIO_INVALID     if the priority you specify is higher that the maximum allowed 
  336. *                                  (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  337. *              OS_TASK_DEL_ERR     if the task you want to delete does not exist
  338. *              OS_TASK_DEL_ISR     if you tried to delete a task from an ISR
  339. *
  340. * Notes      : 1) To reduce interrupt latency, OSTaskDel() 'disables' the task:
  341. *                    a) by making it not ready
  342. *                    b) by removing it from any wait lists
  343. *                    c) by preventing OSTimeTick() from making the task ready to run.
  344. *                 The task can then be 'unlinked' from the miscellaneous structures in uC/OS-II.
  345. *              2) The function OSDummy() is called after OS_EXIT_CRITICAL() because, on most processors, 
  346. *                 the next instruction following the enable interrupt instruction is ignored.  You can 
  347. *                 replace OSDummy() with a macro that basically executes a NO OP (i.e. OS_NOP()).  The 
  348. *                 NO OP macro would avoid the execution time of the function call and return.
  349. *              3) An ISR cannot delete a task.
  350. *              4) The lock nesting counter is incremented because, for a brief instant, if the current
  351. *                 task is being deleted, the current task would not be able to be rescheduled because it
  352. *                 is removed from the ready list.  Incrementing the nesting counter prevents another task
  353. *                 from being schedule.  This means that the ISR would return to the current task which is
  354. *                 being deleted.  The rest of the deletion would thus be able to be completed.
  355. *********************************************************************************************************
  356. */
  357. /*$PAGE*/
  358. #if OS_TASK_DEL_EN
  359. INT8U OSTaskDel (INT8U prio)
  360. {
  361.     OS_TCB   *ptcb;
  362.     OS_EVENT *pevent;
  363.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to delete idle task     */
  364.         return (OS_TASK_DEL_IDLE);
  365.     }
  366.     if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {       /* Task priority valid ?               */
  367.         return (OS_PRIO_INVALID);
  368.     }
  369.     OS_ENTER_CRITICAL();
  370.     if (OSIntNesting > 0) {                                     /* See if trying to delete from ISR    */
  371.         OS_EXIT_CRITICAL();
  372.         return (OS_TASK_DEL_ISR);
  373.     }
  374.     if (prio == OS_PRIO_SELF) {                                 /* See if requesting to delete self    */
  375.         prio = OSTCBCur->OSTCBPrio;                             /* Set priority to delete to current   */
  376.     }
  377.     if ((ptcb = OSTCBPrioTbl[prio]) != (OS_TCB *)0) {           /* Task to delete must exist           */
  378.         if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {/* Make task not ready                 */
  379.             OSRdyGrp &= ~ptcb->OSTCBBitY;
  380.         }
  381.         if ((pevent = ptcb->OSTCBEventPtr) != (OS_EVENT *)0) {  /* If task is waiting on event         */
  382.             if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) { /* ... remove task from */
  383.                 pevent->OSEventGrp &= ~ptcb->OSTCBBitY;                        /* ... event ctrl block */
  384.             }
  385.         }
  386.         ptcb->OSTCBDly  = 0;                                    /* Prevent OSTimeTick() from updating  */
  387.         ptcb->OSTCBStat = OS_STAT_RDY;                          /* Prevent task from being resumed     */
  388.         OSLockNesting++;
  389.         OS_EXIT_CRITICAL();                                     /* Enabling INT. ignores next instruc. */
  390.         OSDummy();                                              /* ... Dummy ensures that INTs will be */
  391.         OS_ENTER_CRITICAL();                                    /* ... disabled HERE!                  */
  392.         OSLockNesting--;
  393.         OSTaskDelHook(ptcb);                                    /* Call user defined hook              */
  394.         OSTaskCtr--;                                            /* One less task being managed         */
  395.         OSTCBPrioTbl[prio] = (OS_TCB *)0;                       /* Clear old priority entry            */
  396.         if (ptcb->OSTCBPrev == (OS_TCB *)0) {                   /* Remove from TCB chain               */
  397.             ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
  398.             OSTCBList                  = ptcb->OSTCBNext;
  399.         } else {
  400.             ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
  401.             ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
  402.         }
  403.         ptcb->OSTCBNext = OSTCBFreeList;                        /* Return TCB to free TCB list         */
  404.         OSTCBFreeList   = ptcb;
  405.         OS_EXIT_CRITICAL();
  406.         OSSched();                                              /* Find new highest priority task      */
  407.         return (OS_NO_ERR);
  408.     } else {
  409.         OS_EXIT_CRITICAL();
  410.         return (OS_TASK_DEL_ERR);
  411.     }
  412. }
  413. #endif
  414. /*$PAGE*/
  415. /*
  416. *********************************************************************************************************
  417. *                                    REQUEST THAT A TASK DELETE ITSELF
  418. *
  419. * Description: This function is used to:
  420. *                   a) notify a task to delete itself.
  421. *                   b) to see if a task requested that the current task delete itself.
  422. *              This function is a little tricky to understand.  Basically, you have a task that needs
  423. *              to be deleted however, this task has resources that it has allocated (memory buffers,
  424. *              semaphores, mailboxes, queues etc.).  The task cannot be deleted otherwise these
  425. *              resources would not be freed.  The requesting task calls OSTaskDelReq() to indicate that
  426. *              the task needs to be deleted.  Deleting of the task is however, deferred to the task to
  427. *              be deleted.  For example, suppose that task #10 needs to be deleted.  The requesting task
  428. *              example, task #5, would call OSTaskDelReq(10).  When task #10 gets to execute, it calls
  429. *              this function by specifying OS_PRIO_SELF and monitors the returned value.  If the return
  430. *              value is OS_TASK_DEL_REQ, another task requested a task delete.  Task #10 would look like
  431. *              this:
  432. *
  433. *                   void Task(void *data)
  434. *                   {
  435. *                       .
  436. *                       .
  437. *                       while (1) {
  438. *                           OSTimeDly(1);
  439. *                           if (OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ) {
  440. *                               Release any owned resources;
  441. *                               De-allocate any dynamic memory;
  442. *                               OSTaskDel(OS_PRIO_SELF);
  443. *                           }
  444. *                       }
  445. *                   }
  446. *
  447. * Arguments  : prio    is the priority of the task to request the delete from
  448. *
  449. * Returns    : OS_NO_ERR          if the task exist and the request has been registered
  450. *              OS_TASK_NOT_EXIST  if the task has been deleted.  This allows the caller to know whether
  451. *                                 the request has been executed.
  452. *              OS_TASK_DEL_IDLE   if you requested to delete uC/OS-II's idle task
  453. *              OS_PRIO_INVALID    if the priority you specify is higher that the maximum allowed 
  454. *                                 (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  455. *              OS_TASK_DEL_REQ    if a task (possibly another task) requested that the running task be 
  456. *                                 deleted.
  457. *********************************************************************************************************
  458. */
  459. /*$PAGE*/
  460. #if OS_TASK_DEL_EN
  461. INT8U OSTaskDelReq (INT8U prio)
  462. {
  463.     BOOLEAN  stat;
  464.     INT8U    err;
  465.     OS_TCB  *ptcb;
  466.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to delete idle task     */
  467.         return (OS_TASK_DEL_IDLE);
  468.     }
  469.     if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {       /* Task priority valid ?               */
  470.         return (OS_PRIO_INVALID);
  471.     }
  472.     if (prio == OS_PRIO_SELF) {                                 /* See if a task is requesting to ...  */
  473.         OS_ENTER_CRITICAL();                                    /* ... this task to delete itself      */
  474.         stat = OSTCBCur->OSTCBDelReq;                           /* Return request status to caller     */
  475.         OS_EXIT_CRITICAL();
  476.         return (stat);
  477.     } else {
  478.         OS_ENTER_CRITICAL();
  479.         if ((ptcb = OSTCBPrioTbl[prio]) != (OS_TCB *)0) {       /* Task to delete must exist           */
  480.             ptcb->OSTCBDelReq = OS_TASK_DEL_REQ;                /* Set flag indicating task to be DEL. */
  481.             err               = OS_NO_ERR;
  482.         } else {
  483.             err               = OS_TASK_NOT_EXIST;              /* Task must be deleted                */
  484.         }
  485.         OS_EXIT_CRITICAL();
  486.         return (err);
  487.     }
  488. }
  489. #endif
  490. /*$PAGE*/
  491. /*
  492. *********************************************************************************************************
  493. *                                        RESUME A SUSPENDED TASK
  494. *
  495. * Description: This function is called to resume a previously suspended task.  This is the only call that
  496. *              will remove an explicit task suspension.
  497. *
  498. * Arguments  : prio     is the priority of the task to resume.
  499. *
  500. * Returns    : OS_NO_ERR                if the requested task is resumed
  501. *              OS_PRIO_INVALID          if the priority you specify is higher that the maximum allowed 
  502. *                                       (i.e. >= OS_LOWEST_PRIO)
  503. *              OS_TASK_RESUME_PRIO      if the task to resume does not exist
  504. *              OS_TASK_NOT_SUSPENDED    if the task to resume has not been suspended
  505. *********************************************************************************************************
  506. */
  507. #if OS_TASK_SUSPEND_EN
  508. INT8U OSTaskResume (INT8U prio)
  509. {
  510.     OS_TCB   *ptcb;
  511.     if (prio >= OS_LOWEST_PRIO) {                               /* Make sure task priority is valid    */
  512.         return (OS_PRIO_INVALID);
  513.     }
  514.     OS_ENTER_CRITICAL();
  515.     if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) {           /* Task to suspend must exist          */
  516.         OS_EXIT_CRITICAL();
  517.         return (OS_TASK_RESUME_PRIO);
  518.     } else {
  519.         if (ptcb->OSTCBStat & OS_STAT_SUSPEND) {                           /* Task must be suspended   */
  520.             if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) &&  /* Remove suspension        */
  521.                  (ptcb->OSTCBDly  == 0)) {                                 /* Must not be delayed      */
  522.                 OSRdyGrp               |= ptcb->OSTCBBitY;                 /* Make task ready to run   */
  523.                 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  524.                 OS_EXIT_CRITICAL();
  525.                 OSSched();
  526.             } else {
  527.                 OS_EXIT_CRITICAL();
  528.             }
  529.             return (OS_NO_ERR);
  530.         } else {
  531.             OS_EXIT_CRITICAL();
  532.             return (OS_TASK_NOT_SUSPENDED);
  533.         }
  534.     }
  535. }
  536. #endif
  537. /*$PAGE*/
  538. /*
  539. *********************************************************************************************************
  540. *                                             STACK CHECKING 
  541. *
  542. * Description: This function is called to check the amount of free memory left on the specified task's
  543. *              stack.
  544. *
  545. * Arguments  : prio     is the task priority
  546. *
  547. *              pdata    is a pointer to a data structure of type OS_STK_DATA.
  548. *
  549. * Returns    : OS_NO_ERR           upon success
  550. *              OS_PRIO_INVALID     if the priority you specify is higher that the maximum allowed 
  551. *                                  (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  552. *              OS_TASK_NOT_EXIST   if the desired task has not been created
  553. *              OS_TASK_OPT_ERR     if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created
  554. *********************************************************************************************************
  555. */
  556. #if   OS_TASK_CREATE_EXT_EN
  557. INT8U OSTaskStkChk (INT8U prio, OS_STK_DATA *pdata)
  558. {
  559.     OS_TCB  *ptcb;
  560.     OS_STK  *pchk;
  561.     INT32U   free;
  562.     INT32U   size;
  563.     pdata->OSFree = 0;                                          /* Assume failure, set to 0 size       */
  564.     pdata->OSUsed = 0;
  565.     if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {        /* Make sure task priority is valid    */
  566.         return (OS_PRIO_INVALID);
  567.     }
  568.     OS_ENTER_CRITICAL();
  569.     if (prio == OS_PRIO_SELF) {                        /* See if check for SELF                        */
  570.         prio = OSTCBCur->OSTCBPrio;
  571.     }
  572.     ptcb = OSTCBPrioTbl[prio];
  573.     if (ptcb == (OS_TCB *)0) {                         /* Make sure task exist                         */
  574.         OS_EXIT_CRITICAL();
  575.         return (OS_TASK_NOT_EXIST);
  576.     }
  577.     if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0) { /* Make sure stack checking option is set       */
  578.         OS_EXIT_CRITICAL();
  579.         return (OS_TASK_OPT_ERR);
  580.     }
  581.     free = 0;
  582.     size = ptcb->OSTCBStkSize;
  583.     pchk = ptcb->OSTCBStkBottom;
  584.     OS_EXIT_CRITICAL();
  585. #if OS_STK_GROWTH == 1
  586.     while (*pchk++ == 0) {                            /* Compute the number of zero entries on the stk */
  587.         free++;
  588.     }
  589. #else
  590.     while (*pchk-- == 0) {
  591.         free++;
  592.     }
  593. #endif
  594.     pdata->OSFree = free * sizeof(OS_STK);            /* Compute number of free bytes on the stack     */
  595.     pdata->OSUsed = (size - free) * sizeof(OS_STK);   /* Compute number of bytes used on the stack     */
  596.     return (OS_NO_ERR);
  597. }
  598. #endif
  599. /*$PAGE*/
  600. /*
  601. *********************************************************************************************************
  602. *                                            SUSPEND A TASK
  603. *
  604. * Description: This function is called to suspend a task.  The task can be the calling task if the
  605. *              priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF.
  606. *
  607. * Arguments  : prio     is the priority of the task to suspend.  If you specify OS_PRIO_SELF, the
  608. *                       calling task will suspend itself and rescheduling will occur.
  609. *
  610. * Returns    : OS_NO_ERR                if the requested task is suspended
  611. *              OS_TASK_SUSPEND_IDLE     if you attempted to suspend the idle task which is not allowed.
  612. *              OS_PRIO_INVALID          if the priority you specify is higher that the maximum allowed 
  613. *                                       (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  614. *              OS_TASK_SUSPEND_PRIO     if the task to suspend does not exist
  615. *
  616. * Note       : You should use this function with great care.  If you suspend a task that is waiting for
  617. *              an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from
  618. *              running when the event arrives.
  619. *********************************************************************************************************
  620. */
  621. #if OS_TASK_SUSPEND_EN
  622. INT8U OSTaskSuspend (INT8U prio)
  623. {
  624.     BOOLEAN   self;
  625.     OS_TCB   *ptcb;
  626.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to suspend idle task    */
  627.         return (OS_TASK_SUSPEND_IDLE);
  628.     }
  629.     if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {       /* Task priority valid ?               */
  630.         return (OS_PRIO_INVALID);
  631.     }
  632.     OS_ENTER_CRITICAL();
  633.     if (prio == OS_PRIO_SELF) {                                 /* See if suspend SELF                 */
  634.         prio = OSTCBCur->OSTCBPrio;
  635.         self = TRUE;
  636.     } else if (prio == OSTCBCur->OSTCBPrio) {                   /* See if suspending self              */
  637.         self = TRUE;
  638.     } else {
  639.         self = FALSE;                                           /* No suspending another task          */
  640.     }
  641.     if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) {                /* Task to suspend must exist     */
  642.         OS_EXIT_CRITICAL();
  643.         return (OS_TASK_SUSPEND_PRIO);
  644.     } else {
  645.         if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {     /* Make task not ready            */
  646.             OSRdyGrp &= ~ptcb->OSTCBBitY;
  647.         }
  648.         ptcb->OSTCBStat |= OS_STAT_SUSPEND;                          /* Status of task is 'SUSPENDED'  */
  649.         OS_EXIT_CRITICAL();
  650.         if (self == TRUE) {                                          /* Context switch only if SELF    */
  651.             OSSched();
  652.         }
  653.         return (OS_NO_ERR);
  654.     }
  655. }
  656. #endif
  657. /*$PAGE*/
  658. /*
  659. *********************************************************************************************************
  660. *                                            QUERY A TASK
  661. *
  662. * Description: This function is called to obtain a copy of the desired task's TCB.
  663. *
  664. * Arguments  : prio     is the priority of the task to obtain information from.  
  665. *
  666. * Returns    : OS_NO_ERR       if the requested task is suspended
  667. *              OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed 
  668. *                              (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  669. *              OS_PRIO_ERR     if the desired task has not been created 
  670. *********************************************************************************************************
  671. */
  672. INT8U OSTaskQuery (INT8U prio, OS_TCB *pdata)
  673. {
  674.     OS_TCB *ptcb;
  675.     if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {   /* Task priority valid ?                    */
  676.         return (OS_PRIO_INVALID);
  677.     }
  678.     OS_ENTER_CRITICAL();
  679.     if (prio == OS_PRIO_SELF) {                            /* See if suspend SELF                      */
  680.         prio = OSTCBCur->OSTCBPrio;
  681.     }
  682.     if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) {      /* Task to query must exist                 */
  683.         OS_EXIT_CRITICAL();
  684.         return (OS_PRIO_ERR);
  685.     }
  686.     *pdata = *ptcb;                                        /* Copy TCB into user storage area          */
  687.     OS_EXIT_CRITICAL();
  688.     return (OS_NO_ERR);
  689. }