训练营PLSR题目
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

1096 rader
40 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. * TIMER MANAGEMENT
  10. *
  11. * File : OS_TMR.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_tmr__c = "$Id: $";
  38. #endif
  39. #if OS_CFG_TMR_EN > 0u
  40. /*
  41. ************************************************************************************************************************
  42. * CONSTANTS
  43. ************************************************************************************************************************
  44. */
  45. #define OS_OPT_LINK_DLY (OS_OPT)(0u)
  46. #define OS_OPT_LINK_PERIODIC (OS_OPT)(1u)
  47. /*
  48. ************************************************************************************************************************
  49. * LOCAL FUNCTION PROTOTYPES
  50. ************************************************************************************************************************
  51. */
  52. static void OS_TmrLock (void);
  53. static void OS_TmrUnlock (void);
  54. /*
  55. ************************************************************************************************************************
  56. * CREATE A TIMER
  57. *
  58. * Description: This function is called by your application code to create a timer.
  59. *
  60. * Arguments : p_tmr Is a pointer to a timer control block
  61. *
  62. * p_name Is a pointer to an ASCII string that is used to name the timer. Names are useful for
  63. * debugging.
  64. *
  65. * dly Initial delay.
  66. * If the timer is configured for ONE-SHOT mode, this is the timeout used
  67. * If the timer is configured for PERIODIC mode, this is the first timeout to wait for
  68. * before the timer starts entering periodic mode
  69. *
  70. * period The 'period' being repeated for the timer.
  71. * If you specified 'OS_OPT_TMR_PERIODIC' as an option, when the timer expires, it will
  72. * automatically restart with the same period.
  73. *
  74. * opt Specifies either:
  75. *
  76. * OS_OPT_TMR_ONE_SHOT The timer counts down only once
  77. * OS_OPT_TMR_PERIODIC The timer counts down and then reloads itself
  78. *
  79. * p_callback Is a pointer to a callback function that will be called when the timer expires. The
  80. * callback function must be declared as follows:
  81. *
  82. * void MyCallback (OS_TMR *p_tmr, void *p_arg);
  83. *
  84. * p_callback_arg Is an argument (a pointer) that is passed to the callback function when it is called.
  85. *
  86. * p_err Is a pointer to an error code. '*p_err' will contain one of the following:
  87. *
  88. * OS_ERR_NONE
  89. * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the timer after you called
  90. * OSSafetyCriticalStart().
  91. * OS_ERR_OBJ_CREATED if the timer has already been created
  92. * OS_ERR_OBJ_PTR_NULL is 'p_tmr' is a NULL pointer
  93. * OS_ERR_OBJ_TYPE if the object type is invalid
  94. * OS_ERR_OPT_INVALID you specified an invalid option
  95. * OS_ERR_TMR_INVALID_DLY you specified an invalid delay
  96. * OS_ERR_TMR_INVALID_PERIOD you specified an invalid period
  97. * OS_ERR_TMR_ISR if the call was made from an ISR
  98. *
  99. * Returns : none
  100. *
  101. * Note(s) : 1) This function only creates the timer. In other words, the timer is not started when created. To
  102. * start the timer, call OSTmrStart().
  103. ************************************************************************************************************************
  104. */
  105. void OSTmrCreate (OS_TMR *p_tmr,
  106. CPU_CHAR *p_name,
  107. OS_TICK dly,
  108. OS_TICK period,
  109. OS_OPT opt,
  110. OS_TMR_CALLBACK_PTR p_callback,
  111. void *p_callback_arg,
  112. OS_ERR *p_err)
  113. {
  114. #ifdef OS_SAFETY_CRITICAL
  115. if (p_err == (OS_ERR *)0) {
  116. OS_SAFETY_CRITICAL_EXCEPTION();
  117. return;
  118. }
  119. #endif
  120. #ifdef OS_SAFETY_CRITICAL_IEC61508
  121. if (OSSafetyCriticalStartFlag == DEF_TRUE) {
  122. *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
  123. return;
  124. }
  125. #endif
  126. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  127. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
  128. *p_err = OS_ERR_TMR_ISR;
  129. return;
  130. }
  131. #endif
  132. #if OS_CFG_ARG_CHK_EN > 0u
  133. if (p_tmr == (OS_TMR *)0) { /* Validate 'p_tmr' */
  134. *p_err = OS_ERR_OBJ_PTR_NULL;
  135. return;
  136. }
  137. switch (opt) {
  138. case OS_OPT_TMR_PERIODIC:
  139. if (period == (OS_TICK)0) {
  140. *p_err = OS_ERR_TMR_INVALID_PERIOD;
  141. return;
  142. }
  143. break;
  144. case OS_OPT_TMR_ONE_SHOT:
  145. if (dly == (OS_TICK)0) {
  146. *p_err = OS_ERR_TMR_INVALID_DLY;
  147. return;
  148. }
  149. break;
  150. default:
  151. *p_err = OS_ERR_OPT_INVALID;
  152. return;
  153. }
  154. #endif
  155. OS_TmrLock();
  156. p_tmr->State = (OS_STATE )OS_TMR_STATE_STOPPED; /* Initialize the timer fields */
  157. #if OS_OBJ_TYPE_REQ > 0u
  158. p_tmr->Type = (OS_OBJ_TYPE )OS_OBJ_TYPE_TMR;
  159. #endif
  160. #if OS_CFG_DBG_EN > 0u
  161. p_tmr->NamePtr = (CPU_CHAR *)p_name;
  162. #else
  163. (void)&p_name;
  164. #endif
  165. p_tmr->Dly = (OS_TICK )dly;
  166. p_tmr->Remain = (OS_TICK )0;
  167. p_tmr->Period = (OS_TICK )period;
  168. p_tmr->Opt = (OS_OPT )opt;
  169. p_tmr->CallbackPtr = (OS_TMR_CALLBACK_PTR)p_callback;
  170. p_tmr->CallbackPtrArg = (void *)p_callback_arg;
  171. p_tmr->NextPtr = (OS_TMR *)0;
  172. p_tmr->PrevPtr = (OS_TMR *)0;
  173. #if OS_CFG_DBG_EN > 0u
  174. OS_TmrDbgListAdd(p_tmr);
  175. #endif
  176. OSTmrQty++; /* Keep track of the number of timers created */
  177. OS_TmrUnlock();
  178. *p_err = OS_ERR_NONE;
  179. }
  180. /*
  181. ************************************************************************************************************************
  182. * DELETE A TIMER
  183. *
  184. * Description: This function is called by your application code to delete a timer.
  185. *
  186. * Arguments : p_tmr Is a pointer to the timer to stop and delete.
  187. *
  188. * p_err Is a pointer to an error code. '*p_err' will contain one of the following:
  189. *
  190. * OS_ERR_NONE
  191. * OS_ERR_OBJ_TYPE 'p_tmr' is not pointing to a timer
  192. * OS_ERR_TMR_INVALID 'p_tmr' is a NULL pointer
  193. * OS_ERR_TMR_ISR if the function was called from an ISR
  194. * OS_ERR_TMR_INACTIVE if the timer was not created
  195. * OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
  196. *
  197. * Returns : DEF_TRUE if the timer was deleted
  198. * DEF_FALSE if not or upon an error
  199. ************************************************************************************************************************
  200. */
  201. #if OS_CFG_TMR_DEL_EN > 0u
  202. CPU_BOOLEAN OSTmrDel (OS_TMR *p_tmr,
  203. OS_ERR *p_err)
  204. {
  205. CPU_BOOLEAN success;
  206. #ifdef OS_SAFETY_CRITICAL
  207. if (p_err == (OS_ERR *)0) {
  208. OS_SAFETY_CRITICAL_EXCEPTION();
  209. return (DEF_FALSE);
  210. }
  211. #endif
  212. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  213. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
  214. *p_err = OS_ERR_TMR_ISR;
  215. return (DEF_FALSE);
  216. }
  217. #endif
  218. #if OS_CFG_ARG_CHK_EN > 0u
  219. if (p_tmr == (OS_TMR *)0) {
  220. *p_err = OS_ERR_TMR_INVALID;
  221. return (DEF_FALSE);
  222. }
  223. #endif
  224. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  225. if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
  226. *p_err = OS_ERR_OBJ_TYPE;
  227. return (DEF_FALSE);
  228. }
  229. #endif
  230. OS_TmrLock();
  231. #if OS_CFG_DBG_EN > 0u
  232. OS_TmrDbgListRemove(p_tmr);
  233. #endif
  234. switch (p_tmr->State) {
  235. case OS_TMR_STATE_RUNNING:
  236. OS_TmrUnlink(p_tmr); /* Remove from the list */
  237. OS_TmrClr(p_tmr);
  238. OS_TmrUnlock();
  239. OSTmrQty--; /* One less timer */
  240. *p_err = OS_ERR_NONE;
  241. success = DEF_TRUE;
  242. break;
  243. case OS_TMR_STATE_STOPPED: /* Timer has not started or ... */
  244. case OS_TMR_STATE_COMPLETED: /* ... timer has completed the ONE-SHOT time */
  245. OS_TmrClr(p_tmr); /* Clear timer fields */
  246. OS_TmrUnlock();
  247. OSTmrQty--; /* One less timer */
  248. *p_err = OS_ERR_NONE;
  249. success = DEF_TRUE;
  250. break;
  251. case OS_TMR_STATE_UNUSED: /* Already deleted */
  252. OS_TmrUnlock();
  253. *p_err = OS_ERR_TMR_INACTIVE;
  254. success = DEF_FALSE;
  255. break;
  256. default:
  257. OS_TmrUnlock();
  258. *p_err = OS_ERR_TMR_INVALID_STATE;
  259. success = DEF_FALSE;
  260. break;
  261. }
  262. return (success);
  263. }
  264. #endif
  265. /*
  266. ************************************************************************************************************************
  267. * GET HOW MUCH TIME IS LEFT BEFORE A TIMER EXPIRES
  268. *
  269. * Description: This function is called to get the number of ticks before a timer times out.
  270. *
  271. * Arguments : p_tmr Is a pointer to the timer to obtain the remaining time from.
  272. *
  273. * p_err Is a pointer to an error code. '*p_err' will contain one of the following:
  274. *
  275. * OS_ERR_NONE
  276. * OS_ERR_OBJ_TYPE 'p_tmr' is not pointing to a timer
  277. * OS_ERR_TMR_INVALID 'p_tmr' is a NULL pointer
  278. * OS_ERR_TMR_ISR if the call was made from an ISR
  279. * OS_ERR_TMR_INACTIVE 'p_tmr' points to a timer that is not active
  280. * OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
  281. *
  282. * Returns : The time remaining for the timer to expire. The time represents 'timer' increments. In other words, if
  283. * OS_TmrTask() is signaled every 1/10 of a second then the returned value represents the number of 1/10 of
  284. * a second remaining before the timer expires.
  285. ************************************************************************************************************************
  286. */
  287. OS_TICK OSTmrRemainGet (OS_TMR *p_tmr,
  288. OS_ERR *p_err)
  289. {
  290. OS_TICK remain;
  291. OS_ERR err;
  292. #ifdef OS_SAFETY_CRITICAL
  293. if (p_err == (OS_ERR *)0) {
  294. OS_SAFETY_CRITICAL_EXCEPTION();
  295. return ((OS_TICK)0);
  296. }
  297. #endif
  298. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  299. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
  300. *p_err = OS_ERR_TMR_ISR;
  301. return ((OS_TICK)0);
  302. }
  303. #endif
  304. #if OS_CFG_ARG_CHK_EN > 0u
  305. if (p_tmr == (OS_TMR *)0) {
  306. *p_err = OS_ERR_TMR_INVALID;
  307. return ((OS_TICK)0);
  308. }
  309. #endif
  310. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  311. if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
  312. *p_err = OS_ERR_OBJ_TYPE;
  313. return ((OS_TICK)0);
  314. }
  315. #endif
  316. OSSchedLock(&err);
  317. (void)&err;
  318. switch (p_tmr->State) {
  319. case OS_TMR_STATE_RUNNING:
  320. remain = p_tmr->Remain;
  321. *p_err = OS_ERR_NONE;
  322. break;
  323. case OS_TMR_STATE_STOPPED: /* It's assumed that the timer has not started yet */
  324. if (p_tmr->Opt == OS_OPT_TMR_PERIODIC) {
  325. if (p_tmr->Dly == 0u) {
  326. remain = p_tmr->Period;
  327. } else {
  328. remain = p_tmr->Dly;
  329. }
  330. } else {
  331. remain = p_tmr->Dly;
  332. }
  333. *p_err = OS_ERR_NONE;
  334. break;
  335. case OS_TMR_STATE_COMPLETED: /* Only ONE-SHOT that timed out can be in this state */
  336. *p_err = OS_ERR_NONE;
  337. remain = (OS_TICK)0;
  338. break;
  339. case OS_TMR_STATE_UNUSED:
  340. *p_err = OS_ERR_TMR_INACTIVE;
  341. remain = (OS_TICK)0;
  342. break;
  343. default:
  344. *p_err = OS_ERR_TMR_INVALID_STATE;
  345. remain = (OS_TICK)0;
  346. break;
  347. }
  348. OSSchedUnlock(&err);
  349. (void)&err;
  350. return (remain);
  351. }
  352. /*
  353. ************************************************************************************************************************
  354. * START A TIMER
  355. *
  356. * Description: This function is called by your application code to start a timer.
  357. *
  358. * Arguments : p_tmr Is a pointer to an OS_TMR
  359. *
  360. * p_err Is a pointer to an error code. '*p_err' will contain one of the following:
  361. *
  362. * OS_ERR_NONE
  363. * OS_ERR_OBJ_TYPE if 'p_tmr' is not pointing to a timer
  364. * OS_ERR_TMR_INVALID
  365. * OS_ERR_TMR_INACTIVE if the timer was not created
  366. * OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
  367. * OS_ERR_TMR_ISR if the call was made from an ISR
  368. *
  369. * Returns : DEF_TRUE is the timer was started
  370. * DEF_FALSE if not or upon an error
  371. *
  372. * Note(s) : 1) When starting/restarting a timer, regardless if it is in PERIODIC or ONE-SHOT mode, the timer is
  373. * linked to the timer list with the OS_OPT_LINK_DLY option. This option sets the initial expiration
  374. * time for the timer. For timers in PERIODIC mode, subsequent expiration times are handled by
  375. * the OS_TmrTask().
  376. ************************************************************************************************************************
  377. */
  378. CPU_BOOLEAN OSTmrStart (OS_TMR *p_tmr,
  379. OS_ERR *p_err)
  380. {
  381. OS_TMR *p_next;
  382. CPU_BOOLEAN success;
  383. CPU_SR_ALLOC();
  384. #ifdef OS_SAFETY_CRITICAL
  385. if (p_err == (OS_ERR *)0) {
  386. OS_SAFETY_CRITICAL_EXCEPTION();
  387. return (DEF_FALSE);
  388. }
  389. #endif
  390. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  391. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
  392. *p_err = OS_ERR_TMR_ISR;
  393. return (DEF_FALSE);
  394. }
  395. #endif
  396. #if OS_CFG_ARG_CHK_EN > 0u
  397. if (p_tmr == (OS_TMR *)0) {
  398. *p_err = OS_ERR_TMR_INVALID;
  399. return (DEF_FALSE);
  400. }
  401. #endif
  402. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  403. if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
  404. *p_err = OS_ERR_OBJ_TYPE;
  405. return (DEF_FALSE);
  406. }
  407. #endif
  408. switch (p_tmr->State) {
  409. case OS_TMR_STATE_RUNNING: /* Restart the timer */
  410. CPU_CRITICAL_ENTER();
  411. p_tmr->Remain = p_tmr->Dly;
  412. CPU_CRITICAL_EXIT();
  413. *p_err = OS_ERR_NONE;
  414. success = DEF_TRUE;
  415. break;
  416. case OS_TMR_STATE_STOPPED: /* Start the timer */
  417. case OS_TMR_STATE_COMPLETED:
  418. OS_TmrLock();
  419. p_tmr->State = OS_TMR_STATE_RUNNING;
  420. if (p_tmr->Dly == (OS_TICK)0) {
  421. p_tmr->Remain = p_tmr->Period;
  422. } else {
  423. p_tmr->Remain = p_tmr->Dly;
  424. }
  425. if (OSTmrListPtr == (OS_TMR *)0) { /* Link into timer list */
  426. p_tmr->NextPtr = (OS_TMR *)0; /* This is the first timer in the list */
  427. p_tmr->PrevPtr = (OS_TMR *)0;
  428. OSTmrListPtr = p_tmr;
  429. OSTmrListEntries = 1u;
  430. } else {
  431. p_next = OSTmrListPtr; /* Insert at the beginning of the list */
  432. p_tmr->NextPtr = OSTmrListPtr;
  433. p_tmr->PrevPtr = (OS_TMR *)0;
  434. p_next->PrevPtr = p_tmr;
  435. OSTmrListPtr = p_tmr;
  436. OSTmrListEntries++;
  437. }
  438. OS_TmrUnlock();
  439. *p_err = OS_ERR_NONE;
  440. success = DEF_TRUE;
  441. break;
  442. case OS_TMR_STATE_UNUSED: /* Timer not created */
  443. *p_err = OS_ERR_TMR_INACTIVE;
  444. success = DEF_FALSE;
  445. break;
  446. default:
  447. *p_err = OS_ERR_TMR_INVALID_STATE;
  448. success = DEF_FALSE;
  449. break;
  450. }
  451. return (success);
  452. }
  453. /*
  454. ************************************************************************************************************************
  455. * FIND OUT WHAT STATE A TIMER IS IN
  456. *
  457. * Description: This function is called to determine what state the timer is in:
  458. *
  459. * OS_TMR_STATE_UNUSED the timer has not been created
  460. * OS_TMR_STATE_STOPPED the timer has been created but has not been started or has been stopped
  461. * OS_TMR_STATE_COMPLETED the timer is in ONE-SHOT mode and has completed it's timeout
  462. * OS_TMR_SATE_RUNNING the timer is currently running
  463. *
  464. * Arguments : p_tmr Is a pointer to the desired timer
  465. *
  466. * p_err Is a pointer to an error code. '*p_err' will contain one of the following:
  467. *
  468. * OS_ERR_NONE
  469. * OS_ERR_OBJ_TYPE if 'p_tmr' is not pointing to a timer
  470. * OS_ERR_TMR_INVALID 'p_tmr' is a NULL pointer
  471. * OS_ERR_TMR_INVALID_STATE if the timer is not in a valid state
  472. * OS_ERR_TMR_ISR if the call was made from an ISR
  473. *
  474. * Returns : The current state of the timer (see description).
  475. ************************************************************************************************************************
  476. */
  477. OS_STATE OSTmrStateGet (OS_TMR *p_tmr,
  478. OS_ERR *p_err)
  479. {
  480. OS_STATE state;
  481. #ifdef OS_SAFETY_CRITICAL
  482. if (p_err == (OS_ERR *)0) {
  483. OS_SAFETY_CRITICAL_EXCEPTION();
  484. return (OS_TMR_STATE_UNUSED);
  485. }
  486. #endif
  487. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  488. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
  489. *p_err = OS_ERR_TMR_ISR;
  490. return (OS_TMR_STATE_UNUSED);
  491. }
  492. #endif
  493. #if OS_CFG_ARG_CHK_EN > 0u
  494. if (p_tmr == (OS_TMR *)0) {
  495. *p_err = OS_ERR_TMR_INVALID;
  496. return (OS_TMR_STATE_UNUSED);
  497. }
  498. #endif
  499. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  500. if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
  501. *p_err = OS_ERR_OBJ_TYPE;
  502. return (OS_TMR_STATE_UNUSED);
  503. }
  504. #endif
  505. state = p_tmr->State;
  506. switch (state) {
  507. case OS_TMR_STATE_UNUSED:
  508. case OS_TMR_STATE_STOPPED:
  509. case OS_TMR_STATE_COMPLETED:
  510. case OS_TMR_STATE_RUNNING:
  511. *p_err = OS_ERR_NONE;
  512. break;
  513. default:
  514. *p_err = OS_ERR_TMR_INVALID_STATE;
  515. break;
  516. }
  517. return (state);
  518. }
  519. /*
  520. ************************************************************************************************************************
  521. * STOP A TIMER
  522. *
  523. * Description: This function is called by your application code to stop a timer.
  524. *
  525. * Arguments : p_tmr Is a pointer to the timer to stop.
  526. *
  527. * opt Allows you to specify an option to this functions which can be:
  528. *
  529. * OS_OPT_TMR_NONE Do nothing special but stop the timer
  530. * OS_OPT_TMR_CALLBACK Execute the callback function, pass it the callback argument
  531. * specified when the timer was created.
  532. * OS_OPT_TMR_CALLBACK_ARG Execute the callback function, pass it the callback argument
  533. * specified in THIS function call
  534. *
  535. * callback_arg Is a pointer to a 'new' callback argument that can be passed to the callback function
  536. * instead of the timer's callback argument. In other words, use 'callback_arg' passed in
  537. * THIS function INSTEAD of p_tmr->OSTmrCallbackArg
  538. *
  539. * p_err Is a pointer to an error code. '*p_err' will contain one of the following:
  540. * OS_ERR_NONE
  541. * OS_ERR_OBJ_TYPE if 'p_tmr' is not pointing to a timer
  542. * OS_ERR_OPT_INVALID if you specified an invalid option for 'opt'
  543. * OS_ERR_TMR_INACTIVE if the timer was not created
  544. * OS_ERR_TMR_INVALID 'p_tmr' is a NULL pointer
  545. * OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
  546. * OS_ERR_TMR_ISR if the function was called from an ISR
  547. * OS_ERR_TMR_NO_CALLBACK if the timer does not have a callback function defined
  548. * OS_ERR_TMR_STOPPED if the timer was already stopped
  549. *
  550. * Returns : DEF_TRUE If we stopped the timer (if the timer is already stopped, we also return DEF_TRUE)
  551. * DEF_FALSE If not
  552. ************************************************************************************************************************
  553. */
  554. CPU_BOOLEAN OSTmrStop (OS_TMR *p_tmr,
  555. OS_OPT opt,
  556. void *p_callback_arg,
  557. OS_ERR *p_err)
  558. {
  559. OS_TMR_CALLBACK_PTR p_fnct;
  560. CPU_BOOLEAN success;
  561. #ifdef OS_SAFETY_CRITICAL
  562. if (p_err == (OS_ERR *)0) {
  563. OS_SAFETY_CRITICAL_EXCEPTION();
  564. return (DEF_FALSE);
  565. }
  566. #endif
  567. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  568. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
  569. *p_err = OS_ERR_TMR_ISR;
  570. return (DEF_FALSE);
  571. }
  572. #endif
  573. #if OS_CFG_ARG_CHK_EN > 0u
  574. if (p_tmr == (OS_TMR *)0) {
  575. *p_err = OS_ERR_TMR_INVALID;
  576. return (DEF_FALSE);
  577. }
  578. #endif
  579. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  580. if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
  581. *p_err = OS_ERR_OBJ_TYPE;
  582. return (DEF_FALSE);
  583. }
  584. #endif
  585. switch (p_tmr->State) {
  586. case OS_TMR_STATE_RUNNING:
  587. OS_TmrLock();
  588. OS_TmrUnlink(p_tmr); /* Remove from timer list */
  589. *p_err = OS_ERR_NONE;
  590. switch (opt) {
  591. case OS_OPT_TMR_CALLBACK:
  592. p_fnct = p_tmr->CallbackPtr; /* Execute callback function ... */
  593. if (p_fnct != (OS_TMR_CALLBACK_PTR)0) { /* ... if available */
  594. (*p_fnct)((void *)p_tmr, p_tmr->CallbackPtrArg); /* Use callback arg when timer was created */
  595. } else {
  596. *p_err = OS_ERR_TMR_NO_CALLBACK;
  597. }
  598. break;
  599. case OS_OPT_TMR_CALLBACK_ARG:
  600. p_fnct = p_tmr->CallbackPtr; /* Execute callback function if available ... */
  601. if (p_fnct != (OS_TMR_CALLBACK_PTR)0) {
  602. (*p_fnct)((void *)p_tmr, p_callback_arg); /* .. using the 'callback_arg' provided in call */
  603. } else {
  604. *p_err = OS_ERR_TMR_NO_CALLBACK;
  605. }
  606. break;
  607. case OS_OPT_TMR_NONE:
  608. break;
  609. default:
  610. OS_TmrUnlock();
  611. *p_err = OS_ERR_OPT_INVALID;
  612. return (DEF_FALSE);
  613. }
  614. OS_TmrUnlock();
  615. success = DEF_TRUE;
  616. break;
  617. case OS_TMR_STATE_COMPLETED: /* Timer has already completed the ONE-SHOT or */
  618. case OS_TMR_STATE_STOPPED: /* ... timer has not started yet. */
  619. *p_err = OS_ERR_TMR_STOPPED;
  620. success = DEF_TRUE;
  621. break;
  622. case OS_TMR_STATE_UNUSED: /* Timer was not created */
  623. *p_err = OS_ERR_TMR_INACTIVE;
  624. success = DEF_FALSE;
  625. break;
  626. default:
  627. *p_err = OS_ERR_TMR_INVALID_STATE;
  628. success = DEF_FALSE;
  629. break;
  630. }
  631. return (success);
  632. }
  633. /*
  634. ************************************************************************************************************************
  635. * CLEAR TIMER FIELDS
  636. *
  637. * Description: This function is called to clear all timer fields.
  638. *
  639. * Argument(s): p_tmr Is a pointer to the timer to clear
  640. * -----
  641. *
  642. * Returns : none
  643. *
  644. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  645. ************************************************************************************************************************
  646. */
  647. void OS_TmrClr (OS_TMR *p_tmr)
  648. {
  649. p_tmr->State = OS_TMR_STATE_UNUSED; /* Clear timer fields */
  650. #if OS_OBJ_TYPE_REQ > 0u
  651. p_tmr->Type = OS_OBJ_TYPE_NONE;
  652. #endif
  653. #if OS_CFG_DBG_EN > 0u
  654. p_tmr->NamePtr = (CPU_CHAR *)((void *)"?TMR");
  655. #endif
  656. p_tmr->Dly = (OS_TICK )0;
  657. p_tmr->Remain = (OS_TICK )0;
  658. p_tmr->Period = (OS_TICK )0;
  659. p_tmr->Opt = (OS_OPT )0;
  660. p_tmr->CallbackPtr = (OS_TMR_CALLBACK_PTR)0;
  661. p_tmr->CallbackPtrArg = (void *)0;
  662. p_tmr->NextPtr = (OS_TMR *)0;
  663. p_tmr->PrevPtr = (OS_TMR *)0;
  664. }
  665. /*
  666. ************************************************************************************************************************
  667. * ADD/REMOVE TIMER TO/FROM DEBUG TABLE
  668. *
  669. * Description: These functions are called by uC/OS-III to add or remove a timer to/from a timer debug table.
  670. *
  671. * Arguments : p_tmr is a pointer to the timer to add/remove
  672. *
  673. * Returns : none
  674. *
  675. * Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
  676. ************************************************************************************************************************
  677. */
  678. #if OS_CFG_DBG_EN > 0u
  679. void OS_TmrDbgListAdd (OS_TMR *p_tmr)
  680. {
  681. p_tmr->DbgPrevPtr = (OS_TMR *)0;
  682. if (OSTmrDbgListPtr == (OS_TMR *)0) {
  683. p_tmr->DbgNextPtr = (OS_TMR *)0;
  684. } else {
  685. p_tmr->DbgNextPtr = OSTmrDbgListPtr;
  686. OSTmrDbgListPtr->DbgPrevPtr = p_tmr;
  687. }
  688. OSTmrDbgListPtr = p_tmr;
  689. }
  690. void OS_TmrDbgListRemove (OS_TMR *p_tmr)
  691. {
  692. OS_TMR *p_tmr_next;
  693. OS_TMR *p_tmr_prev;
  694. p_tmr_prev = p_tmr->DbgPrevPtr;
  695. p_tmr_next = p_tmr->DbgNextPtr;
  696. if (p_tmr_prev == (OS_TMR *)0) {
  697. OSTmrDbgListPtr = p_tmr_next;
  698. if (p_tmr_next != (OS_TMR *)0) {
  699. p_tmr_next->DbgPrevPtr = (OS_TMR *)0;
  700. }
  701. p_tmr->DbgNextPtr = (OS_TMR *)0;
  702. } else if (p_tmr_next == (OS_TMR *)0) {
  703. p_tmr_prev->DbgNextPtr = (OS_TMR *)0;
  704. p_tmr->DbgPrevPtr = (OS_TMR *)0;
  705. } else {
  706. p_tmr_prev->DbgNextPtr = p_tmr_next;
  707. p_tmr_next->DbgPrevPtr = p_tmr_prev;
  708. p_tmr->DbgNextPtr = (OS_TMR *)0;
  709. p_tmr->DbgPrevPtr = (OS_TMR *)0;
  710. }
  711. }
  712. #endif
  713. /*
  714. ************************************************************************************************************************
  715. * INITIALIZE THE TIMER MANAGER
  716. *
  717. * Description: This function is called by OSInit() to initialize the timer manager module.
  718. *
  719. * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
  720. *
  721. * OS_ERR_NONE
  722. * OS_ERR_TMR_STK_INVALID if you didn't specify a stack for the timer task
  723. * OS_ERR_TMR_STK_SIZE_INVALID if you didn't allocate enough space for the timer stack
  724. * OS_ERR_PRIO_INVALID if you specified the same priority as the idle task
  725. * OS_ERR_xxx any error code returned by OSTaskCreate()
  726. *
  727. * Returns : none
  728. *
  729. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  730. ************************************************************************************************************************
  731. */
  732. void OS_TmrInit (OS_ERR *p_err)
  733. {
  734. #ifdef OS_SAFETY_CRITICAL
  735. if (p_err == (OS_ERR *)0) {
  736. OS_SAFETY_CRITICAL_EXCEPTION();
  737. return;
  738. }
  739. #endif
  740. #if OS_CFG_DBG_EN > 0u
  741. OSTmrDbgListPtr = (OS_TMR *)0;
  742. #endif
  743. OSTmrListPtr = (OS_TMR *)0; /* Create an empty timer list */
  744. OSTmrListEntries = 0u;
  745. if (OSCfg_TmrTaskRate_Hz > (OS_RATE_HZ)0) {
  746. OSTmrUpdateCnt = OSCfg_TickRate_Hz / OSCfg_TmrTaskRate_Hz;
  747. } else {
  748. OSTmrUpdateCnt = OSCfg_TickRate_Hz / (OS_RATE_HZ)10;
  749. }
  750. OSTmrUpdateCtr = OSTmrUpdateCnt;
  751. OSTmrTickCtr = (OS_TICK)0;
  752. OSTmrTaskTimeMax = (CPU_TS)0;
  753. #if OS_CFG_MUTEX_EN > 0u
  754. OSMutexCreate(&OSTmrMutex, /* Use a mutex to protect the timers */
  755. "OS Tmr Mutex",
  756. p_err);
  757. if (*p_err != OS_ERR_NONE) {
  758. return;
  759. }
  760. #endif
  761. /* ---------------- CREATE THE TIMER TASK --------------- */
  762. if (OSCfg_TmrTaskStkBasePtr == (CPU_STK*)0) {
  763. *p_err = OS_ERR_TMR_STK_INVALID;
  764. return;
  765. }
  766. if (OSCfg_TmrTaskStkSize < OSCfg_StkSizeMin) {
  767. *p_err = OS_ERR_TMR_STK_SIZE_INVALID;
  768. return;
  769. }
  770. if (OSCfg_TmrTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
  771. *p_err = OS_ERR_TMR_PRIO_INVALID;
  772. return;
  773. }
  774. OSTaskCreate((OS_TCB *)&OSTmrTaskTCB,
  775. (CPU_CHAR *)((void *)"uC/OS-III Timer Task"),
  776. (OS_TASK_PTR )OS_TmrTask,
  777. (void *)0,
  778. (OS_PRIO )OSCfg_TmrTaskPrio,
  779. (CPU_STK *)OSCfg_TmrTaskStkBasePtr,
  780. (CPU_STK_SIZE)OSCfg_TmrTaskStkLimit,
  781. (CPU_STK_SIZE)OSCfg_TmrTaskStkSize,
  782. (OS_MSG_QTY )0,
  783. (OS_TICK )0,
  784. (void *)0,
  785. (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
  786. (OS_ERR *)p_err);
  787. }
  788. /*
  789. ************************************************************************************************************************
  790. * RESET TIMER LIST PEAK DETECTOR
  791. *
  792. * Description: This function is used to reset the peak detector for the number of entries in the timer list
  793. *
  794. * Arguments : void
  795. *
  796. * Returns : none
  797. *
  798. * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
  799. ************************************************************************************************************************
  800. */
  801. void OS_TmrResetPeak (void)
  802. {
  803. }
  804. /*
  805. ************************************************************************************************************************
  806. * REMOVE A TIMER FROM THE TIMER LIST
  807. *
  808. * Description: This function is called to remove the timer from the timer list.
  809. *
  810. * Arguments : p_tmr Is a pointer to the timer to remove.
  811. * -----
  812. *
  813. * Returns : none
  814. *
  815. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  816. ************************************************************************************************************************
  817. */
  818. void OS_TmrUnlink (OS_TMR *p_tmr)
  819. {
  820. OS_TMR *p_tmr1;
  821. OS_TMR *p_tmr2;
  822. if (OSTmrListPtr == p_tmr) { /* See if timer to remove is at the beginning of list */
  823. p_tmr1 = (OS_TMR *)p_tmr->NextPtr;
  824. OSTmrListPtr = (OS_TMR *)p_tmr1;
  825. if (p_tmr1 != (OS_TMR *)0) {
  826. p_tmr1->PrevPtr = (OS_TMR *)0;
  827. }
  828. } else {
  829. p_tmr1 = (OS_TMR *)p_tmr->PrevPtr; /* Remove timer from somewhere in the list */
  830. p_tmr2 = (OS_TMR *)p_tmr->NextPtr;
  831. p_tmr1->NextPtr = p_tmr2;
  832. if (p_tmr2 != (OS_TMR *)0) {
  833. p_tmr2->PrevPtr = (OS_TMR *)p_tmr1;
  834. }
  835. }
  836. p_tmr->State = OS_TMR_STATE_STOPPED;
  837. p_tmr->NextPtr = (OS_TMR *)0;
  838. p_tmr->PrevPtr = (OS_TMR *)0;
  839. OSTmrListEntries--;
  840. }
  841. /*
  842. ************************************************************************************************************************
  843. * TIMER MANAGEMENT TASK
  844. *
  845. * Description: This task is created by OS_TmrInit().
  846. *
  847. * Arguments : none
  848. *
  849. * Returns : none
  850. *
  851. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  852. ************************************************************************************************************************
  853. */
  854. void OS_TmrTask (void *p_arg)
  855. {
  856. OS_ERR err;
  857. OS_TMR_CALLBACK_PTR p_fnct;
  858. OS_TMR *p_tmr;
  859. OS_TMR *p_tmr_next;
  860. CPU_TS ts;
  861. CPU_TS ts_start;
  862. CPU_TS ts_delta;
  863. (void)&p_arg; /* Not using 'p_arg', prevent compiler warning */
  864. while (DEF_ON) {
  865. (void)OSTaskSemPend((OS_TICK )0, /* Wait for signal indicating time to update tmrs */
  866. (OS_OPT )OS_OPT_PEND_BLOCKING,
  867. (CPU_TS *)&ts,
  868. (OS_ERR *)&err);
  869. OS_TmrLock();
  870. ts_start = OS_TS_GET();
  871. OSTmrTickCtr++; /* Increment the current time */
  872. p_tmr = OSTmrListPtr;
  873. while (p_tmr != (OS_TMR *)0) { /* Update all the timers in the list */
  874. OSSchedLock(&err);
  875. (void)&err;
  876. p_tmr_next = p_tmr->NextPtr;
  877. p_tmr->Remain--;
  878. if (p_tmr->Remain == 0) {
  879. if (p_tmr->Opt == OS_OPT_TMR_PERIODIC) {
  880. p_tmr->Remain = p_tmr->Period; /* Reload the time remaining */
  881. } else {
  882. OS_TmrUnlink(p_tmr); /* Remove from list */
  883. p_tmr->State = OS_TMR_STATE_COMPLETED; /* Indicate that the timer has completed */
  884. }
  885. p_fnct = p_tmr->CallbackPtr; /* Execute callback function if available */
  886. if (p_fnct != (OS_TMR_CALLBACK_PTR)0) {
  887. (*p_fnct)((void *)p_tmr,
  888. p_tmr->CallbackPtrArg);
  889. }
  890. }
  891. p_tmr = p_tmr_next;
  892. OSSchedUnlock(&err);
  893. (void)&err;
  894. }
  895. ts_delta = OS_TS_GET() - ts_start; /* Measure execution time of timer task */
  896. OS_TmrUnlock();
  897. if (OSTmrTaskTimeMax < ts_delta) {
  898. OSTmrTaskTimeMax = ts_delta;
  899. }
  900. }
  901. }
  902. /*
  903. ************************************************************************************************************************
  904. * TIMER MANAGEMENT LOCKING MECHANISM
  905. *
  906. * Description: These functions are use to handle timer critical sections. The preferred method is to use a mutex in
  907. * order to avoid locking the scheduler and also, to avoid calling callback functions while the scheduler is
  908. * locked.
  909. *
  910. * Arguments : none
  911. *
  912. * Returns : none
  913. *
  914. * Note(s) : 1) These function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  915. ************************************************************************************************************************
  916. */
  917. static void OS_TmrLock (void)
  918. {
  919. OS_ERR err;
  920. #if OS_CFG_MUTEX_EN > 0u
  921. CPU_TS ts;
  922. OSMutexPend(&OSTmrMutex, /* Use a mutex to protect the timers */
  923. 0u,
  924. OS_OPT_PEND_BLOCKING,
  925. &ts,
  926. &err);
  927. #else
  928. OSSchedLock(&err); /* Lock the scheduler to protect the timers */
  929. #endif
  930. (void)&err;
  931. }
  932. static void OS_TmrUnlock (void)
  933. {
  934. OS_ERR err;
  935. #if OS_CFG_MUTEX_EN > 0u
  936. OSMutexPost(&OSTmrMutex, /* Use a mutex to protect the timers */
  937. OS_OPT_POST_NONE,
  938. &err);
  939. #else
  940. OSSchedUnlock(&err); /* Lock the scheduler to protect the timers */
  941. #endif
  942. (void)&err;
  943. }
  944. #endif