drv_pwm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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. */
  10. #include <board.h>
  11. #ifdef RT_USING_PWM
  12. #include <drivers/rt_drv_pwm.h>
  13. #define LOG_TAG "drv.pwm"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. #define MAX_PERIOD 65535
  17. #define MIN_PERIOD 3
  18. #define MIN_PULSE 2
  19. #define _PWM_GPIO_INIT(port_num, pin_num) \
  20. do \
  21. { \
  22. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIO##port_num); \
  23. gpio_config->pin = GPIO_PIN_##pin_num; \
  24. gpio_config->mode = GPIO_MODE_AF_PP; \
  25. gpio_config->speed = GPIO_SPEED_50MHz; \
  26. GPIO_Config(GPIO##port_num, gpio_config); \
  27. } while (0)
  28. enum
  29. {
  30. #ifdef BSP_USING_PWM1
  31. PWM1_INDEX,
  32. #endif
  33. #ifdef BSP_USING_PWM2
  34. PWM2_INDEX,
  35. #endif
  36. #ifdef BSP_USING_PWM3
  37. PWM3_INDEX,
  38. #endif
  39. #ifdef BSP_USING_PWM4
  40. PWM4_INDEX,
  41. #endif
  42. #ifdef BSP_USING_PWM5
  43. PWM5_INDEX,
  44. #endif
  45. #ifdef BSP_USING_PWM8
  46. PWM8_INDEX,
  47. #endif
  48. };
  49. struct apm32_pwm
  50. {
  51. char *name;
  52. TMR_T *tmr;
  53. rt_uint8_t channel;
  54. struct rt_device_pwm pwm_device;
  55. };
  56. static struct apm32_pwm pwm_config[] =
  57. {
  58. #ifdef BSP_USING_PWM1
  59. {
  60. "pwm1",
  61. TMR1,
  62. 0,
  63. },
  64. #endif
  65. #ifdef BSP_USING_PWM2
  66. {
  67. "pwm2",
  68. TMR2,
  69. 0,
  70. },
  71. #endif
  72. #ifdef BSP_USING_PWM3
  73. {
  74. "pwm3",
  75. TMR3,
  76. 0,
  77. },
  78. #endif
  79. #ifdef BSP_USING_PWM4
  80. {
  81. "pwm4",
  82. TMR4,
  83. 0,
  84. },
  85. #endif
  86. #ifdef BSP_USING_PWM5
  87. {
  88. "pwm5",
  89. TMR5,
  90. 0,
  91. },
  92. #endif
  93. #ifdef BSP_USING_PWM8
  94. {
  95. "pwm8",
  96. TMR8,
  97. 0,
  98. },
  99. #endif
  100. };
  101. static void _pwm_channel_init(GPIO_Config_T *gpio_config)
  102. {
  103. #ifdef BSP_USING_PWM1_CH1
  104. pwm_config[PWM1_INDEX].channel |= 1 << 0;
  105. _PWM_GPIO_INIT(A, 8);
  106. #endif
  107. #ifdef BSP_USING_PWM1_CH2
  108. pwm_config[PWM1_INDEX].channel |= 1 << 1;
  109. _PWM_GPIO_INIT(A, 9);
  110. #endif
  111. #ifdef BSP_USING_PWM1_CH3
  112. pwm_config[PWM1_INDEX].channel |= 1 << 2;
  113. _PWM_GPIO_INIT(A, 10);
  114. #endif
  115. #ifdef BSP_USING_PWM1_CH4
  116. pwm_config[PWM1_INDEX].channel |= 1 << 3;
  117. _PWM_GPIO_INIT(A, 11);
  118. #endif
  119. #ifdef BSP_USING_PWM2_CH1
  120. pwm_config[PWM2_INDEX].channel |= 1 << 0;
  121. _PWM_GPIO_INIT(A, 0);
  122. #endif
  123. #ifdef BSP_USING_PWM2_CH2
  124. pwm_config[PWM2_INDEX].channel |= 1 << 1;
  125. _PWM_GPIO_INIT(A, 1);
  126. #endif
  127. #ifdef BSP_USING_PWM2_CH3
  128. pwm_config[PWM2_INDEX].channel |= 1 << 2;
  129. _PWM_GPIO_INIT(A, 2);
  130. #endif
  131. #ifdef BSP_USING_PWM2_CH4
  132. pwm_config[PWM2_INDEX].channel |= 1 << 3;
  133. _PWM_GPIO_INIT(A, 3);
  134. #endif
  135. #ifdef BSP_USING_PWM3_CH1
  136. pwm_config[PWM3_INDEX].channel |= 1 << 0;
  137. GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3);
  138. _PWM_GPIO_INIT(C, 6);
  139. #endif
  140. #ifdef BSP_USING_PWM3_CH2
  141. pwm_config[PWM3_INDEX].channel |= 1 << 1;
  142. GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3);
  143. _PWM_GPIO_INIT(C, 7);
  144. #endif
  145. #ifdef BSP_USING_PWM3_CH3
  146. pwm_config[PWM3_INDEX].channel |= 1 << 2;
  147. GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3);
  148. _PWM_GPIO_INIT(C, 8);
  149. #endif
  150. #ifdef BSP_USING_PWM3_CH4
  151. pwm_config[PWM3_INDEX].channel |= 1 << 3;
  152. GPIO_ConfigPinRemap(GPIO_FULL_REMAP_TMR3);
  153. _PWM_GPIO_INIT(C, 9);
  154. #endif
  155. #ifdef BSP_USING_PWM4_CH1
  156. pwm_config[PWM4_INDEX].channel |= 1 << 0;
  157. _PWM_GPIO_INIT(B, 6);
  158. #endif
  159. #ifdef BSP_USING_PWM4_CH2
  160. pwm_config[PWM4_INDEX].channel |= 1 << 1;
  161. _PWM_GPIO_INIT(B, 7);
  162. #endif
  163. #ifdef BSP_USING_PWM4_CH3
  164. pwm_config[PWM4_INDEX].channel |= 1 << 2;
  165. _PWM_GPIO_INIT(B, 8);
  166. #endif
  167. #ifdef BSP_USING_PWM4_CH4
  168. pwm_config[PWM4_INDEX].channel |= 1 << 3;
  169. _PWM_GPIO_INIT(B, 9);
  170. #endif
  171. #ifdef BSP_USING_PWM5_CH1
  172. pwm_config[PWM5_INDEX].channel |= 1 << 0;
  173. _PWM_GPIO_INIT(A, 0);
  174. #endif
  175. #ifdef BSP_USING_PWM5_CH2
  176. pwm_config[PWM5_INDEX].channel |= 1 << 1;
  177. _PWM_GPIO_INIT(A, 1);
  178. #endif
  179. #ifdef BSP_USING_PWM5_CH3
  180. pwm_config[PWM5_INDEX].channel |= 1 << 2;
  181. _PWM_GPIO_INIT(A, 2);
  182. #endif
  183. #ifdef BSP_USING_PWM5_CH4
  184. pwm_config[PWM5_INDEX].channel |= 1 << 3;
  185. _PWM_GPIO_INIT(A, 3);
  186. #endif
  187. #ifdef BSP_USING_PWM8_CH1
  188. pwm_config[PWM8_INDEX].channel |= 1 << 0;
  189. _PWM_GPIO_INIT(C, 6);
  190. #endif
  191. #ifdef BSP_USING_PWM8_CH2
  192. pwm_config[PWM8_INDEX].channel |= 1 << 1;
  193. _PWM_GPIO_INIT(C, 7);
  194. #endif
  195. #ifdef BSP_USING_PWM8_CH3
  196. pwm_config[PWM8_INDEX].channel |= 1 << 2;
  197. _PWM_GPIO_INIT(C, 8);
  198. #endif
  199. #ifdef BSP_USING_PWM8_CH4
  200. pwm_config[PWM8_INDEX].channel |= 1 << 3;
  201. _PWM_GPIO_INIT(C, 9);
  202. #endif
  203. }
  204. static rt_err_t _pwm_hw_init(struct apm32_pwm *device)
  205. {
  206. rt_err_t result = RT_EOK;
  207. TMR_T *tmr = RT_NULL;
  208. TMR_BaseConfig_T base_config;
  209. TMR_OCConfig_T oc_config;
  210. RT_ASSERT(device != RT_NULL);
  211. tmr = (TMR_T *)device->tmr;
  212. if (tmr == TMR1)
  213. {
  214. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR1);
  215. }
  216. else if (tmr == TMR8)
  217. {
  218. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR8);
  219. }
  220. else if (tmr == TMR2)
  221. {
  222. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR2);
  223. }
  224. else if (tmr == TMR3)
  225. {
  226. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);
  227. }
  228. else if (tmr == TMR4)
  229. {
  230. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR4);
  231. }
  232. else if (tmr == TMR5)
  233. {
  234. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR5);
  235. }
  236. /* configure the tmrer to pwm mode */
  237. base_config.division = 0;
  238. base_config.countMode = TMR_COUNTER_MODE_UP;
  239. base_config.period = 0;
  240. base_config.clockDivision = TMR_CLOCK_DIV_1;
  241. TMR_ConfigTimeBase(tmr, &base_config);
  242. TMR_SelectOutputTrigger(tmr, TMR_TRGO_SOURCE_RESET);
  243. TMR_DisableMasterSlaveMode(tmr);
  244. oc_config.mode = TMR_OC_MODE_PWM1;
  245. oc_config.pulse = 0;
  246. oc_config.polarity = TMR_OC_POLARITY_HIGH;
  247. oc_config.nIdleState = TMR_OC_NIDLE_STATE_RESET;
  248. oc_config.idleState = TMR_OC_IDLE_STATE_RESET;
  249. oc_config.outputState = TMR_OC_STATE_ENABLE;
  250. /* config pwm channel */
  251. if (device->channel & 0x01)
  252. {
  253. TMR_ConfigOC1(tmr, &oc_config);
  254. }
  255. if (device->channel & 0x02)
  256. {
  257. TMR_ConfigOC2(tmr, &oc_config);
  258. }
  259. if (device->channel & 0x04)
  260. {
  261. TMR_ConfigOC3(tmr, &oc_config);
  262. }
  263. if (device->channel & 0x08)
  264. {
  265. TMR_ConfigOC4(tmr, &oc_config);
  266. }
  267. /* enable update request source */
  268. TMR_ConfigUpdateRequest(tmr, TMR_UPDATE_SOURCE_REGULAR);
  269. return result;
  270. }
  271. static rt_uint32_t _pwm_timer_clock_get(TMR_T *tmr)
  272. {
  273. uint32_t pclk1;
  274. RCM_ReadPCLKFreq(&pclk1, NULL);
  275. return (rt_uint32_t)(pclk1 * ((RCM->CFG_B.APB1PSC != RCM_APB_DIV_1) ? 2 : 1));
  276. }
  277. static rt_err_t _pwm_enable(TMR_T *tmr, struct rt_pwm_configuration *configuration, rt_bool_t enable)
  278. {
  279. rt_uint32_t channel = (configuration->channel - 1) << 2;
  280. if (enable)
  281. {
  282. if (configuration->complementary)
  283. {
  284. TMR_EnableCCxNChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU)));
  285. }
  286. else
  287. {
  288. TMR_EnableCCxChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU)));
  289. }
  290. if (tmr == TMR1 || tmr == TMR8)
  291. {
  292. TMR_EnablePWMOutputs(tmr);
  293. }
  294. TMR_Enable(tmr);
  295. }
  296. else
  297. {
  298. if (configuration->complementary)
  299. {
  300. TMR_DisableCCxNChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU)));
  301. }
  302. else
  303. {
  304. TMR_DisableCCxChannel(tmr, (TMR_CHANNEL_T)(0x01 << (channel & 0x1FU)));
  305. }
  306. if (tmr == TMR1 || tmr == TMR8)
  307. {
  308. TMR_DisablePWMOutputs(tmr);
  309. }
  310. TMR_Disable(tmr);
  311. }
  312. return RT_EOK;
  313. }
  314. static rt_err_t _pwm_get(TMR_T *tmr, struct rt_pwm_configuration *configuration)
  315. {
  316. /* Converts the channel number to the channel number of library */
  317. rt_uint32_t channel = (configuration->channel - 1) << 2;
  318. rt_uint64_t timer_clock;
  319. rt_uint32_t timer_reload, timer_psc;
  320. timer_clock = _pwm_timer_clock_get(tmr);
  321. if (tmr->CTRL1_B.CLKDIV == TMR_CLOCK_DIV_2)
  322. {
  323. timer_clock <<= 1;
  324. }
  325. else if (tmr->CTRL1_B.CLKDIV == TMR_CLOCK_DIV_4)
  326. {
  327. timer_clock <<= 2;
  328. }
  329. uint32_t temp;
  330. temp = (uint32_t)tmr;
  331. temp += (uint32_t)(0x34 + channel);
  332. /* Convert nanosecond to frequency and duty cycle.*/
  333. timer_clock /= 1000000UL;
  334. timer_reload = tmr->AUTORLD;
  335. timer_psc = tmr->PSC;
  336. configuration->period = (timer_reload + 1) * (timer_psc + 1) * 1000UL / timer_clock;
  337. configuration->pulse = ((*(__IO uint32_t *)temp) + 1) * (timer_psc + 1) * 1000UL / timer_clock;
  338. return RT_EOK;
  339. }
  340. static rt_err_t _pwm_set(TMR_T *tmr, struct rt_pwm_configuration *configuration)
  341. {
  342. rt_uint32_t period, pulse;
  343. rt_uint64_t timer_clock, psc;
  344. rt_uint32_t channel = 0x04 * (configuration->channel - 1);
  345. uint32_t temp = (uint32_t)tmr;
  346. timer_clock = _pwm_timer_clock_get(tmr);
  347. /* Convert nanosecond to frequency and duty cycle. */
  348. timer_clock /= 1000000UL;
  349. period = (unsigned long long)configuration->period * timer_clock / 1000ULL ;
  350. psc = period / MAX_PERIOD + 1;
  351. period = period / psc;
  352. tmr->PSC = (uint16_t)(psc - 1);
  353. if (period < MIN_PERIOD)
  354. {
  355. period = MIN_PERIOD;
  356. }
  357. tmr->AUTORLD = (uint16_t)(period - 1);
  358. pulse = (unsigned long long)configuration->pulse * timer_clock / psc / 1000ULL;
  359. if (pulse < MIN_PULSE)
  360. {
  361. pulse = MIN_PULSE;
  362. }
  363. else if (pulse > period)
  364. {
  365. pulse = period;
  366. }
  367. temp += (uint32_t)(0x34 + channel);
  368. *(__IO uint32_t *)temp = pulse - 1;
  369. tmr->CNT = 0;
  370. /* Update frequency value */
  371. TMR_GenerateEvent(tmr, TMR_EVENT_UPDATE);
  372. return RT_EOK;
  373. }
  374. static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  375. {
  376. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  377. TMR_T *tmr = (TMR_T *)device->parent.user_data;
  378. switch (cmd)
  379. {
  380. case PWMN_CMD_ENABLE:
  381. configuration->complementary = RT_TRUE;
  382. case PWM_CMD_ENABLE:
  383. return _pwm_enable(tmr, configuration, RT_TRUE);
  384. case PWMN_CMD_DISABLE:
  385. configuration->complementary = RT_FALSE;
  386. case PWM_CMD_DISABLE:
  387. return _pwm_enable(tmr, configuration, RT_FALSE);
  388. case PWM_CMD_SET:
  389. return _pwm_set(tmr, configuration);
  390. case PWM_CMD_GET:
  391. return _pwm_get(tmr, configuration);
  392. default:
  393. return RT_EINVAL;
  394. }
  395. }
  396. static const struct rt_pwm_ops _pwm_ops =
  397. {
  398. _pwm_control
  399. };
  400. static int rt_hw_pwm_init(void)
  401. {
  402. rt_uint32_t i = 0;
  403. rt_err_t result = RT_EOK;
  404. GPIO_Config_T gpio_config;
  405. _pwm_channel_init(&gpio_config);
  406. for (i = 0; i < sizeof(pwm_config) / sizeof(pwm_config[0]); i++)
  407. {
  408. /* pwm init */
  409. if (_pwm_hw_init(&pwm_config[i]) != RT_EOK)
  410. {
  411. LOG_E("%s init failed", pwm_config[i].name);
  412. return -RT_ERROR;
  413. }
  414. else
  415. {
  416. LOG_D("%s init success", pwm_config[i].name);
  417. /* register pwm device */
  418. if (rt_device_pwm_register(&pwm_config[i].pwm_device, pwm_config[i].name, &_pwm_ops, pwm_config[i].tmr) == RT_EOK)
  419. {
  420. LOG_D("%s register success", pwm_config[i].name);
  421. }
  422. else
  423. {
  424. LOG_E("%s register failed", pwm_config[i].name);
  425. result = -RT_ERROR;
  426. }
  427. }
  428. }
  429. return result;
  430. }
  431. INIT_DEVICE_EXPORT(rt_hw_pwm_init);
  432. #endif /* RT_USING_PWM */