drv_hwtimer.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. /*****************************************************************************
  2. * Copyright (c) 2019, Nations Technologies Inc.
  3. *
  4. * All rights reserved.
  5. * ****************************************************************************
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * - Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the disclaimer below.
  12. *
  13. * Nations' name may not be used to endorse or promote products derived from
  14. * this software without specific prior written permission.
  15. *
  16. * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  19. * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  21. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  22. * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  23. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  24. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  25. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. * ****************************************************************************/
  27. /**
  28. * @file drv_hwtimer.c
  29. * @author Nations
  30. * @version v1.0.0
  31. *
  32. * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
  33. */
  34. #include "drv_hwtimer.h"
  35. #ifdef RT_USING_HWTIMER
  36. #if defined(BSP_USING_HWTIMER1) || defined(BSP_USING_HWTIMER2) || defined(BSP_USING_HWTIMER3) \
  37. || defined(BSP_USING_HWTIMER4) || defined(BSP_USING_HWTIMER5) || defined(BSP_USING_HWTIMER6) \
  38. || defined(BSP_USING_HWTIMER7) || defined(BSP_USING_HWTIMER8)
  39. /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable HWTIMER */
  40. static struct n32_hwtimer_config hwtimer_config[] =
  41. {
  42. #ifdef BSP_USING_HWTIMER1
  43. {
  44. "timer1",
  45. TIM1,
  46. TIM1_UP_IRQn,
  47. },
  48. #endif
  49. #ifdef BSP_USING_HWTIMER2
  50. {
  51. "timer2",
  52. TIM2,
  53. TIM2_IRQn,
  54. },
  55. #endif
  56. #ifdef BSP_USING_HWTIMER3
  57. {
  58. "timer3",
  59. TIM3,
  60. TIM3_IRQn,
  61. },
  62. #endif
  63. #ifdef BSP_USING_HWTIMER4
  64. {
  65. "timer4",
  66. TIM4,
  67. TIM4_IRQn,
  68. },
  69. #endif
  70. #ifdef BSP_USING_HWTIMER5
  71. {
  72. "timer5",
  73. TIM5,
  74. TIM5_IRQn,
  75. },
  76. #endif
  77. #ifdef BSP_USING_HWTIMER6
  78. {
  79. "timer6",
  80. TIM6,
  81. TIM6_IRQn,
  82. },
  83. #endif
  84. #ifdef BSP_USING_HWTIMER7
  85. {
  86. "timer7",
  87. TIM7,
  88. TIM7_IRQn,
  89. },
  90. #endif
  91. #ifdef BSP_USING_HWTIMER8
  92. {
  93. "timer8",
  94. TIM8,
  95. TIM8_UP_IRQn,
  96. },
  97. #endif
  98. };
  99. uint8_t tim1_count = 0, tim2_count = 0, tim3_count = 0, tim4_count = 0,tim5_count = 0, tim6_count = 0, tim7_count = 0, tim8_count = 0;
  100. static void caculate_tim_count()
  101. {
  102. uint8_t count = 0;
  103. #ifdef BSP_USING_HWTIMER1
  104. tim1_count = count;
  105. count++;
  106. #endif
  107. #ifdef BSP_USING_HWTIMER2
  108. tim2_count = count;
  109. count++;
  110. #endif
  111. #ifdef BSP_USING_HWTIMER3
  112. tim3_count = count;
  113. count++;
  114. #endif
  115. #ifdef BSP_USING_HWTIMER4
  116. tim4_count = count;
  117. count++;
  118. #endif
  119. #ifdef BSP_USING_HWTIMER5
  120. tim5_count = count;
  121. count++;
  122. #endif
  123. #ifdef BSP_USING_HWTIMER6
  124. tim6_count = count;
  125. count++;
  126. #endif
  127. #ifdef BSP_USING_HWTIMER7
  128. tim7_count = count;
  129. count++;
  130. #endif
  131. #ifdef BSP_USING_HWTIMER8
  132. tim8_count = count;
  133. count++;
  134. #endif
  135. }
  136. #define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end))))
  137. #define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start))
  138. static struct n32_hwtimer hwtimer_obj[sizeof(hwtimer_config) / sizeof(hwtimer_config[0])] = {0};
  139. static rt_err_t n32_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
  140. {
  141. rt_err_t err = RT_EOK;
  142. struct n32_hwtimer_config *config;
  143. RCC_ClocksType RCC_ClockFreq;
  144. RT_ASSERT(timer != RT_NULL);
  145. config = (struct n32_hwtimer_config *)timer->parent.user_data;
  146. RCC_GetClocksFreqValue(&RCC_ClockFreq);
  147. switch (cmd)
  148. {
  149. case HWTIMER_CTRL_FREQ_SET:
  150. {
  151. uint32_t clk;
  152. uint8_t clkpre;
  153. uint32_t pre;
  154. if (config->timer_periph != TIM1 && config->timer_periph != TIM8)
  155. {
  156. clk = RCC_ClockFreq.Pclk1Freq;
  157. clkpre = GET_BITS(RCC->CFG, 8, 10);
  158. }
  159. else
  160. {
  161. clk = RCC_ClockFreq.Pclk2Freq;
  162. clkpre = GET_BITS(RCC->CFG, 11, 13);
  163. }
  164. if (clkpre >= 4)
  165. {
  166. clk = clk * 2;
  167. }
  168. pre = (clk / * ((uint32_t *)args)) - 1;
  169. TIM_ConfigPrescaler(config->timer_periph, pre, TIM_PSC_RELOAD_MODE_IMMEDIATE);
  170. config->timer_periph->EVTGEN |= TIM_EVTGEN_UDGN;
  171. }
  172. break;
  173. case HWTIMER_CTRL_STOP:
  174. TIM_Enable(config->timer_periph, DISABLE);
  175. break;
  176. default:
  177. err = -RT_ENOSYS;
  178. break;
  179. }
  180. return err;
  181. }
  182. static rt_uint32_t n32_hwtimer_count_get(rt_hwtimer_t *timer)
  183. {
  184. rt_uint32_t CurrentTimer_Count;
  185. struct n32_hwtimer_config *config;
  186. RT_ASSERT(timer != RT_NULL);
  187. config = (struct n32_hwtimer_config *)timer->parent.user_data;
  188. CurrentTimer_Count = TIM_GetCnt(config->timer_periph);
  189. return CurrentTimer_Count;
  190. }
  191. /**
  192. * @brief Configures the NVIC for TIM.
  193. */
  194. void TIM_NVIC_Config(IRQn_Type IRQn, uint8_t PreemptionPriority, uint8_t SubPriority,FunctionalState cmd)
  195. {
  196. NVIC_InitType NVIC_InitStructure;
  197. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  198. NVIC_InitStructure.NVIC_IRQChannel = IRQn;
  199. NVIC_InitStructure.NVIC_IRQChannelCmd = cmd;
  200. if(cmd)
  201. {
  202. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriority;
  203. NVIC_InitStructure.NVIC_IRQChannelSubPriority = SubPriority;
  204. }
  205. NVIC_Init(&NVIC_InitStructure);
  206. }
  207. static void n32_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  208. {
  209. struct n32_hwtimer_config *config;
  210. TIM_TimeBaseInitType TIM_TimeBaseStructure;
  211. RCC_ClocksType RCC_ClockFreq;
  212. RT_ASSERT(timer != RT_NULL);
  213. config = (struct n32_hwtimer_config *)timer->parent.user_data;
  214. if (state == 1)
  215. {
  216. uint32_t clk;
  217. uint8_t clkpre;
  218. uint32_t pre;
  219. RCC_GetClocksFreqValue(&RCC_ClockFreq);
  220. TIM_DeInit(config->timer_periph);
  221. if (config->timer_periph != TIM1 && config->timer_periph != TIM8)
  222. {
  223. clk = RCC_ClockFreq.Pclk1Freq;
  224. clkpre = GET_BITS(RCC->CFG, 8, 10);
  225. }
  226. else
  227. {
  228. clk = RCC_ClockFreq.Pclk2Freq;
  229. clkpre = GET_BITS(RCC->CFG, 11, 13);
  230. }
  231. if (clkpre >= 4)
  232. {
  233. clk = clk * 2;
  234. }
  235. pre = (clk / 10000) - 1;
  236. /* Time Base configuration */
  237. TIM_TimeBaseStructure.Prescaler = pre;
  238. TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
  239. TIM_TimeBaseStructure.Period = 10000 - 1;
  240. TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;
  241. TIM_TimeBaseStructure.RepetCnt = 0;
  242. if (timer->info->cntmode == HWTIMER_CNTMODE_UP)
  243. {
  244. TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
  245. }
  246. else
  247. {
  248. TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_DOWN;
  249. }
  250. TIM_InitTimeBase(config->timer_periph, &TIM_TimeBaseStructure);
  251. /* set the TIMx priority */
  252. TIM_NVIC_Config(config->irqn, 3, 0, ENABLE);
  253. /* clear update flag */
  254. TIM_ClearFlag(config->timer_periph, TIM_FLAG_UPDATE);
  255. }
  256. else
  257. {
  258. TIM_Enable(config->timer_periph, DISABLE);
  259. TIM_ConfigInt(config->timer_periph, TIM_INT_UPDATE, ENABLE);
  260. TIM_NVIC_Config(config->irqn, 3, 0, DISABLE);
  261. }
  262. }
  263. static rt_err_t n32_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
  264. {
  265. struct n32_hwtimer_config *config;
  266. RT_ASSERT(timer != RT_NULL);
  267. config = (struct n32_hwtimer_config *)timer->parent.user_data;
  268. /* set tim cnt */
  269. TIM_SetCnt(config->timer_periph, 0);
  270. /* set tim arr */
  271. TIM_SetAutoReload(config->timer_periph, cnt - 1);
  272. if (mode == HWTIMER_MODE_ONESHOT)
  273. {
  274. TIM_SelectOnePulseMode(config->timer_periph, TIM_OPMODE_SINGLE);
  275. }
  276. else
  277. {
  278. TIM_SelectOnePulseMode(config->timer_periph, TIM_OPMODE_REPET);
  279. }
  280. /* start timer */
  281. TIM_ConfigInt(config->timer_periph, TIM_INT_UPDATE, ENABLE);
  282. /* TIM counter enable */
  283. TIM_Enable(config->timer_periph, ENABLE);
  284. TIM_NVIC_Config(config->irqn, 3, 0, ENABLE);
  285. return RT_EOK;
  286. }
  287. static void n32_hwtimer_stop(rt_hwtimer_t *timer)
  288. {
  289. struct n32_hwtimer_config *config;
  290. RT_ASSERT(timer != RT_NULL);
  291. config = (struct n32_hwtimer_config *)timer->parent.user_data;
  292. TIM_Enable(config->timer_periph, DISABLE);
  293. TIM_NVIC_Config(config->irqn, 3, 0, DISABLE);
  294. }
  295. static const struct rt_hwtimer_ops n32_hwtimer_ops =
  296. {
  297. .init = n32_hwtimer_init,
  298. .start = n32_hwtimer_start,
  299. .stop = n32_hwtimer_stop,
  300. .count_get = n32_hwtimer_count_get,
  301. .control = n32_hwtimer_control,
  302. };
  303. static const struct rt_hwtimer_info n32_hwtimer_info =
  304. {
  305. 1000000, /* the maximum count frequency can be set */
  306. 2000, /* the minimum count frequency can be set */
  307. 0xFFFF,
  308. HWTIMER_CNTMODE_UP,
  309. };
  310. /**
  311. * @brief This function handles TIM interrupts requests.
  312. * @param htim TIM handle
  313. * @retval None
  314. */
  315. void TIM_IRQHandler(TIM_Module* timer_periph)
  316. {
  317. /* Capture compare 1 event */
  318. if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_CC1) != RESET)
  319. {
  320. if(TIM_GetIntStatus(timer_periph, TIM_INT_CC1) !=RESET)
  321. {
  322. {
  323. TIM_ClrIntPendingBit(timer_periph, TIM_INT_CC1);
  324. }
  325. }
  326. }
  327. /* Capture compare 2 event */
  328. if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_CC2) != RESET)
  329. {
  330. if(TIM_GetIntStatus(timer_periph, TIM_INT_CC2) !=RESET)
  331. {
  332. TIM_ClrIntPendingBit(timer_periph, TIM_INT_CC2);
  333. }
  334. }
  335. /* Capture compare 3 event */
  336. if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_CC3) != RESET)
  337. {
  338. if(TIM_GetIntStatus(timer_periph, TIM_INT_CC3) !=RESET)
  339. {
  340. TIM_ClrIntPendingBit(timer_periph, TIM_INT_CC3);
  341. }
  342. }
  343. /* Capture compare 4 event */
  344. if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_CC4) != RESET)
  345. {
  346. if(TIM_GetIntStatus(timer_periph, TIM_INT_CC4) !=RESET)
  347. {
  348. TIM_ClrIntPendingBit(timer_periph, TIM_INT_CC4);
  349. }
  350. }
  351. /* TIM Update event */
  352. if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_UPDATE) != RESET)
  353. {
  354. if(TIM_GetIntStatus(timer_periph, TIM_INT_UPDATE) !=RESET)
  355. {
  356. TIM_ClrIntPendingBit(timer_periph, TIM_INT_UPDATE);
  357. }
  358. }
  359. /* TIM Break input event */
  360. if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_BREAK) != RESET)
  361. {
  362. if(TIM_GetIntStatus(timer_periph, TIM_INT_BREAK) !=RESET)
  363. {
  364. TIM_ClrIntPendingBit(timer_periph, TIM_INT_BREAK);
  365. }
  366. }
  367. /* TIM Trigger detection event */
  368. if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_TRIG) != RESET)
  369. {
  370. if(TIM_GetIntStatus(timer_periph, TIM_INT_TRIG) !=RESET)
  371. {
  372. TIM_ClrIntPendingBit(timer_periph, TIM_INT_TRIG);
  373. }
  374. }
  375. /* TIM commutation event */
  376. if(TIM_GetFlagStatus(timer_periph, TIM_FLAG_COM) != RESET)
  377. {
  378. if(TIM_GetIntStatus(timer_periph, TIM_INT_COM) !=RESET)
  379. {
  380. TIM_ClrIntPendingBit(timer_periph, TIM_INT_COM);
  381. }
  382. }
  383. }
  384. #ifdef BSP_USING_HWTIMER1
  385. void TIM1_UP_IRQHandler(void)
  386. {
  387. /* enter interrupt */
  388. rt_interrupt_enter();
  389. // TIM_IRQHandler(hwtimer_obj[0].config->timer_periph);
  390. TIM_ClrIntPendingBit(hwtimer_obj[tim1_count].config->timer_periph, TIM_INT_UPDATE);
  391. rt_device_hwtimer_isr(&hwtimer_obj[tim1_count].time_device);
  392. /* leave interrupt */
  393. rt_interrupt_leave();
  394. }
  395. #endif
  396. #ifdef BSP_USING_HWTIMER2
  397. void TIM2_IRQHandler(void)
  398. {
  399. /* enter interrupt */
  400. rt_interrupt_enter();
  401. TIM_ClrIntPendingBit(hwtimer_obj[tim2_count].config->timer_periph, TIM_INT_UPDATE);
  402. rt_device_hwtimer_isr(&hwtimer_obj[tim2_count].time_device);
  403. /* leave interrupt */
  404. rt_interrupt_leave();
  405. }
  406. #endif
  407. #ifdef BSP_USING_HWTIMER3
  408. void TIM3_IRQHandler(void)
  409. {
  410. /* enter interrupt */
  411. rt_interrupt_enter();
  412. TIM_ClrIntPendingBit(hwtimer_obj[tim3_count].config->timer_periph, TIM_INT_UPDATE);
  413. rt_device_hwtimer_isr(&hwtimer_obj[tim3_count].time_device);
  414. /* leave interrupt */
  415. rt_interrupt_leave();
  416. }
  417. #endif
  418. #ifdef BSP_USING_HWTIMER4
  419. void TIM4_IRQHandler(void)
  420. {
  421. /* enter interrupt */
  422. rt_interrupt_enter();
  423. TIM_ClrIntPendingBit(hwtimer_obj[tim4_count].config->timer_periph, TIM_INT_UPDATE);
  424. rt_device_hwtimer_isr(&hwtimer_obj[tim4_count].time_device);
  425. /* leave interrupt */
  426. rt_interrupt_leave();
  427. }
  428. #endif
  429. #ifdef BSP_USING_HWTIMER5
  430. void TIM5_IRQHandler(void)
  431. {
  432. /* enter interrupt */
  433. rt_interrupt_enter();
  434. TIM_ClrIntPendingBit(hwtimer_obj[tim5_count].config->timer_periph, TIM_INT_UPDATE);
  435. rt_device_hwtimer_isr(&hwtimer_obj[tim5_count].time_device);
  436. /* leave interrupt */
  437. rt_interrupt_leave();
  438. }
  439. #endif
  440. #ifdef BSP_USING_HWTIMER6
  441. void TIM6_IRQHandler(void)
  442. {
  443. /* enter interrupt */
  444. rt_interrupt_enter();
  445. TIM_ClrIntPendingBit(hwtimer_obj[tim6_count].config->timer_periph, TIM_INT_UPDATE);
  446. rt_device_hwtimer_isr(&hwtimer_obj[tim6_count].time_device);
  447. /* leave interrupt */
  448. rt_interrupt_leave();
  449. }
  450. #endif
  451. #ifdef BSP_USING_HWTIMER7
  452. void TIM7_IRQHandler(void)
  453. {
  454. /* enter interrupt */
  455. rt_interrupt_enter();
  456. TIM_ClrIntPendingBit(hwtimer_obj[tim7_count].config->timer_periph, TIM_INT_UPDATE);
  457. rt_device_hwtimer_isr(&hwtimer_obj[tim7_count].time_device);
  458. /* leave interrupt */
  459. rt_interrupt_leave();
  460. }
  461. #endif
  462. #ifdef BSP_USING_HWTIMER8
  463. void TIM8_UP_IRQHandler(void)
  464. {
  465. /* enter interrupt */
  466. rt_interrupt_enter();
  467. TIM_ClrIntPendingBit(hwtimer_obj[tim8_count].config->timer_periph, TIM_INT_UPDATE);
  468. rt_device_hwtimer_isr(&hwtimer_obj[tim8_count].time_device);
  469. /* leave interrupt */
  470. rt_interrupt_leave();
  471. }
  472. #endif
  473. int rt_hwtimer_init(void)
  474. {
  475. int i = 0;
  476. int result = RT_EOK;
  477. #ifdef BSP_USING_HWTIMER1
  478. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM1, ENABLE);
  479. #endif
  480. #ifdef BSP_USING_HWTIMER2
  481. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE);
  482. #endif
  483. #ifdef BSP_USING_HWTIMER3
  484. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE);
  485. #endif
  486. #ifdef BSP_USING_HWTIMER4
  487. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM4, ENABLE);
  488. #endif
  489. #ifdef BSP_USING_HWTIMER5
  490. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM5, ENABLE);
  491. #endif
  492. #ifdef BSP_USING_HWTIMER6
  493. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM6, ENABLE);
  494. #endif
  495. #ifdef BSP_USING_HWTIMER7
  496. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM7, ENABLE);
  497. #endif
  498. #ifdef BSP_USING_HWTIMER8
  499. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM8, ENABLE);
  500. #endif
  501. caculate_tim_count();
  502. for (i = 0; i < sizeof(hwtimer_obj) / sizeof(hwtimer_obj[0]); i++)
  503. {
  504. hwtimer_obj[i].time_device.info = &n32_hwtimer_info;
  505. hwtimer_obj[i].time_device.ops = &n32_hwtimer_ops;
  506. hwtimer_obj[i].config = &hwtimer_config[i];
  507. rt_device_hwtimer_register(&hwtimer_obj[i].time_device, \
  508. hwtimer_obj[i].config->name, hwtimer_obj[i].config);
  509. }
  510. return result;
  511. }
  512. INIT_DEVICE_EXPORT(rt_hwtimer_init);
  513. #endif /* defined(BSP_USING_HWTIMERx) */
  514. #endif /* RT_USING_HWTIMER */