drv_hwtimer.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-09-10 MXH the first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #ifdef BSP_USING_HWTIMER
  13. #define DBG_TAG "TIM"
  14. #define DBG_LVL DBG_LOG
  15. #include <rtdbg.h>
  16. #include "drv_hwtimer.h"
  17. #include "board.h"
  18. #ifdef RT_USING_HWTIMER
  19. enum
  20. {
  21. #ifdef BSP_USING_TIM1
  22. TIM1_INDEX,
  23. #endif
  24. #ifdef BSP_USING_TIM2
  25. TIM2_INDEX,
  26. #endif
  27. #ifdef BSP_USING_TIM3
  28. TIM3_INDEX,
  29. #endif
  30. #ifdef BSP_USING_TIM4
  31. TIM4_INDEX,
  32. #endif
  33. #ifdef BSP_USING_TIM5
  34. TIM5_INDEX,
  35. #endif
  36. #ifdef BSP_USING_TIM6
  37. TIM6_INDEX,
  38. #endif
  39. #ifdef BSP_USING_TIM7
  40. TIM7_INDEX,
  41. #endif
  42. #ifdef BSP_USING_TIM8
  43. TIM8_INDEX,
  44. #endif
  45. #ifdef BSP_USING_TIM9
  46. TIM9_INDEX,
  47. #endif
  48. #ifdef BSP_USING_TIM10
  49. TIM10_INDEX,
  50. #endif
  51. };
  52. static struct ch32_hwtimer ch32_hwtimer_obj[] =
  53. {
  54. #ifdef BSP_USING_TIM1
  55. TIM1_CONFIG,
  56. #endif
  57. #ifdef BSP_USING_TIM2
  58. TIM2_CONFIG,
  59. #endif
  60. #ifdef BSP_USING_TIM3
  61. TIM3_CONFIG,
  62. #endif
  63. #ifdef BSP_USING_TIM4
  64. TIM4_CONFIG,
  65. #endif
  66. #ifdef BSP_USING_TIM5
  67. TIM5_CONFIG,
  68. #endif
  69. #ifdef BSP_USING_TIM6
  70. TIM6_CONFIG,
  71. #endif
  72. #ifdef BSP_USING_TIM7
  73. TIM7_CONFIG,
  74. #endif
  75. #ifdef BSP_USING_TIM8
  76. TIM8_CONFIG,
  77. #endif
  78. #ifdef BSP_USING_TIM9
  79. TIM9_CONFIG,
  80. #endif
  81. #ifdef BSP_USING_TIM10
  82. TIM10_CONFIG,
  83. #endif
  84. };
  85. /* APBx timer clocks frequency doubler state related to APB1CLKDivider value */
  86. void ch32_get_pclk_doubler(rt_uint32_t *pclk1_doubler, rt_uint32_t *pclk2_doubler)
  87. {
  88. RT_ASSERT(pclk1_doubler != RT_NULL);
  89. RT_ASSERT(pclk2_doubler != RT_NULL);
  90. *pclk1_doubler = 1;
  91. *pclk2_doubler = 1;
  92. if((RCC->CFGR0 & RCC_PPRE1) == RCC_PPRE1_DIV1)
  93. {
  94. *pclk1_doubler = 1;
  95. }
  96. else
  97. {
  98. *pclk1_doubler = 2;
  99. }
  100. if((RCC->CFGR0 & RCC_PPRE2) == RCC_PPRE2_DIV1)
  101. {
  102. *pclk2_doubler = 1;
  103. }
  104. else
  105. {
  106. *pclk2_doubler = 2;
  107. }
  108. }
  109. static void ch32_hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
  110. {
  111. RT_ASSERT(timer != RT_NULL);
  112. TIM_HandleTypeDef *tim = RT_NULL;
  113. RCC_ClocksTypeDef RCC_ClockStruct;
  114. NVIC_InitTypeDef NVIC_InitStruct;
  115. struct ch32_hwtimer *tim_device = RT_NULL;
  116. rt_uint32_t prescaler_value = 0;
  117. rt_uint32_t pclk1_doubler, pclk2_doubler;
  118. RCC_GetClocksFreq(&RCC_ClockStruct);
  119. ch32_get_pclk_doubler(&pclk1_doubler, &pclk2_doubler);
  120. if(state)
  121. {
  122. tim = (TIM_HandleTypeDef *)timer->parent.user_data;
  123. tim_device = (struct ch32_hwtimer *)timer;
  124. if(tim->instance == TIM1 || tim->instance == TIM8 ||
  125. tim->instance == TIM9 || tim->instance == TIM10)
  126. {
  127. RCC_APB2PeriphClockCmd(tim->rcc, ENABLE);
  128. prescaler_value = (RCC_ClockStruct.PCLK2_Frequency * pclk2_doubler / 10000) - 1;
  129. }
  130. else
  131. {
  132. RCC_APB1PeriphClockCmd(tim->rcc, ENABLE);
  133. prescaler_value = (RCC_ClockStruct.PCLK1_Frequency * pclk1_doubler / 10000) - 1;
  134. }
  135. tim->init.TIM_Prescaler = prescaler_value;
  136. tim->init.TIM_ClockDivision = TIM_CKD_DIV1;
  137. tim->init.TIM_Period = 10000 - 1;
  138. tim->init.TIM_RepetitionCounter = 0;
  139. if(timer->info->cntmode == HWTIMER_CNTMODE_UP)
  140. {
  141. tim->init.TIM_CounterMode = TIM_CounterMode_Up;
  142. }
  143. else
  144. {
  145. tim->init.TIM_CounterMode = TIM_CounterMode_Down;
  146. }
  147. /* TIM6 and TIM7 only support counter up mode */
  148. if(tim->instance == TIM6 || tim->instance == TIM7)
  149. {
  150. tim->init.TIM_CounterMode = TIM_CounterMode_Up;
  151. }
  152. TIM_TimeBaseInit(tim->instance, &tim->init);
  153. NVIC_InitStruct.NVIC_IRQChannel = tim_device->irqn;
  154. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
  155. NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
  156. NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  157. NVIC_Init(&NVIC_InitStruct);
  158. TIM_ClearITPendingBit(tim->instance, TIM_IT_Update);
  159. TIM_ITConfig(tim->instance, TIM_IT_Update, ENABLE);
  160. }
  161. }
  162. static rt_err_t ch32_hwtimer_start(struct rt_hwtimer_device *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
  163. {
  164. RT_ASSERT(timer != RT_NULL);
  165. TIM_HandleTypeDef *tim = RT_NULL;
  166. tim = (TIM_HandleTypeDef *)timer->parent.user_data;
  167. /* set tim cnt */
  168. tim->instance->CNT = 0;
  169. /* set tim arr */
  170. tim->instance->ATRLR = cnt - 1;
  171. tim->init.TIM_Period = cnt - 1;
  172. if (mode == HWTIMER_MODE_ONESHOT)
  173. {
  174. /* set timer to single mode */
  175. tim->instance->CTLR1 &= (uint16_t) ~((uint16_t)TIM_OPM);
  176. tim->instance->CTLR1 |= TIM_OPMode_Single;
  177. }
  178. else
  179. {
  180. tim->instance->CTLR1 &= (uint16_t) ~((uint16_t)TIM_OPM);
  181. tim->instance->CTLR1 |= TIM_OPMode_Repetitive;
  182. }
  183. /* start timer */
  184. TIM_Cmd(tim->instance, ENABLE);
  185. return RT_EOK;
  186. }
  187. static void ch32_hwtimer_stop(struct rt_hwtimer_device *timer)
  188. {
  189. RT_ASSERT(timer != RT_NULL);
  190. TIM_HandleTypeDef *tim = RT_NULL;
  191. tim = (TIM_HandleTypeDef *)timer->parent.user_data;
  192. /* stop timer */
  193. TIM_Cmd(tim->instance, DISABLE);
  194. /* set tim cnt */
  195. tim->instance->CNT = 0;
  196. }
  197. static rt_uint32_t ch32_hwtimer_count_get(struct rt_hwtimer_device *timer)
  198. {
  199. RT_ASSERT(timer != RT_NULL);
  200. TIM_HandleTypeDef *tim = RT_NULL;
  201. tim = (TIM_HandleTypeDef *)timer->parent.user_data;
  202. return tim->instance->CNT;
  203. }
  204. static rt_err_t ch32_hwtimer_control(struct rt_hwtimer_device *timer, rt_uint32_t cmd, void *args)
  205. {
  206. RT_ASSERT(timer != RT_NULL);
  207. RT_ASSERT(args != RT_NULL);
  208. TIM_HandleTypeDef *tim = RT_NULL;
  209. rt_err_t result = RT_EOK;
  210. rt_uint32_t pclk1_doubler, pclk2_doubler;
  211. tim = (TIM_HandleTypeDef *)timer->parent.user_data;
  212. switch (cmd)
  213. {
  214. case HWTIMER_CTRL_FREQ_SET:
  215. {
  216. rt_uint32_t freq;
  217. rt_uint16_t val;
  218. RCC_ClocksTypeDef RCC_ClockStruct;
  219. /* set timer frequence */
  220. freq = *((rt_uint32_t *)args);
  221. ch32_get_pclk_doubler(&pclk1_doubler, &pclk2_doubler);
  222. RCC_GetClocksFreq(&RCC_ClockStruct);
  223. if(tim->instance == TIM1 || tim->instance == TIM8 ||
  224. tim->instance == TIM9 || tim->instance == TIM10)
  225. {
  226. val = RCC_ClockStruct.PCLK2_Frequency * pclk2_doubler / freq;
  227. }
  228. else
  229. {
  230. val = RCC_ClockStruct.PCLK1_Frequency * pclk1_doubler / freq;
  231. }
  232. /* Update frequency value */
  233. TIM_PrescalerConfig(tim->instance, val - 1, TIM_PSCReloadMode_Immediate);
  234. result = RT_EOK;
  235. break;
  236. }
  237. case HWTIMER_CTRL_MODE_SET:
  238. {
  239. if (*(rt_hwtimer_mode_t *)args == HWTIMER_MODE_ONESHOT)
  240. {
  241. /* set timer to single mode */
  242. tim->instance->CTLR1 &= (uint16_t) ~((uint16_t)TIM_OPM);
  243. tim->instance->CTLR1 |= TIM_OPMode_Single;
  244. }
  245. else
  246. {
  247. tim->instance->CTLR1 &= (uint16_t) ~((uint16_t)TIM_OPM);
  248. tim->instance->CTLR1 |= TIM_OPMode_Repetitive;
  249. }
  250. break;
  251. }
  252. case HWTIMER_CTRL_INFO_GET:
  253. {
  254. *(rt_hwtimer_mode_t *)args = tim->instance->CNT;
  255. break;
  256. }
  257. case HWTIMER_CTRL_STOP:
  258. {
  259. ch32_hwtimer_stop(timer);
  260. break;
  261. }
  262. default:
  263. {
  264. result = -RT_EINVAL;
  265. break;
  266. }
  267. }
  268. return result;
  269. }
  270. static const struct rt_hwtimer_info ch32_hwtimer_info = TIM_DEV_INFO_CONFIG;
  271. static const struct rt_hwtimer_ops ch32_hwtimer_ops =
  272. {
  273. ch32_hwtimer_init,
  274. ch32_hwtimer_start,
  275. ch32_hwtimer_stop,
  276. ch32_hwtimer_count_get,
  277. ch32_hwtimer_control
  278. };
  279. static void ch32_hwtimer_isr(struct rt_hwtimer_device *device)
  280. {
  281. RT_ASSERT(device != RT_NULL);
  282. struct ch32_hwtimer *hwtimer = RT_NULL;
  283. hwtimer = rt_container_of(device, struct ch32_hwtimer, device);
  284. if(TIM_GetITStatus(hwtimer->handle.instance, TIM_IT_Update) != RESET)
  285. {
  286. rt_device_hwtimer_isr(device);
  287. TIM_ClearITPendingBit(hwtimer->handle.instance, TIM_IT_Update);
  288. }
  289. }
  290. #ifdef BSP_USING_TIM1
  291. void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  292. void TIM1_UP_IRQHandler(void)
  293. {
  294. GET_INT_SP();
  295. rt_interrupt_enter();
  296. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM1_INDEX].device));
  297. rt_interrupt_leave();
  298. FREE_INT_SP();
  299. }
  300. #endif /* BSP_USING_TIM1 */
  301. #ifdef BSP_USING_TIM2
  302. void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  303. void TIM2_IRQHandler(void)
  304. {
  305. GET_INT_SP();
  306. rt_interrupt_enter();
  307. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM2_INDEX].device));
  308. rt_interrupt_leave();
  309. FREE_INT_SP();
  310. }
  311. #endif /* BSP_USING_TIM2 */
  312. #ifdef BSP_USING_TIM3
  313. void TIM3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  314. void TIM3_IRQHandler(void)
  315. {
  316. GET_INT_SP();
  317. rt_interrupt_enter();
  318. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM3_INDEX].device));
  319. rt_interrupt_leave();
  320. FREE_INT_SP();
  321. }
  322. #endif /* BSP_USING_TIM3 */
  323. #ifdef BSP_USING_TIM4
  324. void TIM4_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  325. void TIM4_IRQHandler(void)
  326. {
  327. GET_INT_SP();
  328. rt_interrupt_enter();
  329. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM4_INDEX].device));
  330. rt_interrupt_leave();
  331. FREE_INT_SP();
  332. }
  333. #endif /* BSP_USING_TIM4 */
  334. #ifdef BSP_USING_TIM5
  335. void TIM5_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  336. void TIM5_IRQHandler(void)
  337. {
  338. GET_INT_SP();
  339. rt_interrupt_enter();
  340. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM5_INDEX].device));
  341. rt_interrupt_leave();
  342. FREE_INT_SP();
  343. }
  344. #endif /* BSP_USING_TIM5 */
  345. #ifdef BSP_USING_TIM6
  346. void TIM6_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  347. void TIM6_IRQHandler(void)
  348. {
  349. GET_INT_SP();
  350. rt_interrupt_enter();
  351. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM6_INDEX].device));
  352. rt_interrupt_leave();
  353. FREE_INT_SP();
  354. }
  355. #endif /* BSP_USING_TIM6 */
  356. #ifdef BSP_USING_TIM7
  357. void TIM7_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  358. void TIM7_IRQHandler(void)
  359. {
  360. GET_INT_SP();
  361. rt_interrupt_enter();
  362. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM7_INDEX].device));
  363. rt_interrupt_leave();
  364. FREE_INT_SP();
  365. }
  366. #endif /* BSP_USING_TIM7 */
  367. #ifdef BSP_USING_TIM8
  368. void TIM8_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  369. void TIM8_UP_IRQHandler(void)
  370. {
  371. GET_INT_SP();
  372. rt_interrupt_enter();
  373. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM8_INDEX].device));
  374. rt_interrupt_leave();
  375. FREE_INT_SP();
  376. }
  377. #endif /* BSP_USING_TIM8 */
  378. #ifdef BSP_USING_TIM9
  379. void TIM9_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  380. void TIM9_UP_IRQHandler(void)
  381. {
  382. GET_INT_SP();
  383. rt_interrupt_enter();
  384. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM9_INDEX].device));
  385. rt_interrupt_leave();
  386. FREE_INT_SP();
  387. }
  388. #endif /* BSP_USING_TIM9 */
  389. #ifdef BSP_USING_TIM10
  390. void TIM10_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  391. void TIM10_UP_IRQHandler(void)
  392. {
  393. GET_INT_SP();
  394. rt_interrupt_enter();
  395. ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM10_INDEX].device));
  396. rt_interrupt_leave();
  397. FREE_INT_SP();
  398. }
  399. #endif /* BSP_USING_TIM10 */
  400. static int rt_hw_timer_init(void)
  401. {
  402. int i = 0;
  403. int result = RT_EOK;
  404. for (i = 0; i < sizeof(ch32_hwtimer_obj) / sizeof(ch32_hwtimer_obj[0]); i++)
  405. {
  406. ch32_hwtimer_obj[i].device.info = &ch32_hwtimer_info;
  407. ch32_hwtimer_obj[i].device.ops = &ch32_hwtimer_ops;
  408. result = rt_device_hwtimer_register(&ch32_hwtimer_obj[i].device,
  409. ch32_hwtimer_obj[i].name, (void *)&ch32_hwtimer_obj[i].handle);
  410. RT_ASSERT(result == RT_EOK);
  411. }
  412. return result;
  413. }
  414. INIT_BOARD_EXPORT(rt_hw_timer_init);
  415. #endif /* RT_USING_HWTIMER */
  416. #endif /* BSP_USING_HWTIMER */