1
0

drv_pwm.c 15 KB

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