os_core.c
上传用户:yyyd609
上传日期:2022-07-18
资源大小:183k
文件大小:67k
源码类别:

微处理器开发

开发平台:

C/C++

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