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

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                             CORE FUNCTIONS
  6. *
  7. *                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
  8. *                                           All Rights Reserved
  9. *
  10. *                                                  V2.00
  11. *
  12. * File : OS_CORE.C
  13. * By   : Jean J. Labrosse
  14. *********************************************************************************************************
  15. */
  16. #ifndef  OS_MASTER_FILE
  17. #define  OS_GLOBALS
  18. #include "includes.h"
  19. #endif
  20. /*
  21. *********************************************************************************************************
  22. *                                         LOCAL GLOBAL VARIABLES
  23. *********************************************************************************************************
  24. */
  25.                                        
  26. static  INT8U        OSIntExitY;               /* Variable used by 'OSIntExit' to prevent using locals */
  27. static  OS_STK       OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE];       /* Idle       task stack              */
  28. #if     OS_TASK_STAT_EN
  29. static  OS_STK       OSTaskStatStk[OS_TASK_STAT_STK_SIZE];      /* Statistics task stack               */
  30. #endif
  31. static  OS_TCB       OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];   /* Table of TCBs                       */
  32. /*$PAGE*/
  33. /*
  34. *********************************************************************************************************
  35. *                              MAPPING TABLE TO MAP BIT POSITION TO BIT MASK
  36. *
  37. * Note: Index into table is desired bit position, 0..7
  38. *       Indexed value corresponds to bit mask
  39. *********************************************************************************************************
  40. */
  41. INT8U const OSMapTbl[]   = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
  42. extern void Delay(int);
  43. /*
  44. *********************************************************************************************************
  45. *                                       PRIORITY RESOLUTION TABLE
  46. *
  47. * Note: Index into table is bit pattern to resolve highest priority
  48. *       Indexed value corresponds to highest priority bit position (i.e. 0..7)
  49. *********************************************************************************************************
  50. */
  51. INT8U const OSUnMapTbl[] = {
  52.     0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  53.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  54.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  55.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  56.     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  57.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  58.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  59.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  60.     7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  61.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  62.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  63.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  64.     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  65.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  66.     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  67.     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
  68. };
  69. /*$PAGE*/
  70. /*
  71. *********************************************************************************************************
  72. *                             MAKE TASK READY TO RUN BASED ON EVENT OCCURING
  73. *
  74. * Description: This function is called by other uC/OS-II services and is used to ready a task that was
  75. *              waiting for an event to occur.
  76. *
  77. * Arguments  : pevent    is a pointer to the event control block corresponding to the event.
  78. *
  79. *              msg       is a pointer to a message.  This pointer is used by message oriented services
  80. *                        such as MAILBOXEs and QUEUEs.  The pointer is not used when called by other
  81. *                        service functions.
  82. *
  83. *              msk       is a mask that is used to clear the status byte of the TCB.  For example,
  84. *                        OSSemPost() will pass OS_STAT_SEM, OSMboxPost() will pass OS_STAT_MBOX etc.
  85. *
  86. * Returns    : none
  87. *
  88. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  89. *********************************************************************************************************
  90. */
  91. #if  (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN || OS_SEM_EN
  92. void  OSEventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)
  93. {
  94.     OS_TCB *ptcb;
  95.     INT8U   x;
  96.     INT8U   y;
  97.     INT8U   bitx;
  98.     INT8U   bity;
  99.     INT8U   prio;
  100.     y    = OSUnMapTbl[pevent->OSEventGrp];            /* Find highest prio. task waiting for message   */
  101.     bity = OSMapTbl[y];
  102.     x    = OSUnMapTbl[pevent->OSEventTbl[y]];
  103.     bitx = OSMapTbl[x];
  104.     prio = (INT8U)((y << 3) + x);                     /* Find priority of task getting the msg         */
  105.     if ((pevent->OSEventTbl[y] &= ~bitx) == 0) {      /* Remove this task from the waiting list        */
  106.         pevent->OSEventGrp &= ~bity;
  107.     }
  108.     ptcb                 =  OSTCBPrioTbl[prio];       /* Point to this task's OS_TCB                   */
  109.     ptcb->OSTCBDly       =  0;                        /* Prevent OSTimeTick() from readying task       */
  110.     ptcb->OSTCBEventPtr  = (OS_EVENT *)0;             /* Unlink ECB from this task                     */
  111. #if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN
  112.     ptcb->OSTCBMsg       = msg;                       /* Send message directly to waiting task         */
  113. #else
  114.     msg                  = msg;                       /* Prevent compiler warning if not used          */    
  115. #endif    
  116.     ptcb->OSTCBStat     &= ~msk;                      /* Clear bit associated with event type          */
  117.     if (ptcb->OSTCBStat == OS_STAT_RDY) {             /* See if task is ready (could be susp'd)        */
  118.         OSRdyGrp        |=  bity;                     /* Put task in the ready to run list             */
  119.         OSRdyTbl[y]     |=  bitx;
  120.     }
  121. }
  122. #endif
  123. /*$PAGE*/
  124. /*
  125. *********************************************************************************************************
  126. *                                   MAKE TASK WAIT FOR EVENT TO OCCUR
  127. *
  128. * Description: This function is called by other uC/OS-II services to suspend a task because an event has
  129. *              not occurred.
  130. *
  131. * Arguments  : pevent   is a pointer to the event control block for which the task will be waiting for.
  132. *
  133. * Returns    : none
  134. *
  135. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  136. *********************************************************************************************************
  137. */
  138. #if  (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN || OS_SEM_EN
  139. void  OSEventTaskWait (OS_EVENT *pevent)
  140. {
  141.     OSTCBCur->OSTCBEventPtr = pevent;            /* Store pointer to event control block in TCB        */
  142.     if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {      /* Task no longer ready      */
  143.         OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
  144.     }
  145.     pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;          /* Put task in waiting list  */
  146.     pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
  147. }
  148. #endif
  149. /*$PAGE*/
  150. /*
  151. *********************************************************************************************************
  152. *                              MAKE TASK READY TO RUN BASED ON EVENT TIMEOUT
  153. *
  154. * Description: This function is called by other uC/OS-II services to make a task ready to run because a
  155. *              timeout occurred.
  156. *
  157. * Arguments  : pevent   is a pointer to the event control block which is readying a task.
  158. *
  159. * Returns    : none
  160. *
  161. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  162. *********************************************************************************************************
  163. */
  164. #if  (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN || OS_SEM_EN
  165. void  OSEventTO (OS_EVENT *pevent)
  166. {
  167.     if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {
  168.         pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
  169.     }
  170.     OSTCBCur->OSTCBStat     = OS_STAT_RDY;       /* Set status to ready                                */
  171.     OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;     /* No longer waiting for event                        */
  172. }
  173. #endif
  174. /*$PAGE*/
  175. /*
  176. *********************************************************************************************************
  177. *                                 INITIALIZE EVENT CONTROL BLOCK'S WAIT LIST
  178. *
  179. * Description: This function is called by other uC/OS-II services to initialize the event wait list.
  180. *
  181. * Arguments  : pevent    is a pointer to the event control block allocated to the event.
  182. *
  183. * Returns    : none
  184. *
  185. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  186. *********************************************************************************************************
  187. */
  188. #if  (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN || OS_SEM_EN
  189. void  OSEventWaitListInit (OS_EVENT *pevent)
  190. {
  191.     INT8U i;
  192.     
  193.     
  194.     pevent->OSEventGrp = 0x00;                   /* No task waiting on event                           */
  195.     for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
  196.         pevent->OSEventTbl[i] = 0x00;
  197.     }
  198. }
  199. #endif
  200. /*$PAGE*/
  201. /*
  202. *********************************************************************************************************
  203. *                                             INITIALIZATION
  204. *
  205. * Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to
  206. *              creating any uC/OS-II object and, prior to calling OSStart().
  207. *
  208. * Arguments  : none
  209. *
  210. * Returns    : none
  211. *********************************************************************************************************
  212. */
  213. void OSInit (void)
  214. {
  215.     INT16U i;
  216.     OSTime        = 0L;                                    /* Clear the 32-bit system clock            */
  217.     OSIntNesting  = 0;                                     /* Clear the interrupt nesting counter      */
  218.     OSLockNesting = 0;                                     /* Clear the scheduling lock counter        */
  219. #if OS_TASK_CREATE_EN  || OS_TASK_CREATE_EXT_EN || OS_TASK_DEL_EN
  220.     OSTaskCtr     = 0;                                     /* Clear the number of tasks                */
  221. #endif
  222.     OSRunning     = FALSE;                                 /* Indicate that multitasking not started   */
  223.     OSIdleCtr     = 0L;                                    /* Clear the 32-bit idle counter            */
  224. #if OS_TASK_STAT_EN && OS_TASK_CREATE_EXT_EN
  225.     OSIdleCtrRun  = 0L;
  226.     OSIdleCtrMax  = 0L;
  227.     OSStatRdy     = FALSE;                                 /* Statistic task is not ready              */
  228. #endif
  229.     OSCtxSwCtr    = 0;                                     /* Clear the context switch counter         */
  230.     OSRdyGrp      = 0;                                     /* Clear the ready list                     */
  231.     for (i = 0; i < OS_RDY_TBL_SIZE; i++) {
  232.         OSRdyTbl[i] = 0;
  233.     }
  234.                 
  235.     OSPrioCur     = 0;
  236.     OSPrioHighRdy = 0;                                           
  237.     OSTCBHighRdy  = (OS_TCB *)0;                                 /* TCB Initialization                 */
  238.     OSTCBCur      = (OS_TCB *)0;
  239.     OSTCBList     = (OS_TCB *)0;
  240.     for (i = 0; i < (OS_LOWEST_PRIO + 1); i++) {                 /* Clear the priority table           */
  241.         OSTCBPrioTbl[i] = (OS_TCB *)0;
  242.     }
  243.     for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {  /* Init. list of free TCBs            */
  244.         OSTCBTbl[i].OSTCBNext = &OSTCBTbl[i + 1];
  245.     }
  246.     OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS - 1].OSTCBNext = (OS_TCB *)0;    /* Last OS_TCB             */
  247.     OSTCBFreeList                                         = &OSTCBTbl[0];
  248. #if OS_MAX_EVENTS >= 2
  249.     for (i = 0; i < (OS_MAX_EVENTS - 1); i++) {            /* Init. list of free EVENT control blocks  */
  250.         OSEventTbl[i].OSEventPtr = (OS_EVENT *)&OSEventTbl[i + 1];
  251.     }
  252.     OSEventTbl[OS_MAX_EVENTS - 1].OSEventPtr = (OS_EVENT *)0;
  253.     OSEventFreeList                          = &OSEventTbl[0];    
  254. #endif
  255. #if OS_Q_EN && (OS_MAX_QS >= 2)
  256.     OSQInit();                                             /* Initialize the message queue structures  */
  257. #endif
  258. #if OS_MEM_EN && OS_MAX_MEM_PART >= 2
  259.     OSMemInit();                                           /* Initialize the memory manager            */
  260. #endif    
  261. #if OS_STK_GROWTH == 1
  262.     #if OS_TASK_CREATE_EXT_EN
  263.     OSTaskCreateExt(OSTaskIdle, 
  264.                     (void *)0,                                 /* No arguments passed to OSTaskIdle()  */
  265.                     &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Top-Of-Stack                     */
  266.                     OS_IDLE_PRIO,                              /* Lowest priority level                */
  267.                     OS_TASK_IDLE_ID,
  268.                     &OSTaskIdleStk[0],                         /* Set Bottom-Of-Stack                  */
  269.                     OS_TASK_IDLE_STK_SIZE, 
  270.                     (void *)0,                                 /* No TCB extension                     */
  271.                     OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
  272.     #else
  273.     OSTaskCreate(OSTaskIdle, (void *)0, &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], OS_IDLE_PRIO);
  274.     #endif
  275. #else
  276.     #if OS_TASK_CREATE_EXT_EN
  277.     OSTaskCreateExt(OSTaskIdle, 
  278.                     (void *)0,                                 /* No arguments passed to OSTaskIdle()  */
  279.                     &OSTaskIdleStk[0],                         /* Set Top-Of-Stack                     */
  280.                     OS_IDLE_PRIO,                              /* Lowest priority level                */
  281.                     OS_TASK_IDLE_ID,
  282.                     &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Bottom-Of-Stack                  */
  283.                     OS_TASK_IDLE_STK_SIZE, 
  284.                     (void *)0,                                 /* No TCB extension                     */
  285.                     OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
  286.     #else
  287.     OSTaskCreate(OSTaskIdle, (void *)0, &OSTaskIdleStk[0], OS_IDLE_PRIO);
  288.     #endif
  289. #endif
  290. #if OS_TASK_STAT_EN 
  291.     #if OS_TASK_CREATE_EXT_EN
  292.         #if OS_STK_GROWTH == 1
  293.         OSTaskCreateExt(OSTaskStat, 
  294.                         (void *)0,                                /* No args passed to OSTaskStat()    */
  295.                         &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],/* Set Top-Of-Stack                  */
  296.                         OS_STAT_PRIO,                             /* One higher than the idle task     */
  297.                         OS_TASK_STAT_ID,
  298.                         &OSTaskStatStk[0],                        /* Set Bottom-Of-Stack               */
  299.                         OS_TASK_STAT_STK_SIZE, 
  300.                         (void *)0,                                /* No TCB extension                  */
  301.                         OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */
  302.         #else
  303.         OSTaskCreateExt(OSTaskStat, 
  304.                         (void *)0,                                /* No args passed to OSTaskStat()    */
  305.                         &OSTaskStatStk[0],                        /* Set Top-Of-Stack                  */
  306.                         OS_STAT_PRIO,                             /* One higher than the idle task     */
  307.                         OS_TASK_STAT_ID,
  308.                         &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],/* Set Bottom-Of-Stack               */
  309.                         OS_TASK_STAT_STK_SIZE, 
  310.                         (void *)0,                                /* No TCB extension                  */
  311.                         OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */
  312.         #endif
  313.     #else
  314.         #if OS_STK_GROWTH == 1
  315.         OSTaskCreate(OSTaskStat, 
  316.                      (void *)0,                                   /* No args passed to OSTaskStat()    */
  317.                      &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],   /* Set Top-Of-Stack                  */
  318.                      OS_STAT_PRIO);                               /* One higher than the idle task     */
  319.         #else
  320.         OSTaskCreate(OSTaskStat, 
  321.                      (void *)0,                                   /* No args passed to OSTaskStat()    */
  322.                      &OSTaskStatStk[0],                           /* Set Top-Of-Stack                  */
  323.                      OS_STAT_PRIO);                               /* One higher than the idle task     */
  324.         #endif
  325.     #endif
  326. #endif
  327. }
  328. /*$PAGE*/
  329. /*
  330. *********************************************************************************************************
  331. *                                              ENTER ISR
  332. *
  333. * Description: This function is used to notify uC/OS-II that you are about to service an interrupt
  334. *              service routine (ISR).  This allows uC/OS-II to keep track of interrupt nesting and thus
  335. *              only perform rescheduling at the last nested ISR.
  336. *
  337. * Arguments  : none
  338. *
  339. * Returns    : none
  340. *
  341. * Notes      : 1) Your ISR can directly increment OSIntNesting without calling this function because 
  342. *                 OSIntNesting has been declared 'global'.  You MUST, however, be sure that the increment
  343. *                 is performed 'indivisibly' by your processor to ensure proper access to this critical
  344. *                 resource.
  345. *              2) You MUST still call OSIntExit() even though you increment OSIntNesting directly.
  346. *              3) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
  347. *                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
  348. *                 end of the ISR.
  349. *********************************************************************************************************
  350. */
  351. void OSIntEnter (void)
  352. {
  353.     OS_ENTER_CRITICAL();
  354.     OSIntNesting++;                              /* Increment ISR nesting level                        */
  355.     OS_EXIT_CRITICAL();
  356. }
  357. /*$PAGE*/
  358. /*
  359. *********************************************************************************************************
  360. *                                               EXIT ISR
  361. *
  362. * Description: This function is used to notify uC/OS-II that you have completed serviving an ISR.  When 
  363. *              the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether
  364. *              a new, high-priority task, is ready to run.
  365. *
  366. * Arguments  : none
  367. *
  368. * Returns    : none
  369. *
  370. * Notes      : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
  371. *                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
  372. *                 end of the ISR.
  373. *              2) Rescheduling is prevented when the scheduler is locked (see OSSchedLock())
  374. *********************************************************************************************************
  375. */
  376. void OSIntExit (void)
  377. {
  378.     OS_ENTER_CRITICAL();
  379.     if ((--OSIntNesting | OSLockNesting) == 0) { /* Reschedule only if all ISRs completed & not locked */
  380.         OSIntExitY    = OSUnMapTbl[OSRdyGrp];
  381.         OSPrioHighRdy = (INT8U)((OSIntExitY << 3) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]);
  382.         if (OSPrioHighRdy != OSPrioCur) {        /* No context switch if current task is highest ready */
  383.             OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];
  384.             OSCtxSwCtr++;                        /* Keep track of the number of context switches       */
  385.             OSIntCtxSw();                        /* Perform interrupt level context switch             */
  386.         }
  387.     }
  388.     OS_EXIT_CRITICAL();
  389. }
  390. /*$PAGE*/
  391. /*
  392. *********************************************************************************************************
  393. *                                              SCHEDULER
  394. *
  395. * Description: This function is called by other uC/OS-II services to determine whether a new, high
  396. *              priority task has been made ready to run.  This function is invoked by TASK level code
  397. *              and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).
  398. *
  399. * Arguments  : none
  400. *
  401. * Returns    : none
  402. *
  403. * Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  404. *              2) Rescheduling is prevented when the scheduler is locked (see OSSchedLock())
  405. *********************************************************************************************************
  406. */
  407. void OSSched (void)
  408. {
  409.     INT8U y;
  410.     OS_ENTER_CRITICAL();
  411.     if ((OSLockNesting | OSIntNesting) == 0) {   /* Task scheduling must be enabled and not ISR level  */
  412.         y             = OSUnMapTbl[OSRdyGrp];    /* Get pointer to highest priority task ready to run  */
  413.         OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
  414.         if (OSPrioHighRdy != OSPrioCur) {         /* No context switch if current task is highest ready */
  415.             OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
  416.             OSCtxSwCtr++;                        /* Increment context switch counter                   */
  417.             OS_TASK_SW();                        /* Perform a context switch                           */
  418.         }
  419.     }
  420.     OS_EXIT_CRITICAL();
  421. }
  422. /*$PAGE*/
  423. /*
  424. *********************************************************************************************************
  425. *                                          PREVENT SCHEDULING
  426. *
  427. * Description: This function is used to prevent rescheduling to take place.  This allows your application
  428. *              to prevent context switches until you are ready to permit context switching.
  429. *
  430. * Arguments  : none
  431. *
  432. * Returns    : none
  433. *
  434. * Notes      : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair.  In other words, for every 
  435. *                 call to OSSchedLock() you MUST have a call to OSSchedUnlock().
  436. *********************************************************************************************************
  437. */
  438. void OSSchedLock (void)
  439. {
  440.     if (OSRunning == TRUE) {                     /* Make sure multitasking is running                  */
  441.         OS_ENTER_CRITICAL();
  442.         OSLockNesting++;                         /* Increment lock nesting level                       */
  443.         OS_EXIT_CRITICAL();
  444.     }
  445. }
  446. /*$PAGE*/
  447. /*
  448. *********************************************************************************************************
  449. *                                          ENABLE SCHEDULING
  450. *
  451. * Description: This function is used to re-allow rescheduling.  
  452. *
  453. * Arguments  : none
  454. *
  455. * Returns    : none
  456. *
  457. * Notes      : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair.  In other words, for every 
  458. *                 call to OSSchedLock() you MUST have a call to OSSchedUnlock().
  459. *********************************************************************************************************
  460. */
  461. void OSSchedUnlock (void)
  462. {
  463.     if (OSRunning == TRUE) {                           /* Make sure multitasking is running            */
  464.         OS_ENTER_CRITICAL();
  465.         if (OSLockNesting > 0) {                       /* Do not decrement if already 0                */
  466.             OSLockNesting--;                           /* Decrement lock nesting level                 */
  467.             if ((OSLockNesting | OSIntNesting) == 0) { /* See if scheduling re-enabled and not an ISR  */
  468.                 OS_EXIT_CRITICAL();
  469.                 OSSched();                             /* See if a higher priority task is ready       */
  470.             } else {
  471.                 OS_EXIT_CRITICAL();
  472.             }
  473.         } else {
  474.             OS_EXIT_CRITICAL();
  475.         }
  476.     }
  477. }
  478. /*$PAGE*/
  479. /*
  480. *********************************************************************************************************
  481. *                                          START MULTITASKING
  482. *
  483. * Description: This function is used to start the multitasking process which lets uC/OS-II manages the
  484. *              task that you have created.  Before you can call OSStart(), you MUST have called OSInit()
  485. *              and you MUST have created at least one task.
  486. *
  487. * Arguments  : none
  488. *
  489. * Returns    : none
  490. *
  491. * Note       : OSStartHighRdy() MUST:
  492. *                 a) Call OSTaskSwHook() then,
  493. *                 b) Set OSRunning to TRUE.
  494. *********************************************************************************************************
  495. */
  496. void OSStart (void)
  497. {
  498.     INT8U y;
  499.     INT8U x;
  500.     if (OSRunning == FALSE) {
  501.         y             = OSUnMapTbl[OSRdyGrp];        /* Find highest priority's task priority number   */
  502.         x             = OSUnMapTbl[OSRdyTbl[y]];
  503.         OSPrioHighRdy = (INT8U)((y << 3) + x);
  504.         OSPrioCur     = OSPrioHighRdy;
  505.         OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run    */
  506.         OSTCBCur      = OSTCBHighRdy;
  507.         OSStartHighRdy();                            /* Execute target specific code to start task     */
  508.     }
  509. Delay(100);
  510. }
  511. /*$PAGE*/
  512. /*
  513. *********************************************************************************************************
  514. *                                        STATISTICS INITIALIZATION
  515. *
  516. * Description: This function is called by your application to establish CPU usage by first determining
  517. *              how high a 32-bit counter would count to in 1 second if no other tasks were to execute
  518. *              during that time.  CPU usage is then determined by a low priority task which keeps track
  519. *              of this 32-bit counter every second but this time, with other tasks running.  CPU usage is
  520. *              determined by:
  521. *
  522. *                                             OSIdleCtr
  523. *                 CPU Usage (%) = 100 * (1 - ------------)
  524. *                                            OSIdleCtrMax
  525. *
  526. * Arguments  : none
  527. *
  528. * Returns    : none
  529. *********************************************************************************************************
  530. */
  531. #if OS_TASK_STAT_EN
  532. void OSStatInit (void)
  533. {
  534.     OSTimeDly(2);                                /* Synchronize with clock tick                        */
  535.     OS_ENTER_CRITICAL();
  536.     OSIdleCtr    = 0L;                           /* Clear idle counter                                 */
  537.     OS_EXIT_CRITICAL();
  538.     OSTimeDly(OS_TICKS_PER_SEC);                 /* Determine MAX. idle counter value for 1 second     */
  539.     OS_ENTER_CRITICAL();
  540.     OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1 second       */
  541.     OSStatRdy    = TRUE;
  542.     OS_EXIT_CRITICAL();
  543. }
  544. #endif
  545. /*$PAGE*/
  546. /*
  547. *********************************************************************************************************
  548. *                                              IDLE TASK
  549. *
  550. * Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks
  551. *              executes because they are waiting for event(s) to occur.
  552. *
  553. * Arguments  : none
  554. *
  555. * Returns    : none
  556. *********************************************************************************************************
  557. */
  558. void OSTaskIdle (void *pdata)
  559. {
  560.     pdata = pdata;                               /* Prevent compiler warning for not using 'pdata'     */
  561.     for (;;) {
  562.         OS_ENTER_CRITICAL();
  563.         OSIdleCtr++;
  564.         OS_EXIT_CRITICAL();
  565.     }
  566. }
  567. /*$PAGE*/
  568. /*
  569. *********************************************************************************************************
  570. *                                            STATISTICS TASK
  571. *
  572. * Description: This task is internal to uC/OS-II and is used to compute some statistics about the
  573. *              multitasking environment.  Specifically, OSTaskStat() computes the CPU usage.
  574. *              CPU usage is determined by:
  575. *
  576. *                                          OSIdleCtr
  577. *                 OSCPUUsage = 100 * (1 - ------------)     (units are in %)
  578. *                                         OSIdleCtrMax
  579. *
  580. * Arguments  : pdata     this pointer is not used at this time.
  581. *
  582. * Returns    : none
  583. *
  584. * Notes      : 1) This task runs at a priority level higher than the idle task.  In fact, it runs at the
  585. *                 next higher priority, OS_IDLE_PRIO-1.
  586. *              2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
  587. *              3) We delay for 5 seconds in the beginning to allow the system to reach steady state and
  588. *                 have all other tasks created before we do statistics.  You MUST have at least a delay
  589. *                 of 2 seconds to allow for the system to establish the maximum value for the idle 
  590. *                 counter.
  591. *********************************************************************************************************
  592. */
  593. #if OS_TASK_STAT_EN
  594. void OSTaskStat (void *pdata)
  595. {
  596.     INT32U run;
  597.     INT8S  usage;
  598.     
  599.     
  600.     pdata = pdata;                               /* Prevent compiler warning for not using 'pdata'     */
  601.     while (OSStatRdy == FALSE) {
  602.         OSTimeDly(2 * OS_TICKS_PER_SEC);             /* Wait until statistic task is ready                 */
  603.     }
  604.     for (;;) {
  605.         OS_ENTER_CRITICAL();
  606.         OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
  607.         run          = OSIdleCtr;
  608.         OSIdleCtr    = 0L;                       /* Reset the idle counter for the next second         */
  609.         OS_EXIT_CRITICAL();
  610.         if (OSIdleCtrMax > 0L) {
  611.             usage = (INT8S)(100L - 100L * run / OSIdleCtrMax);
  612.             if (usage > 100) {
  613.                 OSCPUUsage = 100;
  614.             } else if (usage < 0) {
  615.                 OSCPUUsage =   0;
  616.             } else {
  617.                 OSCPUUsage = usage;
  618.             }
  619.         } else {
  620.             OSCPUUsage = 0;
  621.         }
  622.         OSTaskStatHook();                        /* Invoke user definable hook                         */
  623.         OSTimeDly(OS_TICKS_PER_SEC);             /* Accumulate OSIdleCtr for the next second           */
  624.     }
  625. }
  626. #endif
  627. /*$PAGE*/
  628. /*
  629. *********************************************************************************************************
  630. *                                            INITIALIZE TCB
  631. *
  632. * Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when
  633. *              a task is created (see OSTaskCreate() and OSTaskCreateExt()).
  634. *
  635. * Arguments  : prio          is the priority of the task being created
  636. *
  637. *              ptos          is a pointer to the task's top-of-stack assuming that the CPU registers
  638. *                            have been placed on the stack.  Note that the top-of-stack corresponds to a 
  639. *                            'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory
  640. *                            location if OS_STK_GROWTH is set to 0.  Note that stack growth is CPU
  641. *                            specific.
  642. *
  643. *              pbos          is a pointer to the bottom of stack.  A NULL pointer is passed if called by
  644. *                            'OSTaskCreate()'.
  645. *
  646. *              id            is the task's ID (0..65535)
  647. *
  648. *              stk_size      is the size of the stack (in 'stack units').  If the stack units are INT8Us
  649. *                            then, 'stk_size' contains the number of bytes for the stack.  If the stack
  650. *                            units are INT32Us then, the stack contains '4 * stk_size' bytes.  The stack
  651. *                            units are established by the #define constant OS_STK which is CPU
  652. *                            specific.  'stk_size' is 0 if called by 'OSTaskCreate()'.
  653. *
  654. *              pext          is a pointer to a user supplied memory area that is used to extend the task
  655. *                            control block.  This allows you to store the contents of floating-point
  656. *                            registers, MMU registers or anything else you could find useful during a 
  657. *                            context switch.  You can even assign a name to each task and store this name
  658. *                            in this TCB extension.  A NULL pointer is passed if called by OSTaskCreate().
  659. *
  660. *              opt           options as passed to 'OSTaskCreateExt()' or, 
  661. *                            0 if called from 'OSTaskCreate()'.
  662. *
  663. * Returns    : OS_NO_ERR         if the call was successful
  664. *              OS_NO_MORE_TCB    if there are no more free TCBs to be allocated and thus, the task cannot
  665. *                                be created.
  666. *
  667. * Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
  668. *********************************************************************************************************
  669. */
  670. INT8U OSTCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT16U stk_size, void *pext, INT16U opt)
  671. {
  672.     OS_TCB *ptcb;
  673.     OS_ENTER_CRITICAL();
  674.     ptcb = OSTCBFreeList;                                  /* Get a free TCB from the free TCB list    */
  675.     if (ptcb != (OS_TCB *)0) {
  676.         OSTCBFreeList        = ptcb->OSTCBNext;            /* Update pointer to free TCB list          */
  677.         OS_EXIT_CRITICAL();
  678.         ptcb->OSTCBStkPtr    = ptos;                       /* Load Stack pointer in TCB                */
  679.         ptcb->OSTCBPrio      = (INT8U)prio;                /* Load task priority into TCB              */
  680.         ptcb->OSTCBStat      = OS_STAT_RDY;                /* Task is ready to run                     */
  681.         ptcb->OSTCBDly       = 0;                          /* Task is not delayed                      */
  682. #if OS_TASK_CREATE_EXT_EN        
  683.         ptcb->OSTCBExtPtr    = pext;                       /* Store pointer to TCB extension           */
  684.         ptcb->OSTCBStkSize   = stk_size;                   /* Store stack size                         */
  685.         ptcb->OSTCBStkBottom = pbos;                       /* Store pointer to bottom of stack         */
  686.         ptcb->OSTCBOpt       = opt;                        /* Store task options                       */
  687.         ptcb->OSTCBId        = id;                         /* Store task ID                            */
  688. #else
  689.         pext                 = pext;                       /* Prevent compiler warning if not used     */
  690.         stk_size             = stk_size;
  691.         pbos                 = pbos;
  692.         opt                  = opt;
  693.         id                   = id;
  694. #endif
  695. #if OS_TASK_DEL_EN        
  696.         ptcb->OSTCBDelReq    = OS_NO_ERR;
  697. #endif
  698.         ptcb->OSTCBY         = prio >> 3;                  /* Pre-compute X, Y, BitX and BitY          */
  699.         ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];
  700.         ptcb->OSTCBX         = prio & 0x07;
  701.         ptcb->OSTCBBitX      = OSMapTbl[ptcb->OSTCBX];
  702. #if     OS_MBOX_EN || (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_SEM_EN
  703.         ptcb->OSTCBEventPtr  = (OS_EVENT *)0;              /* Task is not pending on an event          */
  704. #endif
  705. #if     OS_MBOX_EN || (OS_Q_EN && (OS_MAX_QS >= 2))
  706.         ptcb->OSTCBMsg       = (void *)0;                  /* No message received                      */
  707. #endif
  708.         OS_ENTER_CRITICAL();
  709.         OSTCBPrioTbl[prio]   = ptcb;
  710.         ptcb->OSTCBNext      = OSTCBList;                  /* Link into TCB chain                      */
  711.         ptcb->OSTCBPrev      = (OS_TCB *)0;
  712.         if (OSTCBList != (OS_TCB *)0) {
  713.             OSTCBList->OSTCBPrev = ptcb;
  714.         }
  715.         OSTCBList               = ptcb;
  716.         OSRdyGrp               |= ptcb->OSTCBBitY;         /* Make task ready to run                   */
  717.         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  718.         OS_EXIT_CRITICAL();
  719.         return (OS_NO_ERR);
  720.     } else {
  721.         OS_EXIT_CRITICAL();
  722.         return (OS_NO_MORE_TCB);
  723.     }
  724. }
  725. /*$PAGE*/
  726. /*
  727. *********************************************************************************************************
  728. *                                         PROCESS SYSTEM TICK
  729. *
  730. * Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
  731. *              as a 'clock tick').  This function should be called by the ticker ISR but, can also be
  732. *              called by a high priority task.
  733. *
  734. * Arguments  : none
  735. *
  736. * Returns    : none
  737. *********************************************************************************************************
  738. */
  739. void OSTimeTick (void)
  740. {
  741.     OS_TCB *ptcb;
  742.     OSTimeTickHook();                                      /* Call user definable hook                 */
  743.     ptcb = OSTCBList;                                      /* Point at first TCB in TCB list           */
  744.     while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {              /* Go through all TCBs in TCB list          */
  745.         OS_ENTER_CRITICAL();
  746.         if (ptcb->OSTCBDly != 0) {                         /* Delayed or waiting for event with TO     */
  747.             if (--ptcb->OSTCBDly == 0) {                   /* Decrement nbr of ticks to end of delay   */
  748.                 if (!(ptcb->OSTCBStat & OS_STAT_SUSPEND)) {    /* Is task suspended?                   */
  749.                     OSRdyGrp               |= ptcb->OSTCBBitY; /* No,  Make task Rdy to Run (timed out)*/
  750.                     OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  751.                 } else {                                       /* Yes, Leave 1 tick to prevent ...     */
  752.                     ptcb->OSTCBDly = 1;                        /* ... loosing the task when the ...    */
  753.                 }                                              /* ... suspension is removed.           */
  754.             }
  755.         }
  756.         ptcb = ptcb->OSTCBNext;                            /* Point at next TCB in TCB list            */
  757.         OS_EXIT_CRITICAL();
  758.     }
  759.     OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter           */
  760.     OSTime++;
  761.     OS_EXIT_CRITICAL();
  762. }
  763. /*$PAGE*/
  764. /*
  765. *********************************************************************************************************
  766. *                                             GET VERSION
  767. *
  768. * Description: This function is used to return the version number of uC/OS-II.  The returned value
  769. *              corresponds to uC/OS-II's version number multiplied by 100.  In other words, version 2.00
  770. *              would be returned as 200.
  771. *
  772. * Arguments  : none
  773. *
  774. * Returns    : the version number of uC/OS-II multiplied by 100.
  775. *********************************************************************************************************
  776. */
  777. INT16U OSVersion (void)
  778. {
  779.     return (OS_VERSION);
  780. }