app_timer_rtx.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "app_timer.h"
  2. #include <stdlib.h>
  3. #include "nrf.h"
  4. #include "nrf_soc.h"
  5. #include "app_error.h"
  6. #include "app_util.h"
  7. #include "cmsis_os.h"
  8. #include "app_util_platform.h"
  9. #define RTC1_IRQ_PRI APP_IRQ_PRIORITY_LOW /**< Priority of the RTC1 interrupt. */
  10. #define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */
  11. /**@brief This structure keeps information about osTimer.*/
  12. typedef struct
  13. {
  14. osTimerDef_t timerDef;
  15. uint32_t buffer[5];
  16. osTimerId id;
  17. }app_timer_info_t;
  18. /**@brief Store an array of timers with configuration. */
  19. typedef struct
  20. {
  21. uint8_t max_timers; /**< The maximum number of timers*/
  22. uint32_t prescaler;
  23. app_timer_info_t * app_timers; /**< Pointer to table of timers*/
  24. }app_timer_control_t;
  25. app_timer_control_t app_timer_control;
  26. /**@brief This structure is defined by RTX. It keeps information about created osTimers. It is used in app_timer_start(). */
  27. typedef struct os_timer_cb_
  28. {
  29. struct os_timer_cb_ * next;
  30. uint8_t state;
  31. uint8_t type;
  32. uint16_t reserved;
  33. uint16_t tcnt;
  34. uint16_t icnt;
  35. void * arg;
  36. const osTimerDef_t * timer;
  37. } os_timer_cb;
  38. /**@brief This functions are defined by RTX.*/
  39. //lint --save -e10 -e19 -e526
  40. extern osStatus svcTimerStop(osTimerId timer_id); /**< Used in app_timer_stop(). */
  41. extern osStatus svcTimerStart(osTimerId timer_id, uint32_t millisec); /**< Used in app_timer_start(). */
  42. // lint --restore
  43. static void * rt_id2obj(void *id) /**< Used in app_timer_start(). This function gives information if osTimerID is valid */
  44. {
  45. if ((uint32_t)id & 3)
  46. return NULL;
  47. #ifdef OS_SECTIONS_LINK_INFO
  48. if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0))
  49. {
  50. if (id < (void *)os_section_id$$Base)
  51. return NULL;
  52. if (id >= (void *)os_section_id$$Limit)
  53. return NULL;
  54. }
  55. #endif
  56. return id;
  57. }
  58. uint32_t app_timer_init(uint32_t prescaler,
  59. uint8_t op_queues_size,
  60. void * p_buffer,
  61. app_timer_evt_schedule_func_t evt_schedule_func)
  62. {
  63. if (p_buffer == NULL)
  64. {
  65. return NRF_ERROR_INVALID_PARAM;
  66. }
  67. app_timer_control.prescaler = prescaler;
  68. app_timer_control.app_timers = p_buffer;
  69. NVIC_SetPriority(RTC1_IRQn, RTC1_IRQ_PRI);
  70. return NRF_SUCCESS;
  71. }
  72. uint32_t app_timer_create(app_timer_id_t const * p_timer_id,
  73. app_timer_mode_t mode,
  74. app_timer_timeout_handler_t timeout_handler)
  75. {
  76. if ((timeout_handler == NULL) || (p_timer_id == NULL))
  77. {
  78. return NRF_ERROR_INVALID_PARAM;
  79. }
  80. app_timer_info_t * p_timer_info = (app_timer_info_t *)*p_timer_id;
  81. p_timer_info->timerDef.timer = p_timer_info->buffer;
  82. p_timer_info->timerDef.ptimer = (os_ptimer)timeout_handler;
  83. p_timer_info->id = osTimerCreate(&(p_timer_info->timerDef), (os_timer_type)mode, NULL);
  84. if (p_timer_info->id)
  85. return NRF_SUCCESS;
  86. else
  87. {
  88. return NRF_ERROR_INVALID_PARAM; // This error is unspecified by rtx
  89. }
  90. }
  91. #define osTimerRunning 2
  92. uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context)
  93. {
  94. if ((timeout_ticks < APP_TIMER_MIN_TIMEOUT_TICKS))
  95. {
  96. return NRF_ERROR_INVALID_PARAM;
  97. }
  98. uint32_t timeout_ms =
  99. ((uint32_t)ROUNDED_DIV(timeout_ticks * 1000 * (app_timer_control.prescaler + 1),
  100. (uint32_t)APP_TIMER_CLOCK_FREQ));
  101. app_timer_info_t * p_timer_info = (app_timer_info_t *)timer_id;
  102. if (rt_id2obj((void *)p_timer_info->id) == NULL)
  103. return NRF_ERROR_INVALID_PARAM;
  104. // Pass p_context to timer_timeout_handler
  105. ((os_timer_cb *)(p_timer_info->id))->arg = p_context;
  106. if (((os_timer_cb *)(p_timer_info->id))->state == osTimerRunning)
  107. {
  108. return NRF_SUCCESS;
  109. }
  110. // osTimerStart() returns osErrorISR if it is called in interrupt routine.
  111. switch (osTimerStart((osTimerId)p_timer_info->id, timeout_ms) )
  112. {
  113. case osOK:
  114. return NRF_SUCCESS;
  115. case osErrorISR:
  116. break;
  117. case osErrorParameter:
  118. return NRF_ERROR_INVALID_PARAM;
  119. default:
  120. return NRF_ERROR_INVALID_PARAM;
  121. }
  122. // Start timer without svcCall
  123. switch (svcTimerStart((osTimerId)p_timer_info->id, timeout_ms))
  124. {
  125. case osOK:
  126. return NRF_SUCCESS;
  127. case osErrorISR:
  128. return NRF_ERROR_INVALID_STATE;
  129. case osErrorParameter:
  130. return NRF_ERROR_INVALID_PARAM;
  131. default:
  132. return NRF_ERROR_INVALID_PARAM;
  133. }
  134. }
  135. uint32_t app_timer_stop(app_timer_id_t timer_id)
  136. {
  137. app_timer_info_t * p_timer_info = (app_timer_info_t *)timer_id;
  138. switch (osTimerStop((osTimerId)p_timer_info->id) )
  139. {
  140. case osOK:
  141. return NRF_SUCCESS;
  142. case osErrorISR:
  143. break;
  144. case osErrorParameter:
  145. return NRF_ERROR_INVALID_PARAM;
  146. case osErrorResource:
  147. return NRF_SUCCESS;
  148. default:
  149. return NRF_ERROR_INVALID_PARAM;
  150. }
  151. // Stop timer without svcCall
  152. switch (svcTimerStop((osTimerId)p_timer_info->id))
  153. {
  154. case osOK:
  155. return NRF_SUCCESS;
  156. case osErrorISR:
  157. return NRF_ERROR_INVALID_STATE;
  158. case osErrorParameter:
  159. return NRF_ERROR_INVALID_PARAM;
  160. case osErrorResource:
  161. return NRF_SUCCESS;
  162. default:
  163. return NRF_ERROR_INVALID_PARAM;
  164. }
  165. }
  166. uint32_t app_timer_stop_all(void)
  167. {
  168. for (int i = 0; i < app_timer_control.max_timers; i++)
  169. {
  170. if (app_timer_control.app_timers[i].id)
  171. {
  172. (void)app_timer_stop((app_timer_id_t)app_timer_control.app_timers[i].id);
  173. }
  174. }
  175. return 0;
  176. }
  177. extern uint32_t os_tick_val(void);
  178. uint32_t app_timer_cnt_get(uint32_t * p_ticks)
  179. {
  180. *p_ticks = os_tick_val();
  181. return NRF_SUCCESS;
  182. }
  183. uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to,
  184. uint32_t ticks_from,
  185. uint32_t * p_ticks_diff)
  186. {
  187. *p_ticks_diff = ((ticks_to - ticks_from) & MAX_RTC_COUNTER_VAL);
  188. return NRF_SUCCESS;
  189. }