os_core.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. /*
  2. * Copyright (c) 2021, Meco Jianting Man <jiantingman@foxmail.com>
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-09-18 Meco Man first version
  9. */
  10. /*
  11. *********************************************************************************************************
  12. * uC/OS-II
  13. * The Real-Time Kernel
  14. *
  15. * Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com
  16. *
  17. * SPDX-License-Identifier: APACHE-2.0
  18. *
  19. * This software is subject to an open source license and is distributed by
  20. * Silicon Laboratories Inc. pursuant to the terms of the Apache License,
  21. * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
  22. *
  23. *********************************************************************************************************
  24. */
  25. /*
  26. *********************************************************************************************************
  27. *
  28. * CORE FUNCTIONS
  29. *
  30. * Filename : os_core.c
  31. * Version : V2.93.00
  32. *********************************************************************************************************
  33. */
  34. #define OS_GLOBALS
  35. #include "ucos_ii.h"
  36. /*
  37. *********************************************************************************************************
  38. * FUNCTION PROTOTYPES
  39. *********************************************************************************************************
  40. */
  41. /*
  42. *********************************************************************************************************
  43. * INITIALIZATION
  44. * INITIALIZE MISCELLANEOUS VARIABLES
  45. *
  46. * Description: This function is called by OSInit() to initialize miscellaneous variables.
  47. *
  48. * Arguments : none
  49. *
  50. * Returns : none
  51. *********************************************************************************************************
  52. */
  53. static void OS_InitMisc (void)
  54. {
  55. OSTaskCtr = 0u; /* Clear the number of tasks */
  56. OSRunning = OS_TRUE; /* 初始化时,rt-thread已经启动因此直接为OS_TRUE*/
  57. #if OS_TASK_STAT_EN > 0u
  58. OSIdleCtrRun = 0uL;
  59. OSIdleCtrMax = 0uL;
  60. OSStatRdy = OS_FALSE; /* Statistic task is not ready */
  61. #endif
  62. #ifdef OS_SAFETY_CRITICAL_IEC61508
  63. OSSafetyCriticalStartFlag = OS_FALSE; /* Still allow creation of objects */
  64. #endif
  65. #if OS_TASK_REG_TBL_SIZE > 0u
  66. OSTaskRegNextAvailID = 0u; /* Initialize the task register ID */
  67. #endif
  68. }
  69. /*
  70. *********************************************************************************************************
  71. * INITIALIZATION
  72. * INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS
  73. *
  74. * Description: This function is called by OSInit() to initialize the free list of OS_TCBs.
  75. *
  76. * Arguments : none
  77. *
  78. * Returns : none
  79. *********************************************************************************************************
  80. */
  81. static void OS_InitTCBList (void)
  82. {
  83. INT8U ix;
  84. INT8U ix_next;
  85. OS_TCB *ptcb1;
  86. OS_TCB *ptcb2;
  87. OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); /* Clear the priority table */
  88. OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl)); /* Clear all the TCBs */
  89. for (ix = 0u; ix < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u); ix++) { /* Init. list of free TCBs */
  90. ix_next = ix + 1u;
  91. ptcb1 = &OSTCBTbl[ix];
  92. ptcb2 = &OSTCBTbl[ix_next];
  93. ptcb1->OSTCBNext = ptcb2;
  94. #if OS_TASK_NAME_EN > 0u
  95. ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; /* Unknown name */
  96. #endif
  97. }
  98. ptcb1 = &OSTCBTbl[ix];
  99. ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */
  100. #if OS_TASK_NAME_EN > 0u
  101. ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; /* Unknown name */
  102. #endif
  103. OSTCBList = (OS_TCB *)0; /* TCB lists initializations */
  104. OSTCBFreeList = &OSTCBTbl[0];
  105. OSTCBPrioTbl[OS_MAX_TASKS + OS_N_SYS_TASKS - 1u] = OS_TCB_RESERVED; /* 空闲任务标记为已经使用 */
  106. }
  107. #if OS_TASK_STAT_EN > 0u
  108. /*
  109. *********************************************************************************************************
  110. * INITIALIZATION
  111. * CREATING THE IDLE TASK
  112. *
  113. * Description: This function creates the Idle Task.
  114. *
  115. * Arguments : none
  116. *
  117. * Returns : none
  118. *********************************************************************************************************
  119. */
  120. static void OS_InitTaskIdle (void)
  121. {
  122. rt_thread_idle_sethook(OS_TaskIdle); /*向RTT注册μCOS-III兼容层空闲任务(实则为回调函数) */
  123. }
  124. #endif
  125. /*
  126. *********************************************************************************************************
  127. * INITIALIZATION
  128. * CREATING THE STATISTIC TASK
  129. *
  130. * Description: This function creates the Statistic Task.
  131. *
  132. * Arguments : none
  133. *
  134. * Returns : none
  135. *********************************************************************************************************
  136. */
  137. #if OS_TASK_STAT_EN > 0u
  138. static void OS_InitTaskStat (void)
  139. {
  140. #if OS_TASK_NAME_EN > 0u
  141. INT8U err;
  142. #endif
  143. #if OS_TASK_CREATE_EXT_EN > 0u
  144. #if OS_STK_GROWTH == 1u
  145. (void)OSTaskCreateExt(OS_TaskStat,
  146. (void *)0, /* No args passed to OS_TaskStat()*/
  147. &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Top-Of-Stack */
  148. OS_TASK_STAT_PRIO, /* One higher than the idle task */
  149. OS_TASK_STAT_ID,
  150. &OSTaskStatStk[0], /* Set Bottom-Of-Stack */
  151. OS_TASK_STAT_STK_SIZE,
  152. (void *)0, /* No TCB extension */
  153. OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */
  154. #else
  155. (void)OSTaskCreateExt(OS_TaskStat,
  156. (void *)0, /* No args passed to OS_TaskStat()*/
  157. &OSTaskStatStk[0], /* Set Top-Of-Stack */
  158. OS_TASK_STAT_PRIO, /* One higher than the idle task */
  159. OS_TASK_STAT_ID,
  160. &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Bottom-Of-Stack */
  161. OS_TASK_STAT_STK_SIZE,
  162. (void *)0, /* No TCB extension */
  163. OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */
  164. #endif
  165. #else
  166. #if OS_STK_GROWTH == 1u
  167. (void)OSTaskCreate(OS_TaskStat,
  168. (void *)0, /* No args passed to OS_TaskStat()*/
  169. &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Top-Of-Stack */
  170. OS_TASK_STAT_PRIO); /* One higher than the idle task */
  171. #else
  172. (void)OSTaskCreate(OS_TaskStat,
  173. (void *)0, /* No args passed to OS_TaskStat()*/
  174. &OSTaskStatStk[0], /* Set Top-Of-Stack */
  175. OS_TASK_STAT_PRIO); /* One higher than the idle task */
  176. #endif
  177. #endif
  178. #if OS_TASK_NAME_EN > 0u
  179. OSTaskNameSet(OS_TASK_STAT_PRIO, (INT8U *)(void *)"uC/OS-II Stat", &err);
  180. #endif
  181. }
  182. #endif
  183. /*
  184. *********************************************************************************************************
  185. * INITIALIZATION
  186. *
  187. * Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to
  188. * creating any uC/OS-II object and, prior to calling OSStart().
  189. *
  190. * Arguments : none
  191. *
  192. * Returns : none
  193. *********************************************************************************************************
  194. */
  195. void OSInit (void)
  196. {
  197. #if OS_TASK_CREATE_EXT_EN > 0u
  198. #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
  199. INT8U err;
  200. #endif
  201. #endif
  202. OSSchedLock();
  203. #if OS_CPU_HOOKS_EN > 0u
  204. OSInitHookBegin(); /* Call port specific initialization code */
  205. #endif
  206. OS_InitMisc(); /* Initialize miscellaneous variables */
  207. OS_InitTCBList(); /* Initialize the free list of OS_TCBs */
  208. #if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
  209. OS_MemInit(); /* Initialize the memory manager */
  210. #endif
  211. #if OS_TASK_STAT_EN > 0u
  212. OS_InitTaskIdle(); /* Create the Idle Task */
  213. OS_InitTaskStat(); /* Create the Statistic Task */
  214. #endif
  215. #if OS_CPU_HOOKS_EN > 0u
  216. OSInitHookEnd(); /* Call port specific init. code */
  217. #endif
  218. OSSchedUnlock();
  219. }
  220. /*
  221. *********************************************************************************************************
  222. * ENTER ISR
  223. *
  224. * Description: This function is used to notify uC/OS-II that you are about to service an interrupt
  225. * service routine (ISR). This allows uC/OS-II to keep track of interrupt nesting and thus
  226. * only perform rescheduling at the last nested ISR.
  227. *
  228. * Arguments : none
  229. *
  230. * Returns : none
  231. *
  232. * Notes : 1) This function should be called with interrupts already disabled
  233. * 2) Your ISR can directly increment OSIntNesting without calling this function because
  234. * OSIntNesting has been declared 'global'.
  235. * 3) You MUST still call OSIntExit() even though you increment OSIntNesting directly.
  236. * 4) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call
  237. * to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
  238. * end of the ISR.
  239. * 5) You are allowed to nest interrupts up to 255 levels deep.
  240. * 6) I removed the OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() around the increment because
  241. * OSIntEnter() is always called with interrupts disabled.
  242. *********************************************************************************************************
  243. */
  244. void OSIntEnter (void)
  245. {
  246. if (OSRunning == OS_TRUE) {
  247. rt_interrupt_enter();
  248. }
  249. }
  250. /*
  251. *********************************************************************************************************
  252. * EXIT ISR
  253. *
  254. * Description: This function is used to notify uC/OS-II that you have completed servicing an ISR. When
  255. * the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether
  256. * a new, high-priority task, is ready to run.
  257. *
  258. * Arguments : none
  259. *
  260. * Returns : none
  261. *
  262. * Notes : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call
  263. * to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
  264. * end of the ISR.
  265. * 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
  266. *********************************************************************************************************
  267. */
  268. void OSIntExit (void)
  269. {
  270. if (OSRunning == OS_TRUE) {
  271. rt_interrupt_leave();
  272. }
  273. }
  274. /*
  275. *********************************************************************************************************
  276. * INDICATE THAT IT'S NO LONGER SAFE TO CREATE OBJECTS
  277. *
  278. * Description: This function is called by the application code to indicate that all initialization has
  279. * been completed and that kernel objects are no longer allowed to be created.
  280. *
  281. * Arguments : none
  282. *
  283. * Returns : none
  284. *
  285. * Note(s) : 1) You should call this function when you no longer want to allow application code to
  286. * create kernel objects.
  287. * 2) You need to define the macro 'OS_SAFETY_CRITICAL_IEC61508'
  288. *********************************************************************************************************
  289. */
  290. #ifdef OS_SAFETY_CRITICAL_IEC61508
  291. void OSSafetyCriticalStart (void)
  292. {
  293. OSSafetyCriticalStartFlag = OS_TRUE;
  294. }
  295. #endif
  296. /*
  297. *********************************************************************************************************
  298. * PREVENT SCHEDULING
  299. *
  300. * Description: This function is used to prevent rescheduling to take place. This allows your application
  301. * to prevent context switches until you are ready to permit context switching.
  302. *
  303. * Arguments : none
  304. *
  305. * Returns : none
  306. *
  307. * Notes : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair. In other words, for every
  308. * call to OSSchedLock() you MUST have a call to OSSchedUnlock().
  309. *********************************************************************************************************
  310. */
  311. #if OS_SCHED_LOCK_EN > 0u
  312. void OSSchedLock (void)
  313. {
  314. if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */
  315. rt_enter_critical();
  316. }
  317. }
  318. #endif
  319. /*
  320. *********************************************************************************************************
  321. * ENABLE SCHEDULING
  322. *
  323. * Description: This function is used to re-allow rescheduling.
  324. *
  325. * Arguments : none
  326. *
  327. * Returns : none
  328. *
  329. * Notes : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair. In other words, for every
  330. * call to OSSchedLock() you MUST have a call to OSSchedUnlock().
  331. *********************************************************************************************************
  332. */
  333. #if OS_SCHED_LOCK_EN > 0u
  334. void OSSchedUnlock (void)
  335. {
  336. if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */
  337. rt_exit_critical();
  338. }
  339. }
  340. #endif
  341. /*
  342. *********************************************************************************************************
  343. * START MULTITASKING
  344. *
  345. * Description: This function is used to start the multitasking process which lets uC/OS-II manages the
  346. * task that you have created. Before you can call OSStart(), you MUST have called OSInit()
  347. * and you MUST have created at least one task.
  348. *
  349. * Arguments : none
  350. *
  351. * Returns : none
  352. *
  353. * Note : OSStartHighRdy() MUST:
  354. * a) Call OSTaskSwHook() then,
  355. * b) Set OSRunning to OS_TRUE.
  356. * c) Load the context of the task pointed to by OSTCBHighRdy.
  357. * d_ Execute the task.
  358. *********************************************************************************************************
  359. */
  360. void OSStart (void)
  361. {
  362. /*do nothing*/
  363. }
  364. /*
  365. *********************************************************************************************************
  366. * STATISTICS INITIALIZATION
  367. *
  368. * Description: This function is called by your application to establish CPU usage by first determining
  369. * how high a 32-bit counter would count to in 1 second if no other tasks were to execute
  370. * during that time. CPU usage is then determined by a low priority task which keeps track
  371. * of this 32-bit counter every second but this time, with other tasks running. CPU usage is
  372. * determined by:
  373. *
  374. * OSIdleCtr
  375. * CPU Usage (%) = 100 * (1 - ------------)
  376. * OSIdleCtrMax
  377. *
  378. * Arguments : none
  379. *
  380. * Returns : none
  381. *********************************************************************************************************
  382. */
  383. #if OS_TASK_STAT_EN > 0u
  384. void OSStatInit (void)
  385. {
  386. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  387. OS_CPU_SR cpu_sr = 0u;
  388. #endif
  389. OSTimeDly(2u); /* Synchronize with clock tick */
  390. OS_ENTER_CRITICAL();
  391. OSIdleCtr = 0uL; /* Clear idle counter */
  392. OS_EXIT_CRITICAL();
  393. OSTimeDly(OS_TICKS_PER_SEC / 10u); /* Determine MAX. idle counter value for 1/10 second */
  394. OS_ENTER_CRITICAL();
  395. OSIdleCtrMax = OSIdleCtr; /* Store maximum idle counter count in 1/10 second */
  396. OSStatRdy = OS_TRUE;
  397. OS_EXIT_CRITICAL();
  398. }
  399. #endif
  400. /*
  401. *********************************************************************************************************
  402. * PROCESS SYSTEM TICK
  403. *
  404. * Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
  405. * as a 'clock tick'). This function should be called by the ticker ISR but, can also be
  406. * called by a high priority task.
  407. *
  408. * Arguments : none
  409. *
  410. * Returns : none
  411. *********************************************************************************************************
  412. */
  413. void OSTimeTick (void)
  414. {
  415. rt_tick_increase();
  416. }
  417. /*
  418. *********************************************************************************************************
  419. * GET VERSION
  420. *
  421. * Description: This function is used to return the version number of uC/OS-II. The returned value
  422. * corresponds to uC/OS-II's version number multiplied by 10000. In other words, version
  423. * 2.01.00 would be returned as 20100.
  424. *
  425. * Arguments : none
  426. *
  427. * Returns : The version number of uC/OS-II multiplied by 10000.
  428. *********************************************************************************************************
  429. */
  430. INT16U OSVersion (void)
  431. {
  432. return (OS_VERSION);
  433. }
  434. /*
  435. *********************************************************************************************************
  436. * CLEAR A SECTION OF MEMORY
  437. *
  438. * Description: This function is called by other uC/OS-II services to clear a contiguous block of RAM.
  439. *
  440. * Arguments : pdest is the start of the RAM to clear (i.e. write 0x00 to)
  441. *
  442. * size is the number of bytes to clear.
  443. *
  444. * Returns : none
  445. *
  446. * Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  447. * 2) Note that we can only clear up to 64K bytes of RAM. This is not an issue because none
  448. * of the uses of this function gets close to this limit.
  449. * 3) The clear is done one byte at a time since this will work on any processor irrespective
  450. * of the alignment of the destination.
  451. *********************************************************************************************************
  452. */
  453. void OS_MemClr (INT8U *pdest,
  454. INT16U size)
  455. {
  456. while (size > 0u) {
  457. *pdest++ = (INT8U)0;
  458. size--;
  459. }
  460. }
  461. /*
  462. *********************************************************************************************************
  463. * COPY A BLOCK OF MEMORY
  464. *
  465. * Description: This function is called by other uC/OS-II services to copy a block of memory from one
  466. * location to another.
  467. *
  468. * Arguments : pdest is a pointer to the 'destination' memory block
  469. *
  470. * psrc is a pointer to the 'source' memory block
  471. *
  472. * size is the number of bytes to copy.
  473. *
  474. * Returns : none
  475. *
  476. * Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. There is
  477. * no provision to handle overlapping memory copy. However, that's not a problem since this
  478. * is not a situation that will happen.
  479. * 2) Note that we can only copy up to 64K bytes of RAM
  480. * 3) The copy is done one byte at a time since this will work on any processor irrespective
  481. * of the alignment of the source and destination.
  482. *********************************************************************************************************
  483. */
  484. void OS_MemCopy (INT8U *pdest,
  485. INT8U *psrc,
  486. INT16U size)
  487. {
  488. rt_memcpy(pdest,psrc,size);
  489. }
  490. /*
  491. *********************************************************************************************************
  492. * DETERMINE THE LENGTH OF AN ASCII STRING
  493. *
  494. * Description: This function is called by other uC/OS-II services to determine the size of an ASCII string
  495. * (excluding the NUL character).
  496. *
  497. * Arguments : psrc is a pointer to the string for which we need to know the size.
  498. *
  499. * Returns : The size of the string (excluding the NUL terminating character)
  500. *
  501. * Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  502. * 2) The string to check must be less than 255 characters long.
  503. *********************************************************************************************************
  504. */
  505. #if (OS_EVENT_NAME_EN > 0u) || (OS_FLAG_NAME_EN > 0u) || (OS_MEM_NAME_EN > 0u) || (OS_TASK_NAME_EN > 0u) || (OS_TMR_CFG_NAME_EN > 0u)
  506. INT8U OS_StrLen (INT8U *psrc)
  507. {
  508. return rt_strlen((const char*)psrc);
  509. }
  510. #endif
  511. /*
  512. *********************************************************************************************************
  513. * SCHEDULER
  514. *
  515. * Description: This function is called by other uC/OS-II services to determine whether a new, high
  516. * priority task has been made ready to run. This function is invoked by TASK level code
  517. * and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).
  518. *
  519. * Arguments : none
  520. *
  521. * Returns : none
  522. *
  523. * Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  524. * 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
  525. *********************************************************************************************************
  526. */
  527. void OS_Sched (void)
  528. {
  529. rt_schedule();
  530. }
  531. #if OS_TASK_STAT_EN > 0u
  532. /*
  533. *********************************************************************************************************
  534. * IDLE TASK
  535. *
  536. * Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks
  537. * executes because they are ALL waiting for event(s) to occur.
  538. *
  539. * Arguments : none
  540. *
  541. * Returns : none
  542. *
  543. * Note(s) : 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be
  544. * enabled for at least a few instructions. On some processors (ex. Philips XA), enabling
  545. * and then disabling interrupts didn't allow the processor enough time to have interrupts
  546. * enabled before they were disabled again. uC/OS-II would thus never recognize
  547. * interrupts.
  548. * 2) This hook has been added to allow you to do such things as STOP the CPU to conserve
  549. * power.
  550. * 3) 在μCOS-II兼容层中,OS_TaskIdle不再是一个函数,而是一个RT-Thread操作系统Idle任务的回调函数
  551. *********************************************************************************************************
  552. */
  553. void OS_TaskIdle (void)
  554. {
  555. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  556. OS_CPU_SR cpu_sr = 0u;
  557. #endif
  558. OS_ENTER_CRITICAL();
  559. OSIdleCtr++;
  560. OS_EXIT_CRITICAL();
  561. #if OS_CPU_HOOKS_EN > 0u
  562. OSTaskIdleHook(); /* Call user definable HOOK */
  563. #endif
  564. }
  565. /*
  566. *********************************************************************************************************
  567. * STATISTICS TASK
  568. *
  569. * Description: This task is internal to uC/OS-II and is used to compute some statistics about the
  570. * multitasking environment. Specifically, OS_TaskStat() computes the CPU usage.
  571. * CPU usage is determined by:
  572. *
  573. * OSIdleCtr
  574. * OSCPUUsage = 100 * (1 - ------------) (units are in %)
  575. * OSIdleCtrMax
  576. *
  577. * Arguments : parg this pointer is not used at this time.
  578. *
  579. * Returns : none
  580. *
  581. * Notes : 1) This task runs at a priority level higher than the idle task. In fact, it runs at the
  582. * next higher priority, OS_TASK_IDLE_PRIO-1.
  583. * 2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
  584. * 3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the
  585. * maximum value for the idle counter.
  586. *********************************************************************************************************
  587. */
  588. void OS_TaskStat (void *p_arg)
  589. {
  590. INT8S usage;
  591. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  592. OS_CPU_SR cpu_sr = 0u;
  593. #endif
  594. p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */
  595. while (OSStatRdy == OS_FALSE) {
  596. OSTimeDly(2u * OS_TICKS_PER_SEC / 10u); /* Wait until statistic task is ready */
  597. }
  598. OSIdleCtrMax /= 100uL;
  599. if (OSIdleCtrMax == 0uL) {
  600. OSCPUUsage = 0u;
  601. #if OS_TASK_SUSPEND_EN > 0u
  602. (void)OSTaskSuspend(OS_PRIO_SELF);
  603. #else
  604. for (;;) {
  605. OSTimeDly(OS_TICKS_PER_SEC);
  606. }
  607. #endif
  608. }
  609. OS_ENTER_CRITICAL();
  610. OSIdleCtr = OSIdleCtrMax * 100uL; /* Set initial CPU usage as 0% */
  611. OS_EXIT_CRITICAL();
  612. for (;;) {
  613. OSTimeDly(1); /* Synchronize with clock tick */
  614. OS_ENTER_CRITICAL();
  615. OSIdleCtr = 0uL; /* Reset the idle counter for the next second */
  616. OS_EXIT_CRITICAL();
  617. OSTimeDly(OS_TICKS_PER_SEC / 10u); /* Accumulate OSIdleCtr for the next 1/10 second */
  618. OS_ENTER_CRITICAL();
  619. OSIdleCtrRun = OSIdleCtr; /* Store number of cycles which elapsed while idle */
  620. OS_EXIT_CRITICAL();
  621. usage = 100 - (INT8S)(OSIdleCtrRun / OSIdleCtrMax);
  622. if (usage >= 0) { /* Make sure we don't have a negative percentage */
  623. OSCPUUsage = (INT8U)usage;
  624. } else {
  625. OSCPUUsage = 0u;
  626. OSIdleCtrMax = OSIdleCtrRun / 100uL; /* Update max counter value to current one */
  627. }
  628. #if OS_CPU_HOOKS_EN > 0u
  629. OSTaskStatHook(); /* Invoke user definable hook */
  630. #endif
  631. #if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
  632. OS_TaskStatStkChk(); /* Check the stacks for each task */
  633. #endif
  634. }
  635. }
  636. #endif
  637. /*
  638. *********************************************************************************************************
  639. * CHECK ALL TASK STACKS
  640. *
  641. * Description: This function is called by OS_TaskStat() to check the stacks of each active task.
  642. *
  643. * Arguments : none
  644. *
  645. * Returns : none
  646. *********************************************************************************************************
  647. */
  648. #if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
  649. void OS_TaskStatStkChk (void)
  650. {
  651. OS_TCB *ptcb;
  652. OS_STK_DATA stk_data;
  653. INT8U err;
  654. INT8U prio;
  655. for (prio = 0u; prio <= OS_TASK_IDLE_PRIO; prio++) {
  656. err = OSTaskStkChk(prio, &stk_data);
  657. if (err == OS_ERR_NONE) {
  658. ptcb = OSTCBPrioTbl[prio];
  659. if (ptcb != (OS_TCB *)0) { /* Make sure task 'ptcb' is ... */
  660. if (ptcb != OS_TCB_RESERVED) { /* ... still valid. */
  661. #if OS_TASK_PROFILE_EN > 0u
  662. #if OS_STK_GROWTH == 1u
  663. ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom + ptcb->OSTCBStkSize;
  664. #else
  665. ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom - ptcb->OSTCBStkSize;
  666. #endif
  667. ptcb->OSTCBStkUsed = stk_data.OSUsed; /* Store number of entries used */
  668. #endif
  669. }
  670. }
  671. }
  672. }
  673. }
  674. #endif
  675. /*
  676. *********************************************************************************************************
  677. * INITIALIZE TCB
  678. *
  679. * Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when
  680. * a task is created (see OSTaskCreate() and OSTaskCreateExt()).
  681. *
  682. * Arguments : ptcb 兼容层新增参数
  683. *
  684. * prio is the priority of the task being created
  685. *
  686. * ptos is a pointer to the task's top-of-stack assuming that the CPU registers
  687. * have been placed on the stack. Note that the top-of-stack corresponds to a
  688. * 'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory
  689. * location if OS_STK_GROWTH is set to 0. Note that stack growth is CPU
  690. * specific.
  691. *
  692. * pbos is a pointer to the bottom of stack. A NULL pointer is passed if called by
  693. * 'OSTaskCreate()'.
  694. *
  695. * id is the task's ID (0..65535)
  696. *
  697. * stk_size is the size of the stack (in 'stack units'). If the stack units are INT8Us
  698. * then, 'stk_size' contains the number of bytes for the stack. If the stack
  699. * units are INT32Us then, the stack contains '4 * stk_size' bytes. The stack
  700. * units are established by the #define constant OS_STK which is CPU
  701. * specific. 'stk_size' is 0 if called by 'OSTaskCreate()'.
  702. *
  703. * pext is a pointer to a user supplied memory area that is used to extend the task
  704. * control block. This allows you to store the contents of floating-point
  705. * registers, MMU registers or anything else you could find useful during a
  706. * context switch. You can even assign a name to each task and store this name
  707. * in this TCB extension. A NULL pointer is passed if called by OSTaskCreate().
  708. *
  709. * opt options as passed to 'OSTaskCreateExt()' or,
  710. * 0 if called from 'OSTaskCreate()'.
  711. *
  712. * pptcb 返回ptcb指针
  713. *
  714. * Returns : OS_ERR_NONE if the call was successful
  715. * OS_ERR_TASK_NO_MORE_TCB if there are no more free TCBs to be allocated and thus, the task
  716. * cannot be created.
  717. *
  718. * Note : This function is INTERNAL to uC/OS-II and your application should not call it.
  719. *********************************************************************************************************
  720. */
  721. INT8U OS_TCBInit (INT8U prio,
  722. OS_STK *ptos,
  723. OS_STK *pbos,
  724. INT16U id,
  725. INT32U stk_size,
  726. void *pext,
  727. INT16U opt,
  728. OS_TCB **pptcb)
  729. {
  730. OS_TCB *ptcb;
  731. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  732. OS_CPU_SR cpu_sr = 0u;
  733. #endif
  734. #if OS_TASK_REG_TBL_SIZE > 0u
  735. INT8U i;
  736. #endif
  737. #if OS_TASK_CREATE_EXT_EN > 0u
  738. #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
  739. INT8U j;
  740. #endif
  741. #endif
  742. OS_ENTER_CRITICAL();
  743. ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */
  744. if (ptcb != (OS_TCB *)0) {
  745. OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */
  746. OS_EXIT_CRITICAL();
  747. ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */
  748. ptcb->OSTCBPrio = prio; /* Load task priority into TCB */
  749. ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */
  750. ptcb->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
  751. #ifndef PKG_USING_UCOSII_WRAPPER_TINY
  752. ptcb->OSTCBDly = 0u; /* Task is not delayed */
  753. #endif
  754. #if OS_TASK_CREATE_EXT_EN > 0u
  755. ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */
  756. ptcb->OSTCBStkSize = stk_size; /* Store stack size */
  757. ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */
  758. ptcb->OSTCBOpt = opt; /* Store task options */
  759. ptcb->OSTCBId = id; /* Store task ID */
  760. #else
  761. pext = pext; /* Prevent compiler warning if not used */
  762. stk_size = stk_size;
  763. pbos = pbos;
  764. opt = opt;
  765. id = id;
  766. #endif
  767. #if OS_TASK_DEL_EN > 0u
  768. ptcb->OSTCBDelReq = OS_ERR_NONE;
  769. #endif
  770. #ifndef PKG_USING_UCOSII_WRAPPER_TINY
  771. #if (OS_EVENT_EN)
  772. ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */
  773. #endif
  774. #endif
  775. #if OS_TASK_PROFILE_EN > 0u
  776. ptcb->OSTCBStkBase = (OS_STK *)0;
  777. ptcb->OSTCBStkUsed = 0uL;
  778. #endif
  779. #if OS_TASK_NAME_EN > 0u
  780. ptcb->OSTCBTaskName = (INT8U *)(void *)"?";
  781. #endif
  782. #if OS_TASK_REG_TBL_SIZE > 0u /* Initialize the task variables */
  783. for (i = 0u; i < OS_TASK_REG_TBL_SIZE; i++) {
  784. ptcb->OSTCBRegTbl[i] = 0u;
  785. }
  786. #endif
  787. #if OS_CPU_HOOKS_EN > 0u
  788. OSTCBInitHook(ptcb);
  789. #endif
  790. OS_ENTER_CRITICAL();
  791. OSTCBPrioTbl[prio] = ptcb;
  792. OS_EXIT_CRITICAL();
  793. #if OS_CPU_HOOKS_EN > 0u
  794. OSTaskCreateHook(ptcb); /* Call user defined hook */
  795. #endif
  796. #if OS_TASK_CREATE_EXT_EN > 0u
  797. #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
  798. for (j = 0u; j < OS_TLS_TBL_SIZE; j++) {
  799. ptcb->OSTCBTLSTbl[j] = (OS_TLS)0;
  800. }
  801. OS_TLS_TaskCreate(ptcb); /* Call TLS hook */
  802. #endif
  803. #endif
  804. OS_ENTER_CRITICAL();
  805. ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */
  806. ptcb->OSTCBPrev = (OS_TCB *)0;
  807. if (OSTCBList != (OS_TCB *)0) {
  808. OSTCBList->OSTCBPrev = ptcb;
  809. }
  810. OSTCBList = ptcb;
  811. OSTaskCtr++; /* Increment the #tasks counter */
  812. *pptcb = ptcb;
  813. OS_EXIT_CRITICAL();
  814. return (OS_ERR_NONE);
  815. }
  816. OS_EXIT_CRITICAL();
  817. return (OS_ERR_TASK_NO_MORE_TCB);
  818. }