app_timer_ble_gzll.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include "app_timer.h"
  13. #include <stdlib.h>
  14. #include "nrf.h"
  15. #include "nrf_soc.h"
  16. #include "nrf_delay.h"
  17. #include "app_util_platform.h"
  18. #include "sdk_common.h"
  19. #define RTC1_IRQ_PRI APP_IRQ_PRIORITY_LOW /**< Priority of the RTC1 interrupt (used for checking for timeouts and executing timeout handlers). */
  20. #define SWI_IRQ_PRI APP_IRQ_PRIORITY_LOW /**< Priority of the SWI interrupt (used for updating the timer list). */
  21. // The current design assumes that both interrupt handlers run at the same interrupt level.
  22. // If this is to be changed, protection must be added to prevent them from interrupting each other
  23. // (e.g. by using guard/trigger flags).
  24. STATIC_ASSERT(RTC1_IRQ_PRI == SWI_IRQ_PRI);
  25. #define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */
  26. #define APP_HIGH_USER_ID 0 /**< User Id for the Application High "user". */
  27. #define APP_LOW_USER_ID 1 /**< User Id for the Application Low "user". */
  28. #define THREAD_MODE_USER_ID 2 /**< User Id for the Thread Mode "user". */
  29. #define RTC_COMPARE_OFFSET_MIN 3 /**< Minimum offset between the current RTC counter value and the Capture Compare register. Although the nRF51 Series User Specification recommends this value to be 2, we use 3 to be safer.*/
  30. #define MAX_RTC_TASKS_DELAY 47 /**< Maximum delay until an RTC task is executed. */
  31. #ifdef NRF51
  32. #define SWI_IRQn SWI1_IRQn
  33. #define SWI_IRQHandler SWI1_IRQHandler
  34. #elif defined NRF52
  35. #define SWI_IRQn SWI1_EGU1_IRQn
  36. #define SWI_IRQHandler SWI1_EGU1_IRQHandler
  37. #endif
  38. /**@brief Timer node type. The nodes will be used form a linked list of running timers. */
  39. typedef struct
  40. {
  41. uint32_t ticks_to_expire; /**< Number of ticks from previous timer interrupt to timer expiry. */
  42. uint32_t ticks_at_start; /**< Current RTC counter value when the timer was started. */
  43. uint32_t ticks_first_interval; /**< Number of ticks in the first timer interval. */
  44. uint32_t ticks_periodic_interval; /**< Timer period (for repeating timers). */
  45. bool is_running; /**< True if timer is running, False otherwise. */
  46. app_timer_mode_t mode; /**< Timer mode. */
  47. app_timer_timeout_handler_t p_timeout_handler; /**< Pointer to function to be executed when the timer expires. */
  48. void * p_context; /**< General purpose pointer. Will be passed to the timeout handler when the timer expires. */
  49. void * next; /**< Pointer to the next node. */
  50. } timer_node_t;
  51. STATIC_ASSERT(sizeof(timer_node_t) == APP_TIMER_NODE_SIZE);
  52. /**@brief Set of available timer operation types. */
  53. typedef enum
  54. {
  55. TIMER_USER_OP_TYPE_NONE, /**< Invalid timer operation type. */
  56. TIMER_USER_OP_TYPE_START, /**< Timer operation type Start. */
  57. TIMER_USER_OP_TYPE_STOP, /**< Timer operation type Stop. */
  58. TIMER_USER_OP_TYPE_STOP_ALL /**< Timer operation type Stop All. */
  59. } timer_user_op_type_t;
  60. /**@brief Structure describing a timer start operation. */
  61. typedef struct
  62. {
  63. uint32_t ticks_at_start; /**< Current RTC counter value when the timer was started. */
  64. uint32_t ticks_first_interval; /**< Number of ticks in the first timer interval. */
  65. uint32_t ticks_periodic_interval; /**< Timer period (for repeating timers). */
  66. void * p_context; /**< General purpose pointer. Will be passed to the timeout handler when the timer expires. */
  67. } timer_user_op_start_t;
  68. /**@brief Structure describing a timer operation. */
  69. typedef struct
  70. {
  71. timer_user_op_type_t op_type; /**< Id of timer on which the operation is to be performed. */
  72. timer_node_t * p_node;
  73. union
  74. {
  75. timer_user_op_start_t start; /**< Structure describing a timer start operation. */
  76. } params;
  77. } timer_user_op_t;
  78. STATIC_ASSERT(sizeof(timer_user_op_t) <= APP_TIMER_USER_OP_SIZE);
  79. STATIC_ASSERT(sizeof(timer_user_op_t) % 4 == 0);
  80. /**@brief Structure describing a timer user.
  81. *
  82. * @details For each user of the timer module, there will be a timer operations queue. This queue
  83. * will hold timer operations issued by this user until the timer interrupt handler
  84. * processes these operations. For the current implementation, there will be one user for
  85. * each interrupt level available to the application (APP_HIGH, APP_LOW and THREAD_MODE),
  86. * but the module can easily be modified to e.g. have one queue per process when using an
  87. * RTOS. The purpose of the queues is to be able to have a completely lockless timer
  88. * implementation.
  89. */
  90. typedef struct
  91. {
  92. uint8_t first; /**< Index of first entry to have been inserted in the queue (i.e. the next entry to be executed). */
  93. uint8_t last; /**< Index of last entry to have been inserted in the queue. */
  94. uint8_t user_op_queue_size; /**< Queue size. */
  95. timer_user_op_t * p_user_op_queue; /**< Queue buffer. */
  96. } timer_user_t;
  97. STATIC_ASSERT(sizeof(timer_user_t) == APP_TIMER_USER_SIZE);
  98. STATIC_ASSERT(sizeof(timer_user_t) % 4 == 0);
  99. /**@brief User id type.
  100. *
  101. * @details In the current implementation, this will automatically be generated from the current
  102. * interrupt level.
  103. */
  104. typedef uint32_t timer_user_id_t;
  105. #define CONTEXT_QUEUE_SIZE_MAX (2)
  106. static uint8_t m_user_array_size; /**< Size of timer user array. */
  107. static timer_user_t * mp_users = NULL; /**< Array of timer users. */
  108. static timer_node_t * mp_timer_id_head; /**< First timer in list of running timers. */
  109. static uint32_t m_ticks_latest; /**< Last known RTC counter value. */
  110. static uint32_t m_ticks_elapsed[CONTEXT_QUEUE_SIZE_MAX]; /**< Timer internal elapsed ticks queue. */
  111. static uint8_t m_ticks_elapsed_q_read_ind; /**< Timer internal elapsed ticks queue read index. */
  112. static uint8_t m_ticks_elapsed_q_write_ind; /**< Timer internal elapsed ticks queue write index. */
  113. static app_timer_evt_schedule_func_t m_evt_schedule_func; /**< Pointer to function for propagating timeout events to the scheduler. */
  114. static bool m_rtc1_running; /**< Boolean indicating if RTC1 is running. */
  115. static bool m_rtc1_reset; /**< Boolean indicating if RTC1 counter has been reset due to last timer removed from timer list during the timer list handling. */
  116. #define MODULE_INITIALIZED (mp_users != NULL)
  117. #include "sdk_macros.h"
  118. /**@brief Function for initializing the RTC1 counter.
  119. *
  120. * @param[in] prescaler Value of the RTC1 PRESCALER register. Set to 0 for no prescaling.
  121. */
  122. static void rtc1_init(uint32_t prescaler)
  123. {
  124. NRF_RTC1->PRESCALER = prescaler;
  125. NVIC_SetPriority(RTC1_IRQn, RTC1_IRQ_PRI);
  126. }
  127. /**@brief Function for starting the RTC1 timer.
  128. */
  129. static void rtc1_start(void)
  130. {
  131. NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk;
  132. NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;
  133. NVIC_ClearPendingIRQ(RTC1_IRQn);
  134. NVIC_EnableIRQ(RTC1_IRQn);
  135. NRF_RTC1->TASKS_START = 1;
  136. nrf_delay_us(MAX_RTC_TASKS_DELAY);
  137. m_rtc1_running = true;
  138. }
  139. /**@brief Function for stopping the RTC1 timer.
  140. */
  141. static void rtc1_stop(void)
  142. {
  143. NVIC_DisableIRQ(RTC1_IRQn);
  144. NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
  145. NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
  146. NRF_RTC1->TASKS_STOP = 1;
  147. nrf_delay_us(MAX_RTC_TASKS_DELAY);
  148. NRF_RTC1->TASKS_CLEAR = 1;
  149. m_ticks_latest = 0;
  150. nrf_delay_us(MAX_RTC_TASKS_DELAY);
  151. m_rtc1_running = false;
  152. }
  153. /**@brief Function for returning the current value of the RTC1 counter.
  154. *
  155. * @return Current value of the RTC1 counter.
  156. */
  157. static __INLINE uint32_t rtc1_counter_get(void)
  158. {
  159. return NRF_RTC1->COUNTER;
  160. }
  161. /**@brief Function for computing the difference between two RTC1 counter values.
  162. *
  163. * @return Number of ticks elapsed from ticks_old to ticks_now.
  164. */
  165. static __INLINE uint32_t ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old)
  166. {
  167. return ((ticks_now - ticks_old) & MAX_RTC_COUNTER_VAL);
  168. }
  169. /**@brief Function for setting the RTC1 Capture Compare register 0, and enabling the corresponding
  170. * event.
  171. *
  172. * @param[in] value New value of Capture Compare register 0.
  173. */
  174. static __INLINE void rtc1_compare0_set(uint32_t value)
  175. {
  176. NRF_RTC1->CC[0] = value;
  177. }
  178. /**@brief Function for inserting a timer in the timer list.
  179. *
  180. * @param[in] timer_id Id of timer to insert.
  181. */
  182. static void timer_list_insert(timer_node_t * p_timer)
  183. {
  184. if (mp_timer_id_head == NULL)
  185. {
  186. mp_timer_id_head = p_timer;
  187. }
  188. else
  189. {
  190. if (p_timer->ticks_to_expire <= mp_timer_id_head->ticks_to_expire)
  191. {
  192. mp_timer_id_head->ticks_to_expire -= p_timer->ticks_to_expire;
  193. p_timer->next = mp_timer_id_head;
  194. mp_timer_id_head = p_timer;
  195. }
  196. else
  197. {
  198. timer_node_t * p_previous;
  199. timer_node_t * p_current;
  200. uint32_t ticks_to_expire;
  201. ticks_to_expire = p_timer->ticks_to_expire;
  202. p_previous = mp_timer_id_head;
  203. p_current = mp_timer_id_head;
  204. while ((p_current != NULL) && (ticks_to_expire > p_current->ticks_to_expire))
  205. {
  206. ticks_to_expire -= p_current->ticks_to_expire;
  207. p_previous = p_current;
  208. p_current = p_current->next;
  209. }
  210. if (p_current != NULL)
  211. {
  212. p_current->ticks_to_expire -= ticks_to_expire;
  213. }
  214. p_timer->ticks_to_expire = ticks_to_expire;
  215. p_timer->next = p_current;
  216. p_previous->next = p_timer;
  217. }
  218. }
  219. }
  220. /**@brief Function for removing a timer from the timer queue.
  221. *
  222. * @param[in] timer_id Id of timer to remove.
  223. */
  224. static void timer_list_remove(timer_node_t * p_timer)
  225. {
  226. timer_node_t * p_previous;
  227. timer_node_t * p_current;
  228. uint32_t timeout;
  229. // Find the timer's position in timer list.
  230. p_previous = mp_timer_id_head;
  231. p_current = p_previous;
  232. while (p_current != NULL)
  233. {
  234. if (p_current == p_timer)
  235. {
  236. break;
  237. }
  238. p_previous = p_current;
  239. p_current = p_current->next;
  240. }
  241. // Timer not in active list.
  242. if (p_current == NULL)
  243. {
  244. return;
  245. }
  246. // Timer is the first in the list
  247. if (p_previous == p_current)
  248. {
  249. mp_timer_id_head = mp_timer_id_head->next;
  250. // No more timers in the list. Reset RTC1 in case Start timer operations are present in the queue.
  251. if (mp_timer_id_head == NULL)
  252. {
  253. NRF_RTC1->TASKS_CLEAR = 1;
  254. m_ticks_latest = 0;
  255. m_rtc1_reset = true;
  256. }
  257. }
  258. // Remaining timeout between next timeout.
  259. timeout = p_current->ticks_to_expire;
  260. // Link previous timer with next of this timer, i.e. removing the timer from list.
  261. p_previous->next = p_current->next;
  262. // If this is not the last timer, increment the next timer by this timer timeout.
  263. p_current = p_previous->next;
  264. if (p_current != NULL)
  265. {
  266. p_current->ticks_to_expire += timeout;
  267. }
  268. }
  269. /**@brief Function for scheduling a check for timeouts by generating a RTC1 interrupt.
  270. */
  271. static void timer_timeouts_check_sched(void)
  272. {
  273. NVIC_SetPendingIRQ(RTC1_IRQn);
  274. }
  275. /**@brief Function for scheduling a timer list update by generating a SWI interrupt.
  276. */
  277. static void timer_list_handler_sched(void)
  278. {
  279. NVIC_SetPendingIRQ(SWI_IRQn);
  280. }
  281. /**@brief Function for executing an application timeout handler, either by calling it directly, or
  282. * by passing an event to the @ref app_scheduler.
  283. *
  284. * @param[in] p_timer Pointer to expired timer.
  285. */
  286. static void timeout_handler_exec(timer_node_t * p_timer)
  287. {
  288. if (m_evt_schedule_func != NULL)
  289. {
  290. uint32_t err_code = m_evt_schedule_func(p_timer->p_timeout_handler, p_timer->p_context);
  291. APP_ERROR_CHECK(err_code);
  292. }
  293. else
  294. {
  295. p_timer->p_timeout_handler(p_timer->p_context);
  296. }
  297. }
  298. /**@brief Function for checking for expired timers.
  299. */
  300. static void timer_timeouts_check(void)
  301. {
  302. // Handle expired of timer
  303. if (mp_timer_id_head != NULL)
  304. {
  305. timer_node_t * p_timer;
  306. timer_node_t * p_previous_timer;
  307. uint32_t ticks_elapsed;
  308. uint32_t ticks_expired;
  309. // Initialize actual elapsed ticks being consumed to 0.
  310. ticks_expired = 0;
  311. // ticks_elapsed is collected here, job will use it.
  312. ticks_elapsed = ticks_diff_get(rtc1_counter_get(), m_ticks_latest);
  313. // Auto variable containing the head of timers expiring.
  314. p_timer = mp_timer_id_head;
  315. // Expire all timers within ticks_elapsed and collect ticks_expired.
  316. while (p_timer != NULL)
  317. {
  318. // Do nothing if timer did not expire.
  319. if (ticks_elapsed < p_timer->ticks_to_expire)
  320. {
  321. break;
  322. }
  323. // Decrement ticks_elapsed and collect expired ticks.
  324. ticks_elapsed -= p_timer->ticks_to_expire;
  325. ticks_expired += p_timer->ticks_to_expire;
  326. // Move to next timer.
  327. p_previous_timer = p_timer;
  328. p_timer = p_timer->next;
  329. // Execute Task.
  330. timeout_handler_exec(p_previous_timer);
  331. }
  332. // Prepare to queue the ticks expired in the m_ticks_elapsed queue.
  333. if (m_ticks_elapsed_q_read_ind == m_ticks_elapsed_q_write_ind)
  334. {
  335. // The read index of the queue is equal to the write index. This means the new
  336. // value of ticks_expired should be stored at a new location in the m_ticks_elapsed
  337. // queue (which is implemented as a double buffer).
  338. // Check if there will be a queue overflow.
  339. if (++m_ticks_elapsed_q_write_ind == CONTEXT_QUEUE_SIZE_MAX)
  340. {
  341. // There will be a queue overflow. Hence the write index should point to the start
  342. // of the queue.
  343. m_ticks_elapsed_q_write_ind = 0;
  344. }
  345. }
  346. // Queue the ticks expired.
  347. m_ticks_elapsed[m_ticks_elapsed_q_write_ind] = ticks_expired;
  348. timer_list_handler_sched();
  349. }
  350. }
  351. /**@brief Function for acquiring the number of ticks elapsed.
  352. *
  353. * @param[out] p_ticks_elapsed Number of ticks elapsed.
  354. *
  355. * @return TRUE if elapsed ticks was read from queue, FALSE otherwise.
  356. */
  357. static bool elapsed_ticks_acquire(uint32_t * p_ticks_elapsed)
  358. {
  359. // Pick the elapsed value from queue.
  360. if (m_ticks_elapsed_q_read_ind != m_ticks_elapsed_q_write_ind)
  361. {
  362. // Dequeue elapsed value.
  363. m_ticks_elapsed_q_read_ind++;
  364. if (m_ticks_elapsed_q_read_ind == CONTEXT_QUEUE_SIZE_MAX)
  365. {
  366. m_ticks_elapsed_q_read_ind = 0;
  367. }
  368. *p_ticks_elapsed = m_ticks_elapsed[m_ticks_elapsed_q_read_ind];
  369. m_ticks_latest += *p_ticks_elapsed;
  370. m_ticks_latest &= MAX_RTC_COUNTER_VAL;
  371. return true;
  372. }
  373. else
  374. {
  375. // No elapsed value in queue.
  376. *p_ticks_elapsed = 0;
  377. return false;
  378. }
  379. }
  380. /**@brief Function for handling the timer list deletions.
  381. *
  382. * @return TRUE if Capture Compare register must be updated, FALSE otherwise.
  383. */
  384. static bool list_deletions_handler(void)
  385. {
  386. timer_node_t * p_timer_old_head;
  387. uint8_t user_id;
  388. // Remember the old head, so as to decide if new compare needs to be set.
  389. p_timer_old_head = mp_timer_id_head;
  390. user_id = m_user_array_size;
  391. while (user_id--)
  392. {
  393. timer_user_t * p_user = &mp_users[user_id];
  394. uint8_t user_ops_first = p_user->first;
  395. while (user_ops_first != p_user->last)
  396. {
  397. timer_node_t * p_timer;
  398. timer_user_op_t * p_user_op = &p_user->p_user_op_queue[user_ops_first];
  399. // Traverse to next operation in queue.
  400. user_ops_first++;
  401. if (user_ops_first == p_user->user_op_queue_size)
  402. {
  403. user_ops_first = 0;
  404. }
  405. switch (p_user_op->op_type)
  406. {
  407. case TIMER_USER_OP_TYPE_STOP:
  408. // Delete node if timer is running.
  409. p_timer = p_user_op->p_node;
  410. if (p_timer->is_running)
  411. {
  412. timer_list_remove(p_user_op->p_node);
  413. p_timer->is_running = false;
  414. }
  415. break;
  416. case TIMER_USER_OP_TYPE_STOP_ALL:
  417. // Delete list of running timers, and mark all timers as not running.
  418. while (mp_timer_id_head != NULL)
  419. {
  420. timer_node_t * p_head = mp_timer_id_head;
  421. p_head->is_running = false;
  422. mp_timer_id_head = p_head->next;
  423. }
  424. break;
  425. default:
  426. // No implementation needed.
  427. break;
  428. }
  429. }
  430. }
  431. // Detect change in head of the list.
  432. return (mp_timer_id_head != p_timer_old_head);
  433. }
  434. /**@brief Function for updating the timer list for expired timers.
  435. *
  436. * @param[in] ticks_elapsed Number of elapsed ticks.
  437. * @param[in] ticks_previous Previous known value of the RTC counter.
  438. * @param[out] p_restart_list_head List of repeating timers to be restarted.
  439. */
  440. static void expired_timers_handler(uint32_t ticks_elapsed,
  441. uint32_t ticks_previous,
  442. timer_node_t ** p_restart_list_head)
  443. {
  444. uint32_t ticks_expired = 0;
  445. while (mp_timer_id_head != NULL)
  446. {
  447. timer_node_t * p_timer;
  448. timer_node_t * p_timer_expired;
  449. // Auto variable for current timer node.
  450. p_timer = mp_timer_id_head;
  451. // Do nothing if timer did not expire
  452. if (ticks_elapsed < p_timer->ticks_to_expire)
  453. {
  454. p_timer->ticks_to_expire -= ticks_elapsed;
  455. break;
  456. }
  457. // Decrement ticks_elapsed and collect expired ticks.
  458. ticks_elapsed -= p_timer->ticks_to_expire;
  459. ticks_expired += p_timer->ticks_to_expire;
  460. // Timer expired, set ticks_to_expire zero.
  461. p_timer->ticks_to_expire = 0;
  462. p_timer->is_running = false;
  463. // Remove the expired timer from head.
  464. p_timer_expired = mp_timer_id_head;
  465. mp_timer_id_head = p_timer->next;
  466. // Timer will be restarted if periodic.
  467. if (p_timer->ticks_periodic_interval != 0)
  468. {
  469. p_timer->ticks_at_start = (ticks_previous + ticks_expired) & MAX_RTC_COUNTER_VAL;
  470. p_timer->ticks_first_interval = p_timer->ticks_periodic_interval;
  471. p_timer->next = *p_restart_list_head;
  472. *p_restart_list_head = p_timer_expired;
  473. }
  474. }
  475. }
  476. /**@brief Function for handling timer list insertions.
  477. *
  478. * @param[in] p_restart_list_head List of repeating timers to be restarted.
  479. *
  480. * @return TRUE if Capture Compare register must be updated, FALSE otherwise.
  481. */
  482. static bool list_insertions_handler(timer_node_t * p_restart_list_head)
  483. {
  484. timer_node_t * p_timer_id_old_head;
  485. uint8_t user_id;
  486. // Remember the old head, so as to decide if new compare needs to be set.
  487. p_timer_id_old_head = mp_timer_id_head;
  488. user_id = m_user_array_size;
  489. while (user_id--)
  490. {
  491. timer_user_t * p_user = &mp_users[user_id];
  492. // Handle insertions of timers.
  493. while ((p_restart_list_head != NULL) || (p_user->first != p_user->last))
  494. {
  495. timer_node_t * p_timer;
  496. if (p_restart_list_head != NULL)
  497. {
  498. p_timer = p_restart_list_head;
  499. p_restart_list_head = p_timer->next;
  500. }
  501. else
  502. {
  503. timer_user_op_t * p_user_op = &p_user->p_user_op_queue[p_user->first];
  504. p_user->first++;
  505. if (p_user->first == p_user->user_op_queue_size)
  506. {
  507. p_user->first = 0;
  508. }
  509. p_timer = p_user_op->p_node;
  510. if ((p_user_op->op_type != TIMER_USER_OP_TYPE_START) || p_timer->is_running)
  511. {
  512. continue;
  513. }
  514. p_timer->ticks_at_start = p_user_op->params.start.ticks_at_start;
  515. p_timer->ticks_first_interval = p_user_op->params.start.ticks_first_interval;
  516. p_timer->ticks_periodic_interval = p_user_op->params.start.ticks_periodic_interval;
  517. p_timer->p_context = p_user_op->params.start.p_context;
  518. if (m_rtc1_reset)
  519. {
  520. p_timer->ticks_at_start = 0;
  521. }
  522. }
  523. // Prepare the node to be inserted.
  524. if (
  525. ((p_timer->ticks_at_start - m_ticks_latest) & MAX_RTC_COUNTER_VAL)
  526. <
  527. (MAX_RTC_COUNTER_VAL / 2)
  528. )
  529. {
  530. p_timer->ticks_to_expire = ticks_diff_get(p_timer->ticks_at_start, m_ticks_latest) +
  531. p_timer->ticks_first_interval;
  532. }
  533. else
  534. {
  535. uint32_t delta_current_start;
  536. delta_current_start = ticks_diff_get(m_ticks_latest, p_timer->ticks_at_start);
  537. if (p_timer->ticks_first_interval > delta_current_start)
  538. {
  539. p_timer->ticks_to_expire = p_timer->ticks_first_interval - delta_current_start;
  540. }
  541. else
  542. {
  543. p_timer->ticks_to_expire = 0;
  544. }
  545. }
  546. p_timer->ticks_at_start = 0;
  547. p_timer->ticks_first_interval = 0;
  548. p_timer->is_running = true;
  549. p_timer->next = NULL;
  550. // Insert into list
  551. timer_list_insert(p_timer);
  552. }
  553. }
  554. return (mp_timer_id_head != p_timer_id_old_head);
  555. }
  556. /**@brief Function for updating the Capture Compare register.
  557. */
  558. static void compare_reg_update(timer_node_t * p_timer_id_head_old)
  559. {
  560. // Setup the timeout for timers on the head of the list
  561. if (mp_timer_id_head != NULL)
  562. {
  563. uint32_t ticks_to_expire = mp_timer_id_head->ticks_to_expire;
  564. uint32_t pre_counter_val = rtc1_counter_get();
  565. uint32_t cc = m_ticks_latest;
  566. uint32_t ticks_elapsed = ticks_diff_get(pre_counter_val, cc) + RTC_COMPARE_OFFSET_MIN;
  567. if (!m_rtc1_running)
  568. {
  569. // No timers were already running, start RTC
  570. rtc1_start();
  571. }
  572. cc += (ticks_elapsed < ticks_to_expire) ? ticks_to_expire : ticks_elapsed;
  573. cc &= MAX_RTC_COUNTER_VAL;
  574. rtc1_compare0_set(cc);
  575. uint32_t post_counter_val = rtc1_counter_get();
  576. if (
  577. (ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN)
  578. >
  579. ticks_diff_get(cc, pre_counter_val)
  580. )
  581. {
  582. // When this happens the COMPARE event may not be triggered by the RTC.
  583. // The nRF51 Series User Specification states that if the COUNTER value is N
  584. // (i.e post_counter_val = N), writing N or N+1 to a CC register may not trigger a
  585. // COMPARE event. Hence the RTC interrupt is forcefully pended by calling the following
  586. // function.
  587. timer_timeouts_check_sched();
  588. }
  589. }
  590. else
  591. {
  592. // No timers are running, stop RTC
  593. rtc1_stop();
  594. }
  595. }
  596. /**@brief Function for handling changes to the timer list.
  597. */
  598. static void timer_list_handler(void)
  599. {
  600. timer_node_t * p_restart_list_head = NULL;
  601. uint32_t ticks_elapsed;
  602. uint32_t ticks_previous;
  603. bool ticks_have_elapsed;
  604. bool compare_update;
  605. timer_node_t * p_timer_id_head_old;
  606. // Back up the previous known tick and previous list head
  607. ticks_previous = m_ticks_latest;
  608. p_timer_id_head_old = mp_timer_id_head;
  609. // Get number of elapsed ticks
  610. ticks_have_elapsed = elapsed_ticks_acquire(&ticks_elapsed);
  611. // Handle list deletions
  612. compare_update = list_deletions_handler();
  613. // Handle expired timers
  614. if (ticks_have_elapsed)
  615. {
  616. expired_timers_handler(ticks_elapsed, ticks_previous, &p_restart_list_head);
  617. compare_update = true;
  618. }
  619. // Handle list insertions
  620. if (list_insertions_handler(p_restart_list_head))
  621. {
  622. compare_update = true;
  623. }
  624. // Update compare register if necessary
  625. if (compare_update)
  626. {
  627. compare_reg_update(p_timer_id_head_old);
  628. }
  629. m_rtc1_reset = false;
  630. }
  631. /**@brief Function for enqueueing a new operations queue entry.
  632. *
  633. * @param[in] p_user User that the entry is to be enqueued for.
  634. * @param[in] last_index Index of the next last index to be enqueued.
  635. */
  636. static void user_op_enque(timer_user_t * p_user, uint8_t last_index)
  637. {
  638. p_user->last = last_index;
  639. }
  640. /**@brief Function for allocating a new operations queue entry.
  641. *
  642. * @param[in] p_user User that the entry is to be allocated for.
  643. * @param[out] p_last_index Index of the next last index to be enqueued.
  644. *
  645. * @return Pointer to allocated queue entry, or NULL if queue is full.
  646. */
  647. static timer_user_op_t * user_op_alloc(timer_user_t * p_user, uint8_t * p_last_index)
  648. {
  649. uint8_t last;
  650. timer_user_op_t * p_user_op;
  651. last = p_user->last + 1;
  652. if (last == p_user->user_op_queue_size)
  653. {
  654. // Overflow case.
  655. last = 0;
  656. }
  657. if (last == p_user->first)
  658. {
  659. // Queue is full.
  660. return NULL;
  661. }
  662. *p_last_index = last;
  663. p_user_op = &p_user->p_user_op_queue[p_user->last];
  664. return p_user_op;
  665. }
  666. /**@brief Function for scheduling a Timer Start operation.
  667. *
  668. * @param[in] user_id Id of user calling this function.
  669. * @param[in] timer_id Id of timer to start.
  670. * @param[in] timeout_initial Time (in ticks) to first timer expiry.
  671. * @param[in] timeout_periodic Time (in ticks) between periodic expiries.
  672. * @param[in] p_context General purpose pointer. Will be passed to the timeout handler when
  673. * the timer expires.
  674. * @return NRF_SUCCESS on success, otherwise an error code.
  675. */
  676. static uint32_t timer_start_op_schedule(timer_user_id_t user_id,
  677. timer_node_t * p_node,
  678. uint32_t timeout_initial,
  679. uint32_t timeout_periodic,
  680. void * p_context)
  681. {
  682. uint8_t last_index;
  683. timer_user_op_t * p_user_op = user_op_alloc(&mp_users[user_id], &last_index);
  684. if (p_user_op == NULL)
  685. {
  686. return NRF_ERROR_NO_MEM;
  687. }
  688. p_user_op->op_type = TIMER_USER_OP_TYPE_START;
  689. p_user_op->p_node = p_node;
  690. p_user_op->params.start.ticks_at_start = rtc1_counter_get();
  691. p_user_op->params.start.ticks_first_interval = timeout_initial;
  692. p_user_op->params.start.ticks_periodic_interval = timeout_periodic;
  693. p_user_op->params.start.p_context = p_context;
  694. user_op_enque(&mp_users[user_id], last_index);
  695. timer_list_handler_sched();
  696. return NRF_SUCCESS;
  697. }
  698. /**@brief Function for scheduling a Timer Stop operation.
  699. *
  700. * @param[in] user_id Id of user calling this function.
  701. * @param[in] timer_id Id of timer to stop.
  702. *
  703. * @return NRF_SUCCESS on successful scheduling a timer stop operation. NRF_ERROR_NO_MEM when there
  704. * is no memory left to schedule the timer stop operation.
  705. */
  706. static uint32_t timer_stop_op_schedule(timer_user_id_t user_id, timer_node_t * p_node)
  707. {
  708. uint8_t last_index;
  709. timer_user_op_t * p_user_op = user_op_alloc(&mp_users[user_id], &last_index);
  710. if (p_user_op == NULL)
  711. {
  712. return NRF_ERROR_NO_MEM;
  713. }
  714. p_user_op->op_type = TIMER_USER_OP_TYPE_STOP;
  715. p_user_op->p_node = p_node;
  716. user_op_enque(&mp_users[user_id], last_index);
  717. timer_list_handler_sched();
  718. return NRF_SUCCESS;
  719. }
  720. /**@brief Function for scheduling a Timer Stop All operation.
  721. *
  722. * @param[in] user_id Id of user calling this function.
  723. */
  724. static uint32_t timer_stop_all_op_schedule(timer_user_id_t user_id)
  725. {
  726. uint8_t last_index;
  727. timer_user_op_t * p_user_op = user_op_alloc(&mp_users[user_id], &last_index);
  728. if (p_user_op == NULL)
  729. {
  730. return NRF_ERROR_NO_MEM;
  731. }
  732. p_user_op->op_type = TIMER_USER_OP_TYPE_STOP_ALL;
  733. p_user_op->p_node = NULL;
  734. user_op_enque(&mp_users[user_id], last_index);
  735. timer_list_handler_sched();
  736. return NRF_SUCCESS;
  737. }
  738. /**@brief Function for handling the RTC1 interrupt.
  739. *
  740. * @details Checks for timeouts, and executes timeout handlers for expired timers.
  741. */
  742. void RTC1_IRQHandler(void)
  743. {
  744. // Clear all events (also unexpected ones)
  745. NRF_RTC1->EVENTS_COMPARE[0] = 0;
  746. NRF_RTC1->EVENTS_COMPARE[1] = 0;
  747. NRF_RTC1->EVENTS_COMPARE[2] = 0;
  748. NRF_RTC1->EVENTS_COMPARE[3] = 0;
  749. NRF_RTC1->EVENTS_TICK = 0;
  750. NRF_RTC1->EVENTS_OVRFLW = 0;
  751. // Check for expired timers
  752. timer_timeouts_check();
  753. }
  754. /**@brief Function for handling the SWI interrupt.
  755. *
  756. * @details Performs all updates to the timer list.
  757. */
  758. void SWI_IRQHandler(void)
  759. {
  760. timer_list_handler();
  761. }
  762. uint32_t app_timer_init(uint32_t prescaler,
  763. uint8_t op_queues_size,
  764. void * p_buffer,
  765. app_timer_evt_schedule_func_t evt_schedule_func)
  766. {
  767. int i;
  768. // Check that buffer is correctly aligned
  769. if (!is_word_aligned(p_buffer))
  770. {
  771. return NRF_ERROR_INVALID_PARAM;
  772. }
  773. // Check for NULL buffer
  774. if (p_buffer == NULL)
  775. {
  776. mp_users = NULL;
  777. return NRF_ERROR_INVALID_PARAM;
  778. }
  779. // Stop RTC to prevent any running timers from expiring (in case of reinitialization)
  780. rtc1_stop();
  781. m_evt_schedule_func = evt_schedule_func;
  782. // Initialize users array
  783. m_user_array_size = APP_TIMER_INT_LEVELS;
  784. mp_users = p_buffer;
  785. // Skip user array
  786. p_buffer = &((uint8_t *)p_buffer)[APP_TIMER_INT_LEVELS * sizeof(timer_user_t)];
  787. // Initialize operation queues
  788. for (i = 0; i < APP_TIMER_INT_LEVELS; i++)
  789. {
  790. timer_user_t * p_user = &mp_users[i];
  791. p_user->first = 0;
  792. p_user->last = 0;
  793. p_user->user_op_queue_size = op_queues_size;
  794. p_user->p_user_op_queue = p_buffer;
  795. // Skip operation queue
  796. p_buffer = &((uint8_t *)p_buffer)[op_queues_size * sizeof(timer_user_op_t)];
  797. }
  798. mp_timer_id_head = NULL;
  799. m_ticks_elapsed_q_read_ind = 0;
  800. m_ticks_elapsed_q_write_ind = 0;
  801. NVIC_ClearPendingIRQ(SWI_IRQn);
  802. NVIC_SetPriority(SWI_IRQn, SWI_IRQ_PRI);
  803. NVIC_EnableIRQ(SWI_IRQn);
  804. rtc1_init(prescaler);
  805. m_ticks_latest = rtc1_counter_get();
  806. return NRF_SUCCESS;
  807. }
  808. uint32_t app_timer_create(app_timer_id_t const * p_timer_id,
  809. app_timer_mode_t mode,
  810. app_timer_timeout_handler_t timeout_handler)
  811. {
  812. // Check state and parameters
  813. VERIFY_MODULE_INITIALIZED();
  814. if (timeout_handler == NULL)
  815. {
  816. return NRF_ERROR_INVALID_PARAM;
  817. }
  818. if (p_timer_id == NULL)
  819. {
  820. return NRF_ERROR_INVALID_PARAM;
  821. }
  822. if (((timer_node_t*)*p_timer_id)->is_running)
  823. {
  824. return NRF_ERROR_INVALID_STATE;
  825. }
  826. timer_node_t * p_node = (timer_node_t *)*p_timer_id;
  827. p_node->is_running = false;
  828. p_node->mode = mode;
  829. p_node->p_timeout_handler = timeout_handler;
  830. return NRF_SUCCESS;
  831. }
  832. /**@brief Function for creating a timer user id from the current interrupt level.
  833. *
  834. * @return Timer user id.
  835. */
  836. static timer_user_id_t user_id_get(void)
  837. {
  838. timer_user_id_t ret;
  839. STATIC_ASSERT(APP_TIMER_INT_LEVELS == 3);
  840. switch (current_int_priority_get())
  841. {
  842. case APP_IRQ_PRIORITY_HIGH:
  843. ret = APP_HIGH_USER_ID;
  844. break;
  845. case APP_IRQ_PRIORITY_LOW:
  846. ret = APP_LOW_USER_ID;
  847. break;
  848. default:
  849. ret = THREAD_MODE_USER_ID;
  850. break;
  851. }
  852. return ret;
  853. }
  854. uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context)
  855. {
  856. uint32_t timeout_periodic;
  857. timer_node_t * p_node = (timer_node_t*)timer_id;
  858. // Check state and parameters
  859. VERIFY_MODULE_INITIALIZED();
  860. if (timer_id == 0)
  861. {
  862. return NRF_ERROR_INVALID_STATE;
  863. }
  864. if (timeout_ticks < APP_TIMER_MIN_TIMEOUT_TICKS)
  865. {
  866. return NRF_ERROR_INVALID_PARAM;
  867. }
  868. if (p_node->p_timeout_handler == NULL)
  869. {
  870. return NRF_ERROR_INVALID_STATE;
  871. }
  872. // Schedule timer start operation
  873. timeout_periodic = (p_node->mode == APP_TIMER_MODE_REPEATED) ? timeout_ticks : 0;
  874. return timer_start_op_schedule(user_id_get(),
  875. p_node,
  876. timeout_ticks,
  877. timeout_periodic,
  878. p_context);
  879. }
  880. uint32_t app_timer_stop(app_timer_id_t timer_id)
  881. {
  882. timer_node_t * p_node = (timer_node_t*)timer_id;
  883. // Check state and parameters
  884. VERIFY_MODULE_INITIALIZED();
  885. if ((timer_id == NULL) || (p_node->p_timeout_handler == NULL))
  886. {
  887. return NRF_ERROR_INVALID_STATE;
  888. }
  889. // Schedule timer stop operation
  890. return timer_stop_op_schedule(user_id_get(), p_node);
  891. }
  892. uint32_t app_timer_stop_all(void)
  893. {
  894. // Check state
  895. VERIFY_MODULE_INITIALIZED();
  896. return timer_stop_all_op_schedule(user_id_get());
  897. }
  898. uint32_t app_timer_cnt_get(uint32_t * p_ticks)
  899. {
  900. *p_ticks = rtc1_counter_get();
  901. return NRF_SUCCESS;
  902. }
  903. uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to,
  904. uint32_t ticks_from,
  905. uint32_t * p_ticks_diff)
  906. {
  907. *p_ticks_diff = ticks_diff_get(ticks_to, ticks_from);
  908. return NRF_SUCCESS;
  909. }