drv_pwm.c 14 KB

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