drv_hwtimer.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-11-21 chenyingchun first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <board.h>
  13. #include <nrfx_timer.h>
  14. #ifdef SOFTDEVICE_PRESENT
  15. #ifdef BSP_USING_TIM0
  16. #error "TIMER0 cannot be used when SOFTDEVICE has been used."
  17. #endif
  18. #endif
  19. #ifdef BSP_USING_TIM
  20. #define LOG_TAG "drv.hwtimer"
  21. #define DBG_LVL DBG_INFO
  22. #include <rtdbg.h>
  23. #ifdef RT_USING_HWTIMER
  24. #ifndef TIM_DEV_INFO_CONFIG
  25. // maxfreq and minfreq unit is HZ
  26. #define TIM_DEV_INFO_CONFIG \
  27. { \
  28. .maxfreq = 16000000, \
  29. .minfreq = 31250, \
  30. .maxcnt = 0xFFFFFFFF, \
  31. .cntmode = HWTIMER_CNTMODE_UP, \
  32. }
  33. #endif
  34. typedef struct
  35. {
  36. nrfx_timer_t timer_inst;
  37. nrfx_timer_config_t timer_cfg;
  38. nrf_timer_cc_channel_t cc_channel;
  39. }nrf5x_timer_info_t;
  40. struct nrf5x_hwtimer
  41. {
  42. rt_hwtimer_t timer_device;
  43. nrf5x_timer_info_t timer_info;
  44. char *name;
  45. };
  46. static struct nrf5x_hwtimer nrf5x_hwtimer_obj[] =
  47. {
  48. #ifdef BSP_USING_TIM0
  49. {
  50. .timer_info.timer_inst = NRFX_TIMER_INSTANCE(0),
  51. .timer_info.timer_cfg = NRFX_TIMER_DEFAULT_CONFIG,
  52. .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL0,
  53. .name = "timer0",
  54. },
  55. #endif
  56. #ifdef BSP_USING_TIM1
  57. {
  58. .timer_info.timer_inst = NRFX_TIMER_INSTANCE(1),
  59. .timer_info.timer_cfg = NRFX_TIMER_DEFAULT_CONFIG,
  60. .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL1,
  61. .name = "timer1",
  62. },
  63. #endif
  64. #ifdef BSP_USING_TIM2
  65. {
  66. .timer_info.timer_inst = NRFX_TIMER_INSTANCE(2),
  67. .timer_info.timer_cfg = NRFX_TIMER_DEFAULT_CONFIG,
  68. .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL2,
  69. .name = "timer2",
  70. },
  71. #endif
  72. #ifdef BSP_USING_TIM3
  73. {
  74. .timer_info.timer_inst = NRFX_TIMER_INSTANCE(3),
  75. .timer_info.timer_cfg = NRFX_TIMER_DEFAULT_CONFIG,
  76. .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL3,
  77. .name = "timer3",
  78. },
  79. #endif
  80. #ifdef BSP_USING_TIM4
  81. {
  82. .timer_info.timer_inst = NRFX_TIMER_INSTANCE(4),
  83. .timer_info.timer_cfg = NRFX_TIMER_DEFAULT_CONFIG,
  84. .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL4,
  85. .name = "timer4",
  86. }
  87. #endif
  88. };
  89. static void timer_callback(nrf_timer_event_t event_type, void* p_context)
  90. {
  91. rt_hwtimer_t *timer_device = (struct rt_hwtimer_device *)p_context;
  92. // no matter what event_type is(NRF_TIMER_EVENT_COMPARE0 or others), call same function "rt_device_hwtimer_isr"
  93. LOG_D("timer_callback event_type = %d, inst_id = %d, cc conunt = %d\r\n",
  94. event_type, timer_info->timer_inst.instance_id, timer_info->timer_inst.cc_channel_count);
  95. rt_device_hwtimer_isr(timer_device);
  96. }
  97. static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
  98. {
  99. nrf5x_timer_info_t *timer_info = RT_NULL;
  100. nrfx_timer_config_t *timer_cfg = RT_NULL;
  101. RT_ASSERT(timer != RT_NULL);
  102. if (state)
  103. {
  104. timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
  105. timer_cfg = &(timer_info->timer_cfg);
  106. timer_cfg->bit_width = NRF_TIMER_BIT_WIDTH_32;
  107. timer_cfg->p_context = timer;
  108. nrfx_timer_init(&(timer_info->timer_inst), timer_cfg, timer_callback);
  109. }
  110. }
  111. static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode)
  112. {
  113. nrf5x_timer_info_t *timer_info = RT_NULL;
  114. nrf_timer_short_mask_t mask = NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK;
  115. RT_ASSERT(timer != RT_NULL);
  116. timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
  117. if (opmode == HWTIMER_MODE_ONESHOT)
  118. {
  119. // means TIMER_SHORTS_COMPARE0_STOP_Msk or TIMER_SHORTS_COMPARE1_STOP_Msk ..., according to cc_channel.
  120. mask = (nrf_timer_short_mask_t)(1 << (timer_info->cc_channel + 8));
  121. }
  122. else
  123. {
  124. // means TIMER_SHORTS_COMPARE0_CLEAR_Msk or TIMER_SHORTS_COMPARE1_CLEAR_Msk ..., according to cc_channel.
  125. mask = (nrf_timer_short_mask_t)(1 << timer_info->cc_channel);
  126. }
  127. nrfx_timer_extended_compare(&(timer_info->timer_inst), timer_info->cc_channel, t, mask, true);
  128. nrfx_timer_enable(&(timer_info->timer_inst));
  129. return RT_EOK;
  130. }
  131. static void timer_stop(rt_hwtimer_t *timer)
  132. {
  133. nrf5x_timer_info_t *timer_info = RT_NULL;
  134. RT_ASSERT(timer != RT_NULL);
  135. timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
  136. nrfx_timer_disable(&(timer_info->timer_inst));
  137. /* set time count register to zero*/
  138. nrfx_timer_clear(&(timer_info->timer_inst));
  139. }
  140. static nrf_timer_frequency_t frequency_convert(rt_uint32_t freq)
  141. {
  142. nrf_timer_frequency_t frequency = NRF_TIMER_FREQ_1MHz;
  143. switch (freq)
  144. {
  145. case 16000000:
  146. {
  147. frequency = NRF_TIMER_FREQ_16MHz;
  148. break;
  149. }
  150. case 8000000:
  151. {
  152. frequency = NRF_TIMER_FREQ_8MHz;
  153. break;
  154. }
  155. case 2000000:
  156. {
  157. frequency = NRF_TIMER_FREQ_2MHz;
  158. break;
  159. }
  160. case 1000000:
  161. {
  162. frequency = NRF_TIMER_FREQ_1MHz;
  163. break;
  164. }
  165. case 500000:
  166. {
  167. frequency = NRF_TIMER_FREQ_500kHz;
  168. break;
  169. }
  170. case 250000:
  171. {
  172. frequency = NRF_TIMER_FREQ_250kHz;
  173. break;
  174. }
  175. case 125000:
  176. {
  177. frequency = NRF_TIMER_FREQ_125kHz;
  178. break;
  179. }
  180. case 62500:
  181. {
  182. frequency = NRF_TIMER_FREQ_62500Hz;
  183. break;
  184. }
  185. case 31250:
  186. {
  187. frequency = NRF_TIMER_FREQ_31250Hz;
  188. break;
  189. }
  190. default:
  191. {
  192. break;
  193. }
  194. }
  195. return frequency;
  196. }
  197. static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
  198. {
  199. rt_err_t result = RT_EOK;
  200. nrf5x_timer_info_t *timer_info = RT_NULL;
  201. nrfx_timer_t *timer_inst = RT_NULL;
  202. RT_ASSERT(timer != RT_NULL);
  203. RT_ASSERT(arg != RT_NULL);
  204. timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
  205. timer_inst = &(timer_info->timer_inst);
  206. switch (cmd)
  207. {
  208. case HWTIMER_CTRL_FREQ_SET:
  209. {
  210. rt_uint32_t freq;
  211. /* set timer frequence */
  212. freq = *((rt_uint32_t *)arg);
  213. nrf_timer_frequency_set(timer_inst->p_reg, frequency_convert(freq));
  214. break;
  215. }
  216. default:
  217. {
  218. result = -RT_ENOSYS;
  219. break;
  220. }
  221. }
  222. return result;
  223. }
  224. static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer)
  225. {
  226. rt_uint32_t count = 0;
  227. nrf5x_timer_info_t *timer_info = RT_NULL;
  228. RT_ASSERT(timer != RT_NULL);
  229. timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
  230. // capture method will copy the current counter register to the specified cc channel (here is NRF_TIMER_CC_CHANNEL5).
  231. // the specified cc channel cannot be same with the already used cc channels
  232. count = nrfx_timer_capture(&(timer_info->timer_inst), NRF_TIMER_CC_CHANNEL5);
  233. return count;
  234. }
  235. static const struct rt_hwtimer_info _info = TIM_DEV_INFO_CONFIG;
  236. static const struct rt_hwtimer_ops _ops =
  237. {
  238. .init = timer_init,
  239. .start = timer_start,
  240. .stop = timer_stop,
  241. .count_get = timer_counter_get,
  242. .control = timer_ctrl,
  243. };
  244. static int nrf5x_hwtimer_init(void)
  245. {
  246. int i = 0;
  247. int result = RT_EOK;
  248. for (i = 0; i < sizeof(nrf5x_hwtimer_obj) / sizeof(nrf5x_hwtimer_obj[0]); i++)
  249. {
  250. nrf5x_hwtimer_obj[i].timer_device.info = &_info;
  251. nrf5x_hwtimer_obj[i].timer_device.ops = &_ops;
  252. if (rt_device_hwtimer_register(&nrf5x_hwtimer_obj[i].timer_device, nrf5x_hwtimer_obj[i].name, &nrf5x_hwtimer_obj[i].timer_info) == RT_EOK)
  253. {
  254. LOG_D("%s register success", nrf5x_hwtimer_obj[i].name);
  255. }
  256. else
  257. {
  258. LOG_E("%s register failed", nrf5x_hwtimer_obj[i].name);
  259. result = -RT_ERROR;
  260. }
  261. }
  262. return result;
  263. }
  264. INIT_BOARD_EXPORT(nrf5x_hwtimer_init);
  265. #endif /* RT_USING_HWTIMER */
  266. #endif /* BSP_USING_TIM */