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

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                             CORE FUNCTIONS
  6. *
  7. *                          (c) Copyright 1992-2006, Jean J. Labrosse, Weston, FL
  8. *                                           All Rights Reserved
  9. *
  10. * File    : OS_CORE.C
  11. * By      : Jean J. Labrosse
  12. * Version : V2.83
  13. *********************************************************************************************************
  14. */
  15. #ifndef  OS_MASTER_FILE
  16. #define  OS_GLOBALS
  17. #include <ucos_ii.h>
  18. #endif
  19. /*
  20. *********************************************************************************************************
  21. *                                       PRIORITY RESOLUTION TABLE
  22. *
  23. * Note: Index into table is bit pattern to resolve highest priority
  24. *       Indexed value corresponds to highest priority bit position (i.e. 0..7)
  25. *********************************************************************************************************
  26. */
  27. INT8U  const  OSUnMapTbl[256] = {
  28.     0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x00 to 0x0F                             */
  29.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x10 to 0x1F                             */
  30.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x20 to 0x2F                             */
  31.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x30 to 0x3F                             */
  32.     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x40 to 0x4F                             */
  33.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x50 to 0x5F                             */
  34.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x60 to 0x6F                             */
  35.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x70 to 0x7F                             */
  36.     7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x80 to 0x8F                             */
  37.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x90 to 0x9F                             */
  38.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xA0 to 0xAF                             */
  39.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xB0 to 0xBF                             */
  40.     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xC0 to 0xCF                             */
  41.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xD0 to 0xDF                             */
  42.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xE0 to 0xEF                             */
  43.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0        /* 0xF0 to 0xFF                             */
  44. };
  45. /*$PAGE*/
  46. /*
  47. *********************************************************************************************************
  48. *                                       FUNCTION PROTOTYPES
  49. *********************************************************************************************************
  50. */
  51. static  void  OS_InitEventList(void);
  52. static  void  OS_InitMisc(void);
  53. static  void  OS_InitRdyList(void);
  54. static  void  OS_InitTaskIdle(void);
  55. #if OS_TASK_STAT_EN > 0
  56. static  void  OS_InitTaskStat(void);
  57. #endif
  58. static  void  OS_InitTCBList(void);
  59. static  void  OS_SchedNew(void);
  60. /*$PAGE*/
  61. /*
  62. *********************************************************************************************************
  63. *                         GET THE NAME OF A SEMAPHORE, MUTEX, MAILBOX or QUEUE
  64. *
  65. * Description: This function is used to obtain the name assigned to a semaphore, mutex, mailbox or queue.
  66. *
  67. * Arguments  : pevent    is a pointer to the event group.  'pevent' can point either to a semaphore,
  68. *                        a mutex, a mailbox or a queue.  Where this function is concerned, the actual
  69. *                        type is irrelevant.
  70. *
  71. *              pname     is a pointer to an ASCII string that will receive the name of the semaphore,
  72. *                        mutex, mailbox or queue.  The string must be able to hold at least
  73. *                        OS_EVENT_NAME_SIZE characters.
  74. *
  75. *              err       is a pointer to an error code that can contain one of the following values:
  76. *
  77. *                        OS_NO_ERR                  if the name was copied to 'pname'
  78. *                        OS_ERR_EVENT_TYPE          if 'pevent' is not pointing to the proper event
  79. *                                                   control block type.
  80. *                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
  81. *                        OS_ERR_PEVENT_NULL         if you passed a NULL pointer for 'pevent'
  82. *
  83. * Returns    : The length of the string or 0 if the 'pevent' is a NULL pointer.
  84. *********************************************************************************************************
  85. */
  86. #if OS_EVENT_EN && (OS_EVENT_NAME_SIZE > 1)
  87. INT8U  OSEventNameGet (OS_EVENT *pevent, INT8U *pname, INT8U *err)
  88. {
  89.     INT8U      len;
  90. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  91.     OS_CPU_SR  cpu_sr = 0;
  92. #endif
  93. #if OS_ARG_CHK_EN > 0
  94.     if (err == (INT8U *)0) {                     /* Validate 'err'                                     */
  95.         return (0);
  96.     }
  97.     if (pevent == (OS_EVENT *)0) {               /* Is 'pevent' a NULL pointer?                        */
  98.         *err = OS_ERR_PEVENT_NULL;
  99.         return (0);
  100.     }
  101.     if (pname == (INT8U *)0) {                   /* Is 'pname' a NULL pointer?                         */
  102.         *err = OS_ERR_PNAME_NULL;
  103.         return (0);
  104.     }
  105. #endif
  106.     switch (pevent->OSEventType) {
  107.         case OS_EVENT_TYPE_SEM:
  108.         case OS_EVENT_TYPE_MUTEX:
  109.         case OS_EVENT_TYPE_MBOX:
  110.         case OS_EVENT_TYPE_Q:
  111.              break;
  112.         default:
  113.              *err = OS_ERR_EVENT_TYPE;
  114.              return (0);
  115.     }
  116.     OS_ENTER_CRITICAL();
  117.     len  = OS_StrCopy(pname, pevent->OSEventName);    /* Copy name from OS_EVENT                       */
  118.     OS_EXIT_CRITICAL();
  119.     *err = OS_NO_ERR;
  120.     return (len);
  121. }
  122. #endif
  123. /*$PAGE*/
  124. /*
  125. *********************************************************************************************************
  126. *                         ASSIGN A NAME TO A SEMAPHORE, MUTEX, MAILBOX or QUEUE
  127. *
  128. * Description: This function assigns a name to a semaphore, mutex, mailbox or queue.
  129. *
  130. * Arguments  : pevent    is a pointer to the event group.  'pevent' can point either to a semaphore,
  131. *                        a mutex, a mailbox or a queue.  Where this function is concerned, it doesn't
  132. *                        matter the actual type.
  133. *
  134. *              pname     is a pointer to an ASCII string that will be used as the name of the semaphore,
  135. *                        mutex, mailbox or queue.  The string must be able to hold at least
  136. *                        OS_EVENT_NAME_SIZE characters.
  137. *
  138. *              err       is a pointer to an error code that can contain one of the following values:
  139. *
  140. *                        OS_NO_ERR                  if the requested task is resumed
  141. *                        OS_ERR_EVENT_TYPE          if 'pevent' is not pointing to the proper event
  142. *                                                   control block type.
  143. *                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
  144. *                        OS_ERR_PEVENT_NULL         if you passed a NULL pointer for 'pevent'
  145. *
  146. * Returns    : None
  147. *********************************************************************************************************
  148. */
  149. #if OS_EVENT_EN && (OS_EVENT_NAME_SIZE > 1)
  150. void  OSEventNameSet (OS_EVENT *pevent, INT8U *pname, INT8U *err)
  151. {
  152.     INT8U      len;
  153. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  154.     OS_CPU_SR  cpu_sr = 0;
  155. #endif
  156. #if OS_ARG_CHK_EN > 0
  157.     if (err == (INT8U *)0) {                     /* Validate 'err'                                     */
  158.         return;
  159.     }
  160.     if (pevent == (OS_EVENT *)0) {               /* Is 'pevent' a NULL pointer?                        */
  161.         *err = OS_ERR_PEVENT_NULL;
  162.         return;
  163.     }
  164.     if (pname == (INT8U *)0) {                    /* Is 'pname' a NULL pointer?                         */
  165.         *err = OS_ERR_PNAME_NULL;
  166.         return;
  167.     }
  168. #endif
  169.     switch (pevent->OSEventType) {
  170.         case OS_EVENT_TYPE_SEM:
  171.         case OS_EVENT_TYPE_MUTEX:
  172.         case OS_EVENT_TYPE_MBOX:
  173.         case OS_EVENT_TYPE_Q:
  174.              break;
  175.         default:
  176.              *err = OS_ERR_EVENT_TYPE;
  177.              return;
  178.     }
  179.     OS_ENTER_CRITICAL();
  180.     len = OS_StrLen(pname);                           /* Can we fit the string in the storage area?    */
  181.     if (len > (OS_EVENT_NAME_SIZE - 1)) {             /* No                                            */
  182.         OS_EXIT_CRITICAL();
  183.         *err = OS_ERR_EVENT_NAME_TOO_LONG;
  184.         return;
  185.     }
  186.     (void)OS_StrCopy(pevent->OSEventName, pname);     /* Yes, copy name to the event control block     */
  187.     OS_EXIT_CRITICAL();
  188.     *err = OS_NO_ERR;
  189. }
  190. #endif
  191. /*$PAGE*/
  192. /*
  193. *********************************************************************************************************
  194. *                                             INITIALIZATION
  195. *
  196. * Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to
  197. *              creating any uC/OS-II object and, prior to calling OSStart().
  198. *
  199. * Arguments  : none
  200. *
  201. * Returns    : none
  202. *********************************************************************************************************
  203. */
  204. void  OSInit (void)
  205. {
  206. #if OS_VERSION >= 204
  207.     OSInitHookBegin();                                           /* Call port specific initialization code   */
  208. #endif
  209.     OS_InitMisc();                                               /* Initialize miscellaneous variables       */
  210.     OS_InitRdyList();                                            /* Initialize the Ready List                */
  211.     OS_InitTCBList();                                            /* Initialize the free list of OS_TCBs      */
  212.     OS_InitEventList();                                          /* Initialize the free list of OS_EVENTs    */
  213. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
  214.     OS_FlagInit();                                               /* Initialize the event flag structures     */
  215. #endif
  216. #if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
  217.     OS_MemInit();                                                /* Initialize the memory manager            */
  218. #endif
  219. #if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
  220.     OS_QInit();                                                  /* Initialize the message queue structures  */
  221. #endif
  222.     OS_InitTaskIdle();                                           /* Create the Idle Task                     */
  223. #if OS_TASK_STAT_EN > 0
  224.     OS_InitTaskStat();                                           /* Create the Statistic Task                */
  225. #endif
  226. #if OS_TMR_EN > 0
  227.     OSTmr_Init();                                                /* Initialize the Timer Manager             */
  228. #endif
  229. #if OS_VERSION >= 204
  230.     OSInitHookEnd();                                             /* Call port specific init. code            */
  231. #endif
  232. #if OS_VERSION >= 270 && OS_DEBUG_EN > 0
  233.     OSDebugInit();
  234. #endif
  235. }
  236. /*$PAGE*/
  237. /*
  238. *********************************************************************************************************
  239. *                                              ENTER ISR
  240. *
  241. * Description: This function is used to notify uC/OS-II that you are about to service an interrupt
  242. *              service routine (ISR).  This allows uC/OS-II to keep track of interrupt nesting and thus
  243. *              only perform rescheduling at the last nested ISR.
  244. *
  245. * Arguments  : none
  246. *
  247. * Returns    : none
  248. *
  249. * Notes      : 1) This function should be called ith interrupts already disabled
  250. *              2) Your ISR can directly increment OSIntNesting without calling this function because
  251. *                 OSIntNesting has been declared 'global'.
  252. *              3) You MUST still call OSIntExit() even though you increment OSIntNesting directly.
  253. *              4) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
  254. *                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
  255. *                 end of the ISR.
  256. *              5) You are allowed to nest interrupts up to 255 levels deep.
  257. *              6) I removed the OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() around the increment because
  258. *                 OSIntEnter() is always called with interrupts disabled.
  259. *********************************************************************************************************
  260. */
  261. void  OSIntEnter (void)
  262. {
  263.     if (OSRunning == OS_TRUE) {
  264.         if (OSIntNesting < 255u) {
  265.             OSIntNesting++;                      /* Increment ISR nesting level                        */
  266.         }
  267.     }
  268. }
  269. /*$PAGE*/
  270. /*
  271. *********************************************************************************************************
  272. *                                               EXIT ISR
  273. *
  274. * Description: This function is used to notify uC/OS-II that you have completed serviving an ISR.  When
  275. *              the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether
  276. *              a new, high-priority task, is ready to run.
  277. *
  278. * Arguments  : none
  279. *
  280. * Returns    : none
  281. *
  282. * Notes      : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
  283. *                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
  284. *                 end of the ISR.
  285. *              2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
  286. *********************************************************************************************************
  287. */
  288. void  OSIntExit (void)
  289. {
  290. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  291.     OS_CPU_SR  cpu_sr = 0;
  292. #endif
  293.     if (OSRunning == OS_TRUE) {
  294.         OS_ENTER_CRITICAL();
  295.         if (OSIntNesting > 0) {                            /* Prevent OSIntNesting from wrapping       */
  296.             OSIntNesting--;
  297.         }
  298.         if (OSIntNesting == 0) {                           /* Reschedule only if all ISRs complete ... */
  299.             if (OSLockNesting == 0) {                      /* ... and not locked.                      */
  300.                 OS_SchedNew();
  301.                 if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy */
  302.                     OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];
  303. #if OS_TASK_PROFILE_EN > 0
  304.                     OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task  */
  305. #endif
  306.                     OSCtxSwCtr++;                          /* Keep track of the number of ctx switches */
  307.                     OSIntCtxSw();                          /* Perform interrupt level ctx switch       */
  308.                 }
  309.             }
  310.         }
  311.         OS_EXIT_CRITICAL();
  312.     }
  313. }
  314. /*$PAGE*/
  315. /*
  316. *********************************************************************************************************
  317. *                                          PREVENT SCHEDULING
  318. *
  319. * Description: This function is used to prevent rescheduling to take place.  This allows your application
  320. *              to prevent context switches until you are ready to permit context switching.
  321. *
  322. * Arguments  : none
  323. *
  324. * Returns    : none
  325. *
  326. * Notes      : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair.  In other words, for every
  327. *                 call to OSSchedLock() you MUST have a call to OSSchedUnlock().
  328. *********************************************************************************************************
  329. */
  330. #if OS_SCHED_LOCK_EN > 0
  331. void  OSSchedLock (void)
  332. {
  333. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  334.     OS_CPU_SR  cpu_sr = 0;
  335. #endif
  336.     if (OSRunning == OS_TRUE) {                  /* Make sure multitasking is running                  */
  337.         OS_ENTER_CRITICAL();
  338.         if (OSIntNesting == 0) {                 /* Can't call from an ISR                             */
  339.             if (OSLockNesting < 255u) {          /* Prevent OSLockNesting from wrapping back to 0      */
  340.                 OSLockNesting++;                 /* Increment lock nesting level                       */
  341.             }
  342.         }
  343.         OS_EXIT_CRITICAL();
  344.     }
  345. }
  346. #endif
  347. /*$PAGE*/
  348. /*
  349. *********************************************************************************************************
  350. *                                          ENABLE SCHEDULING
  351. *
  352. * Description: This function is used to re-allow rescheduling.
  353. *
  354. * Arguments  : none
  355. *
  356. * Returns    : none
  357. *
  358. * Notes      : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair.  In other words, for every
  359. *                 call to OSSchedLock() you MUST have a call to OSSchedUnlock().
  360. *********************************************************************************************************
  361. */
  362. #if OS_SCHED_LOCK_EN > 0
  363. void  OSSchedUnlock (void)
  364. {
  365. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  366.     OS_CPU_SR  cpu_sr = 0;
  367. #endif
  368.     if (OSRunning == OS_TRUE) {                            /* Make sure multitasking is running        */
  369.         OS_ENTER_CRITICAL();
  370.         if (OSLockNesting > 0) {                           /* Do not decrement if already 0            */
  371.             OSLockNesting--;                               /* Decrement lock nesting level             */
  372.             if (OSLockNesting == 0) {                      /* See if scheduler is enabled and ...      */
  373.                 if (OSIntNesting == 0) {                   /* ... not in an ISR                        */
  374.                     OS_EXIT_CRITICAL();
  375.                     OS_Sched();                            /* See if a HPT is ready                    */
  376.                 } else {
  377.                     OS_EXIT_CRITICAL();
  378.                 }
  379.             } else {
  380.                 OS_EXIT_CRITICAL();
  381.             }
  382.         } else {
  383.             OS_EXIT_CRITICAL();
  384.         }
  385.     }
  386. }
  387. #endif
  388. /*$PAGE*/
  389. /*
  390. *********************************************************************************************************
  391. *                                          START MULTITASKING
  392. *
  393. * Description: This function is used to start the multitasking process which lets uC/OS-II manages the
  394. *              task that you have created.  Before you can call OSStart(), you MUST have called OSInit()
  395. *              and you MUST have created at least one task.
  396. *
  397. * Arguments  : none
  398. *
  399. * Returns    : none
  400. *
  401. * Note       : OSStartHighRdy() MUST:
  402. *                 a) Call OSTaskSwHook() then,
  403. *                 b) Set OSRunning to OS_TRUE.
  404. *                 c) Load the context of the task pointed to by OSTCBHighRdy.
  405. *                 d_ Execute the task.
  406. *********************************************************************************************************
  407. */
  408. void  OSStart (void)
  409. {
  410.     if (OSRunning == OS_FALSE) {
  411.         OS_SchedNew();                               /* Find highest priority's task priority number   */
  412.         OSPrioCur     = OSPrioHighRdy;
  413.         OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run    */
  414.         OSTCBCur      = OSTCBHighRdy;
  415.         OSStartHighRdy();                            /* Execute target specific code to start task     */
  416.     }
  417. }
  418. /*$PAGE*/
  419. /*
  420. *********************************************************************************************************
  421. *                                        STATISTICS INITIALIZATION
  422. *
  423. * Description: This function is called by your application to establish CPU usage by first determining
  424. *              how high a 32-bit counter would count to in 1 second if no other tasks were to execute
  425. *              during that time.  CPU usage is then determined by a low priority task which keeps track
  426. *              of this 32-bit counter every second but this time, with other tasks running.  CPU usage is
  427. *              determined by:
  428. *
  429. *                                             OSIdleCtr
  430. *                 CPU Usage (%) = 100 * (1 - ------------)
  431. *                                            OSIdleCtrMax
  432. *
  433. * Arguments  : none
  434. *
  435. * Returns    : none
  436. *********************************************************************************************************
  437. */
  438. #if OS_TASK_STAT_EN > 0
  439. void  OSStatInit (void)
  440. {
  441. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  442.     OS_CPU_SR  cpu_sr = 0;
  443. #endif
  444.     OSTimeDly(2);                                /* Synchronize with clock tick                        */
  445.     OS_ENTER_CRITICAL();
  446.     OSIdleCtr    = 0L;                           /* Clear idle counter                                 */
  447.     OS_EXIT_CRITICAL();
  448.     OSTimeDly(OS_TICKS_PER_SEC / 10);            /* Determine MAX. idle counter value for 1/10 second  */
  449.     OS_ENTER_CRITICAL();
  450.     OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1/10 second    */
  451.     OSStatRdy    = OS_TRUE;
  452.     OS_EXIT_CRITICAL();
  453. }
  454. #endif
  455. /*$PAGE*/
  456. /*
  457. *********************************************************************************************************
  458. *                                         PROCESS SYSTEM TICK
  459. *
  460. * Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
  461. *              as a 'clock tick').  This function should be called by the ticker ISR but, can also be
  462. *              called by a high priority task.
  463. *
  464. * Arguments  : none
  465. *
  466. * Returns    : none
  467. *********************************************************************************************************
  468. */
  469. void  OSTimeTick (void)
  470. {
  471.     OS_TCB    *ptcb;
  472. #if OS_TICK_STEP_EN > 0
  473.     BOOLEAN    step;
  474. #endif
  475. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register     */
  476.     OS_CPU_SR  cpu_sr = 0;
  477. #endif
  478. #if OS_TIME_TICK_HOOK_EN > 0
  479.     OSTimeTickHook();                                      /* Call user definable hook                     */
  480. #endif
  481. #if OS_TIME_GET_SET_EN > 0
  482.     OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter               */
  483.     OSTime++;
  484.     OS_EXIT_CRITICAL();
  485. #endif
  486.     if (OSRunning == OS_TRUE) {
  487. #if OS_TICK_STEP_EN > 0
  488.         switch (OSTickStepState) {                         /* Determine whether we need to process a tick  */
  489.             case OS_TICK_STEP_DIS:                         /* Yes, stepping is disabled                    */
  490.                  step = OS_TRUE;
  491.                  break;
  492.             case OS_TICK_STEP_WAIT:                        /* No,  waiting for uC/OS-View to set ...       */
  493.                  step = OS_FALSE;                          /*      .. OSTickStepState to OS_TICK_STEP_ONCE */
  494.                  break;
  495.             case OS_TICK_STEP_ONCE:                        /* Yes, process tick once and wait for next ... */
  496.                  step            = OS_TRUE;                /*      ... step command from uC/OS-View        */
  497.                  OSTickStepState = OS_TICK_STEP_WAIT;
  498.                  break;
  499.             default:                                       /* Invalid case, correct situation              */
  500.                  step            = OS_TRUE;
  501.                  OSTickStepState = OS_TICK_STEP_DIS;
  502.                  break;
  503.         }
  504.         if (step == OS_FALSE) {                            /* Return if waiting for step command           */
  505.             return;
  506.         }
  507. #endif
  508.         ptcb = OSTCBList;                                  /* Point at first TCB in TCB list               */
  509.         while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {     /* Go through all TCBs in TCB list              */
  510.             OS_ENTER_CRITICAL();
  511.             if (ptcb->OSTCBDly != 0) {                     /* No, Delayed or waiting for event with TO     */
  512.                 if (--ptcb->OSTCBDly == 0) {               /* Decrement nbr of ticks to end of delay       */
  513.                                                            /* Check for timeout                            */
  514.                     if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
  515.                         ptcb->OSTCBStat   &= ~OS_STAT_PEND_ANY;                /* Yes, Clear status flag   */
  516.                         ptcb->OSTCBPendTO  = OS_TRUE;                          /* Indicate PEND timeout    */
  517.                     } else {
  518.                         ptcb->OSTCBPendTO  = OS_FALSE;
  519.                     }
  520.                     if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?       */
  521.                         OSRdyGrp               |= ptcb->OSTCBBitY;             /* No,  Make ready          */
  522.                         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  523.                     }
  524.                 }
  525.             }
  526.             ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list                */
  527.             OS_EXIT_CRITICAL();
  528.         }
  529.     }
  530. }
  531. /*$PAGE*/
  532. /*
  533. *********************************************************************************************************
  534. *                                             GET VERSION
  535. *
  536. * Description: This function is used to return the version number of uC/OS-II.  The returned value
  537. *              corresponds to uC/OS-II's version number multiplied by 100.  In other words, version 2.00
  538. *              would be returned as 200.
  539. *
  540. * Arguments  : none
  541. *
  542. * Returns    : the version number of uC/OS-II multiplied by 100.
  543. *********************************************************************************************************
  544. */
  545. INT16U  OSVersion (void)
  546. {
  547.     return (OS_VERSION);
  548. }
  549. /*$PAGE*/
  550. /*
  551. *********************************************************************************************************
  552. *                                            DUMMY FUNCTION
  553. *
  554. * Description: This function doesn't do anything.  It is called by OSTaskDel().
  555. *
  556. * Arguments  : none
  557. *
  558. * Returns    : none
  559. *********************************************************************************************************
  560. */
  561. #if OS_TASK_DEL_EN > 0
  562. void  OS_Dummy (void)
  563. {
  564. }
  565. #endif
  566. /*$PAGE*/
  567. /*
  568. *********************************************************************************************************
  569. *                             MAKE TASK READY TO RUN BASED ON EVENT OCCURING
  570. *
  571. * Description: This function is called by other uC/OS-II services and is used to ready a task that was
  572. *              waiting for an event to occur.
  573. *
  574. * Arguments  : pevent    is a pointer to the event control block corresponding to the event.
  575. *
  576. *              msg       is a pointer to a message.  This pointer is used by message oriented services
  577. *                        such as MAILBOXEs and QUEUEs.  The pointer is not used when called by other
  578. *                        service functions.
  579. *
  580. *              msk       is a mask that is used to clear the status byte of the TCB.  For example,
  581. *                        OSSemPost() will pass OS_STAT_SEM, OSMboxPost() will pass OS_STAT_MBOX etc.
  582. *
  583. * Returns    : none
  584. *
  585. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  586. *********************************************************************************************************
  587. */
  588. #if OS_EVENT_EN
  589. INT8U  OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)
  590. {
  591.     OS_TCB  *ptcb;
  592.     INT8U    x;
  593.     INT8U    y;
  594.     INT8U    prio;
  595. #if OS_LOWEST_PRIO <= 63
  596.     INT8U    bitx;
  597.     INT8U    bity;
  598. #else
  599.     INT16U   bitx;
  600.     INT16U   bity;
  601.     INT16U  *ptbl;
  602. #endif
  603. #if OS_LOWEST_PRIO <= 63
  604.     y     = OSUnMapTbl[pevent->OSEventGrp];             /* Find HPT waiting for message                */
  605.     bity  = (INT8U)(1 << y);
  606.     x     = OSUnMapTbl[pevent->OSEventTbl[y]];
  607.     bitx  = (INT8U)(1 << x);
  608.     prio  = (INT8U)((y << 3) + x);                      /* Find priority of task getting the msg       */
  609. #else
  610.     if ((pevent->OSEventGrp & 0xFF) != 0) {             /* Find HPT waiting for message                */
  611.         y = OSUnMapTbl[pevent->OSEventGrp & 0xFF];
  612.     } else {
  613.         y = OSUnMapTbl[(pevent->OSEventGrp >> 8) & 0xFF] + 8;
  614.     }
  615.     bity = (INT16U)(1 << y);
  616.     ptbl = &pevent->OSEventTbl[y];
  617.     if ((*ptbl & 0xFF) != 0) {
  618.         x = OSUnMapTbl[*ptbl & 0xFF];
  619.     } else {
  620.         x = OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8;
  621.     }
  622.     bitx = (INT16U)(1 << x);
  623.     prio = (INT8U)((y << 4) + x);                       /* Find priority of task getting the msg       */
  624. #endif
  625.     pevent->OSEventTbl[y] &= ~bitx;                     /* Remove this task from the waiting list      */
  626.     if (pevent->OSEventTbl[y] == 0) {
  627.         pevent->OSEventGrp &= ~bity;                    /* Clr group bit if this was only task pending */
  628.     }
  629.     ptcb                 =  OSTCBPrioTbl[prio];         /* Point to this task's OS_TCB                 */
  630.     ptcb->OSTCBDly       =  0;                          /* Prevent OSTimeTick() from readying task     */
  631.     ptcb->OSTCBEventPtr  = (OS_EVENT *)0;               /* Unlink ECB from this task                   */
  632. #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
  633.     ptcb->OSTCBMsg       = msg;                         /* Send message directly to waiting task       */
  634. #else
  635.     msg                  = msg;                         /* Prevent compiler warning if not used        */
  636. #endif
  637.     ptcb->OSTCBPendTO    = OS_FALSE;                    /* Cancel 'any' timeout because of post        */
  638.     ptcb->OSTCBStat     &= ~msk;                        /* Clear bit associated with event type        */
  639.     if (ptcb->OSTCBStat == OS_STAT_RDY) {               /* See if task is ready (could be susp'd)      */
  640.         OSRdyGrp        |=  bity;                       /* Put task in the ready to run list           */
  641.         OSRdyTbl[y]     |=  bitx;
  642.     }
  643.     return (prio);
  644. }
  645. #endif
  646. /*$PAGE*/
  647. /*
  648. *********************************************************************************************************
  649. *                                   MAKE TASK WAIT FOR EVENT TO OCCUR
  650. *
  651. * Description: This function is called by other uC/OS-II services to suspend a task because an event has
  652. *              not occurred.
  653. *
  654. * Arguments  : pevent   is a pointer to the event control block for which the task will be waiting for.
  655. *
  656. * Returns    : none
  657. *
  658. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  659. *********************************************************************************************************
  660. */
  661. #if OS_EVENT_EN
  662. void  OS_EventTaskWait (OS_EVENT *pevent)
  663. {
  664.     INT8U  y;
  665.     OSTCBCur->OSTCBEventPtr = pevent;             /* Store pointer to event control block in TCB       */
  666.     y                       = OSTCBCur->OSTCBY;   /* Task no longer ready                              */
  667.     OSRdyTbl[y]            &= ~OSTCBCur->OSTCBBitX;
  668.     if (OSRdyTbl[y] == 0) {
  669.         OSRdyGrp &= ~OSTCBCur->OSTCBBitY;         /* Clear event grp bit if this was only task pending */
  670.     }
  671.     pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;          /* Put task in waiting list  */
  672.     pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
  673. }
  674. #endif
  675. /*$PAGE*/
  676. /*
  677. *********************************************************************************************************
  678. *                              MAKE TASK READY TO RUN BASED ON EVENT TIMEOUT
  679. *
  680. * Description: This function is called by other uC/OS-II services to make a task ready to run because a
  681. *              timeout occurred.
  682. *
  683. * Arguments  : pevent   is a pointer to the event control block which is readying a task.
  684. *
  685. * Returns    : none
  686. *
  687. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  688. *********************************************************************************************************
  689. */
  690. #if OS_EVENT_EN
  691. void  OS_EventTO (OS_EVENT *pevent)
  692. {
  693.     INT8U  y;
  694.     y                      = OSTCBCur->OSTCBY;
  695.     pevent->OSEventTbl[y] &= ~OSTCBCur->OSTCBBitX;     /* Remove task from wait list                   */
  696.     if (pevent->OSEventTbl[y] == 0x00) {
  697.         pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
  698.     }
  699.     OSTCBCur->OSTCBPendTO   = OS_FALSE;                /* Clear the Pend Timeout flag                  */
  700.     OSTCBCur->OSTCBStat     = OS_STAT_RDY;             /* Set status to ready                          */
  701.     OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;           /* No longer waiting for event                  */
  702. }
  703. #endif
  704. /*$PAGE*/
  705. /*
  706. *********************************************************************************************************
  707. *                                 INITIALIZE EVENT CONTROL BLOCK'S WAIT LIST
  708. *
  709. * Description: This function is called by other uC/OS-II services to initialize the event wait list.
  710. *
  711. * Arguments  : pevent    is a pointer to the event control block allocated to the event.
  712. *
  713. * Returns    : none
  714. *
  715. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  716. *********************************************************************************************************
  717. */
  718. #if OS_EVENT_EN
  719. void  OS_EventWaitListInit (OS_EVENT *pevent)
  720. {
  721. #if OS_LOWEST_PRIO <= 63
  722.     INT8U  *ptbl;
  723. #else
  724.     INT16U *ptbl;
  725. #endif
  726.     INT8U   i;
  727.     pevent->OSEventGrp = 0;                      /* No task waiting on event                           */
  728.     ptbl               = &pevent->OSEventTbl[0];
  729.     for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
  730.         *ptbl++ = 0;
  731.     }
  732. }
  733. #endif
  734. /*$PAGE*/
  735. /*
  736. *********************************************************************************************************
  737. *                                             INITIALIZATION
  738. *                           INITIALIZE THE FREE LIST OF EVENT CONTROL BLOCKS
  739. *
  740. * Description: This function is called by OSInit() to initialize the free list of event control blocks.
  741. *
  742. * Arguments  : none
  743. *
  744. * Returns    : none
  745. *********************************************************************************************************
  746. */
  747. static  void  OS_InitEventList (void)
  748. {
  749. #if OS_EVENT_EN && (OS_MAX_EVENTS > 0)
  750. #if (OS_MAX_EVENTS > 1)
  751.     INT16U     i;
  752.     OS_EVENT  *pevent1;
  753.     OS_EVENT  *pevent2;
  754.     OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); /* Clear the event table                   */
  755.     pevent1 = &OSEventTbl[0];
  756.     pevent2 = &OSEventTbl[1];
  757.     for (i = 0; i < (OS_MAX_EVENTS - 1); i++) {             /* Init. list of free EVENT control blocks */
  758.         pevent1->OSEventType    = OS_EVENT_TYPE_UNUSED;
  759.         pevent1->OSEventPtr     = pevent2;
  760. #if OS_EVENT_NAME_SIZE > 1
  761.         pevent1->OSEventName[0] = '?';                      /* Unknown name                            */
  762.         pevent1->OSEventName[1] = OS_ASCII_NUL;
  763. #endif
  764.         pevent1++;
  765.         pevent2++;
  766.     }
  767.     pevent1->OSEventType            = OS_EVENT_TYPE_UNUSED;
  768.     pevent1->OSEventPtr             = (OS_EVENT *)0;
  769. #if OS_EVENT_NAME_SIZE > 1
  770.     pevent1->OSEventName[0]         = '?';
  771.     pevent1->OSEventName[1]         = OS_ASCII_NUL;
  772. #endif
  773.     OSEventFreeList                 = &OSEventTbl[0];
  774. #else
  775.     OSEventFreeList                 = &OSEventTbl[0];       /* Only have ONE event control block       */
  776.     OSEventFreeList->OSEventType    = OS_EVENT_TYPE_UNUSED;
  777.     OSEventFreeList->OSEventPtr     = (OS_EVENT *)0;
  778. #if OS_EVENT_NAME_SIZE > 1
  779.     OSEventFreeList->OSEventName[0] = '?';                  /* Unknown name                            */
  780.     OSEventFreeList->OSEventName[1] = OS_ASCII_NUL;
  781. #endif
  782. #endif
  783. #endif
  784. }
  785. /*$PAGE*/
  786. /*
  787. *********************************************************************************************************
  788. *                                             INITIALIZATION
  789. *                                    INITIALIZE MISCELLANEOUS VARIABLES
  790. *
  791. * Description: This function is called by OSInit() to initialize miscellaneous variables.
  792. *
  793. * Arguments  : none
  794. *
  795. * Returns    : none
  796. *********************************************************************************************************
  797. */
  798. static  void  OS_InitMisc (void)
  799. {
  800. #if OS_TIME_GET_SET_EN > 0
  801.     OSTime        = 0L;                                    /* Clear the 32-bit system clock            */
  802. #endif
  803.     OSIntNesting  = 0;                                     /* Clear the interrupt nesting counter      */
  804.     OSLockNesting = 0;                                     /* Clear the scheduling lock counter        */
  805.     OSTaskCtr     = 0;                                     /* Clear the number of tasks                */
  806.     OSRunning     = OS_FALSE;                              /* Indicate that multitasking not started   */
  807.     OSCtxSwCtr    = 0;                                     /* Clear the context switch counter         */
  808.     OSIdleCtr     = 0L;                                    /* Clear the 32-bit idle counter            */
  809. #if OS_TASK_STAT_EN > 0
  810.     OSIdleCtrRun  = 0L;
  811.     OSIdleCtrMax  = 0L;
  812.     OSStatRdy     = OS_FALSE;                              /* Statistic task is not ready              */
  813. #endif
  814. }
  815. /*$PAGE*/
  816. /*
  817. *********************************************************************************************************
  818. *                                             INITIALIZATION
  819. *                                       INITIALIZE THE READY LIST
  820. *
  821. * Description: This function is called by OSInit() to initialize the Ready List.
  822. *
  823. * Arguments  : none
  824. *
  825. * Returns    : none
  826. *********************************************************************************************************
  827. */
  828. static  void  OS_InitRdyList (void)
  829. {
  830.     INT8U    i;
  831. #if OS_LOWEST_PRIO <= 63
  832.     INT8U   *prdytbl;
  833. #else
  834.     INT16U  *prdytbl;
  835. #endif
  836.     OSRdyGrp      = 0;                                     /* Clear the ready list                     */
  837.     prdytbl       = &OSRdyTbl[0];
  838.     for (i = 0; i < OS_RDY_TBL_SIZE; i++) {
  839.         *prdytbl++ = 0;
  840.     }
  841.     OSPrioCur     = 0;
  842.     OSPrioHighRdy = 0;
  843.     OSTCBHighRdy  = (OS_TCB *)0;
  844.     OSTCBCur      = (OS_TCB *)0;
  845. }
  846. /*$PAGE*/
  847. /*
  848. *********************************************************************************************************
  849. *                                             INITIALIZATION
  850. *                                         CREATING THE IDLE TASK
  851. *
  852. * Description: This function creates the Idle Task.
  853. *
  854. * Arguments  : none
  855. *
  856. * Returns    : none
  857. *********************************************************************************************************
  858. */
  859. static  void  OS_InitTaskIdle (void)
  860. {
  861. #if OS_TASK_NAME_SIZE > 7
  862.     INT8U  err;
  863. #endif
  864. #if OS_TASK_CREATE_EXT_EN > 0
  865.     #if OS_STK_GROWTH == 1
  866.     (void)OSTaskCreateExt(OS_TaskIdle,
  867.                           (void *)0,                                 /* No arguments passed to OS_TaskIdle() */
  868.                           &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Top-Of-Stack                     */
  869.                           OS_TASK_IDLE_PRIO,                         /* Lowest priority level                */
  870.                           OS_TASK_IDLE_ID,
  871.                           &OSTaskIdleStk[0],                         /* Set Bottom-Of-Stack                  */
  872.                           OS_TASK_IDLE_STK_SIZE,
  873.                           (void *)0,                                 /* No TCB extension                     */
  874.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
  875.     #else
  876.     (void)OSTaskCreateExt(OS_TaskIdle,
  877.                           (void *)0,                                 /* No arguments passed to OS_TaskIdle() */
  878.                           &OSTaskIdleStk[0],                         /* Set Top-Of-Stack                     */
  879.                           OS_TASK_IDLE_PRIO,                         /* Lowest priority level                */
  880.                           OS_TASK_IDLE_ID,
  881.                           &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Bottom-Of-Stack                  */
  882.                           OS_TASK_IDLE_STK_SIZE,
  883.                           (void *)0,                                 /* No TCB extension                     */
  884.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
  885.     #endif
  886. #else
  887.     #if OS_STK_GROWTH == 1
  888.     (void)OSTaskCreate(OS_TaskIdle,
  889.                        (void *)0,
  890.                        &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1],
  891.                        OS_TASK_IDLE_PRIO);
  892.     #else
  893.     (void)OSTaskCreate(OS_TaskIdle,
  894.                        (void *)0,
  895.                        &OSTaskIdleStk[0],
  896.                        OS_TASK_IDLE_PRIO);
  897.     #endif
  898. #endif
  899. #if OS_TASK_NAME_SIZE > 14
  900.     OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)"uC/OS-II Idle", &err);
  901. #else
  902. #if OS_TASK_NAME_SIZE > 7
  903.     OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)"OS-Idle", &err);
  904. #endif
  905. #endif
  906. }
  907. /*$PAGE*/
  908. /*
  909. *********************************************************************************************************
  910. *                                             INITIALIZATION
  911. *                                      CREATING THE STATISTIC TASK
  912. *
  913. * Description: This function creates the Statistic Task.
  914. *
  915. * Arguments  : none
  916. *
  917. * Returns    : none
  918. *********************************************************************************************************
  919. */
  920. #if OS_TASK_STAT_EN > 0
  921. static  void  OS_InitTaskStat (void)
  922. {
  923. #if OS_TASK_NAME_SIZE > 7
  924.     INT8U  err;
  925. #endif
  926. #if OS_TASK_CREATE_EXT_EN > 0
  927.     #if OS_STK_GROWTH == 1
  928.     (void)OSTaskCreateExt(OS_TaskStat,
  929.                           (void *)0,                                   /* No args passed to OS_TaskStat()*/
  930.                           &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],   /* Set Top-Of-Stack               */
  931.                           OS_TASK_STAT_PRIO,                           /* One higher than the idle task  */
  932.                           OS_TASK_STAT_ID,
  933.                           &OSTaskStatStk[0],                           /* Set Bottom-Of-Stack            */
  934.                           OS_TASK_STAT_STK_SIZE,
  935.                           (void *)0,                                   /* No TCB extension               */
  936.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */
  937.     #else
  938.     (void)OSTaskCreateExt(OS_TaskStat,
  939.                           (void *)0,                                   /* No args passed to OS_TaskStat()*/
  940.                           &OSTaskStatStk[0],                           /* Set Top-Of-Stack               */
  941.                           OS_TASK_STAT_PRIO,                           /* One higher than the idle task  */
  942.                           OS_TASK_STAT_ID,
  943.                           &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],   /* Set Bottom-Of-Stack            */
  944.                           OS_TASK_STAT_STK_SIZE,
  945.                           (void *)0,                                   /* No TCB extension               */
  946.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */
  947.     #endif
  948. #else
  949.     #if OS_STK_GROWTH == 1
  950.     (void)OSTaskCreate(OS_TaskStat,
  951.                        (void *)0,                                      /* No args passed to OS_TaskStat()*/
  952.                        &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],      /* Set Top-Of-Stack               */
  953.                        OS_TASK_STAT_PRIO);                             /* One higher than the idle task  */
  954.     #else
  955.     (void)OSTaskCreate(OS_TaskStat,
  956.                        (void *)0,                                      /* No args passed to OS_TaskStat()*/
  957.                        &OSTaskStatStk[0],                              /* Set Top-Of-Stack               */
  958.                        OS_TASK_STAT_PRIO);                             /* One higher than the idle task  */
  959.     #endif
  960. #endif
  961. #if OS_TASK_NAME_SIZE > 14
  962.     OSTaskNameSet(OS_TASK_STAT_PRIO, (INT8U *)"uC/OS-II Stat", &err);
  963. #else
  964. #if OS_TASK_NAME_SIZE > 7
  965.     OSTaskNameSet(OS_TASK_STAT_PRIO, (INT8U *)"OS-Stat", &err);
  966. #endif
  967. #endif
  968. }
  969. #endif
  970. /*$PAGE*/
  971. /*
  972. *********************************************************************************************************
  973. *                                             INITIALIZATION
  974. *                            INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS
  975. *
  976. * Description: This function is called by OSInit() to initialize the free list of OS_TCBs.
  977. *
  978. * Arguments  : none
  979. *
  980. * Returns    : none
  981. *********************************************************************************************************
  982. */
  983. static  void  OS_InitTCBList (void)
  984. {
  985.     INT8U    i;
  986.     OS_TCB  *ptcb1;
  987.     OS_TCB  *ptcb2;
  988.     OS_MemClr((INT8U *)&OSTCBTbl[0],     sizeof(OSTCBTbl));      /* Clear all the TCBs                 */
  989.     OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl));  /* Clear the priority table           */
  990.     ptcb1 = &OSTCBTbl[0];
  991.     ptcb2 = &OSTCBTbl[1];
  992.     for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {  /* Init. list of free TCBs            */
  993.         ptcb1->OSTCBNext = ptcb2;
  994. #if OS_TASK_NAME_SIZE > 1
  995.         ptcb1->OSTCBTaskName[0] = '?';                           /* Unknown name                       */
  996.         ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;
  997. #endif
  998.         ptcb1++;
  999.         ptcb2++;
  1000.     }
  1001.     ptcb1->OSTCBNext = (OS_TCB *)0;                              /* Last OS_TCB                        */
  1002. #if OS_TASK_NAME_SIZE > 1
  1003.     ptcb1->OSTCBTaskName[0] = '?';                               /* Unknown name                       */
  1004.     ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;
  1005. #endif
  1006.     OSTCBList               = (OS_TCB *)0;                       /* TCB lists initializations          */
  1007.     OSTCBFreeList           = &OSTCBTbl[0];
  1008. }
  1009. /*$PAGE*/
  1010. /*
  1011. *********************************************************************************************************
  1012. *                                        CLEAR A SECTION OF MEMORY
  1013. *
  1014. * Description: This function is called by other uC/OS-II services to clear a contiguous block of RAM.
  1015. *
  1016. * Arguments  : pdest    is the start of the RAM to clear (i.e. write 0x00 to)
  1017. *
  1018. *              size     is the number of bytes to clear.
  1019. *
  1020. * Returns    : none
  1021. *
  1022. * Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  1023. *              2) Note that we can only clear up to 64K bytes of RAM.  This is not an issue because none
  1024. *                 of the uses of this function gets close to this limit.
  1025. *              3) The clear is done one byte at a time since this will work on any processor irrespective
  1026. *                 of the alignment of the destination.
  1027. *********************************************************************************************************
  1028. */
  1029. void  OS_MemClr (INT8U *pdest, INT16U size)
  1030. {
  1031.     while (size > 0) {
  1032.         *pdest++ = (INT8U)0;
  1033.         size--;
  1034.     }
  1035. }
  1036. /*$PAGE*/
  1037. /*
  1038. *********************************************************************************************************
  1039. *                                        COPY A BLOCK OF MEMORY
  1040. *
  1041. * Description: This function is called by other uC/OS-II services to copy a block of memory from one
  1042. *              location to another.
  1043. *
  1044. * Arguments  : pdest    is a pointer to the 'destination' memory block
  1045. *
  1046. *              psrc     is a pointer to the 'source'      memory block
  1047. *
  1048. *              size     is the number of bytes to copy.
  1049. *
  1050. * Returns    : none
  1051. *
  1052. * Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.  There is
  1053. *                 no provision to handle overlapping memory copy.  However, that's not a problem since this
  1054. *                 is not a situation that will happen.
  1055. *              2) Note that we can only copy up to 64K bytes of RAM
  1056. *              3) The copy is done one byte at a time since this will work on any processor irrespective
  1057. *                 of the alignment of the source and destination.
  1058. *********************************************************************************************************
  1059. */
  1060. void  OS_MemCopy (INT8U *pdest, INT8U *psrc, INT16U size)
  1061. {
  1062.     while (size > 0) {
  1063.         *pdest++ = *psrc++;
  1064.         size--;
  1065.     }
  1066. }
  1067. /*$PAGE*/
  1068. /*
  1069. *********************************************************************************************************
  1070. *                                              SCHEDULER
  1071. *
  1072. * Description: This function is called by other uC/OS-II services to determine whether a new, high
  1073. *              priority task has been made ready to run.  This function is invoked by TASK level code
  1074. *              and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).
  1075. *
  1076. * Arguments  : none
  1077. *
  1078. * Returns    : none
  1079. *
  1080. * Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  1081. *              2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
  1082. *********************************************************************************************************
  1083. */
  1084. void  OS_Sched (void)
  1085. {
  1086. #if OS_CRITICAL_METHOD == 3                            /* Allocate storage for CPU status register     */
  1087.     OS_CPU_SR  cpu_sr = 0;
  1088. #endif
  1089.     OS_ENTER_CRITICAL();
  1090.     if (OSIntNesting == 0) {                           /* Schedule only if all ISRs done and ...       */
  1091.         if (OSLockNesting == 0) {                      /* ... scheduler is not locked                  */
  1092.             OS_SchedNew();
  1093.             if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy     */
  1094.                 OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
  1095. #if OS_TASK_PROFILE_EN > 0
  1096.                 OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task      */
  1097. #endif
  1098.                 OSCtxSwCtr++;                          /* Increment context switch counter             */
  1099.                 OS_TASK_SW();                          /* Perform a context switch                     */
  1100.             }
  1101.         }
  1102.     }
  1103.     OS_EXIT_CRITICAL();
  1104. }
  1105. /*
  1106. *********************************************************************************************************
  1107. *                              FIND HIGHEST PRIORITY TASK READY TO RUN
  1108. *
  1109. * Description: This function is called by other uC/OS-II services to determine the highest priority task
  1110. *              that is ready to run.  The global variable 'OSPrioHighRdy' is changed accordingly.
  1111. *
  1112. * Arguments  : none
  1113. *
  1114. * Returns    : none
  1115. *
  1116. * Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  1117. *              2) Interrupts are assumed to be disabled when this function is called.
  1118. *********************************************************************************************************
  1119. */
  1120. static  void  OS_SchedNew (void)
  1121. {
  1122. #if OS_LOWEST_PRIO <= 63                         /* See if we support up to 64 tasks                   */
  1123.     INT8U   y;
  1124.     y             = OSUnMapTbl[OSRdyGrp];
  1125.     OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
  1126. #else                                            /* We support up to 256 tasks                         */
  1127.     INT8U   y;
  1128.     INT16U *ptbl;
  1129.     if ((OSRdyGrp & 0xFF) != 0) {
  1130.         y = OSUnMapTbl[OSRdyGrp & 0xFF];
  1131.     } else {
  1132.         y = OSUnMapTbl[(OSRdyGrp >> 8) & 0xFF] + 8;
  1133.     }
  1134.     ptbl = &OSRdyTbl[y];
  1135.     if ((*ptbl & 0xFF) != 0) {
  1136.         OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl & 0xFF)]);
  1137.     } else {
  1138.         OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8);
  1139.     }
  1140. #endif
  1141. }
  1142. /*$PAGE*/
  1143. /*
  1144. *********************************************************************************************************
  1145. *                                        COPY AN ASCII STRING
  1146. *
  1147. * Description: This function is called by other uC/OS-II services to copy an ASCII string from a 'source'
  1148. *              string to a 'destination' string.
  1149. *
  1150. * Arguments  : pdest    is a pointer to the string that will be receiving the copy.  Note that there MUST
  1151. *                       be sufficient space in the destination storage area to receive this string.
  1152. *
  1153. *              psrc     is a pointer to the source string.  The source string MUST NOT be greater than
  1154. *                       254 characters.
  1155. *
  1156. * Returns    : The size of the string (excluding the NUL terminating character)
  1157. *
  1158. * Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  1159. *********************************************************************************************************
  1160. */
  1161. #if (OS_EVENT_NAME_SIZE > 1) || (OS_FLAG_NAME_SIZE > 1) || (OS_MEM_NAME_SIZE > 1) || (OS_TASK_NAME_SIZE > 1) || (OS_TMR_CFG_NAME_SIZE > 1)
  1162. INT8U  OS_StrCopy (INT8U *pdest, INT8U *psrc)
  1163. {
  1164.     INT8U  len;
  1165.     len = 0;
  1166.     while (*psrc != OS_ASCII_NUL) {
  1167.         *pdest++ = *psrc++;
  1168.         len++;
  1169.     }
  1170.     *pdest = OS_ASCII_NUL;
  1171.     return (len);
  1172. }
  1173. #endif
  1174. /*$PAGE*/
  1175. /*
  1176. *********************************************************************************************************
  1177. *                                DETERMINE THE LENGTH OF AN ASCII STRING
  1178. *
  1179. * Description: This function is called by other uC/OS-II services to determine the size of an ASCII string
  1180. *              (excluding the NUL character).
  1181. *
  1182. * Arguments  : psrc     is a pointer to the string for which we need to know the size.
  1183. *
  1184. * Returns    : The size of the string (excluding the NUL terminating character)
  1185. *
  1186. * Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  1187. *              2) The string to check must be less than 255 characters long.
  1188. *********************************************************************************************************
  1189. */
  1190. #if (OS_EVENT_NAME_SIZE > 1) || (OS_FLAG_NAME_SIZE > 1) || (OS_MEM_NAME_SIZE > 1) || (OS_TASK_NAME_SIZE > 1) || (OS_TMR_CFG_NAME_SIZE > 1)
  1191. INT8U  OS_StrLen (INT8U *psrc)
  1192. {
  1193.     INT8U  len;
  1194.     len = 0;
  1195.     while (*psrc != OS_ASCII_NUL) {
  1196.         psrc++;
  1197.         len++;
  1198.     }
  1199.     return (len);
  1200. }
  1201. #endif
  1202. /*$PAGE*/
  1203. /*
  1204. *********************************************************************************************************
  1205. *                                              IDLE TASK
  1206. *
  1207. * Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks
  1208. *              executes because they are ALL waiting for event(s) to occur.
  1209. *
  1210. * Arguments  : none
  1211. *
  1212. * Returns    : none
  1213. *
  1214. * Note(s)    : 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be
  1215. *                 enabled for at least a few instructions.  On some processors (ex. Philips XA), enabling
  1216. *                 and then disabling interrupts didn't allow the processor enough time to have interrupts
  1217. *                 enabled before they were disabled again.  uC/OS-II would thus never recognize
  1218. *                 interrupts.
  1219. *              2) This hook has been added to allow you to do such things as STOP the CPU to conserve
  1220. *                 power.
  1221. *********************************************************************************************************
  1222. */
  1223. void  OS_TaskIdle (void *p_arg)
  1224. {
  1225. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  1226.     OS_CPU_SR  cpu_sr = 0;
  1227. #endif
  1228.     (void)p_arg;                                 /* Prevent compiler warning for not using 'parg'      */
  1229.     for (;;) {
  1230.         OS_ENTER_CRITICAL();
  1231.         OSIdleCtr++;
  1232.         OS_EXIT_CRITICAL();
  1233.         OSTaskIdleHook();                        /* Call user definable HOOK                           */
  1234.     }
  1235. }
  1236. /*$PAGE*/
  1237. /*
  1238. *********************************************************************************************************
  1239. *                                            STATISTICS TASK
  1240. *
  1241. * Description: This task is internal to uC/OS-II and is used to compute some statistics about the
  1242. *              multitasking environment.  Specifically, OS_TaskStat() computes the CPU usage.
  1243. *              CPU usage is determined by:
  1244. *
  1245. *                                          OSIdleCtr
  1246. *                 OSCPUUsage = 100 * (1 - ------------)     (units are in %)
  1247. *                                         OSIdleCtrMax
  1248. *
  1249. * Arguments  : parg     this pointer is not used at this time.
  1250. *
  1251. * Returns    : none
  1252. *
  1253. * Notes      : 1) This task runs at a priority level higher than the idle task.  In fact, it runs at the
  1254. *                 next higher priority, OS_TASK_IDLE_PRIO-1.
  1255. *              2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
  1256. *              3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the
  1257. *                 maximum value for the idle counter.
  1258. *********************************************************************************************************
  1259. */
  1260. #if OS_TASK_STAT_EN > 0
  1261. void  OS_TaskStat (void *p_arg)
  1262. {
  1263.     INT32U     run;
  1264.     INT32U     max;
  1265.     INT8S      usage;
  1266. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  1267.     OS_CPU_SR  cpu_sr = 0;
  1268. #endif
  1269.     p_arg = p_arg;                               /* Prevent compiler warning for not using 'parg'      */
  1270.     while (OSStatRdy == OS_FALSE) {
  1271.         OSTimeDly(2 * OS_TICKS_PER_SEC / 10);    /* Wait until statistic task is ready                 */
  1272.     }
  1273.     max = OSIdleCtrMax / 100L;
  1274.     for (;;) {
  1275.         OS_ENTER_CRITICAL();
  1276.         OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
  1277.         run          = OSIdleCtr;
  1278.         OSIdleCtr    = 0L;                       /* Reset the idle counter for the next second         */
  1279.         OS_EXIT_CRITICAL();
  1280.         if (max > 0L) {
  1281.             usage = (INT8S)(100L - run / max);
  1282.             if (usage >= 0) {                    /* Make sure we don't have a negative percentage      */
  1283.                 OSCPUUsage = usage;
  1284.             } else {
  1285.                 OSCPUUsage = 0;
  1286.             }
  1287.         } else {
  1288.             OSCPUUsage = 0;
  1289.             max        = OSIdleCtrMax / 100L;
  1290.         }
  1291.         OSTaskStatHook();                        /* Invoke user definable hook                         */
  1292. #if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0)
  1293.         OS_TaskStatStkChk();                     /* Check the stacks for each task                     */
  1294. #endif
  1295.         OSTimeDly(OS_TICKS_PER_SEC / 10);        /* Accumulate OSIdleCtr for the next 1/10 second      */
  1296.     }
  1297. }
  1298. #endif
  1299. /*$PAGE*/
  1300. /*
  1301. *********************************************************************************************************
  1302. *                                      CHECK ALL TASK STACKS
  1303. *
  1304. * Description: This function is called by OS_TaskStat() to check the stacks of each active task.
  1305. *
  1306. * Arguments  : none
  1307. *
  1308. * Returns    : none
  1309. *********************************************************************************************************
  1310. */
  1311. #if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0)
  1312. void  OS_TaskStatStkChk (void)
  1313. {
  1314.     OS_TCB      *ptcb;
  1315.     OS_STK_DATA  stk_data;
  1316.     INT8U        err;
  1317.     INT8U        prio;
  1318.     for (prio = 0; prio <= OS_TASK_IDLE_PRIO; prio++) {
  1319.         err = OSTaskStkChk(prio, &stk_data);
  1320.         if (err == OS_NO_ERR) {
  1321.             ptcb = OSTCBPrioTbl[prio];
  1322.             if (ptcb != (OS_TCB *)0) {                               /* Make sure task 'ptcb' is ...   */
  1323.                 if (ptcb != (OS_TCB *)1) {                           /* ... still valid.               */
  1324. #if OS_TASK_PROFILE_EN > 0
  1325.                     #if OS_STK_GROWTH == 1
  1326.                     ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom + ptcb->OSTCBStkSize;
  1327.                     #else
  1328.                     ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom - ptcb->OSTCBStkSize;
  1329.                     #endif
  1330.                     ptcb->OSTCBStkUsed = stk_data.OSUsed;            /* Store the number of bytes used */
  1331. #endif
  1332.                 }
  1333.             }
  1334.         }
  1335.     }
  1336. }
  1337. #endif
  1338. /*$PAGE*/
  1339. /*
  1340. *********************************************************************************************************
  1341. *                                            INITIALIZE TCB
  1342. *
  1343. * Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when
  1344. *              a task is created (see OSTaskCreate() and OSTaskCreateExt()).
  1345. *
  1346. * Arguments  : prio          is the priority of the task being created
  1347. *
  1348. *              ptos          is a pointer to the task's top-of-stack assuming that the CPU registers
  1349. *                            have been placed on the stack.  Note that the top-of-stack corresponds to a
  1350. *                            'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory
  1351. *                            location if OS_STK_GROWTH is set to 0.  Note that stack growth is CPU
  1352. *                            specific.
  1353. *
  1354. *              pbos          is a pointer to the bottom of stack.  A NULL pointer is passed if called by
  1355. *                            'OSTaskCreate()'.
  1356. *
  1357. *              id            is the task's ID (0..65535)
  1358. *
  1359. *              stk_size      is the size of the stack (in 'stack units').  If the stack units are INT8Us
  1360. *                            then, 'stk_size' contains the number of bytes for the stack.  If the stack
  1361. *                            units are INT32Us then, the stack contains '4 * stk_size' bytes.  The stack
  1362. *                            units are established by the #define constant OS_STK which is CPU
  1363. *                            specific.  'stk_size' is 0 if called by 'OSTaskCreate()'.
  1364. *
  1365. *              pext          is a pointer to a user supplied memory area that is used to extend the task
  1366. *                            control block.  This allows you to store the contents of floating-point
  1367. *                            registers, MMU registers or anything else you could find useful during a
  1368. *                            context switch.  You can even assign a name to each task and store this name
  1369. *                            in this TCB extension.  A NULL pointer is passed if called by OSTaskCreate().
  1370. *
  1371. *              opt           options as passed to 'OSTaskCreateExt()' or,
  1372. *                            0 if called from 'OSTaskCreate()'.
  1373. *
  1374. * Returns    : OS_NO_ERR         if the call was successful
  1375. *              OS_NO_MORE_TCB    if there are no more free TCBs to be allocated and thus, the task cannot
  1376. *                                be created.
  1377. *
  1378. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  1379. *********************************************************************************************************
  1380. */
  1381. INT8U  OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
  1382. {
  1383.     OS_TCB    *ptcb;
  1384. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  1385.     OS_CPU_SR  cpu_sr = 0;
  1386. #endif
  1387.     OS_ENTER_CRITICAL();
  1388.     ptcb = OSTCBFreeList;                                  /* Get a free TCB from the free TCB list    */
  1389.     if (ptcb != (OS_TCB *)0) {
  1390.         OSTCBFreeList        = ptcb->OSTCBNext;            /* Update pointer to free TCB list          */
  1391.         OS_EXIT_CRITICAL();
  1392.         ptcb->OSTCBStkPtr    = ptos;                       /* Load Stack pointer in TCB                */
  1393.         ptcb->OSTCBPrio      = prio;                       /* Load task priority into TCB              */
  1394.         ptcb->OSTCBStat      = OS_STAT_RDY;                /* Task is ready to run                     */
  1395.         ptcb->OSTCBPendTO    = OS_FALSE;                   /* Clear the Pend timeout flag              */
  1396.         ptcb->OSTCBDly       = 0;                          /* Task is not delayed                      */
  1397. #if OS_TASK_CREATE_EXT_EN > 0
  1398.         ptcb->OSTCBExtPtr    = pext;                       /* Store pointer to TCB extension           */
  1399.         ptcb->OSTCBStkSize   = stk_size;                   /* Store stack size                         */
  1400.         ptcb->OSTCBStkBottom = pbos;                       /* Store pointer to bottom of stack         */
  1401.         ptcb->OSTCBOpt       = opt;                        /* Store task options                       */
  1402.         ptcb->OSTCBId        = id;                         /* Store task ID                            */
  1403. #else
  1404.         pext                 = pext;                       /* Prevent compiler warning if not used     */
  1405.         stk_size             = stk_size;
  1406.         pbos                 = pbos;
  1407.         opt                  = opt;
  1408.         id                   = id;
  1409. #endif
  1410. #if OS_TASK_DEL_EN > 0
  1411.         ptcb->OSTCBDelReq    = OS_NO_ERR;
  1412. #endif
  1413. #if OS_LOWEST_PRIO <= 63
  1414.         ptcb->OSTCBY         = (INT8U)(prio >> 3);         /* Pre-compute X, Y, BitX and BitY          */
  1415.         ptcb->OSTCBBitY      = (INT8U)(1 << ptcb->OSTCBY);
  1416.         ptcb->OSTCBX         = (INT8U)(prio & 0x07);
  1417.         ptcb->OSTCBBitX      = (INT8U)(1 << ptcb->OSTCBX);
  1418. #else
  1419.         ptcb->OSTCBY         = (INT8U)((prio >> 4) & 0xFF);/* Pre-compute X, Y, BitX and BitY          */
  1420.         ptcb->OSTCBBitY      = (INT16U)(1 << ptcb->OSTCBY);
  1421.         ptcb->OSTCBX         = (INT8U)(prio & 0x0F);
  1422.         ptcb->OSTCBBitX      = (INT16U)(1 << ptcb->OSTCBX);
  1423. #endif
  1424. #if OS_EVENT_EN
  1425.         ptcb->OSTCBEventPtr  = (OS_EVENT *)0;              /* Task is not pending on an event          */
  1426. #endif
  1427. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
  1428.         ptcb->OSTCBFlagNode  = (OS_FLAG_NODE *)0;          /* Task is not pending on an event flag     */
  1429. #endif
  1430. #if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
  1431.         ptcb->OSTCBMsg       = (void *)0;                  /* No message received                      */
  1432. #endif
  1433. #if OS_TASK_PROFILE_EN > 0
  1434.         ptcb->OSTCBCtxSwCtr    = 0L;                       /* Initialize profiling variables           */
  1435.         ptcb->OSTCBCyclesStart = 0L;
  1436.         ptcb->OSTCBCyclesTot   = 0L;
  1437.         ptcb->OSTCBStkBase     = (OS_STK *)0;
  1438.         ptcb->OSTCBStkUsed     = 0L;
  1439. #endif
  1440. #if OS_TASK_NAME_SIZE > 1
  1441.         ptcb->OSTCBTaskName[0] = '?';                      /* Unknown name at task creation            */
  1442.         ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;
  1443. #endif
  1444. #if OS_VERSION >= 204
  1445.         OSTCBInitHook(ptcb);
  1446. #endif
  1447.         OSTaskCreateHook(ptcb);                            /* Call user defined hook                   */
  1448.         OS_ENTER_CRITICAL();
  1449.         OSTCBPrioTbl[prio] = ptcb;
  1450.         ptcb->OSTCBNext    = OSTCBList;                    /* Link into TCB chain                      */
  1451.         ptcb->OSTCBPrev    = (OS_TCB *)0;
  1452.         if (OSTCBList != (OS_TCB *)0) {
  1453.             OSTCBList->OSTCBPrev = ptcb;
  1454.         }
  1455.         OSTCBList               = ptcb;
  1456.         OSRdyGrp               |= ptcb->OSTCBBitY;         /* Make task ready to run                   */
  1457.         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  1458.         OSTaskCtr++;                                       /* Increment the #tasks counter             */
  1459.         OS_EXIT_CRITICAL();
  1460.         return (OS_NO_ERR);
  1461.     }
  1462.     OS_EXIT_CRITICAL();
  1463.     return (OS_NO_MORE_TCB);
  1464. }