OS_TASK.C
上传用户:dsfgsdff
上传日期:2022-07-10
资源大小:319k
文件大小:35k
源码类别:

微处理器开发

开发平台:

C/C++

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