OS_CORE.C
Upload User: dsfgsdff
Upload Date: 2022-07-10
Package Size: 319k
Code Size: 49k
Development Platform:

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