训练营PLSR题目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

579 line
23 KiB

  1. /*
  2. ************************************************************************************************************************
  3. * uC/OS-III
  4. * The Real-Time Kernel
  5. *
  6. * (c) Copyright 2009-2014; Micrium, Inc.; Weston, FL
  7. * All rights reserved. Protected by international copyright laws.
  8. *
  9. * TIME MANAGEMENT
  10. *
  11. * File : OS_TIME.C
  12. * By : JJL
  13. * Version : V3.04.04
  14. *
  15. * LICENSING TERMS:
  16. * ---------------
  17. * uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
  18. * for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
  19. * product then, you need to contact Micrium to properly license uC/OS-III for its use in your
  20. * application/product. We provide ALL the source code for your convenience and to help you
  21. * experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
  22. * it commercially without paying a licensing fee.
  23. *
  24. * Knowledge of the source code may NOT be used to develop a similar product.
  25. *
  26. * Please help us continue to provide the embedded community with the finest software available.
  27. * Your honesty is greatly appreciated.
  28. *
  29. * You can find our product's user manual, API reference, release notes and
  30. * more information at https://doc.micrium.com.
  31. * You can contact us at www.micrium.com.
  32. ************************************************************************************************************************
  33. */
  34. #define MICRIUM_SOURCE
  35. #include "os.h"
  36. #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
  37. const CPU_CHAR *os_time__c = "$Id: $";
  38. #endif
  39. /*
  40. ************************************************************************************************************************
  41. * DELAY TASK 'n' TICKS
  42. *
  43. * Description: This function is called to delay execution of the currently running task until the specified number of
  44. * system ticks expires. This, of course, directly equates to delaying the current task for some time to
  45. * expire. No delay will result if the specified delay is 0. If the specified delay is greater than 0
  46. * then, a context switch will result.
  47. *
  48. * Arguments : dly is a value in 'clock ticks' that the task will either delay for or, the target match value
  49. * of the tick counter (OSTickCtr). Note that specifying 0 means the task is not to delay.
  50. *
  51. * depending on the option argument, the task will wake up when OSTickCtr reaches:
  52. *
  53. * OS_OPT_TIME_DLY : OSTickCtr + dly
  54. * OS_OPT_TIME_TIMEOUT : OSTickCtr + dly
  55. * OS_OPT_TIME_MATCH : dly
  56. * OS_OPT_TIME_PERIODIC : OSTCBCurPtr.TickCtrPrev + dly
  57. *
  58. * opt specifies whether 'dly' represents absolute or relative time; default option marked with *** :
  59. *
  60. * *** OS_OPT_TIME_DLY specifies a relative time from the current value of OSTickCtr.
  61. * OS_OPT_TIME_TIMEOUT same as OS_OPT_TIME_DLY.
  62. * OS_OPT_TIME_MATCH indicates that 'dly' specifies the absolute value that OSTickCtr
  63. * must reach before the task will be resumed.
  64. * OS_OPT_TIME_PERIODIC indicates that 'dly' specifies the periodic value that OSTickCtr
  65. * must reach before the task will be resumed.
  66. *
  67. * p_err is a pointer to a variable that will contain an error code from this call.
  68. *
  69. * OS_ERR_NONE the call was successful and the delay occurred.
  70. * OS_ERR_OPT_INVALID if you specified an invalid option for this function.
  71. * OS_ERR_SCHED_LOCKED can't delay when the scheduler is locked.
  72. * OS_ERR_TIME_DLY_ISR if you called this function from an ISR.
  73. * OS_ERR_TIME_ZERO_DLY if you specified a delay of zero.
  74. *
  75. * Returns : none
  76. ************************************************************************************************************************
  77. */
  78. void OSTimeDly (OS_TICK dly,
  79. OS_OPT opt,
  80. OS_ERR *p_err)
  81. {
  82. CPU_SR_ALLOC();
  83. #ifdef OS_SAFETY_CRITICAL
  84. if (p_err == (OS_ERR *)0) {
  85. OS_SAFETY_CRITICAL_EXCEPTION();
  86. return;
  87. }
  88. #endif
  89. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  90. if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to call from an ISR */
  91. *p_err = OS_ERR_TIME_DLY_ISR;
  92. return;
  93. }
  94. #endif
  95. if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) { /* Can't delay when the scheduler is locked */
  96. *p_err = OS_ERR_SCHED_LOCKED;
  97. return;
  98. }
  99. switch (opt) {
  100. case OS_OPT_TIME_DLY:
  101. case OS_OPT_TIME_TIMEOUT:
  102. case OS_OPT_TIME_PERIODIC:
  103. if (dly == (OS_TICK)0u) { /* 0 means no delay! */
  104. *p_err = OS_ERR_TIME_ZERO_DLY;
  105. return;
  106. }
  107. break;
  108. case OS_OPT_TIME_MATCH:
  109. break;
  110. default:
  111. *p_err = OS_ERR_OPT_INVALID;
  112. return;
  113. }
  114. OS_CRITICAL_ENTER();
  115. OS_TickListInsertDly(OSTCBCurPtr,
  116. dly,
  117. opt,
  118. p_err);
  119. if (*p_err != OS_ERR_NONE) {
  120. OS_CRITICAL_EXIT_NO_SCHED();
  121. return;
  122. }
  123. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  124. TRACE_OS_TASK_DLY(dly); /* Record the event. */
  125. #endif
  126. OS_RdyListRemove(OSTCBCurPtr); /* Remove current task from ready list */
  127. OS_CRITICAL_EXIT_NO_SCHED();
  128. OSSched(); /* Find next task to run! */
  129. *p_err = OS_ERR_NONE;
  130. }
  131. /*
  132. ************************************************************************************************************************
  133. * DELAY TASK FOR SPECIFIED TIME
  134. *
  135. * Description: This function is called to delay execution of the currently running task until some time expires. This
  136. * call allows you to specify the delay time in HOURS, MINUTES, SECONDS and MILLISECONDS instead of ticks.
  137. *
  138. * Arguments : hours specifies the number of hours that the task will be delayed (max. is 999 if the tick rate is
  139. * 1000 Hz or less otherwise, a higher value would overflow a 32-bit unsigned counter).
  140. *
  141. * minutes specifies the number of minutes (max. 59 if 'opt' is OS_OPT_TIME_HMSM_STRICT)
  142. *
  143. * seconds specifies the number of seconds (max. 59 if 'opt' is OS_OPT_TIME_HMSM_STRICT)
  144. *
  145. * milli specifies the number of milliseconds (max. 999 if 'opt' is OS_OPT_TIME_HMSM_STRICT)
  146. *
  147. * opt specifies time delay bit-field options logically OR'd; default options marked with *** :
  148. *
  149. * *** OS_OPT_TIME_DLY specifies a relative time from the current value of OSTickCtr.
  150. * OS_OPT_TIME_TIMEOUT same as OS_OPT_TIME_DLY.
  151. * OS_OPT_TIME_MATCH indicates that the delay specifies the absolute value that OSTickCtr
  152. * must reach before the task will be resumed.
  153. * OS_OPT_TIME_PERIODIC indicates that the delay specifies the periodic value that OSTickCtr
  154. * must reach before the task will be resumed.
  155. *
  156. * *** OS_OPT_TIME_HMSM_STRICT strictly allow only hours (0...99)
  157. * minutes (0...59)
  158. * seconds (0...59)
  159. * milliseconds (0...999)
  160. * OS_OPT_TIME_HMSM_NON_STRICT allow any value of hours (0...999)
  161. * minutes (0...9999)
  162. * seconds (0...65535)
  163. * milliseconds (0...4294967295)
  164. *
  165. * p_err is a pointer to a variable that will receive an error code from this call.
  166. *
  167. * OS_ERR_NONE If the function returns from the desired delay
  168. * OS_ERR_OPT_INVALID If you specified an invalid option for 'opt'
  169. * OS_ERR_SCHED_LOCKED Can't delay when the scheduler is locked
  170. * OS_ERR_TIME_DLY_ISR If called from an ISR
  171. * OS_ERR_TIME_INVALID_HOURS If you didn't specify a valid value for 'hours'
  172. * OS_ERR_TIME_INVALID_MINUTES If you didn't specify a valid value for 'minutes'
  173. * OS_ERR_TIME_INVALID_SECONDS If you didn't specify a valid value for 'seconds'
  174. * OS_ERR_TIME_INVALID_MILLISECONDS If you didn't specify a valid value for 'milli'
  175. * OS_ERR_TIME_ZERO_DLY If hours, minutes, seconds and milli are all 0
  176. *
  177. * Returns : none
  178. *
  179. * Note(s) : 1) The resolution on the milliseconds depends on the tick rate. For example, you can't do a 10 mS delay
  180. * if the ticker interrupts every 100 mS. In this case, the delay would be set to 0. The actual delay
  181. * is rounded to the nearest tick.
  182. *
  183. * 2) Although this function allows you to delay a task for many, many hours, it's not recommended to put
  184. * a task to sleep for that long.
  185. ************************************************************************************************************************
  186. */
  187. #if OS_CFG_TIME_DLY_HMSM_EN > 0u
  188. void OSTimeDlyHMSM (CPU_INT16U hours,
  189. CPU_INT16U minutes,
  190. CPU_INT16U seconds,
  191. CPU_INT32U milli,
  192. OS_OPT opt,
  193. OS_ERR *p_err)
  194. {
  195. #if OS_CFG_ARG_CHK_EN > 0u
  196. CPU_BOOLEAN opt_invalid;
  197. CPU_BOOLEAN opt_non_strict;
  198. #endif
  199. OS_OPT opt_time;
  200. OS_RATE_HZ tick_rate;
  201. OS_TICK ticks;
  202. CPU_SR_ALLOC();
  203. #ifdef OS_SAFETY_CRITICAL
  204. if (p_err == (OS_ERR *)0) {
  205. OS_SAFETY_CRITICAL_EXCEPTION();
  206. return;
  207. }
  208. #endif
  209. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  210. if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to call from an ISR */
  211. *p_err = OS_ERR_TIME_DLY_ISR;
  212. return;
  213. }
  214. #endif
  215. if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) { /* Can't delay when the scheduler is locked */
  216. *p_err = OS_ERR_SCHED_LOCKED;
  217. return;
  218. }
  219. opt_time = opt & OS_OPT_TIME_MASK; /* Retrieve time options only. */
  220. switch (opt_time) {
  221. case OS_OPT_TIME_DLY:
  222. case OS_OPT_TIME_TIMEOUT:
  223. case OS_OPT_TIME_PERIODIC:
  224. if (milli == (CPU_INT32U)0u) { /* Make sure we didn't specify a 0 delay */
  225. if (seconds == (CPU_INT16U)0u) {
  226. if (minutes == (CPU_INT16U)0u) {
  227. if (hours == (CPU_INT16U)0u) {
  228. *p_err = OS_ERR_TIME_ZERO_DLY;
  229. return;
  230. }
  231. }
  232. }
  233. }
  234. break;
  235. case OS_OPT_TIME_MATCH:
  236. break;
  237. default:
  238. *p_err = OS_ERR_OPT_INVALID;
  239. return;
  240. }
  241. #if OS_CFG_ARG_CHK_EN > 0u /* Validate arguments to be within range */
  242. opt_invalid = DEF_BIT_IS_SET_ANY(opt, ~OS_OPT_TIME_OPTS_MASK);
  243. if (opt_invalid == DEF_YES) {
  244. *p_err = OS_ERR_OPT_INVALID;
  245. return;
  246. }
  247. opt_non_strict = DEF_BIT_IS_SET(opt, OS_OPT_TIME_HMSM_NON_STRICT);
  248. if (opt_non_strict != DEF_YES) {
  249. if (milli > (CPU_INT32U)999u) {
  250. *p_err = OS_ERR_TIME_INVALID_MILLISECONDS;
  251. return;
  252. }
  253. if (seconds > (CPU_INT16U)59u) {
  254. *p_err = OS_ERR_TIME_INVALID_SECONDS;
  255. return;
  256. }
  257. if (minutes > (CPU_INT16U)59u) {
  258. *p_err = OS_ERR_TIME_INVALID_MINUTES;
  259. return;
  260. }
  261. if (hours > (CPU_INT16U)99u) {
  262. *p_err = OS_ERR_TIME_INVALID_HOURS;
  263. return;
  264. }
  265. } else {
  266. if (minutes > (CPU_INT16U)9999u) {
  267. *p_err = OS_ERR_TIME_INVALID_MINUTES;
  268. return;
  269. }
  270. if (hours > (CPU_INT16U)999u) {
  271. *p_err = OS_ERR_TIME_INVALID_HOURS;
  272. return;
  273. }
  274. }
  275. #endif
  276. /* Compute the total number of clock ticks required.. */
  277. /* .. (rounded to the nearest tick) */
  278. tick_rate = OSCfg_TickRate_Hz;
  279. ticks = ((OS_TICK)hours * (OS_TICK)3600u + (OS_TICK)minutes * (OS_TICK)60u + (OS_TICK)seconds) * tick_rate
  280. + (tick_rate * ((OS_TICK)milli + (OS_TICK)500u / tick_rate)) / (OS_TICK)1000u;
  281. if (ticks > (OS_TICK)0u) {
  282. OS_CRITICAL_ENTER();
  283. OS_TickListInsertDly(OSTCBCurPtr,
  284. ticks,
  285. opt_time,
  286. p_err);
  287. if (*p_err != OS_ERR_NONE) {
  288. OS_CRITICAL_EXIT_NO_SCHED();
  289. return;
  290. }
  291. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  292. TRACE_OS_TASK_DLY(ticks); /* Record the event. */
  293. #endif
  294. OS_RdyListRemove(OSTCBCurPtr); /* Remove current task from ready list */
  295. OS_CRITICAL_EXIT_NO_SCHED();
  296. OSSched(); /* Find next task to run! */
  297. *p_err = OS_ERR_NONE;
  298. } else {
  299. *p_err = OS_ERR_TIME_ZERO_DLY;
  300. }
  301. }
  302. #endif
  303. /*
  304. ************************************************************************************************************************
  305. * RESUME A DELAYED TASK
  306. *
  307. * Description: This function is used resume a task that has been delayed through a call to either OSTimeDly() or
  308. * OSTimeDlyHMSM(). Note that you cannot call this function to resume a task that is waiting for an event
  309. * with timeout.
  310. *
  311. * Arguments : p_tcb is a pointer to the TCB of the task to resume.
  312. *
  313. * p_err is a pointer to a variable that will receive an error code
  314. *
  315. * OS_ERR_NONE Task has been resumed
  316. * OS_ERR_STATE_INVALID Task is in an invalid state
  317. * OS_ERR_TIME_DLY_RESUME_ISR If called from an ISR
  318. * OS_ERR_TIME_NOT_DLY Task is not waiting for time to expire
  319. * OS_ERR_TASK_SUSPENDED Task cannot be resumed, it was suspended by OSTaskSuspend()
  320. *
  321. * Note(s) : none
  322. ************************************************************************************************************************
  323. */
  324. #if OS_CFG_TIME_DLY_RESUME_EN > 0u
  325. void OSTimeDlyResume (OS_TCB *p_tcb,
  326. OS_ERR *p_err)
  327. {
  328. CPU_SR_ALLOC();
  329. #ifdef OS_SAFETY_CRITICAL
  330. if (p_err == (OS_ERR *)0) {
  331. OS_SAFETY_CRITICAL_EXCEPTION();
  332. return;
  333. }
  334. #endif
  335. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  336. if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to call from an ISR */
  337. *p_err = OS_ERR_TIME_DLY_RESUME_ISR;
  338. return;
  339. }
  340. #endif
  341. #if OS_CFG_ARG_CHK_EN > 0u
  342. if (p_tcb == (OS_TCB *)0) { /* Not possible for the running task to be delayed! */
  343. *p_err = OS_ERR_TASK_NOT_DLY;
  344. return;
  345. }
  346. #endif
  347. CPU_CRITICAL_ENTER();
  348. if (p_tcb == OSTCBCurPtr) { /* Not possible for the running task to be delayed! */
  349. *p_err = OS_ERR_TASK_NOT_DLY;
  350. CPU_CRITICAL_EXIT();
  351. return;
  352. }
  353. switch (p_tcb->TaskState) {
  354. case OS_TASK_STATE_RDY: /* Cannot Abort delay if task is ready */
  355. CPU_CRITICAL_EXIT();
  356. *p_err = OS_ERR_TASK_NOT_DLY;
  357. break;
  358. case OS_TASK_STATE_DLY:
  359. OS_CRITICAL_ENTER_CPU_EXIT();
  360. p_tcb->TaskState = OS_TASK_STATE_RDY;
  361. OS_TickListRemove(p_tcb); /* Remove task from tick list */
  362. OS_RdyListInsert(p_tcb); /* Add to ready list */
  363. OS_CRITICAL_EXIT_NO_SCHED();
  364. *p_err = OS_ERR_NONE;
  365. break;
  366. case OS_TASK_STATE_PEND:
  367. CPU_CRITICAL_EXIT();
  368. *p_err = OS_ERR_TASK_NOT_DLY;
  369. break;
  370. case OS_TASK_STATE_PEND_TIMEOUT:
  371. CPU_CRITICAL_EXIT();
  372. *p_err = OS_ERR_TASK_NOT_DLY;
  373. break;
  374. case OS_TASK_STATE_SUSPENDED:
  375. CPU_CRITICAL_EXIT();
  376. *p_err = OS_ERR_TASK_NOT_DLY;
  377. break;
  378. case OS_TASK_STATE_DLY_SUSPENDED:
  379. OS_CRITICAL_ENTER_CPU_EXIT();
  380. p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
  381. OS_TickListRemove(p_tcb); /* Remove task from tick list */
  382. OS_CRITICAL_EXIT_NO_SCHED();
  383. *p_err = OS_ERR_TASK_SUSPENDED;
  384. break;
  385. case OS_TASK_STATE_PEND_SUSPENDED:
  386. CPU_CRITICAL_EXIT();
  387. *p_err = OS_ERR_TASK_NOT_DLY;
  388. break;
  389. case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
  390. CPU_CRITICAL_EXIT();
  391. *p_err = OS_ERR_TASK_NOT_DLY;
  392. break;
  393. default:
  394. CPU_CRITICAL_EXIT();
  395. *p_err = OS_ERR_STATE_INVALID;
  396. break;
  397. }
  398. OSSched();
  399. }
  400. #endif
  401. /*
  402. ************************************************************************************************************************
  403. * GET CURRENT SYSTEM TIME
  404. *
  405. * Description: This function is used by your application to obtain the current value of the counter which keeps track of
  406. * the number of clock ticks.
  407. *
  408. * Arguments : p_err is a pointer to a variable that will receive an error code
  409. *
  410. * OS_ERR_NONE If the call was successful
  411. *
  412. * Returns : The current value of OSTickCtr
  413. ************************************************************************************************************************
  414. */
  415. OS_TICK OSTimeGet (OS_ERR *p_err)
  416. {
  417. OS_TICK ticks;
  418. CPU_SR_ALLOC();
  419. #ifdef OS_SAFETY_CRITICAL
  420. if (p_err == (OS_ERR *)0) {
  421. OS_SAFETY_CRITICAL_EXCEPTION();
  422. return ((OS_TICK)0);
  423. }
  424. #endif
  425. CPU_CRITICAL_ENTER();
  426. ticks = OSTickCtr;
  427. CPU_CRITICAL_EXIT();
  428. *p_err = OS_ERR_NONE;
  429. return (ticks);
  430. }
  431. /*
  432. ************************************************************************************************************************
  433. * SET SYSTEM CLOCK
  434. *
  435. * Description: This function sets the counter which keeps track of the number of clock ticks.
  436. *
  437. * Arguments : ticks is the desired tick value
  438. *
  439. * p_err is a pointer to a variable that will receive an error code
  440. *
  441. * OS_ERR_NONE If the call was successful
  442. *
  443. * Returns : none
  444. ************************************************************************************************************************
  445. */
  446. void OSTimeSet (OS_TICK ticks,
  447. OS_ERR *p_err)
  448. {
  449. CPU_SR_ALLOC();
  450. #ifdef OS_SAFETY_CRITICAL
  451. if (p_err == (OS_ERR *)0) {
  452. OS_SAFETY_CRITICAL_EXCEPTION();
  453. return;
  454. }
  455. #endif
  456. CPU_CRITICAL_ENTER();
  457. OSTickCtr = ticks;
  458. CPU_CRITICAL_EXIT();
  459. *p_err = OS_ERR_NONE;
  460. }
  461. /*
  462. ************************************************************************************************************************
  463. * PROCESS SYSTEM TICK
  464. *
  465. * Description: This function is used to signal to uC/OS-III the occurrence of a 'system tick' (also known as a
  466. * 'clock tick'). This function should be called by the tick ISR.
  467. *
  468. * Arguments : none
  469. *
  470. * Returns : none
  471. ************************************************************************************************************************
  472. */
  473. void OSTimeTick (void)
  474. {
  475. OS_ERR err;
  476. #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
  477. CPU_TS ts;
  478. #endif
  479. OSTimeTickHook(); /* Call user definable hook */
  480. #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
  481. ts = OS_TS_GET(); /* Get timestamp */
  482. OS_IntQPost((OS_OBJ_TYPE) OS_OBJ_TYPE_TICK, /* Post to ISR queue */
  483. (void *)&OSRdyList[OSPrioCur],
  484. (void *) 0,
  485. (OS_MSG_SIZE) 0u,
  486. (OS_FLAGS ) 0u,
  487. (OS_OPT ) 0u,
  488. (CPU_TS ) ts,
  489. (OS_ERR *)&err);
  490. #else
  491. (void)OSTaskSemPost((OS_TCB *)&OSTickTaskTCB, /* Signal tick task */
  492. (OS_OPT ) OS_OPT_POST_NONE,
  493. (OS_ERR *)&err);
  494. #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
  495. OS_SchedRoundRobin(&OSRdyList[OSPrioCur]);
  496. #endif
  497. #if OS_CFG_TMR_EN > 0u
  498. OSTmrUpdateCtr--;
  499. if (OSTmrUpdateCtr == (OS_CTR)0u) {
  500. OSTmrUpdateCtr = OSTmrUpdateCnt;
  501. OSTaskSemPost((OS_TCB *)&OSTmrTaskTCB, /* Signal timer task */
  502. (OS_OPT ) OS_OPT_POST_NONE,
  503. (OS_ERR *)&err);
  504. }
  505. #endif
  506. #endif
  507. }