OSAL_Timers.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /**************************************************************************************************
  2. Filename: OSAL_Timers.c
  3. Revised: $Date: 2010-09-17 16:25:30 -0700 (Fri, 17 Sep 2010) $
  4. Revision: $Revision: 23835 $
  5. Description: OSAL Timer definition and manipulation functions.
  6. Copyright 2004-2009 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. /*********************************************************************
  34. * INCLUDES
  35. */
  36. #include "comdef.h"
  37. #include "OnBoard.h"
  38. #include "OSAL.h"
  39. #include "OSAL_Timers.h"
  40. #include "hal_timer.h"
  41. /*********************************************************************
  42. * MACROS
  43. */
  44. /*********************************************************************
  45. * CONSTANTS
  46. */
  47. /*********************************************************************
  48. * TYPEDEFS
  49. */
  50. typedef struct
  51. {
  52. void *next;
  53. uint16 timeout;
  54. uint16 event_flag;
  55. uint8 task_id;
  56. uint16 reloadTimeout;
  57. } osalTimerRec_t;
  58. /*********************************************************************
  59. * GLOBAL VARIABLES
  60. */
  61. osalTimerRec_t *timerHead;
  62. /*********************************************************************
  63. * EXTERNAL VARIABLES
  64. */
  65. /*********************************************************************
  66. * EXTERNAL FUNCTIONS
  67. */
  68. /*********************************************************************
  69. * LOCAL VARIABLES
  70. */
  71. // Milliseconds since last reboot
  72. static uint32 osal_systemClock;
  73. /*********************************************************************
  74. * LOCAL FUNCTION PROTOTYPES
  75. */
  76. osalTimerRec_t *osalAddTimer( uint8 task_id, uint16 event_flag, uint16 timeout );
  77. osalTimerRec_t *osalFindTimer( uint8 task_id, uint16 event_flag );
  78. void osalDeleteTimer( osalTimerRec_t *rmTimer );
  79. /*********************************************************************
  80. * FUNCTIONS
  81. *********************************************************************/
  82. /*********************************************************************
  83. * @fn osalTimerInit
  84. *
  85. * @brief Initialization for the OSAL Timer System.
  86. *
  87. * @param none
  88. *
  89. * @return
  90. */
  91. void osalTimerInit( void )
  92. {
  93. osal_systemClock = 0;
  94. }
  95. /*********************************************************************
  96. * @fn osalAddTimer
  97. *
  98. * @brief Add a timer to the timer list.
  99. * Ints must be disabled.
  100. *
  101. * @param task_id
  102. * @param event_flag
  103. * @param timeout
  104. *
  105. * @return osalTimerRec_t * - pointer to newly created timer
  106. */
  107. osalTimerRec_t * osalAddTimer( uint8 task_id, uint16 event_flag, uint16 timeout )
  108. {
  109. osalTimerRec_t *newTimer;
  110. osalTimerRec_t *srchTimer;
  111. // Look for an existing timer first
  112. newTimer = osalFindTimer( task_id, event_flag );
  113. if ( newTimer )
  114. {
  115. // Timer is found - update it.
  116. newTimer->timeout = timeout;
  117. return ( newTimer );
  118. }
  119. else
  120. {
  121. // New Timer
  122. newTimer = osal_mem_alloc( sizeof( osalTimerRec_t ) );
  123. if ( newTimer )
  124. {
  125. // Fill in new timer
  126. newTimer->task_id = task_id;
  127. newTimer->event_flag = event_flag;
  128. newTimer->timeout = timeout;
  129. newTimer->next = (void *)NULL;
  130. newTimer->reloadTimeout = 0;
  131. // Does the timer list already exist
  132. if ( timerHead == NULL )
  133. {
  134. // Start task list
  135. timerHead = newTimer;
  136. }
  137. else
  138. {
  139. // Add it to the end of the timer list
  140. srchTimer = timerHead;
  141. // Stop at the last record
  142. while ( srchTimer->next )
  143. srchTimer = srchTimer->next;
  144. // Add to the list
  145. srchTimer->next = newTimer;
  146. }
  147. return ( newTimer );
  148. }
  149. else
  150. return ( (osalTimerRec_t *)NULL );
  151. }
  152. }
  153. /*********************************************************************
  154. * @fn osalFindTimer
  155. *
  156. * @brief Find a timer in a timer list.
  157. * Ints must be disabled.
  158. *
  159. * @param task_id
  160. * @param event_flag
  161. *
  162. * @return osalTimerRec_t *
  163. */
  164. osalTimerRec_t *osalFindTimer( uint8 task_id, uint16 event_flag )
  165. {
  166. osalTimerRec_t *srchTimer;
  167. // Head of the timer list
  168. srchTimer = timerHead;
  169. // Stop when found or at the end
  170. while ( srchTimer )
  171. {
  172. if ( srchTimer->event_flag == event_flag &&
  173. srchTimer->task_id == task_id )
  174. break;
  175. // Not this one, check another
  176. srchTimer = srchTimer->next;
  177. }
  178. return ( srchTimer );
  179. }
  180. /*********************************************************************
  181. * @fn osalDeleteTimer
  182. *
  183. * @brief Delete a timer from a timer list.
  184. *
  185. * @param table
  186. * @param rmTimer
  187. *
  188. * @return none
  189. */
  190. void osalDeleteTimer( osalTimerRec_t *rmTimer )
  191. {
  192. // Does the timer list really exist
  193. if ( rmTimer )
  194. {
  195. // Clear the event flag and osalTimerUpdate() will delete
  196. // the timer from the list.
  197. rmTimer->event_flag = 0;
  198. }
  199. }
  200. /*********************************************************************
  201. * @fn osal_start_timerEx
  202. *
  203. * @brief
  204. *
  205. * This function is called to start a timer to expire in n mSecs.
  206. * When the timer expires, the calling task will get the specified event.
  207. *
  208. * @param uint8 taskID - task id to set timer for
  209. * @param uint16 event_id - event to be notified with
  210. * @param UNINT16 timeout_value - in milliseconds.
  211. *
  212. * @return SUCCESS, or NO_TIMER_AVAIL.
  213. */
  214. uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint16 timeout_value )
  215. {
  216. halIntState_t intState;
  217. osalTimerRec_t *newTimer;
  218. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  219. // Add timer
  220. newTimer = osalAddTimer( taskID, event_id, timeout_value );
  221. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  222. return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL );
  223. }
  224. /*********************************************************************
  225. * @fn osal_start_reload_timer
  226. *
  227. * @brief
  228. *
  229. * This function is called to start a timer to expire in n mSecs.
  230. * When the timer expires, the calling task will get the specified event
  231. * and the timer will be reloaded with the timeout value.
  232. *
  233. * @param uint8 taskID - task id to set timer for
  234. * @param uint16 event_id - event to be notified with
  235. * @param UNINT16 timeout_value - in milliseconds.
  236. *
  237. * @return SUCCESS, or NO_TIMER_AVAIL.
  238. */
  239. uint8 osal_start_reload_timer( uint8 taskID, uint16 event_id, uint16 timeout_value )
  240. {
  241. halIntState_t intState;
  242. osalTimerRec_t *newTimer;
  243. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  244. // Add timer
  245. newTimer = osalAddTimer( taskID, event_id, timeout_value );
  246. if ( newTimer )
  247. {
  248. // Load the reload timeout value
  249. newTimer->reloadTimeout = timeout_value;
  250. }
  251. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  252. return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL );
  253. }
  254. /*********************************************************************
  255. * @fn osal_stop_timerEx
  256. *
  257. * @brief
  258. *
  259. * This function is called to stop a timer that has already been started.
  260. * If ZSUCCESS, the function will cancel the timer and prevent the event
  261. * associated with the timer from being set for the calling task.
  262. *
  263. * @param uint8 task_id - task id of timer to stop
  264. * @param uint16 event_id - identifier of the timer that is to be stopped
  265. *
  266. * @return SUCCESS or INVALID_EVENT_ID
  267. */
  268. uint8 osal_stop_timerEx( uint8 task_id, uint16 event_id )
  269. {
  270. halIntState_t intState;
  271. osalTimerRec_t *foundTimer;
  272. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  273. // Find the timer to stop
  274. foundTimer = osalFindTimer( task_id, event_id );
  275. if ( foundTimer )
  276. {
  277. osalDeleteTimer( foundTimer );
  278. }
  279. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  280. return ( (foundTimer != NULL) ? SUCCESS : INVALID_EVENT_ID );
  281. }
  282. /*********************************************************************
  283. * @fn osal_get_timeoutEx
  284. *
  285. * @brief
  286. *
  287. * @param uint8 task_id - task id of timer to check
  288. * @param uint16 event_id - identifier of timer to be checked
  289. *
  290. * @return Return the timer's tick count if found, zero otherwise.
  291. */
  292. uint16 osal_get_timeoutEx( uint8 task_id, uint16 event_id )
  293. {
  294. halIntState_t intState;
  295. uint16 rtrn = 0;
  296. osalTimerRec_t *tmr;
  297. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  298. tmr = osalFindTimer( task_id, event_id );
  299. if ( tmr )
  300. {
  301. rtrn = tmr->timeout;
  302. }
  303. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  304. return rtrn;
  305. }
  306. /*********************************************************************
  307. * @fn osal_timer_num_active
  308. *
  309. * @brief
  310. *
  311. * This function counts the number of active timers.
  312. *
  313. * @return uint8 - number of timers
  314. */
  315. uint8 osal_timer_num_active( void )
  316. {
  317. halIntState_t intState;
  318. uint8 num_timers = 0;
  319. osalTimerRec_t *srchTimer;
  320. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  321. // Head of the timer list
  322. srchTimer = timerHead;
  323. // Count timers in the list
  324. while ( srchTimer != NULL )
  325. {
  326. num_timers++;
  327. srchTimer = srchTimer->next;
  328. }
  329. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  330. return num_timers;
  331. }
  332. /*********************************************************************
  333. * @fn osalTimerUpdate
  334. *
  335. * @brief Update the timer structures for a timer tick.
  336. *
  337. * @param none
  338. *
  339. * @return none
  340. *********************************************************************/
  341. void osalTimerUpdate( uint16 updateTime )
  342. {
  343. halIntState_t intState;
  344. osalTimerRec_t *srchTimer;
  345. osalTimerRec_t *prevTimer;
  346. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  347. // Update the system time
  348. osal_systemClock += updateTime;
  349. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  350. // Look for open timer slot
  351. if ( timerHead != NULL )
  352. {
  353. // Add it to the end of the timer list
  354. srchTimer = timerHead;
  355. prevTimer = (void *)NULL;
  356. // Look for open timer slot
  357. while ( srchTimer )
  358. {
  359. osalTimerRec_t *freeTimer = NULL;
  360. HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
  361. if (srchTimer->timeout <= updateTime)
  362. {
  363. srchTimer->timeout = 0;
  364. }
  365. else
  366. {
  367. srchTimer->timeout = srchTimer->timeout - updateTime;
  368. }
  369. // Check for reloading
  370. if ( (srchTimer->timeout == 0) && (srchTimer->reloadTimeout) && (srchTimer->event_flag) )
  371. {
  372. // Notify the task of a timeout
  373. osal_set_event( srchTimer->task_id, srchTimer->event_flag );
  374. // Reload the timer timeout value
  375. srchTimer->timeout = srchTimer->reloadTimeout;
  376. }
  377. // When timeout or delete (event_flag == 0)
  378. if ( srchTimer->timeout == 0 || srchTimer->event_flag == 0 )
  379. {
  380. // Take out of list
  381. if ( prevTimer == NULL )
  382. timerHead = srchTimer->next;
  383. else
  384. prevTimer->next = srchTimer->next;
  385. // Setup to free memory
  386. freeTimer = srchTimer;
  387. // Next
  388. srchTimer = srchTimer->next;
  389. }
  390. else
  391. {
  392. // Get next
  393. prevTimer = srchTimer;
  394. srchTimer = srchTimer->next;
  395. }
  396. HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
  397. if ( freeTimer )
  398. {
  399. if ( freeTimer->timeout == 0 )
  400. {
  401. osal_set_event( freeTimer->task_id, freeTimer->event_flag );
  402. }
  403. osal_mem_free( freeTimer );
  404. }
  405. }
  406. }
  407. }
  408. #ifdef POWER_SAVING
  409. /*********************************************************************
  410. * @fn osal_adjust_timers
  411. *
  412. * @brief Update the timer structures for elapsed ticks.
  413. *
  414. * @param none
  415. *
  416. * @return none
  417. *********************************************************************/
  418. void osal_adjust_timers( void )
  419. {
  420. uint16 eTime;
  421. if ( timerHead != NULL )
  422. {
  423. // Compute elapsed time (msec)
  424. eTime = TimerElapsed() / TICK_COUNT;
  425. if ( eTime )
  426. osalTimerUpdate( eTime );
  427. }
  428. }
  429. /*********************************************************************
  430. * @fn osal_next_timeout
  431. *
  432. * @brief
  433. *
  434. * Search timer table to return the lowest timeout value. If the
  435. * timer list is empty, then the returned timeout will be zero.
  436. *
  437. * @param none
  438. *
  439. * @return none
  440. *********************************************************************/
  441. uint16 osal_next_timeout( void )
  442. {
  443. uint16 nextTimeout;
  444. osalTimerRec_t *srchTimer;
  445. if ( timerHead != NULL )
  446. {
  447. // Head of the timer list
  448. srchTimer = timerHead;
  449. nextTimeout = OSAL_TIMERS_MAX_TIMEOUT;
  450. // Look for the next timeout timer
  451. while ( srchTimer != NULL )
  452. {
  453. if (srchTimer->timeout < nextTimeout)
  454. {
  455. nextTimeout = srchTimer->timeout;
  456. }
  457. // Check next timer
  458. srchTimer = srchTimer->next;
  459. }
  460. }
  461. else
  462. {
  463. // No timers
  464. nextTimeout = 0;
  465. }
  466. return ( nextTimeout );
  467. }
  468. #endif // POWER_SAVING
  469. /*********************************************************************
  470. * @fn osal_GetSystemClock()
  471. *
  472. * @brief Read the local system clock.
  473. *
  474. * @param none
  475. *
  476. * @return local clock in milliseconds
  477. */
  478. uint32 osal_GetSystemClock( void )
  479. {
  480. return ( osal_systemClock );
  481. }
  482. /*********************************************************************
  483. *********************************************************************/