EXT_cbtimer.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. /**
  2. * \file EM_timer.c
  3. *
  4. * This File contains source codes for the EtherMind
  5. * Timer Library Implementation for FreeRTOS.
  6. */
  7. /*
  8. * Copyright (C) 2015. Phyplus Ltd.
  9. * All rights reserved.
  10. */
  11. /* ----------------------------------------------- Header File Inclusion */
  12. #include "EXT_cbtimer.h"
  13. //#include "EM_timer_internal.h" //todo
  14. //#include "EXT_cbtimer.h"
  15. #include "OSAL_Clock.h"
  16. #include "gpio.h"
  17. #include "OSAL_Tasks.h"
  18. /* ----------------------------------------------- Global Definitions */
  19. /* Timer Elements */
  20. EXT_CBTIMER_ENTITY ext_cbtimer_entity[EXT_CBTIMER_MAX_ENTITIES];
  21. EXT_CBTIMER_ENTITY *ext_cbtimer_q_start = NULL;
  22. EXT_CBTIMER_ENTITY *ext_cbtimer_q_end = NULL;
  23. #if 0
  24. /* Timer Library Mutex */
  25. EM_thread_mutex_type timer_mutex;
  26. #endif /* 0 */
  27. #if 1
  28. /* Timer */
  29. #if defined ( CBTIMER_NUM_TASKS )
  30. #include "cbTimer.h"
  31. #endif
  32. /* ----------------------------------------------- Static Global Variables */
  33. /*********************************************************************
  34. * CONSTANTS
  35. */
  36. // Number of callback timers supported per task (limited by the number of OSAL event timers)
  37. #define EXT_NUM_CBTIMERS_PER_TASK 16
  38. // Total number of callback timers
  39. #define EXT_NUM_CBTIMERS ( CBTIMER_NUM_TASKS * EXT_NUM_CBTIMERS_PER_TASK )
  40. #define ext_timer_malloc EM_alloc_mem
  41. #define ext_timer_free EM_free_mem
  42. typedef struct
  43. {
  44. extpfnCbTimer_t pfnCbTimer; // callback function to be called when timer expires
  45. uint8 *pData; // data to be passed in to callback function
  46. } ext_cbTimer_t;
  47. ext_cbTimer_t ext_cbTimers[EXT_NUM_CBTIMERS];
  48. uint16 extbaseTaskID = TASK_NO_TASK;
  49. #define EXT_EVENT_ID( timerId ) ( 0x0001 << ( ( timerId ) % EXT_NUM_CBTIMERS_PER_TASK ) )
  50. // Find out task id using timer id
  51. #define EXT_TASK_ID( timerId ) ( ( ( timerId ) / EXT_NUM_CBTIMERS_PER_TASK ) + extbaseTaskID )
  52. // Find out bank task id using task id
  53. #define EXT_BANK_TASK_ID( taskId ) ( ( ( taskId ) - extbaseTaskID ) * EXT_NUM_CBTIMERS_PER_TASK )
  54. /*********************************************************************
  55. * LOCAL FUNCTIONS
  56. */
  57. /*********************************************************************
  58. * API FUNCTIONS
  59. */
  60. EM_RESULT ext_timer_init_entity (EXT_CBTIMER_ENTITY *timer);
  61. EM_RESULT ext_timer_search_entity_timer_id
  62. (
  63. EXT_CBTIMER_ENTITY **timer,
  64. UINT8 handle
  65. );
  66. EM_RESULT ext_timer_del_entity
  67. (
  68. EXT_CBTIMER_ENTITY *timer,
  69. UCHAR free
  70. );
  71. EM_RESULT ext_timer_search_entity ( EXT_CBTIMER_ENTITY *timer );
  72. EM_RESULT ext_timer_add_entity ( EXT_CBTIMER_ENTITY *timer );
  73. #ifdef EXT_CBTIMER_SUPPORT_REMAINING_TIME
  74. /*
  75. * This function returns elapsed time in microsecond since system power on.
  76. */
  77. UINT64 ext_cbtimer_get_ms_timestamp(void);
  78. #endif
  79. /*********************************************************************
  80. * @fn CbTimerInit
  81. *
  82. * @brief Callback Timer task initialization function. This function
  83. * can be called more than once (CBTIMER_NUM_TASKS times).
  84. *
  85. * @param taskId - Message Timer task ID.
  86. *
  87. * @return void
  88. */
  89. void CbTimerInit( uint8 taskId )
  90. {
  91. if ( extbaseTaskID == TASK_NO_TASK )
  92. {
  93. // Only initialize the base task id
  94. extbaseTaskID = taskId;
  95. // Initialize all timer structures
  96. osal_memset( ext_cbTimers, 0, sizeof( ext_cbTimers ) );
  97. }
  98. }
  99. /*********************************************************************
  100. * @fn CbTimerProcessEvent
  101. *
  102. * @brief Callback Timer task event processing function.
  103. *
  104. * @param taskId - task ID.
  105. * @param events - events.
  106. *
  107. * @return events not processed
  108. */
  109. uint16 CbTimerProcessEvent( uint8 taskId, uint16 events )
  110. {
  111. if ( events )
  112. {
  113. uint8 i;
  114. uint16 event;
  115. // Process event timers
  116. for ( i = 0; i < EXT_NUM_CBTIMERS_PER_TASK; i++ )
  117. {
  118. if ( ( events >> i ) & 0x0001 )
  119. {
  120. ext_cbTimer_t *pTimer = &ext_cbTimers[EXT_BANK_TASK_ID( taskId )+i];
  121. // Found the first event
  122. event = 0x0001 << i;
  123. // Timer expired, call the registered callback function
  124. if(pTimer->pData != NULL)
  125. {
  126. pTimer->pfnCbTimer( pTimer->pData );
  127. }
  128. // Mark entry as free
  129. pTimer->pfnCbTimer = NULL;
  130. // Null out data pointer
  131. pTimer->pData = NULL;
  132. // We only process one event at a time
  133. break;
  134. }
  135. }
  136. // return unprocessed events
  137. return ( events ^ event );
  138. }
  139. // If reach here, the events are unknown
  140. // Discard or make more handlers
  141. return 0;
  142. }
  143. /*********************************************************************
  144. * @fn CbTimerStart
  145. *
  146. * @brief This function is called to start a callback timer to expire
  147. * in n mSecs. When the timer expires, the registered callback
  148. * function will be called.
  149. *
  150. * @param pfnCbTimer - callback function to be called when timer expires
  151. * @param pData - data to be passed in to callback function
  152. * @param timeout - in milliseconds.
  153. * @param pTimerId - will point to new timer Id (if not null)
  154. *
  155. * @return Success, or Failure.
  156. */
  157. Status_t CbTimerStart( extpfnCbTimer_t pfnCbTimer, uint8 *pData,
  158. uint16 timeout, uint8 *pTimerId )
  159. {
  160. uint8 i;
  161. // Validate input parameters
  162. if ( pfnCbTimer == NULL )
  163. {
  164. return ( INVALIDPARAMETER );
  165. }
  166. // Look for an unused timer first
  167. for ( i = 0; i < EXT_NUM_CBTIMERS; i++ )
  168. {
  169. if ( ext_cbTimers[i].pfnCbTimer == NULL )
  170. {
  171. // Start the OSAL event timer first
  172. if ( osal_start_timerEx( EXT_TASK_ID( i ), EXT_EVENT_ID( i ), timeout ) == SUCCESS )
  173. {
  174. // Set up the callback timer
  175. ext_cbTimers[i].pfnCbTimer = pfnCbTimer;
  176. ext_cbTimers[i].pData = pData;
  177. if ( pTimerId != NULL )
  178. {
  179. // Caller is intreseted in the timer id
  180. *pTimerId = i;
  181. }
  182. return ( SUCCESS );
  183. }
  184. }
  185. }
  186. // No timer available
  187. return ( NO_TIMER_AVAIL );
  188. }
  189. /*********************************************************************
  190. * @fn CbTimerUpdate
  191. *
  192. * @brief This function is called to update a message timer that has
  193. * already been started. If SUCCESS, the function will update
  194. * the timer's timeout value. If INVALIDPARAMETER, the timer
  195. * either doesn't exit.
  196. *
  197. * @param timerId - identifier of the timer that is to be updated
  198. * @param timeout - new timeout in milliseconds.
  199. *
  200. * @return SUCCESS or INVALIDPARAMETER if timer not found
  201. */
  202. Status_t CbTimerUpdate( uint8 timerId, uint16 timeout )
  203. {
  204. // Look for the existing timer
  205. if ( timerId < EXT_NUM_CBTIMERS )
  206. {
  207. if ( ext_cbTimers[timerId].pfnCbTimer != NULL )
  208. {
  209. // Make sure the corresponding OSAL event timer is still running
  210. if ( osal_get_timeoutEx( EXT_TASK_ID( timerId ), EXT_EVENT_ID( timerId ) ) != 0 )
  211. {
  212. // Timer exists; update it
  213. osal_start_timerEx( EXT_TASK_ID( timerId ), EXT_EVENT_ID( timerId ), timeout );
  214. return ( SUCCESS );
  215. }
  216. }
  217. }
  218. // Timer not found
  219. return ( INVALIDPARAMETER );
  220. }
  221. /*********************************************************************
  222. * @fn CbTimerStop
  223. *
  224. * @brief This function is called to stop a timer that has already been
  225. * started. If SUCCESS, the function will cancel the timer. If
  226. * INVALIDPARAMETER, the timer doesn't exit.
  227. *
  228. * @param timerId - identifier of the timer that is to be stopped
  229. *
  230. * @return SUCCESS or INVALIDPARAMETER if timer not found
  231. */
  232. Status_t CbTimerStop( uint8 timerId )
  233. {
  234. // Look for the existing timer
  235. if ( timerId < EXT_NUM_CBTIMERS )
  236. {
  237. if ( ext_cbTimers[timerId].pfnCbTimer != NULL )
  238. {
  239. // Timer exists; stop the OSAL event timer first
  240. osal_stop_timerEx( EXT_TASK_ID( timerId ), EXT_EVENT_ID( timerId ) );
  241. // Mark entry as free
  242. ext_cbTimers[timerId].pfnCbTimer = NULL;
  243. // Null out data pointer
  244. ext_cbTimers[timerId].pData = NULL;
  245. return ( SUCCESS );
  246. }
  247. }
  248. // Timer not found
  249. return ( INVALIDPARAMETER );
  250. }
  251. #endif
  252. #undef EM_RESTART_TIMER
  253. /* ----------------------------------------------- Functions */
  254. void EXT_cbtimer_init (void)
  255. {
  256. UINT16 index;
  257. // EM_TIMER_TRC(
  258. // "Initializing EtherMind Timer Library Module ...\n");
  259. #if 0
  260. /* Initialize Timer Mutex */
  261. EM_thread_mutex_init(&timer_mutex, NULL);
  262. #endif /* 0 */
  263. /* Initialize Timer Elements */
  264. for (index = 0; index < EXT_CBTIMER_MAX_ENTITIES; index ++)
  265. {
  266. ext_timer_init_entity(&ext_cbtimer_entity[index]);
  267. ext_cbtimer_entity[index].timer_id = EXT_PHYOS_INVALID_TIMER_ID;
  268. ext_cbtimer_entity[index].handle = index;
  269. }
  270. return;
  271. }
  272. void ext_cbtimer_em_init ( void )
  273. {
  274. EXT_CBTIMER_ENTITY *timer;
  275. UINT16 index;
  276. /* Lock Timer */
  277. // timer_lock();
  278. // EM_TIMER_TRC(
  279. // "Stack ON Initialization for Timer Library ...\n");
  280. /* Initialize Timer Entities */
  281. for (index = 0; index < EXT_CBTIMER_MAX_ENTITIES; index ++)
  282. {
  283. timer = &ext_cbtimer_entity[index];
  284. timer->timer_id = EXT_PHYOS_INVALID_TIMER_ID;
  285. }
  286. /* Initialize Timer Q */
  287. ext_cbtimer_q_start = ext_cbtimer_q_end = NULL;
  288. // timer_unlock();
  289. return;
  290. }
  291. EM_RESULT EXT_cbtimer_start_timer
  292. (
  293. EXT_cbtimer_handle *handle,
  294. UINT32 timeout,
  295. void (* callback) (void *, UINT16),
  296. void *data,
  297. UINT16 data_length
  298. )
  299. {
  300. UCHAR *data_ptr = NULL;
  301. EM_RESULT retval;
  302. EXT_CBTIMER_ENTITY current_timer;
  303. // HZF
  304. osalTimeUpdate();
  305. if (NULL == handle)
  306. {
  307. // EM_TIMER_ERR(
  308. // "NULL Argument Unacceptable for Timer Handles.\n");
  309. return EXT_CBTIMER_HANDLE_IS_NULL;
  310. }
  311. // EM_TIMER_TRC(
  312. // "Preparing to Add New Timer Entity. Timeout = %d, Data Size = %d.\n",
  313. // timeout, data_length);
  314. /* Timer Library expects to have a valid callback */
  315. if (NULL == callback)
  316. {
  317. // EM_TIMER_ERR(
  318. // "FAILED to Add New Timer Element. NULL Callback.\n");
  319. return EXT_CBTIMER_CALLBACK_IS_NULL;
  320. }
  321. if (0 != data_length)
  322. {
  323. if (data_length > EXT_CBTIMER_STATIC_DATA_SIZE)
  324. {
  325. data_ptr = (UCHAR *) ext_timer_malloc (data_length);
  326. if (NULL == data_ptr)
  327. {
  328. // EM_TIMER_ERR(
  329. // "FAILED to allocate Memory for Timer Handler Argument.\n");
  330. return EXT_CBTIMER_MEMORY_ALLOCATION_FAILED;
  331. }
  332. current_timer.allocated_data = data_ptr;
  333. }
  334. else
  335. {
  336. data_ptr = current_timer.static_data;
  337. }
  338. /* Copy the Data to be passed to the Timer Handler */
  339. EM_mem_copy(data_ptr, data, data_length);
  340. }
  341. /* Store Timer Data Length, Callback & Timeout */
  342. current_timer.callback = callback;
  343. current_timer.data_length = data_length;
  344. current_timer.timeout = timeout;
  345. /* Lock Timer */
  346. // timer_lock();
  347. /* Insert this Timer Entity into the List */
  348. retval = ext_timer_add_entity(&current_timer);
  349. if (EM_SUCCESS != retval)
  350. {
  351. // EM_TIMER_ERR(
  352. // "FAILED to Add New Timer to Timer Queue. Error Code = 0x%04X\n",
  353. // retval);
  354. if (current_timer.data_length > EXT_CBTIMER_STATIC_DATA_SIZE)
  355. {
  356. ext_timer_free (current_timer.allocated_data);
  357. }
  358. // timer_unlock();
  359. return retval;
  360. }
  361. /* Store the Handle */
  362. *handle = current_timer.handle;
  363. // printf(
  364. // "Successfully Added EXT New Timer to Timer Queue. Handle = 0x%02X\n",
  365. // *handle);
  366. // timer_unlock();
  367. return EM_SUCCESS;
  368. }
  369. void ext_cbtimer_em_shutdown ( void )
  370. {
  371. UINT16 index;
  372. EXT_CBTIMER_ENTITY *timer;
  373. /* Lock Timer */
  374. // timer_lock();
  375. /* Initialize Timer Q */
  376. ext_cbtimer_q_start = ext_cbtimer_q_end = NULL;
  377. /* Initialize Timer Entities */
  378. for (index = 0; index < EXT_CBTIMER_MAX_ENTITIES; index++)
  379. {
  380. timer = &ext_cbtimer_entity[index];
  381. if (EXT_CBTIMER_ENTITY_IN_USE == timer->in_use)
  382. {
  383. /* Stop Timer */
  384. CbTimerStop(timer->timer_id);
  385. if (timer->data_length > EXT_CBTIMER_STATIC_DATA_SIZE)
  386. {
  387. ext_timer_free(timer->allocated_data);
  388. }
  389. ext_timer_init_entity(timer);
  390. timer->timer_id = EXT_PHYOS_INVALID_TIMER_ID;
  391. }
  392. }
  393. // EM_TIMER_TRC(
  394. // "Stack OFF on Timer Library Module ...\n");
  395. // timer_unlock();
  396. return;
  397. }
  398. //Status_t osal_CbTimerStart32( pfnCbTimer_t pfnCbTimer, uint8 *pData,
  399. // uint32 timeout, uint8 *pTimerId )
  400. //{
  401. // uint8 i;
  402. //
  403. // // Validate input parameters
  404. // if ( pfnCbTimer == NULL )
  405. // {
  406. // return ( INVALIDPARAMETER );
  407. // }
  408. // // Look for an unused timer first
  409. // for ( i = 0; i < NUM_CBTIMERS32; i++ )
  410. // {
  411. // if ( cbTimers[i].pfnCbTimer == NULL )
  412. // {
  413. // // Start the OSAL event timer first
  414. // if ( osal_start_timerEx( TASK_ID32( i ), EVENT_ID32( i ), timeout ) == SUCCESS )
  415. // {
  416. // // Set up the callback timer
  417. // cbTimers[i].pfnCbTimer = pfnCbTimer;
  418. // cbTimers[i].pData = pData;
  419. // if ( pTimerId != NULL )
  420. // {
  421. // // Caller is intreseted in the timer id
  422. // *pTimerId = i;
  423. // }
  424. // return ( SUCCESS );
  425. // }
  426. // }
  427. // }
  428. // // No timer available
  429. // return ( NO_TIMER_AVAIL );
  430. //}
  431. /* Callback registered with timer module */
  432. void ext_cbtimer_timeout_handler (UINT8 * handle)
  433. {
  434. EM_RESULT retval;
  435. EXT_CBTIMER_ENTITY *timer;
  436. // EM_TIMER_TRC (
  437. // "In Timer handler (Timer Handle: 0x%02X)\n", *handle);
  438. /* Lock Timer */
  439. // timer_lock();
  440. /* Get the appropriate timer entity */
  441. retval = ext_timer_search_entity_timer_id (&timer, *handle);
  442. if (EM_SUCCESS != retval)
  443. {
  444. // EM_TIMER_ERR(
  445. // "*** UNKNOWN Spurious Timeout Callback?!?!\n");
  446. /* Unlock Timer */
  447. // timer_unlock ();
  448. return;
  449. }
  450. /* Unlock Timer */
  451. // timer_unlock ();
  452. if (timer->data_length > EXT_CBTIMER_STATIC_DATA_SIZE)
  453. {
  454. /* Call the registered timeout handler */
  455. timer->callback (timer->allocated_data, timer->data_length);
  456. }
  457. else
  458. {
  459. /* Use Static Data */
  460. timer->callback (timer->static_data, timer->data_length);
  461. }
  462. /* Lock Timer */
  463. // timer_lock ();
  464. #if 0
  465. /* Stop Timer */
  466. xTimerStop (timer->timer_id, 0);
  467. #endif /* 0 */
  468. /* Free the Timer */
  469. retval = ext_timer_del_entity (timer, 1);
  470. if (EM_SUCCESS != retval)
  471. {
  472. // EM_TIMER_ERR(
  473. // "FAILED to find Timer Element. Handle = 0x%02X. Error Code = 0x%04X\n",
  474. // handle, retval);
  475. printf(
  476. "FAILED to find Timer Element. Handle = 0x%02X. Error Code = 0x%04X\n",
  477. *handle, retval);
  478. }
  479. /* Unlock Timer */
  480. // timer_unlock ();
  481. return;
  482. }
  483. EM_RESULT EXT_cbtimer_stop_timer
  484. (
  485. EXT_cbtimer_handle handle
  486. )
  487. {
  488. EXT_CBTIMER_ENTITY *timer;
  489. EM_RESULT retval;
  490. UINT8 timer_id;
  491. UINT32 new_timeout;
  492. Status_t status;
  493. if (EXT_CBTIMER_MAX_ENTITIES <= handle)
  494. {
  495. // EM_TIMER_ERR(
  496. // "NULL Argument Unacceptable for Timer Handles.\r\n");
  497. /* TODO: Use appropriate error value */
  498. return EXT_CBTIMER_HANDLE_IS_NULL;
  499. }
  500. retval = EM_FAILURE;
  501. /* Lock Timer */
  502. // timer_lock();
  503. timer = &ext_cbtimer_entity[handle];
  504. /* Store the timer id before deleting entity */
  505. timer_id = timer->timer_id;
  506. new_timeout = 0x10;
  507. if(CbTimerUpdate(timer_id,new_timeout) == EM_SUCCESS)
  508. {
  509. retval = ext_timer_del_entity(timer, 0x01);
  510. if (EM_SUCCESS != retval)
  511. {
  512. // EM_TIMER_ERR(
  513. // "FAILED to find Timer Element. Handle = 0x%02X. Error Code = 0x%04X\n",
  514. // handle, retval);
  515. printf(
  516. "FAILED to find Timer Element. Handle = 0x%02X. Error Code = 0x%04X\n",
  517. handle, retval);
  518. }
  519. else
  520. {
  521. // EM_TIMER_TRC(
  522. // "Successfully Deleted Timer Element for Handle 0x%02X.\n",
  523. // handle);
  524. /* Stop Timer */
  525. status = CbTimerStop(timer_id);
  526. osal_clear_event(EXT_TASK_ID( timer->timer_id ),EXT_EVENT_ID( timer->timer_id ));
  527. if (SUCCESS != status)
  528. {
  529. retval = EM_FAILURE;
  530. }
  531. // EM_TIMER_TRC("*** Stopped Timer [ID: %04X]\n",
  532. // timer_id);
  533. }
  534. }
  535. /* Unlock Timer */
  536. // timer_unlock();
  537. return retval;
  538. }
  539. UINT32 EXT_cbtimer_get_remain_timer
  540. (
  541. EXT_cbtimer_handle handle
  542. )
  543. {
  544. EXT_CBTIMER_ENTITY *timer;
  545. UINT32 remain_timeout;
  546. if (EXT_CBTIMER_MAX_ENTITIES <= handle)
  547. {
  548. // EM_TIMER_ERR(
  549. // "NULL Argument Unacceptable for Timer Handles.\r\n");
  550. /* TODO: Use appropriate error value */
  551. return EXT_CBTIMER_HANDLE_IS_NULL;
  552. }
  553. /* Lock Timer */
  554. // timer_lock();
  555. timer = &ext_cbtimer_entity[handle];
  556. remain_timeout = osal_get_timeoutEx(EXT_TASK_ID( timer->timer_id ),EXT_EVENT_ID( timer->timer_id ));
  557. /* Unlock Timer */
  558. // timer_unlock();
  559. return remain_timeout;
  560. }
  561. EM_RESULT EXT_cbtimer_restart_timer
  562. (
  563. EXT_cbtimer_handle handle,
  564. UINT32 new_timeout
  565. )
  566. {
  567. EXT_CBTIMER_ENTITY *timer;
  568. EM_RESULT retval;
  569. if (EXT_CBTIMER_MAX_ENTITIES <= handle)
  570. {
  571. // EM_TIMER_ERR(
  572. // "NULL Argument Unacceptable for Timer Handles.\n");
  573. /* TODO: Use appropriate error value */
  574. return EXT_CBTIMER_HANDLE_IS_NULL;
  575. }
  576. // timer_lock();
  577. timer = &ext_cbtimer_entity[handle];
  578. retval = ext_timer_search_entity(timer);
  579. if (EM_SUCCESS != retval)
  580. {
  581. // EM_TIMER_ERR(
  582. // "FAILED to Find Timer ELement for Handle 0x%02X. Error Code = 0x%04X\n",
  583. // handle, retval);
  584. }
  585. else
  586. {
  587. if(CbTimerUpdate(timer->timer_id,new_timeout) == EM_SUCCESS)
  588. {
  589. return ( SUCCESS );
  590. }
  591. }
  592. // No timer available
  593. return ( NO_TIMER_AVAIL );
  594. }
  595. EM_RESULT EXT_cbtimer_is_active_timer
  596. (
  597. EXT_cbtimer_handle handle
  598. )
  599. {
  600. EXT_CBTIMER_ENTITY *timer;
  601. EM_RESULT retval;
  602. if (EXT_CBTIMER_MAX_ENTITIES <= handle)
  603. {
  604. // EM_TIMER_ERR(
  605. // "NULL Argument Unacceptable for Timer Handles.\n");
  606. /* TODO: Use appropriate error value */
  607. return EXT_CBTIMER_HANDLE_IS_NULL;
  608. }
  609. /* Lock Timer */
  610. // timer_lock();
  611. timer = &ext_cbtimer_entity[handle];
  612. retval = ext_timer_search_entity(timer);
  613. if (EM_SUCCESS != retval)
  614. {
  615. // EM_TIMER_ERR(
  616. // "FAILED to Find the Timer Entity for Handle 0x%02X. Error Code = 0x%04X\n",
  617. // handle, retval);
  618. }
  619. // timer_unlock();
  620. return retval;
  621. }
  622. EM_RESULT ext_timer_search_entity ( EXT_CBTIMER_ENTITY *timer )
  623. {
  624. EXT_CBTIMER_ENTITY *current_timer;
  625. /* Is Queue Empty */
  626. if (NULL == ext_cbtimer_q_start)
  627. {
  628. return EXT_CBTIMER_QUEUE_EMPTY;
  629. }
  630. /* Handle the first Element */
  631. if (timer == ext_cbtimer_q_start)
  632. {
  633. return EM_SUCCESS;
  634. }
  635. current_timer = ext_cbtimer_q_start->next;
  636. while (NULL != current_timer)
  637. {
  638. if (timer == current_timer)
  639. {
  640. return EM_SUCCESS;
  641. }
  642. current_timer = current_timer->next;
  643. }
  644. return EXT_CBTIMER_ENTITY_SEARCH_FAILED;
  645. }
  646. /* Get the timer based on obtained timer id */
  647. EM_RESULT ext_timer_search_entity_timer_id
  648. (
  649. EXT_CBTIMER_ENTITY **timer,
  650. UINT8 handle
  651. )
  652. {
  653. EXT_CBTIMER_ENTITY *current_timer;
  654. /* Is Queue Empty */
  655. if (NULL == ext_cbtimer_q_start)
  656. {
  657. return EXT_CBTIMER_QUEUE_EMPTY;
  658. }
  659. /* Handle the first Element */
  660. if (handle == ext_cbtimer_q_start->handle)
  661. {
  662. /* Note the timer entity */
  663. *timer = ext_cbtimer_q_start;
  664. return EM_SUCCESS;
  665. }
  666. current_timer = ext_cbtimer_q_start->next;
  667. while (NULL != current_timer)
  668. {
  669. if (handle == current_timer->handle)
  670. {
  671. /* Note the timer entity */
  672. *timer = current_timer;
  673. return EM_SUCCESS;
  674. }
  675. current_timer = current_timer->next;
  676. }
  677. return EXT_CBTIMER_ENTITY_SEARCH_FAILED;
  678. }
  679. EM_RESULT ext_timer_add_entity ( EXT_CBTIMER_ENTITY *timer )
  680. {
  681. UINT16 index;
  682. Status_t ret;
  683. EXT_CBTIMER_ENTITY *new_timer;
  684. new_timer = NULL;
  685. for (index = 0; index < EXT_CBTIMER_MAX_ENTITIES; index++)
  686. {
  687. new_timer = &ext_cbtimer_entity[index];
  688. if (EXT_CBTIMER_ENTITY_FREE == new_timer->in_use)
  689. {
  690. new_timer->in_use = EXT_CBTIMER_ENTITY_IN_USE;
  691. break;
  692. }
  693. else
  694. {
  695. new_timer = NULL;
  696. }
  697. }
  698. if (NULL == new_timer)
  699. {
  700. printf(
  701. "FAILED to Allocate EXT New Timer Entity. Timer List FULL !\n");
  702. #ifdef EM_STATUS
  703. /* Timer List Full: Update EtherMind Status Flag */
  704. EM_status_set_bit (STATUS_BIT_TIMER_ENTITY_FULL, STATUS_BIT_SET);
  705. #endif /* EM_STATUS */
  706. return EXT_CBTIMER_QUEUE_FULL;
  707. }
  708. new_timer->next = NULL;
  709. new_timer->timeout = timer->timeout;
  710. new_timer->callback = timer->callback;
  711. new_timer->data_length = timer->data_length;
  712. if (new_timer->data_length > EXT_CBTIMER_STATIC_DATA_SIZE)
  713. {
  714. new_timer->allocated_data = timer->allocated_data;
  715. }
  716. else
  717. {
  718. EM_mem_copy
  719. (
  720. new_timer->static_data,
  721. timer->static_data,
  722. new_timer->data_length
  723. );
  724. }
  725. /* Start the timer */
  726. #ifdef EXT_CBTIMER_SUPPORT_REMAINING_TIME
  727. new_timer->start_timestamp = ext_cbtimer_get_ms_timestamp();
  728. #endif /* EM_TIMER_SUPPORT_REMAINING_TIME */
  729. /* Start timer. Set Timeout. This will also start the timer. */
  730. ret = CbTimerStart
  731. (
  732. ext_cbtimer_timeout_handler,
  733. &new_timer->handle,
  734. ((EXT_CBTIMEOUT_MILLISEC & new_timer->timeout) ?
  735. (new_timer->timeout & (UINT32)~(EXT_CBTIMEOUT_MILLISEC)):
  736. (new_timer->timeout * 1000)),
  737. &new_timer->timer_id
  738. );
  739. if (SUCCESS != ret)
  740. {
  741. // EM_TIMER_ERR("*** FAILED to Start timer\n");
  742. // printf("*** FAILED to Start timer, ret = %d\r\n", ret);
  743. return EXT_CBTIMER_FAILED_SET_TIME_EVENT;
  744. }
  745. // EM_TIMER_TRC("Successfully started Timer [ID: %02X]. Handle: 0x%02X\n",
  746. // new_timer->timer_id, timer->handle);
  747. timer->handle = new_timer->handle;
  748. timer->timer_id = new_timer->timer_id;
  749. /* If the Timer Q Empty */
  750. if (NULL == ext_cbtimer_q_start)
  751. {
  752. ext_cbtimer_q_start = ext_cbtimer_q_end = new_timer;
  753. return EM_SUCCESS;
  754. }
  755. ext_cbtimer_q_end->next = new_timer;
  756. ext_cbtimer_q_end = new_timer;
  757. return EM_SUCCESS;
  758. }
  759. EM_RESULT ext_timer_del_entity
  760. (
  761. EXT_CBTIMER_ENTITY *timer,
  762. UCHAR free
  763. )
  764. {
  765. EXT_CBTIMER_ENTITY *current_timer, *previous_timer;
  766. /* Either None or One Element */
  767. if (ext_cbtimer_q_start == ext_cbtimer_q_end)
  768. {
  769. if (NULL == ext_cbtimer_q_start)
  770. {
  771. /* Queue is Empty */
  772. return EXT_CBTIMER_QUEUE_EMPTY;
  773. }
  774. else
  775. {
  776. if (timer == ext_cbtimer_q_start)
  777. {
  778. /* Queue has One Element */
  779. ext_cbtimer_q_start = ext_cbtimer_q_end = NULL;
  780. }
  781. else
  782. {
  783. /* Match NOT found in the Only element in Timer Queue */
  784. return EXT_CBTIMER_ENTITY_SEARCH_FAILED;
  785. }
  786. }
  787. }
  788. else
  789. {
  790. /* Queue has more than One Element */
  791. if (timer == ext_cbtimer_q_start)
  792. {
  793. /* Match in the First Element */
  794. ext_cbtimer_q_start = ext_cbtimer_q_start->next;
  795. }
  796. else
  797. {
  798. previous_timer = ext_cbtimer_q_start;
  799. current_timer = ext_cbtimer_q_start->next;
  800. while (NULL != current_timer)
  801. {
  802. if (timer == current_timer)
  803. {
  804. previous_timer->next = current_timer->next;
  805. if (current_timer == ext_cbtimer_q_end)
  806. {
  807. ext_cbtimer_q_end = previous_timer;
  808. }
  809. break;
  810. }
  811. previous_timer = current_timer;
  812. current_timer = current_timer->next;
  813. }
  814. if (NULL == current_timer)
  815. {
  816. return EXT_CBTIMER_ENTITY_SEARCH_FAILED;
  817. }
  818. }
  819. }
  820. /* Free Allocated Data */
  821. if ((0x01 == free) &&
  822. (timer->data_length > EXT_CBTIMER_STATIC_DATA_SIZE))
  823. {
  824. ext_timer_free (timer->allocated_data);
  825. }
  826. ext_timer_init_entity(timer);
  827. return EM_SUCCESS;
  828. }
  829. EM_RESULT ext_timer_init_entity (EXT_CBTIMER_ENTITY *timer)
  830. {
  831. timer->in_use = EXT_CBTIMER_ENTITY_FREE;
  832. timer->timeout = 0;
  833. timer->callback = NULL;
  834. timer->allocated_data = NULL;
  835. timer->data_length = 0;
  836. timer->next = NULL;
  837. #ifdef EM_TIMER_SUPPORT_REMAINING_TIME
  838. timer->start_timestamp = 0;
  839. #endif /* EM_TIMER_SUPPORT_REMAINING_TIME */
  840. return EM_SUCCESS;
  841. }
  842. #ifdef EXT_CBTIMER_SUPPORT_REMAINING_TIME
  843. /*
  844. * This function returns elapsed time in microsecond since system power on.
  845. */
  846. UINT64 ext_cbtimer_get_ms_timestamp(void)
  847. {
  848. return osal_GetSystemClock();
  849. }
  850. EM_RESULT EXT_cbtimer_get_remaining_time
  851. (
  852. EXT_cbtimer_handle handle,
  853. UINT32 * remaining_time_ms
  854. )
  855. {
  856. EXT_CBTIMER_ENTITY *timer;
  857. EM_RESULT retval;
  858. UINT64 current_timestamp;
  859. UINT32 time_ms;
  860. if (NULL == handle)
  861. {
  862. // EM_TIMER_ERR(
  863. // "NULL Argument Unacceptable for Timer Handles.\n");
  864. return EXT_CBTIMER_HANDLE_IS_NULL;
  865. }
  866. /* Lock Timer */
  867. // timer_lock();
  868. timer = (EXT_CBTIMER_ENTITY *)handle;
  869. retval = ext_timer_search_entity(timer);
  870. if (EM_SUCCESS != retval)
  871. {
  872. // EM_TIMER_ERR(
  873. // "FAILED to Find Timer ELement for Handle %p. Error Code = 0x%04X\n",
  874. // (void *)handle, retval);
  875. }
  876. else
  877. {
  878. time_ms = ((EXT_CBTIMEOUT_MILLISEC & timer->timeout) ?
  879. (timer->timeout & (UINT32)~(EXT_CBTIMEOUT_MILLISEC)) :
  880. (timer->timeout * 1000));
  881. /* Get Current Time */
  882. /* Remaining Time = (Timeout in ms) - (Current Time - Timer Start Time) */
  883. current_timestamp = ext_cbtimer_get_ms_timestamp();
  884. if ((current_timestamp < timer->start_timestamp) ||
  885. (time_ms < (current_timestamp - timer->start_timestamp))
  886. )
  887. {
  888. // EM_TIMER_ERR(
  889. // "FAILED to Find Remaining Time.TO:%d < (CurT:%lld - StartT:%lld\n",
  890. // time_ms, current_timestamp, timer->start_timestamp);
  891. }
  892. else
  893. {
  894. time_ms -= (UINT32)(current_timestamp - timer->start_timestamp);
  895. *remaining_time_ms = time_ms;
  896. // EM_TIMER_TRC(
  897. // "[EM_TIMER] Remaining Time (ms): %d\n", time_ms);
  898. retval = EM_SUCCESS;
  899. }
  900. }
  901. // timer_unlock();
  902. return retval;
  903. }
  904. #endif /* EM_TIMER_SUPPORT_REMAINING_TIME */
  905. EM_RESULT EXT_cbtimer_list_timer ( void )
  906. {
  907. #ifdef EM_TIMERL_DEBUG
  908. UINT16 index, free;
  909. EXT_CBTIMER_ENTITY *timer;
  910. timer_lock();
  911. EM_TIMERL_TRC("\n");
  912. EM_TIMERL_TRC("========================================= \n");
  913. EM_TIMERL_TRC("Start Q = %p\n", ext_cbtimer_q_start);
  914. timer = ext_cbtimer_q_start;
  915. while(NULL != timer)
  916. {
  917. EM_TIMERL_TRC(" Handle = 0x%02X",
  918. timer->handle);
  919. timer = timer->next;
  920. }
  921. EM_TIMERL_TRC("End Q = %p\n", ext_cbtimer_q_end);
  922. free = 0;
  923. for (index = 0; index < EXT_CBTIMER_MAX_ENTITIES; index ++)
  924. {
  925. if (EXT_CBTIMER_ENTITY_FREE == ext_cbtimer_entity[index].in_use)
  926. {
  927. free ++;
  928. }
  929. }
  930. EM_TIMERL_TRC("Max Q Entity = %d, Free = %d\n",
  931. EXT_CBTIMER_MAX_ENTITIES, free);
  932. EM_TIMERL_TRC("========================================= \n");
  933. EM_TIMERL_TRC("\n");
  934. timer_unlock();
  935. #endif /* EM_TIMERL_DEBUG */
  936. return EM_SUCCESS;
  937. }