drv_pwm.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  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-03-04 stevetong459 first version
  9. * 2022-07-15 Aligagago add apm32F4 serie MCU support
  10. */
  11. #include <board.h>
  12. #ifdef RT_USING_PWM
  13. #include <drivers/rt_drv_pwm.h>
  14. #define LOG_TAG "drv.pwm"
  15. #define DBG_LVL DBG_INFO
  16. #include <rtdbg.h>
  17. #define MAX_PERIOD 65535
  18. #define MIN_PERIOD 3
  19. #define MIN_PULSE 2
  20. #ifdef APM32F10X_HD
  21. #define _PWM_GPIO_INIT(port_num, pin_num) \
  22. do \
  23. { \
  24. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIO##port_num); \
  25. gpio_config->pin = GPIO_PIN_##pin_num; \
  26. gpio_config->mode = GPIO_MODE_AF_PP; \
  27. gpio_config->speed = GPIO_SPEED_50MHz; \
  28. GPIO_Config(GPIO##port_num, gpio_config); \
  29. } while (0)
  30. #elif APM32F40X
  31. #define _PWM_GPIO_INIT(port_num, pin_num) \
  32. do \
  33. { \
  34. RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIO##port_num); \
  35. gpio_config->pin = GPIO_PIN_##pin_num; \
  36. gpio_config->mode = GPIO_MODE_AF; \
  37. gpio_config->otype = GPIO_OTYPE_PP; \
  38. gpio_config->speed = GPIO_SPEED_50MHz; \
  39. GPIO_Config(GPIO##port_num, gpio_config); \
  40. } while (0)
  41. #endif
  42. enum
  43. {
  44. #ifdef BSP_USING_PWM1
  45. PWM1_INDEX,
  46. #endif
  47. #ifdef BSP_USING_PWM2
  48. PWM2_INDEX,
  49. #endif
  50. #ifdef BSP_USING_PWM3
  51. PWM3_INDEX,
  52. #endif
  53. #ifdef BSP_USING_PWM4
  54. PWM4_INDEX,
  55. #endif
  56. #ifdef BSP_USING_PWM5
  57. PWM5_INDEX,
  58. #endif
  59. #ifdef BSP_USING_PWM8
  60. PWM8_INDEX,
  61. #endif
  62. #ifdef BSP_USING_PWM9
  63. PWM9_INDEX,
  64. #endif
  65. #ifdef BSP_USING_PWM10
  66. PWM10_INDEX,
  67. #endif
  68. #ifdef BSP_USING_PWM11
  69. PWM11_INDEX,
  70. #endif
  71. #ifdef BSP_USING_PWM12
  72. PWM12_INDEX,
  73. #endif
  74. #ifdef BSP_USING_PWM13
  75. PWM13_INDEX,
  76. #endif
  77. #ifdef BSP_USING_PWM14
  78. PWM14_INDEX,
  79. #endif
  80. };
  81. struct apm32_pwm
  82. {
  83. char *name;
  84. TMR_T *tmr;
  85. rt_uint8_t channel;
  86. struct rt_device_pwm pwm_device;
  87. };
  88. static struct apm32_pwm pwm_config[] =
  89. {
  90. #ifdef BSP_USING_PWM1
  91. {
  92. "pwm1",
  93. TMR1,
  94. 0,
  95. },
  96. #endif
  97. #ifdef BSP_USING_PWM2
  98. {
  99. "pwm2",
  100. TMR2,
  101. 0,
  102. },
  103. #endif
  104. #ifdef BSP_USING_PWM3
  105. {
  106. "pwm3",
  107. TMR3,
  108. 0,
  109. },
  110. #endif
  111. #ifdef BSP_USING_PWM4
  112. {
  113. "pwm4",
  114. TMR4,
  115. 0,
  116. },
  117. #endif
  118. #ifdef BSP_USING_PWM5
  119. {
  120. "pwm5",
  121. TMR5,
  122. 0,
  123. },
  124. #endif
  125. #ifdef BSP_USING_PWM8
  126. {
  127. "pwm8",
  128. TMR8,
  129. 0,
  130. },
  131. #endif
  132. #ifdef BSP_USING_PWM9
  133. {
  134. "pwm9",
  135. TMR9,
  136. 0,
  137. },
  138. #endif
  139. #ifdef BSP_USING_PWM10
  140. {
  141. "pwm10",
  142. TMR10,
  143. 0,
  144. },
  145. #endif
  146. #ifdef BSP_USING_PWM11
  147. {
  148. "pwm11",
  149. TMR11,
  150. 0,
  151. },
  152. #endif
  153. #ifdef BSP_USING_PWM12
  154. {
  155. "pwm12",
  156. TMR12,
  157. 0,
  158. },
  159. #endif
  160. #ifdef BSP_USING_PWM13
  161. {
  162. "pwm13",
  163. TMR13,
  164. 0,
  165. },
  166. #endif
  167. #ifdef BSP_USING_PWM14
  168. {
  169. "pwm14",
  170. TMR14,
  171. 0,
  172. },
  173. #endif
  174. };
  175. static void _pwm_channel_init(GPIO_Config_T *gpio_config)
  176. {
  177. #ifdef BSP_USING_PWM1_CH1
  178. pwm_config[PWM1_INDEX].channel |= 1 << 0;
  179. _PWM_GPIO_INIT(A, 8);
  180. #endif
  181. #ifdef BSP_USING_PWM1_CH2
  182. pwm_config[PWM1_INDEX].channel |= 1 << 1;
  183. _PWM_GPIO_INIT(A, 9);
  184. #endif
  185. #ifdef BSP_USING_PWM1_CH3
  186. pwm_config[PWM1_INDEX].channel |= 1 << 2;
  187. _PWM_GPIO_INIT(A, 10);
  188. #endif
  189. #ifdef BSP_USING_PWM1_CH4
  190. pwm_config[PWM1_INDEX].channel |= 1 << 3;
  191. _PWM_GPIO_INIT(A, 11);
  192. #endif
  193. #ifdef BSP_USING_PWM2_CH1
  194. pwm_config[PWM2_INDEX].channel |= 1 << 0;
  195. _PWM_GPIO_INIT(A, 0);
  196. #endif
  197. #ifdef BSP_USING_PWM2_CH2
  198. pwm_config[PWM2_INDEX].channel |= 1 << 1;
  199. _PWM_GPIO_INIT(A, 1);
  200. #endif
  201. #ifdef BSP_USING_PWM2_CH3
  202. pwm_config[PWM2_INDEX].channel |= 1 << 2;
  203. _PWM_GPIO_INIT(A, 2);
  204. #endif
  205. #ifdef BSP_USING_PWM2_CH4
  206. pwm_config[PWM2_INDEX].channel |= 1 << 3;
  207. _PWM_GPIO_INIT(A, 3);
  208. #endif
  209. #ifdef APM32F10X_HD
  210. #ifdef BSP_USING_PWM3_CH1
  211. pwm_config[PWM3_INDEX].channel |= 1 << 0;
  212. GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3);
  213. _PWM_GPIO_INIT(C, 6);
  214. #endif
  215. #ifdef BSP_USING_PWM3_CH2
  216. pwm_config[PWM3_INDEX].channel |= 1 << 1;
  217. GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3);
  218. _PWM_GPIO_INIT(C, 7);
  219. #endif
  220. #ifdef BSP_USING_PWM3_CH3
  221. pwm_config[PWM3_INDEX].channel |= 1 << 2;
  222. GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3);
  223. _PWM_GPIO_INIT(C, 8);
  224. #endif
  225. #ifdef BSP_USING_PWM3_CH4
  226. pwm_config[PWM3_INDEX].channel |= 1 << 3;
  227. GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3);
  228. _PWM_GPIO_INIT(C, 9);
  229. #endif
  230. #elif APM32F40X
  231. #ifdef BSP_USING_PWM3_CH1
  232. pwm_config[PWM3_INDEX].channel |= 1 << 0;
  233. GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_6, GPIO_AF_TMR3);
  234. _PWM_GPIO_INIT(C, 6);
  235. #endif
  236. #ifdef BSP_USING_PWM3_CH2
  237. pwm_config[PWM3_INDEX].channel |= 1 << 1;
  238. GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_7, GPIO_AF_TMR3);
  239. _PWM_GPIO_INIT(C, 7);
  240. #endif
  241. #ifdef BSP_USING_PWM3_CH3
  242. pwm_config[PWM3_INDEX].channel |= 1 << 2;
  243. GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_8, GPIO_AF_TMR3);
  244. _PWM_GPIO_INIT(C, 8);
  245. #endif
  246. #ifdef BSP_USING_PWM3_CH4
  247. pwm_config[PWM3_INDEX].channel |= 1 << 3;
  248. GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_9, GPIO_AF_TMR3);
  249. _PWM_GPIO_INIT(C, 9);
  250. #endif
  251. #endif
  252. #ifdef BSP_USING_PWM4_CH1
  253. pwm_config[PWM4_INDEX].channel |= 1 << 0;
  254. _PWM_GPIO_INIT(B, 6);
  255. #endif
  256. #ifdef BSP_USING_PWM4_CH2
  257. pwm_config[PWM4_INDEX].channel |= 1 << 1;
  258. _PWM_GPIO_INIT(B, 7);
  259. #endif
  260. #ifdef BSP_USING_PWM4_CH3
  261. pwm_config[PWM4_INDEX].channel |= 1 << 2;
  262. _PWM_GPIO_INIT(B, 8);
  263. #endif
  264. #ifdef BSP_USING_PWM4_CH4
  265. pwm_config[PWM4_INDEX].channel |= 1 << 3;
  266. _PWM_GPIO_INIT(B, 9);
  267. #endif
  268. #ifdef BSP_USING_PWM5_CH1
  269. pwm_config[PWM5_INDEX].channel |= 1 << 0;
  270. _PWM_GPIO_INIT(A, 0);
  271. #endif
  272. #ifdef BSP_USING_PWM5_CH2
  273. pwm_config[PWM5_INDEX].channel |= 1 << 1;
  274. _PWM_GPIO_INIT(A, 1);
  275. #endif
  276. #ifdef BSP_USING_PWM5_CH3
  277. pwm_config[PWM5_INDEX].channel |= 1 << 2;
  278. _PWM_GPIO_INIT(A, 2);
  279. #endif
  280. #ifdef BSP_USING_PWM5_CH4
  281. pwm_config[PWM5_INDEX].channel |= 1 << 3;
  282. _PWM_GPIO_INIT(A, 3);
  283. #endif
  284. #ifdef BSP_USING_PWM8_CH1
  285. pwm_config[PWM8_INDEX].channel |= 1 << 0;
  286. _PWM_GPIO_INIT(C, 6);
  287. #endif
  288. #ifdef BSP_USING_PWM8_CH2
  289. pwm_config[PWM8_INDEX].channel |= 1 << 1;
  290. _PWM_GPIO_INIT(C, 7);
  291. #endif
  292. #ifdef BSP_USING_PWM8_CH3
  293. pwm_config[PWM8_INDEX].channel |= 1 << 2;
  294. _PWM_GPIO_INIT(C, 8);
  295. #endif
  296. #ifdef BSP_USING_PWM8_CH4
  297. pwm_config[PWM8_INDEX].channel |= 1 << 3;
  298. _PWM_GPIO_INIT(C, 9);
  299. #endif
  300. #ifdef APM32F40X
  301. #ifdef BSP_USING_PWM9_CH1
  302. pwm_config[PWM9_INDEX].channel |= 1 << 0;
  303. _PWM_GPIO_INIT(E, 5);
  304. #endif
  305. #ifdef BSP_USING_PWM9_CH2
  306. pwm_config[PWM9_INDEX].channel |= 1 << 1;
  307. _PWM_GPIO_INIT(E, 6);
  308. #endif
  309. #ifdef BSP_USING_PWM10_CH1
  310. pwm_config[PWM10_INDEX].channel |= 1 << 0;
  311. _PWM_GPIO_INIT(F, 6);
  312. #endif
  313. #ifdef BSP_USING_PWM11_CH1
  314. pwm_config[PWM11_INDEX].channel |= 1 << 0;
  315. _PWM_GPIO_INIT(F, 7);
  316. #endif
  317. #ifdef BSP_USING_PWM12_CH1
  318. pwm_config[PWM9_INDEX].channel |= 1 << 0;
  319. _PWM_GPIO_INIT(H, 6);
  320. #endif
  321. #ifdef BSP_USING_PWM12_CH2
  322. pwm_config[PWM9_INDEX].channel |= 1 << 1;
  323. _PWM_GPIO_INIT(H, 9);
  324. #endif
  325. #ifdef BSP_USING_PWM13_CH1
  326. pwm_config[PWM10_INDEX].channel |= 1 << 0;
  327. _PWM_GPIO_INIT(F, 8);
  328. #endif
  329. #ifdef BSP_USING_PWM14_CH1
  330. pwm_config[PWM11_INDEX].channel |= 1 << 0;
  331. _PWM_GPIO_INIT(F, 9);
  332. #endif
  333. #endif
  334. }
  335. static rt_err_t _pwm_hw_init(struct apm32_pwm *device)
  336. {
  337. rt_err_t result = RT_EOK;
  338. TMR_T *tmr = RT_NULL;
  339. TMR_BaseConfig_T base_config;
  340. TMR_OCConfig_T oc_config;
  341. RT_ASSERT(device != RT_NULL);
  342. tmr = (TMR_T *)device->tmr;
  343. if (tmr == TMR1)
  344. {
  345. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR1);
  346. }
  347. else if (tmr == TMR8)
  348. {
  349. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR8);
  350. }
  351. else if (tmr == TMR2)
  352. {
  353. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR2);
  354. }
  355. else if (tmr == TMR3)
  356. {
  357. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);
  358. }
  359. else if (tmr == TMR4)
  360. {
  361. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR4);
  362. }
  363. else if (tmr == TMR5)
  364. {
  365. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR5);
  366. }
  367. /* configure the tmrer to pwm mode */
  368. base_config.division = 0;
  369. base_config.countMode = TMR_COUNTER_MODE_UP;
  370. base_config.period = 0;
  371. base_config.clockDivision = TMR_CLOCK_DIV_1;
  372. TMR_ConfigTimeBase(tmr, &base_config);
  373. TMR_SelectOutputTrigger(tmr, TMR_TRGO_SOURCE_RESET);
  374. TMR_DisableMasterSlaveMode(tmr);
  375. oc_config.mode = TMR_OC_MODE_PWM1;
  376. oc_config.pulse = 0;
  377. oc_config.polarity = TMR_OC_POLARITY_HIGH;
  378. oc_config.nIdleState = TMR_OC_NIDLE_STATE_RESET;
  379. oc_config.idleState = TMR_OC_IDLE_STATE_RESET;
  380. oc_config.outputState = TMR_OC_STATE_ENABLE;
  381. /* config pwm channel */
  382. if (device->channel & 0x01)
  383. {
  384. TMR_ConfigOC1(tmr, &oc_config);
  385. }
  386. if (device->channel & 0x02)
  387. {
  388. TMR_ConfigOC2(tmr, &oc_config);
  389. }
  390. if (device->channel & 0x04)
  391. {
  392. TMR_ConfigOC3(tmr, &oc_config);
  393. }
  394. if (device->channel & 0x08)
  395. {
  396. TMR_ConfigOC4(tmr, &oc_config);
  397. }
  398. /* enable update request source */
  399. TMR_ConfigUpdateRequest(tmr, TMR_UPDATE_SOURCE_REGULAR);
  400. return result;
  401. }
  402. static rt_uint32_t _pwm_timer_clock_get(TMR_T *tmr)
  403. {
  404. uint32_t pclk1;
  405. RCM_ReadPCLKFreq(&pclk1, NULL);
  406. return (rt_uint32_t)(pclk1 * ((RCM->CFG_B.APB1PSC != RCM_APB_DIV_1) ? 2 : 1));
  407. }
  408. static rt_err_t _pwm_enable(TMR_T *tmr, struct rt_pwm_configuration *configuration, rt_bool_t enable)
  409. {
  410. rt_uint32_t channel = (configuration->channel - 1) << 2;
  411. if (enable)
  412. {
  413. if (configuration->complementary)
  414. {
  415. TMR_EnableCCxNChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU)));
  416. }
  417. else
  418. {
  419. TMR_EnableCCxChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU)));
  420. }
  421. if (tmr == TMR1 || tmr == TMR8)
  422. {
  423. TMR_EnablePWMOutputs(tmr);
  424. }
  425. TMR_Enable(tmr);
  426. }
  427. else
  428. {
  429. if (configuration->complementary)
  430. {
  431. TMR_DisableCCxNChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU)));
  432. }
  433. else
  434. {
  435. TMR_DisableCCxChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU)));
  436. }
  437. if (tmr == TMR1 || tmr == TMR8)
  438. {
  439. TMR_DisablePWMOutputs(tmr);
  440. }
  441. TMR_Disable(tmr);
  442. }
  443. return RT_EOK;
  444. }
  445. static rt_err_t _pwm_get(TMR_T *tmr, struct rt_pwm_configuration *configuration)
  446. {
  447. /* Converts the channel number to the channel number of library */
  448. rt_uint32_t channel = (configuration->channel - 1) << 2;
  449. rt_uint64_t timer_clock;
  450. rt_uint32_t timer_reload, timer_psc;
  451. timer_clock = _pwm_timer_clock_get(tmr);
  452. if (tmr->CTRL1_B.CLKDIV == TMR_CLOCK_DIV_2)
  453. {
  454. timer_clock <<= 1;
  455. }
  456. else if (tmr->CTRL1_B.CLKDIV == TMR_CLOCK_DIV_4)
  457. {
  458. timer_clock <<= 2;
  459. }
  460. uint32_t temp;
  461. temp = (uint32_t)tmr;
  462. temp += (uint32_t)(0x34 + channel);
  463. /* Convert nanosecond to frequency and duty cycle.*/
  464. timer_clock /= 1000000UL;
  465. timer_reload = tmr->AUTORLD;
  466. timer_psc = tmr->PSC;
  467. configuration->period = (timer_reload + 1) * (timer_psc + 1) * 1000UL / timer_clock;
  468. configuration->pulse = ((*(__IO uint32_t *)temp) + 1) * (timer_psc + 1) * 1000UL / timer_clock;
  469. return RT_EOK;
  470. }
  471. static rt_err_t _pwm_set(TMR_T *tmr, struct rt_pwm_configuration *configuration)
  472. {
  473. rt_uint32_t period, pulse;
  474. rt_uint64_t timer_clock, psc;
  475. rt_uint32_t channel = 0x04 * (configuration->channel - 1);
  476. uint32_t temp = (uint32_t)tmr;
  477. timer_clock = _pwm_timer_clock_get(tmr);
  478. /* Convert nanosecond to frequency and duty cycle. */
  479. timer_clock /= 1000000UL;
  480. period = (unsigned long long)configuration->period * timer_clock / 1000ULL ;
  481. psc = period / MAX_PERIOD + 1;
  482. period = period / psc;
  483. tmr->PSC = (uint16_t)(psc - 1);
  484. if (period < MIN_PERIOD)
  485. {
  486. period = MIN_PERIOD;
  487. }
  488. tmr->AUTORLD = (uint16_t)(period - 1);
  489. pulse = (unsigned long long)configuration->pulse * timer_clock / psc / 1000ULL;
  490. if (pulse < MIN_PULSE)
  491. {
  492. pulse = MIN_PULSE;
  493. }
  494. else if (pulse > period)
  495. {
  496. pulse = period;
  497. }
  498. temp += (uint32_t)(0x34 + channel);
  499. *(__IO uint32_t *)temp = pulse - 1;
  500. tmr->CNT = 0;
  501. /* Update frequency value */
  502. TMR_GenerateEvent(tmr, TMR_EVENT_UPDATE);
  503. return RT_EOK;
  504. }
  505. static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  506. {
  507. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  508. TMR_T *tmr = (TMR_T *)device->parent.user_data;
  509. switch (cmd)
  510. {
  511. case PWMN_CMD_ENABLE:
  512. configuration->complementary = RT_TRUE;
  513. case PWM_CMD_ENABLE:
  514. return _pwm_enable(tmr, configuration, RT_TRUE);
  515. case PWMN_CMD_DISABLE:
  516. configuration->complementary = RT_FALSE;
  517. case PWM_CMD_DISABLE:
  518. return _pwm_enable(tmr, configuration, RT_FALSE);
  519. case PWM_CMD_SET:
  520. return _pwm_set(tmr, configuration);
  521. case PWM_CMD_GET:
  522. return _pwm_get(tmr, configuration);
  523. default:
  524. return RT_EINVAL;
  525. }
  526. }
  527. static const struct rt_pwm_ops _pwm_ops =
  528. {
  529. _pwm_control
  530. };
  531. static int rt_hw_pwm_init(void)
  532. {
  533. rt_uint32_t i = 0;
  534. rt_err_t result = RT_EOK;
  535. GPIO_Config_T gpio_config;
  536. _pwm_channel_init(&gpio_config);
  537. for (i = 0; i < sizeof(pwm_config) / sizeof(pwm_config[0]); i++)
  538. {
  539. /* pwm init */
  540. if (_pwm_hw_init(&pwm_config[i]) != RT_EOK)
  541. {
  542. LOG_E("%s init failed", pwm_config[i].name);
  543. return -RT_ERROR;
  544. }
  545. else
  546. {
  547. LOG_D("%s init success", pwm_config[i].name);
  548. /* register pwm device */
  549. if (rt_device_pwm_register(&pwm_config[i].pwm_device, pwm_config[i].name, &_pwm_ops, pwm_config[i].tmr) == RT_EOK)
  550. {
  551. LOG_D("%s register success", pwm_config[i].name);
  552. }
  553. else
  554. {
  555. LOG_E("%s register failed", pwm_config[i].name);
  556. result = -RT_ERROR;
  557. }
  558. }
  559. }
  560. return result;
  561. }
  562. INIT_DEVICE_EXPORT(rt_hw_pwm_init);
  563. #endif /* RT_USING_PWM */