OS_CORE.C
上传用户:ssllxx2007
上传日期:2022-06-12
资源大小:784k
文件大小:49k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                             CORE FUNCTIONS
  6. *
  7. *                          (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
  8. *                                           All Rights Reserved
  9. *
  10. * File : OS_CORE.C
  11. * By   : Jean J. Labrosse
  12. *********************************************************************************************************
  13. */
  14. #ifndef  OS_MASTER_FILE
  15. #define  OS_GLOBALS
  16. #include "..APPincludes.h"
  17. #endif
  18. /*
  19. *********************************************************************************************************
  20. *                              MAPPING TABLE TO MAP BIT POSITION TO BIT MASK
  21. *
  22. * Note: Index into table is desired bit position, 0..7
  23. *       Indexed value corresponds to bit mask
  24. *********************************************************************************************************
  25. */
  26. INT8U  const  OSMapTbl[]   = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
  27. /*
  28. *********************************************************************************************************
  29. *                                       PRIORITY RESOLUTION TABLE
  30. *
  31. * Note: Index into table is bit pattern to resolve highest priority
  32. *       Indexed value corresponds to highest priority bit position (i.e. 0..7)
  33. *********************************************************************************************************
  34. */
  35. INT8U  const  OSUnMapTbl[] = {
  36.     0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x00 to 0x0F                             */
  37.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x10 to 0x1F                             */
  38.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x20 to 0x2F                             */
  39.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x30 to 0x3F                             */
  40.     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x40 to 0x4F                             */
  41.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x50 to 0x5F                             */
  42.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x60 to 0x6F                             */
  43.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x70 to 0x7F                             */
  44.     7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x80 to 0x8F                             */
  45.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x90 to 0x9F                             */
  46.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xA0 to 0xAF                             */
  47.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xB0 to 0xBF                             */
  48.     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xC0 to 0xCF                             */
  49.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xD0 to 0xDF                             */
  50.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xE0 to 0xEF                             */
  51.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0        /* 0xF0 to 0xFF                             */
  52. };
  53. /*
  54. *********************************************************************************************************
  55. *                                       FUNCTION PROTOTYPES
  56. *********************************************************************************************************
  57. */
  58. static  void  OS_InitEventList(void);
  59. static  void  OS_InitMisc(void);
  60. static  void  OS_InitRdyList(void);
  61. static  void  OS_InitTaskIdle(void);
  62. static  void  OS_InitTaskStat(void);
  63. static  void  OS_InitTCBList(void);
  64. /*$PAGE*/
  65. /*
  66. *********************************************************************************************************
  67. *                                             INITIALIZATION
  68. *
  69. * Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to
  70. *              creating any uC/OS-II object and, prior to calling OSStart().
  71. *
  72. * Arguments  : none
  73. *
  74. * Returns    : none
  75. *********************************************************************************************************
  76. */
  77. void  OSInit (void)
  78. {
  79. #if OS_VERSION >= 204
  80.     OSInitHookBegin();                                           /* Call port specific initialization code   */
  81. #endif
  82.     OS_InitMisc();                                               /* Initialize miscellaneous variables       */
  83.     OS_InitRdyList();                                            /* Initialize the Ready List                */
  84.     OS_InitTCBList();                                            /* Initialize the free list of OS_TCBs      */
  85.     OS_InitEventList();                                          /* Initialize the free list of OS_EVENTs    */
  86. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
  87.     OS_FlagInit();                                               /* Initialize the event flag structures     */
  88. #endif
  89. #if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
  90.     OS_MemInit();                                                /* Initialize the memory manager            */
  91. #endif
  92. #if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
  93.     OS_QInit();                                                  /* Initialize the message queue structures  */
  94. #endif
  95.     OS_InitTaskIdle();                                           /* Create the Idle Task                     */
  96. #if OS_TASK_STAT_EN > 0
  97.     OS_InitTaskStat();                                           /* Create the Statistic Task                */
  98. #endif
  99. #if OS_VERSION >= 204
  100.     OSInitHookEnd();                                             /* Call port specific init. code            */
  101. #endif
  102. }
  103. /*$PAGE*/
  104. /*
  105. *********************************************************************************************************
  106. *                                              ENTER ISR
  107. *
  108. * Description: This function is used to notify uC/OS-II that you are about to service an interrupt
  109. *              service routine (ISR).  This allows uC/OS-II to keep track of interrupt nesting and thus
  110. *              only perform rescheduling at the last nested ISR.
  111. *
  112. * Arguments  : none
  113. *
  114. * Returns    : none
  115. *
  116. * Notes      : 1) This function should be called ith interrupts already disabled
  117. *              2) Your ISR can directly increment OSIntNesting without calling this function because
  118. *                 OSIntNesting has been declared 'global'.  
  119. *              3) You MUST still call OSIntExit() even though you increment OSIntNesting directly.
  120. *              4) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
  121. *                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
  122. *                 end of the ISR.
  123. *              5) You are allowed to nest interrupts up to 255 levels deep.
  124. *              6) I removed the OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() around the increment because
  125. *                 OSIntEnter() is always called with interrupts disabled.
  126. *********************************************************************************************************
  127. */
  128. void  OSIntEnter (void)
  129. {
  130.     if (OSRunning == TRUE) {
  131.         if (OSIntNesting < 255) {
  132.             OSIntNesting++;                      /* Increment ISR nesting level                        */
  133.         }
  134.     }
  135. }
  136. /*$PAGE*/
  137. /*
  138. *********************************************************************************************************
  139. *                                               EXIT ISR
  140. *
  141. * Description: This function is used to notify uC/OS-II that you have completed serviving an ISR.  When
  142. *              the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether
  143. *              a new, high-priority task, is ready to run.
  144. *
  145. * Arguments  : none
  146. *
  147. * Returns    : none
  148. *
  149. * Notes      : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
  150. *                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
  151. *                 end of the ISR.
  152. *              2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
  153. *********************************************************************************************************
  154. */
  155. void  OSIntExit (void)
  156. {
  157. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  158.     OS_CPU_SR  cpu_sr;
  159. #endif
  160.     
  161.     
  162.     if (OSRunning == TRUE) {
  163.         OS_ENTER_CRITICAL();
  164.         if (OSIntNesting > 0) {                            /* Prevent OSIntNesting from wrapping       */
  165.             OSIntNesting--;
  166.         }
  167.         if ((OSIntNesting == 0) && (OSLockNesting == 0)) { /* Reschedule only if all ISRs complete ... */
  168.             OSIntExitY    = OSUnMapTbl[OSRdyGrp];          /* ... and not locked.                      */
  169.             OSPrioHighRdy = (INT8U)((OSIntExitY << 3) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]);
  170.             if (OSPrioHighRdy != OSPrioCur) {              /* No Ctx Sw if current task is highest rdy */
  171.                 OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];
  172.                 OSCtxSwCtr++;                              /* Keep track of the number of ctx switches */
  173.                 OSIntCtxSw();                              /* Perform interrupt level ctx switch       */
  174.             }
  175.         }
  176.         OS_EXIT_CRITICAL();
  177.     }
  178. }
  179. /*$PAGE*/
  180. /*
  181. *********************************************************************************************************
  182. *                                          PREVENT SCHEDULING
  183. *
  184. * Description: This function is used to prevent rescheduling to take place.  This allows your application
  185. *              to prevent context switches until you are ready to permit context switching.
  186. *
  187. * Arguments  : none
  188. *
  189. * Returns    : none
  190. *
  191. * Notes      : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair.  In other words, for every
  192. *                 call to OSSchedLock() you MUST have a call to OSSchedUnlock().
  193. *********************************************************************************************************
  194. */
  195. #if OS_SCHED_LOCK_EN > 0
  196. void  OSSchedLock (void)
  197. {
  198. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  199.     OS_CPU_SR  cpu_sr;
  200. #endif    
  201.     
  202.     
  203.     if (OSRunning == TRUE) {                     /* Make sure multitasking is running                  */
  204.         OS_ENTER_CRITICAL();
  205.         if (OSLockNesting < 255) {               /* Prevent OSLockNesting from wrapping back to 0      */
  206.             OSLockNesting++;                     /* Increment lock nesting level                       */
  207.         }
  208.         OS_EXIT_CRITICAL();
  209.     }
  210. }
  211. #endif    
  212. /*$PAGE*/
  213. /*
  214. *********************************************************************************************************
  215. *                                          ENABLE SCHEDULING
  216. *
  217. * Description: This function is used to re-allow rescheduling.
  218. *
  219. * Arguments  : none
  220. *
  221. * Returns    : none
  222. *
  223. * Notes      : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair.  In other words, for every
  224. *                 call to OSSchedLock() you MUST have a call to OSSchedUnlock().
  225. *********************************************************************************************************
  226. */
  227. #if OS_SCHED_LOCK_EN > 0
  228. void  OSSchedUnlock (void)
  229. {
  230. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  231.     OS_CPU_SR  cpu_sr;
  232. #endif    
  233.     
  234.     
  235.     if (OSRunning == TRUE) {                                   /* Make sure multitasking is running    */
  236.         OS_ENTER_CRITICAL();
  237.         if (OSLockNesting > 0) {                               /* Do not decrement if already 0        */
  238.             OSLockNesting--;                                   /* Decrement lock nesting level         */
  239.             if ((OSLockNesting == 0) && (OSIntNesting == 0)) { /* See if sched. enabled and not an ISR */
  240.                 OS_EXIT_CRITICAL();
  241.                 OS_Sched();                                    /* See if a HPT is ready                */
  242.             } else {
  243.                 OS_EXIT_CRITICAL();
  244.             }
  245.         } else {
  246.             OS_EXIT_CRITICAL();
  247.         }
  248.     }
  249. }
  250. #endif    
  251. /*$PAGE*/
  252. /*
  253. *********************************************************************************************************
  254. *                                          START MULTITASKING
  255. *
  256. * Description: This function is used to start the multitasking process which lets uC/OS-II manages the
  257. *              task that you have created.  Before you can call OSStart(), you MUST have called OSInit()
  258. *              and you MUST have created at least one task.
  259. *
  260. * Arguments  : none
  261. *
  262. * Returns    : none
  263. *
  264. * Note       : OSStartHighRdy() MUST:
  265. *                 a) Call OSTaskSwHook() then,
  266. *                 b) Set OSRunning to TRUE.
  267. *                 c) Load the context of the task pointed to by OSTCBHighRdy.
  268. *                 d_ Execute the task.
  269. *********************************************************************************************************
  270. */
  271. void  OSStart (void)
  272. {
  273.     INT8U y;
  274.     INT8U x;
  275.     if (OSRunning == FALSE) {
  276.         y             = OSUnMapTbl[OSRdyGrp];        /* Find highest priority's task priority number   */
  277.         x             = OSUnMapTbl[OSRdyTbl[y]];
  278.         OSPrioHighRdy = (INT8U)((y << 3) + x);
  279.         OSPrioCur     = OSPrioHighRdy;
  280.         OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run    */
  281.         OSTCBCur      = OSTCBHighRdy;
  282.         OSStartHighRdy();                            /* Execute target specific code to start task     */
  283.     }
  284. }
  285. /*$PAGE*/
  286. /*
  287. *********************************************************************************************************
  288. *                                        STATISTICS INITIALIZATION
  289. *
  290. * Description: This function is called by your application to establish CPU usage by first determining
  291. *              how high a 32-bit counter would count to in 1 second if no other tasks were to execute
  292. *              during that time.  CPU usage is then determined by a low priority task which keeps track
  293. *              of this 32-bit counter every second but this time, with other tasks running.  CPU usage is
  294. *              determined by:
  295. *
  296. *                                             OSIdleCtr
  297. *                 CPU Usage (%) = 100 * (1 - ------------)
  298. *                                            OSIdleCtrMax
  299. *
  300. * Arguments  : none
  301. *
  302. * Returns    : none
  303. *********************************************************************************************************
  304. */
  305. #if OS_TASK_STAT_EN > 0
  306. void  OSStatInit (void)
  307. {
  308. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  309.     OS_CPU_SR  cpu_sr;
  310. #endif    
  311.     
  312.     
  313.     OSTimeDly(2);                                /* Synchronize with clock tick                        */
  314.     OS_ENTER_CRITICAL();
  315.     OSIdleCtr    = 0L;                           /* Clear idle counter                                 */
  316.     OS_EXIT_CRITICAL();
  317.     OSTimeDly(OS_TICKS_PER_SEC);                 /* Determine MAX. idle counter value for 1 second     */
  318.     OS_ENTER_CRITICAL();
  319.     OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1 second       */
  320.     OSStatRdy    = TRUE;
  321.     OS_EXIT_CRITICAL();
  322. }
  323. #endif
  324. /*$PAGE*/
  325. /*
  326. *********************************************************************************************************
  327. *                                         PROCESS SYSTEM TICK
  328. *
  329. * Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
  330. *              as a 'clock tick').  This function should be called by the ticker ISR but, can also be
  331. *              called by a high priority task.
  332. *
  333. * Arguments  : none
  334. *
  335. * Returns    : none
  336. *********************************************************************************************************
  337. */
  338. void  OSTimeTick (void)
  339. {
  340. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  341.     OS_CPU_SR  cpu_sr;
  342. #endif    
  343.     OS_TCB    *ptcb;
  344.     OSTimeTickHook();                                      /* Call user definable hook                 */
  345. #if OS_TIME_GET_SET_EN > 0   
  346.     OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter           */
  347.     OSTime++;
  348.     OS_EXIT_CRITICAL();
  349. #endif
  350.     if (OSRunning == TRUE) {    
  351.         ptcb = OSTCBList;                                  /* Point at first TCB in TCB list           */
  352.         while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {          /* Go through all TCBs in TCB list          */
  353.             OS_ENTER_CRITICAL();
  354.             if (ptcb->OSTCBDly != 0) {                     /* Delayed or waiting for event with TO     */
  355.                 if (--ptcb->OSTCBDly == 0) {               /* Decrement nbr of ticks to end of delay   */
  356.                     if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended?    */
  357.                         OSRdyGrp               |= ptcb->OSTCBBitY; /* No,  Make task R-to-R (timed out)*/
  358.                         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  359.                     } else {                               /* Yes, Leave 1 tick to prevent ...         */
  360.                         ptcb->OSTCBDly = 1;                /* ... loosing the task when the ...        */
  361.                     }                                      /* ... suspension is removed.               */
  362.                 }
  363.             }
  364.             ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list            */
  365.             OS_EXIT_CRITICAL();
  366.         }
  367.     }
  368. }
  369. /*$PAGE*/
  370. /*
  371. *********************************************************************************************************
  372. *                                             GET VERSION
  373. *
  374. * Description: This function is used to return the version number of uC/OS-II.  The returned value
  375. *              corresponds to uC/OS-II's version number multiplied by 100.  In other words, version 2.00
  376. *              would be returned as 200.
  377. *
  378. * Arguments  : none
  379. *
  380. * Returns    : the version number of uC/OS-II multiplied by 100.
  381. *********************************************************************************************************
  382. */
  383. INT16U  OSVersion (void)
  384. {
  385.     return (OS_VERSION);
  386. }
  387. /*$PAGE*/
  388. /*
  389. *********************************************************************************************************
  390. *                                            DUMMY FUNCTION
  391. *
  392. * Description: This function doesn't do anything.  It is called by OSTaskDel().
  393. *
  394. * Arguments  : none
  395. *
  396. * Returns    : none
  397. *********************************************************************************************************
  398. */
  399. #if OS_TASK_DEL_EN > 0
  400. void  OS_Dummy (void)
  401. {
  402. }
  403. #endif
  404. /*$PAGE*/
  405. /*
  406. *********************************************************************************************************
  407. *                             MAKE TASK READY TO RUN BASED ON EVENT OCCURING
  408. *
  409. * Description: This function is called by other uC/OS-II services and is used to ready a task that was
  410. *              waiting for an event to occur.
  411. *
  412. * Arguments  : pevent    is a pointer to the event control block corresponding to the event.
  413. *
  414. *              msg       is a pointer to a message.  This pointer is used by message oriented services
  415. *                        such as MAILBOXEs and QUEUEs.  The pointer is not used when called by other
  416. *                        service functions.
  417. *
  418. *              msk       is a mask that is used to clear the status byte of the TCB.  For example,
  419. *                        OSSemPost() will pass OS_STAT_SEM, OSMboxPost() will pass OS_STAT_MBOX etc.
  420. *
  421. * Returns    : none
  422. *
  423. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  424. *********************************************************************************************************
  425. */
  426. #if OS_EVENT_EN > 0
  427. INT8U  OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)
  428. {
  429.     OS_TCB *ptcb;
  430.     INT8U   x;
  431.     INT8U   y;
  432.     INT8U   bitx;
  433.     INT8U   bity;
  434.     INT8U   prio;
  435.     y    = OSUnMapTbl[pevent->OSEventGrp];            /* Find highest prio. task waiting for message   */
  436.     bity = OSMapTbl[y];
  437.     x    = OSUnMapTbl[pevent->OSEventTbl[y]];
  438.     bitx = OSMapTbl[x];
  439.     prio = (INT8U)((y << 3) + x);                     /* Find priority of task getting the msg         */
  440.     if ((pevent->OSEventTbl[y] &= ~bitx) == 0x00) {   /* Remove this task from the waiting list        */
  441.         pevent->OSEventGrp &= ~bity;                  /* Clr group bit if this was only task pending   */
  442.     }
  443.     ptcb                 =  OSTCBPrioTbl[prio];       /* Point to this task's OS_TCB                   */
  444.     ptcb->OSTCBDly       =  0;                        /* Prevent OSTimeTick() from readying task       */
  445.     ptcb->OSTCBEventPtr  = (OS_EVENT *)0;             /* Unlink ECB from this task                     */
  446. #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
  447.     ptcb->OSTCBMsg       = msg;                       /* Send message directly to waiting task         */
  448. #else
  449.     msg                  = msg;                       /* Prevent compiler warning if not used          */
  450. #endif
  451.     ptcb->OSTCBStat     &= ~msk;                      /* Clear bit associated with event type          */
  452.     if (ptcb->OSTCBStat == OS_STAT_RDY) {             /* See if task is ready (could be susp'd)        */
  453.         OSRdyGrp        |=  bity;                     /* Put task in the ready to run list             */
  454.         OSRdyTbl[y]     |=  bitx;
  455.     }
  456.     return (prio);
  457. }
  458. #endif
  459. /*$PAGE*/
  460. /*
  461. *********************************************************************************************************
  462. *                                   MAKE TASK WAIT FOR EVENT TO OCCUR
  463. *
  464. * Description: This function is called by other uC/OS-II services to suspend a task because an event has
  465. *              not occurred.
  466. *
  467. * Arguments  : pevent   is a pointer to the event control block for which the task will be waiting for.
  468. *
  469. * Returns    : none
  470. *
  471. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  472. *********************************************************************************************************
  473. */
  474. #if OS_EVENT_EN > 0
  475. void  OS_EventTaskWait (OS_EVENT *pevent)
  476. {
  477.     OSTCBCur->OSTCBEventPtr = pevent;            /* Store pointer to event control block in TCB        */
  478.     if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0x00) {   /* Task no longer ready      */
  479.         OSRdyGrp &= ~OSTCBCur->OSTCBBitY;        /* Clear event grp bit if this was only task pending  */
  480.     }
  481.     pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;          /* Put task in waiting list  */
  482.     pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
  483. }
  484. #endif
  485. /*$PAGE*/
  486. /*
  487. *********************************************************************************************************
  488. *                              MAKE TASK READY TO RUN BASED ON EVENT TIMEOUT
  489. *
  490. * Description: This function is called by other uC/OS-II services to make a task ready to run because a
  491. *              timeout occurred.
  492. *
  493. * Arguments  : pevent   is a pointer to the event control block which is readying a task.
  494. *
  495. * Returns    : none
  496. *
  497. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  498. *********************************************************************************************************
  499. */
  500. #if OS_EVENT_EN > 0
  501. void  OS_EventTO (OS_EVENT *pevent)
  502. {
  503.     if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0x00) {
  504.         pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
  505.     }
  506.     OSTCBCur->OSTCBStat     = OS_STAT_RDY;       /* Set status to ready                                */
  507.     OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;     /* No longer waiting for event                        */
  508. }
  509. #endif
  510. /*$PAGE*/
  511. /*
  512. *********************************************************************************************************
  513. *                                 INITIALIZE EVENT CONTROL BLOCK'S WAIT LIST
  514. *
  515. * Description: This function is called by other uC/OS-II services to initialize the event wait list.
  516. *
  517. * Arguments  : pevent    is a pointer to the event control block allocated to the event.
  518. *
  519. * Returns    : none
  520. *
  521. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  522. *********************************************************************************************************
  523. */
  524. #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) || (OS_SEM_EN > 0) || (OS_MUTEX_EN > 0)
  525. void  OS_EventWaitListInit (OS_EVENT *pevent)
  526. {
  527.     INT8U  *ptbl;
  528.     pevent->OSEventGrp = 0x00;                   /* No task waiting on event                           */
  529.     ptbl               = &pevent->OSEventTbl[0];
  530. #if OS_EVENT_TBL_SIZE > 0
  531.     *ptbl++            = 0x00;
  532. #endif
  533. #if OS_EVENT_TBL_SIZE > 1
  534.     *ptbl++            = 0x00;
  535. #endif
  536. #if OS_EVENT_TBL_SIZE > 2
  537.     *ptbl++            = 0x00;
  538. #endif
  539. #if OS_EVENT_TBL_SIZE > 3
  540.     *ptbl++            = 0x00;
  541. #endif
  542. #if OS_EVENT_TBL_SIZE > 4
  543.     *ptbl++            = 0x00;
  544. #endif
  545. #if OS_EVENT_TBL_SIZE > 5
  546.     *ptbl++            = 0x00;
  547. #endif
  548. #if OS_EVENT_TBL_SIZE > 6
  549.     *ptbl++            = 0x00;
  550. #endif
  551. #if OS_EVENT_TBL_SIZE > 7
  552.     *ptbl              = 0x00;
  553. #endif
  554. }
  555. #endif
  556. /*$PAGE*/
  557. /*
  558. *********************************************************************************************************
  559. *                                             INITIALIZATION
  560. *                           INITIALIZE THE FREE LIST OF EVENT CONTROL BLOCKS
  561. *
  562. * Description: This function is called by OSInit() to initialize the free list of event control blocks.
  563. *
  564. * Arguments  : none
  565. *
  566. * Returns    : none
  567. *********************************************************************************************************
  568. */
  569. static  void  OS_InitEventList (void)
  570. {
  571. #if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0)
  572. #if (OS_MAX_EVENTS > 1)
  573.     INT16U     i;
  574.     OS_EVENT  *pevent1;
  575.     OS_EVENT  *pevent2;
  576.     pevent1 = &OSEventTbl[0];
  577.     pevent2 = &OSEventTbl[1];
  578.     for (i = 0; i < (OS_MAX_EVENTS - 1); i++) {                  /* Init. list of free EVENT control blocks  */
  579.         pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;
  580.         pevent1->OSEventPtr  = pevent2;
  581.         pevent1++;
  582.         pevent2++;
  583.     }
  584.     pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;
  585.     pevent1->OSEventPtr  = (OS_EVENT *)0;
  586.     OSEventFreeList      = &OSEventTbl[0];
  587. #else
  588.     OSEventFreeList              = &OSEventTbl[0];               /* Only have ONE event control block        */
  589.     OSEventFreeList->OSEventType = OS_EVENT_TYPE_UNUSED;
  590.     OSEventFreeList->OSEventPtr  = (OS_EVENT *)0;
  591. #endif
  592. #endif
  593. }
  594. /*$PAGE*/
  595. /*
  596. *********************************************************************************************************
  597. *                                             INITIALIZATION
  598. *                                    INITIALIZE MISCELLANEOUS VARIABLES
  599. *
  600. * Description: This function is called by OSInit() to initialize miscellaneous variables.
  601. *
  602. * Arguments  : none
  603. *
  604. * Returns    : none
  605. *********************************************************************************************************
  606. */
  607. static  void  OS_InitMisc (void)
  608. {
  609. #if OS_TIME_GET_SET_EN > 0   
  610.     OSTime        = 0L;                                          /* Clear the 32-bit system clock            */
  611. #endif
  612.     OSIntNesting  = 0;                                           /* Clear the interrupt nesting counter      */
  613.     OSLockNesting = 0;                                           /* Clear the scheduling lock counter        */
  614.     OSTaskCtr     = 0;                                           /* Clear the number of tasks                */
  615.     OSRunning     = FALSE;                                       /* Indicate that multitasking not started   */
  616.     
  617.     OSCtxSwCtr    = 0;                                           /* Clear the context switch counter         */
  618.     OSIdleCtr     = 0L;                                          /* Clear the 32-bit idle counter            */
  619. #if (OS_TASK_STAT_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0)
  620.     OSIdleCtrRun  = 0L;
  621.     OSIdleCtrMax  = 0L;
  622.     OSStatRdy     = FALSE;                                       /* Statistic task is not ready              */
  623. #endif
  624. }
  625. /*$PAGE*/
  626. /*
  627. *********************************************************************************************************
  628. *                                             INITIALIZATION
  629. *                                       INITIALIZE THE READY LIST
  630. *
  631. * Description: This function is called by OSInit() to initialize the Ready List.
  632. *
  633. * Arguments  : none
  634. *
  635. * Returns    : none
  636. *********************************************************************************************************
  637. */
  638. static  void  OS_InitRdyList (void)
  639. {
  640.     INT16U   i;
  641.     INT8U   *prdytbl;
  642.     OSRdyGrp      = 0x00;                                        /* Clear the ready list                     */
  643.     prdytbl       = &OSRdyTbl[0];
  644.     for (i = 0; i < OS_RDY_TBL_SIZE; i++) {
  645.         *prdytbl++ = 0x00;
  646.     }
  647.     OSPrioCur     = 0;
  648.     OSPrioHighRdy = 0;
  649.     OSTCBHighRdy  = (OS_TCB *)0;                                 
  650.     OSTCBCur      = (OS_TCB *)0;
  651. }
  652. /*$PAGE*/
  653. /*
  654. *********************************************************************************************************
  655. *                                             INITIALIZATION
  656. *                                         CREATING THE IDLE TASK
  657. *
  658. * Description: This function creates the Idle Task.
  659. *
  660. * Arguments  : none
  661. *
  662. * Returns    : none
  663. *********************************************************************************************************
  664. */
  665. static  void  OS_InitTaskIdle (void)
  666. {
  667. #if OS_TASK_CREATE_EXT_EN > 0
  668.     #if OS_STK_GROWTH == 1
  669.     (void)OSTaskCreateExt(OS_TaskIdle,
  670.                           (void *)0,                                 /* No arguments passed to OS_TaskIdle() */
  671.                           &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Top-Of-Stack                     */
  672.                           OS_IDLE_PRIO,                              /* Lowest priority level                */
  673.                           OS_TASK_IDLE_ID,
  674.                           &OSTaskIdleStk[0],                         /* Set Bottom-Of-Stack                  */
  675.                           OS_TASK_IDLE_STK_SIZE,
  676.                           (void *)0,                                 /* No TCB extension                     */
  677.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
  678.     #else
  679.     (void)OSTaskCreateExt(OS_TaskIdle,
  680.                           (void *)0,                                 /* No arguments passed to OS_TaskIdle() */
  681.                           &OSTaskIdleStk[0],                         /* Set Top-Of-Stack                     */
  682.                           OS_IDLE_PRIO,                              /* Lowest priority level                */
  683.                           OS_TASK_IDLE_ID,
  684.                           &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Bottom-Of-Stack                  */
  685.                           OS_TASK_IDLE_STK_SIZE,
  686.                           (void *)0,                                 /* No TCB extension                     */
  687.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
  688.     #endif
  689. #else
  690.     #if OS_STK_GROWTH == 1
  691.     (void)OSTaskCreate(OS_TaskIdle,
  692.                        (void *)0,
  693.                        &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1],
  694.                        OS_IDLE_PRIO);
  695.     #else
  696.     (void)OSTaskCreate(OS_TaskIdle,
  697.                        (void *)0,
  698.                        &OSTaskIdleStk[0],
  699.                        OS_IDLE_PRIO);
  700.     #endif
  701. #endif
  702. }
  703. /*$PAGE*/
  704. /*
  705. *********************************************************************************************************
  706. *                                             INITIALIZATION
  707. *                                      CREATING THE STATISTIC TASK
  708. *
  709. * Description: This function creates the Statistic Task.
  710. *
  711. * Arguments  : none
  712. *
  713. * Returns    : none
  714. *********************************************************************************************************
  715. */
  716. #if OS_TASK_STAT_EN > 0
  717. static  void  OS_InitTaskStat (void)
  718. {
  719. #if OS_TASK_CREATE_EXT_EN > 0
  720.     #if OS_STK_GROWTH == 1
  721.     (void)OSTaskCreateExt(OS_TaskStat,
  722.                           (void *)0,                                   /* No args passed to OS_TaskStat()*/
  723.                           &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],   /* Set Top-Of-Stack               */
  724.                           OS_STAT_PRIO,                                /* One higher than the idle task  */
  725.                           OS_TASK_STAT_ID,
  726.                           &OSTaskStatStk[0],                           /* Set Bottom-Of-Stack            */
  727.                           OS_TASK_STAT_STK_SIZE,
  728.                           (void *)0,                                   /* No TCB extension               */
  729.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */
  730.     #else
  731.     (void)OSTaskCreateExt(OS_TaskStat,
  732.                           (void *)0,                                   /* No args passed to OS_TaskStat()*/
  733.                           &OSTaskStatStk[0],                           /* Set Top-Of-Stack               */
  734.                           OS_STAT_PRIO,                                /* One higher than the idle task  */
  735.                           OS_TASK_STAT_ID,
  736.                           &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],   /* Set Bottom-Of-Stack            */
  737.                           OS_TASK_STAT_STK_SIZE,
  738.                           (void *)0,                                   /* No TCB extension               */
  739.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */
  740.     #endif
  741. #else
  742.     #if OS_STK_GROWTH == 1
  743.     (void)OSTaskCreate(OS_TaskStat,
  744.                        (void *)0,                                      /* No args passed to OS_TaskStat()*/
  745.                        &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],      /* Set Top-Of-Stack               */
  746.                        OS_STAT_PRIO);                                  /* One higher than the idle task  */
  747.     #else
  748.     (void)OSTaskCreate(OS_TaskStat,
  749.                        (void *)0,                                      /* No args passed to OS_TaskStat()*/
  750.                        &OSTaskStatStk[0],                              /* Set Top-Of-Stack               */
  751.                        OS_STAT_PRIO);                                  /* One higher than the idle task  */
  752.     #endif
  753. #endif
  754. }
  755. #endif
  756. /*$PAGE*/
  757. /*
  758. *********************************************************************************************************
  759. *                                             INITIALIZATION
  760. *                            INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS
  761. *
  762. * Description: This function is called by OSInit() to initialize the free list of OS_TCBs.
  763. *
  764. * Arguments  : none
  765. *
  766. * Returns    : none
  767. *********************************************************************************************************
  768. */
  769. static  void  OS_InitTCBList (void)
  770. {
  771.     INT8U    i;
  772.     OS_TCB  *ptcb1;
  773.     OS_TCB  *ptcb2;
  774.     OSTCBList     = (OS_TCB *)0;                                 /* TCB Initialization                       */
  775.     for (i = 0; i < (OS_LOWEST_PRIO + 1); i++) {                 /* Clear the priority table                 */
  776.         OSTCBPrioTbl[i] = (OS_TCB *)0;
  777.     }
  778.     ptcb1 = &OSTCBTbl[0];
  779.     ptcb2 = &OSTCBTbl[1];
  780.     for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {  /* Init. list of free TCBs                  */
  781.         ptcb1->OSTCBNext = ptcb2;
  782.         ptcb1++;
  783.         ptcb2++;
  784.     }
  785.     ptcb1->OSTCBNext = (OS_TCB *)0;                              /* Last OS_TCB                              */
  786.     OSTCBFreeList    = &OSTCBTbl[0];
  787. }
  788. /*$PAGE*/
  789. /*
  790. *********************************************************************************************************
  791. *                                              SCHEDULER
  792. *
  793. * Description: This function is called by other uC/OS-II services to determine whether a new, high
  794. *              priority task has been made ready to run.  This function is invoked by TASK level code
  795. *              and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).
  796. *
  797. * Arguments  : none
  798. *
  799. * Returns    : none
  800. *
  801. * Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  802. *              2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
  803. *********************************************************************************************************
  804. */
  805. void  OS_Sched (void)
  806. {
  807. #if OS_CRITICAL_METHOD == 3                            /* Allocate storage for CPU status register     */
  808.     OS_CPU_SR  cpu_sr;
  809. #endif    
  810.     INT8U      y;
  811.     OS_ENTER_CRITICAL();
  812.     if ((OSIntNesting == 0) && (OSLockNesting == 0)) { /* Sched. only if all ISRs done & not locked    */
  813.         y             = OSUnMapTbl[OSRdyGrp];          /* Get pointer to HPT ready to run              */
  814.         OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
  815.         if (OSPrioHighRdy != OSPrioCur) {              /* No Ctx Sw if current task is highest rdy     */
  816.             OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
  817.             OSCtxSwCtr++;                              /* Increment context switch counter             */
  818.             OS_TASK_SW();                              /* Perform a context switch                     */
  819.         }
  820.     }
  821.     OS_EXIT_CRITICAL();
  822. }
  823. /*$PAGE*/
  824. /*
  825. *********************************************************************************************************
  826. *                                              IDLE TASK
  827. *
  828. * Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks
  829. *              executes because they are ALL waiting for event(s) to occur.
  830. *
  831. * Arguments  : none
  832. *
  833. * Returns    : none
  834. *
  835. * Note(s)    : 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be
  836. *                 enabled for at least a few instructions.  On some processors (ex. Philips XA), enabling
  837. *                 and then disabling interrupts didn't allow the processor enough time to have interrupts
  838. *                 enabled before they were disabled again.  uC/OS-II would thus never recognize
  839. *                 interrupts.
  840. *              2) This hook has been added to allow you to do such things as STOP the CPU to conserve 
  841. *                 power.
  842. *********************************************************************************************************
  843. */
  844. void  OS_TaskIdle (void *pdata)
  845. {
  846. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  847.     OS_CPU_SR  cpu_sr;
  848. #endif    
  849.     
  850.     
  851.     pdata = pdata;                               /* Prevent compiler warning for not using 'pdata'     */
  852.     for (;;) {
  853.         OS_ENTER_CRITICAL();
  854.         OSIdleCtr++;
  855.         OS_EXIT_CRITICAL();
  856.         OSTaskIdleHook();                        /* Call user definable HOOK                           */
  857.     }
  858. }
  859. /*$PAGE*/
  860. /*
  861. *********************************************************************************************************
  862. *                                            STATISTICS TASK
  863. *
  864. * Description: This task is internal to uC/OS-II and is used to compute some statistics about the
  865. *              multitasking environment.  Specifically, OS_TaskStat() computes the CPU usage.
  866. *              CPU usage is determined by:
  867. *
  868. *                                          OSIdleCtr
  869. *                 OSCPUUsage = 100 * (1 - ------------)     (units are in %)
  870. *                                         OSIdleCtrMax
  871. *
  872. * Arguments  : pdata     this pointer is not used at this time.
  873. *
  874. * Returns    : none
  875. *
  876. * Notes      : 1) This task runs at a priority level higher than the idle task.  In fact, it runs at the
  877. *                 next higher priority, OS_IDLE_PRIO-1.
  878. *              2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
  879. *              3) We delay for 5 seconds in the beginning to allow the system to reach steady state and
  880. *                 have all other tasks created before we do statistics.  You MUST have at least a delay
  881. *                 of 2 seconds to allow for the system to establish the maximum value for the idle
  882. *                 counter.
  883. *********************************************************************************************************
  884. */
  885. #if OS_TASK_STAT_EN > 0
  886. void  OS_TaskStat (void *pdata)
  887. {
  888. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  889.     OS_CPU_SR  cpu_sr;
  890. #endif    
  891.     INT32U     run;
  892.     INT32U     max;
  893.     INT8S      usage;
  894.     pdata = pdata;                               /* Prevent compiler warning for not using 'pdata'     */
  895.     while (OSStatRdy == FALSE) {
  896.         OSTimeDly(2 * OS_TICKS_PER_SEC);         /* Wait until statistic task is ready                 */
  897.     }
  898.     max = OSIdleCtrMax / 100L;
  899.     for (;;) {
  900.         OS_ENTER_CRITICAL();
  901.         OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
  902.         run          = OSIdleCtr;
  903.         OSIdleCtr    = 0L;                       /* Reset the idle counter for the next second         */
  904.         OS_EXIT_CRITICAL();
  905.         if (max > 0L) {
  906.             usage = (INT8S)(100L - run / max);
  907.             if (usage >= 0) {                    /* Make sure we don't have a negative percentage      */
  908.                 OSCPUUsage = usage;
  909.             } else {
  910.                 OSCPUUsage = 0;
  911.             }
  912.         } else {
  913.             OSCPUUsage = 0;
  914.             max        = OSIdleCtrMax / 100L;
  915.         }
  916.         OSTaskStatHook();                        /* Invoke user definable hook                         */
  917.         OSTimeDly(OS_TICKS_PER_SEC);             /* Accumulate OSIdleCtr for the next second           */
  918.     }
  919. }
  920. #endif
  921. /*$PAGE*/
  922. /*
  923. *********************************************************************************************************
  924. *                                            INITIALIZE TCB
  925. *
  926. * Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when
  927. *              a task is created (see OSTaskCreate() and OSTaskCreateExt()).
  928. *
  929. * Arguments  : prio          is the priority of the task being created
  930. *
  931. *              ptos          is a pointer to the task's top-of-stack assuming that the CPU registers
  932. *                            have been placed on the stack.  Note that the top-of-stack corresponds to a
  933. *                            'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory
  934. *                            location if OS_STK_GROWTH is set to 0.  Note that stack growth is CPU
  935. *                            specific.
  936. *
  937. *              pbos          is a pointer to the bottom of stack.  A NULL pointer is passed if called by
  938. *                            'OSTaskCreate()'.
  939. *
  940. *              id            is the task's ID (0..65535)
  941. *
  942. *              stk_size      is the size of the stack (in 'stack units').  If the stack units are INT8Us
  943. *                            then, 'stk_size' contains the number of bytes for the stack.  If the stack
  944. *                            units are INT32Us then, the stack contains '4 * stk_size' bytes.  The stack
  945. *                            units are established by the #define constant OS_STK which is CPU
  946. *                            specific.  'stk_size' is 0 if called by 'OSTaskCreate()'.
  947. *
  948. *              pext          is a pointer to a user supplied memory area that is used to extend the task
  949. *                            control block.  This allows you to store the contents of floating-point
  950. *                            registers, MMU registers or anything else you could find useful during a
  951. *                            context switch.  You can even assign a name to each task and store this name
  952. *                            in this TCB extension.  A NULL pointer is passed if called by OSTaskCreate().
  953. *
  954. *              opt           options as passed to 'OSTaskCreateExt()' or,
  955. *                            0 if called from 'OSTaskCreate()'.
  956. *
  957. * Returns    : OS_NO_ERR         if the call was successful
  958. *              OS_NO_MORE_TCB    if there are no more free TCBs to be allocated and thus, the task cannot
  959. *                                be created.
  960. *
  961. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  962. *********************************************************************************************************
  963. */
  964. INT8U  OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
  965. {
  966. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  967.     OS_CPU_SR  cpu_sr;
  968. #endif    
  969.     OS_TCB    *ptcb;
  970.     OS_ENTER_CRITICAL();
  971.     ptcb = OSTCBFreeList;                                  /* Get a free TCB from the free TCB list    */
  972.     if (ptcb != (OS_TCB *)0) {
  973.         OSTCBFreeList        = ptcb->OSTCBNext;            /* Update pointer to free TCB list          */
  974.         OS_EXIT_CRITICAL();
  975.         ptcb->OSTCBStkPtr    = ptos;                       /* Load Stack pointer in TCB                */
  976.         ptcb->OSTCBPrio      = (INT8U)prio;                /* Load task priority into TCB              */
  977.         ptcb->OSTCBStat      = OS_STAT_RDY;                /* Task is ready to run                     */
  978.         ptcb->OSTCBDly       = 0;                          /* Task is not delayed                      */
  979. #if OS_TASK_CREATE_EXT_EN > 0
  980.         ptcb->OSTCBExtPtr    = pext;                       /* Store pointer to TCB extension           */
  981.         ptcb->OSTCBStkSize   = stk_size;                   /* Store stack size                         */
  982.         ptcb->OSTCBStkBottom = pbos;                       /* Store pointer to bottom of stack         */
  983.         ptcb->OSTCBOpt       = opt;                        /* Store task options                       */
  984.         ptcb->OSTCBId        = id;                         /* Store task ID                            */
  985. #else
  986.         pext                 = pext;                       /* Prevent compiler warning if not used     */
  987.         stk_size             = stk_size;
  988.         pbos                 = pbos;
  989.         opt                  = opt;
  990.         id                   = id;
  991. #endif
  992. #if OS_TASK_DEL_EN > 0
  993.         ptcb->OSTCBDelReq    = OS_NO_ERR;
  994. #endif
  995.         ptcb->OSTCBY         = prio >> 3;                  /* Pre-compute X, Y, BitX and BitY          */
  996.         ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];
  997.         ptcb->OSTCBX         = prio & 0x07;
  998.         ptcb->OSTCBBitX      = OSMapTbl[ptcb->OSTCBX];
  999. #if OS_EVENT_EN > 0
  1000.         ptcb->OSTCBEventPtr  = (OS_EVENT *)0;              /* Task is not pending on an event          */
  1001. #endif
  1002. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
  1003.         ptcb->OSTCBFlagNode  = (OS_FLAG_NODE *)0;          /* Task is not pending on an event flag     */
  1004. #endif
  1005. #if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
  1006.         ptcb->OSTCBMsg       = (void *)0;                  /* No message received                      */
  1007. #endif
  1008. #if OS_VERSION >= 204
  1009.         OSTCBInitHook(ptcb);
  1010. #endif
  1011.         OSTaskCreateHook(ptcb);                            /* Call user defined hook                   */
  1012.         
  1013.         OS_ENTER_CRITICAL();
  1014.         OSTCBPrioTbl[prio] = ptcb;
  1015.         ptcb->OSTCBNext    = OSTCBList;                    /* Link into TCB chain                      */
  1016.         ptcb->OSTCBPrev    = (OS_TCB *)0;
  1017.         if (OSTCBList != (OS_TCB *)0) {
  1018.             OSTCBList->OSTCBPrev = ptcb;
  1019.         }
  1020.         OSTCBList               = ptcb;
  1021.         OSRdyGrp               |= ptcb->OSTCBBitY;         /* Make task ready to run                   */
  1022.         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  1023.         OS_EXIT_CRITICAL();
  1024.         return (OS_NO_ERR);
  1025.     }
  1026.     OS_EXIT_CRITICAL();
  1027.     return (OS_NO_MORE_TCB);
  1028. }