drv_pwm.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /*
  2. * Copyright (c) 2006-2023
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-06-05 zengjianwei first version
  9. */
  10. #include <board.h>
  11. #include <gd32f30x.h>
  12. #include <rtdevice.h>
  13. #include <rtthread.h>
  14. #ifdef RT_USING_PWM
  15. //#define DRV_DEBUG
  16. #define LOG_TAG "drv.pwm"
  17. #include <rtdbg.h>
  18. #define MAX_PERIOD 65535
  19. #define MIN_PERIOD 3
  20. #define MIN_PULSE 2
  21. typedef struct
  22. {
  23. rt_int8_t TimerIndex; // timer index:0~13
  24. rt_uint32_t Port; // gpio port:GPIOA/GPIOB/GPIOC/...
  25. rt_uint32_t pin; // gpio pin:GPIO_PIN_0~GPIO_PIN_15
  26. rt_uint16_t channel; // timer channel
  27. char *name;
  28. } TIMER_PORT_CHANNEL_MAP_S;
  29. struct gd32_pwm
  30. {
  31. struct rt_device_pwm pwm_device;
  32. TIMER_PORT_CHANNEL_MAP_S tim_handle;
  33. };
  34. static struct gd32_pwm gd32_pwm_obj[] = {
  35. #ifdef RT_USING_PWM1
  36. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm1"}},
  37. #endif
  38. #ifdef RT_USING_PWM2
  39. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm2"}},
  40. #endif
  41. #ifdef RT_USING_PWM3
  42. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm3"}},
  43. #endif
  44. #ifdef RT_USING_PWM4
  45. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm4"}},
  46. #endif
  47. #ifdef RT_USING_PWM5
  48. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm5"}},
  49. #endif
  50. #ifdef RT_USING_PWM6
  51. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm6"}},
  52. #endif
  53. #ifdef RT_USING_PWM7
  54. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm7"}},
  55. #endif
  56. #ifdef RT_USING_PWM8
  57. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm8"}},
  58. #endif
  59. #ifdef RT_USING_PWM9
  60. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm9"}},
  61. #endif
  62. #ifdef RT_USING_PWM10
  63. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm10"}},
  64. #endif
  65. #ifdef RT_USING_PWM11
  66. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm11"}},
  67. #endif
  68. #ifdef RT_USING_PWM12
  69. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm12"}},
  70. #endif
  71. #ifdef RT_USING_PWM13
  72. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm13"}},
  73. #endif
  74. #ifdef RT_USING_PWM14
  75. {.tim_handle = {3, GPIOB, GPIO_PIN_8, 2, "pwm14"}},
  76. #endif
  77. };
  78. typedef struct
  79. {
  80. rt_uint32_t Port[7];
  81. rt_int8_t TimerIndex[14];
  82. } TIMER_PERIPH_LIST_S;
  83. static TIMER_PERIPH_LIST_S gd32_timer_periph_list = {
  84. .Port = {0, 0, 0, 0, 0, 0, 0},
  85. .TimerIndex = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  86. };
  87. /*
  88. * 将所有用到的 gpio port 和 timer 不重复地列举出来,以方便后面不重复地初始化
  89. */
  90. static rt_err_t pwm_find_timer_periph(void)
  91. {
  92. rt_int16_t i, j, k;
  93. /* find gpio port of defined table */
  94. for (i = 0; i < sizeof(gd32_pwm_obj) / sizeof(gd32_pwm_obj[0]); ++i)
  95. {
  96. /* find -1 of gd32_periph_list's member of Port */
  97. for (j = 0; j < sizeof(gd32_timer_periph_list.Port) / sizeof(gd32_timer_periph_list.Port[0]); ++j)
  98. {
  99. if (0 == gd32_timer_periph_list.Port[j])
  100. {
  101. break;
  102. }
  103. }
  104. if (j >= sizeof(gd32_timer_periph_list.Port) / sizeof(gd32_timer_periph_list.Port[0]))
  105. {
  106. LOG_E("Can not find -1 of gd32_periph_list's member of Port!\n");
  107. break;
  108. }
  109. /* find the different of Port */
  110. for (k = 0; k < j; ++k)
  111. {
  112. if (gd32_pwm_obj[i].tim_handle.Port == gd32_timer_periph_list.Port[k])
  113. {
  114. break;
  115. }
  116. }
  117. /* if can not find the same Port */
  118. if (k == j)
  119. {
  120. gd32_timer_periph_list.Port[j] = gd32_pwm_obj[i].tim_handle.Port;
  121. }
  122. }
  123. /* find timer periph of defined table */
  124. for (i = 0; i < sizeof(gd32_pwm_obj) / sizeof(gd32_pwm_obj[0]); ++i)
  125. {
  126. /* find -1 of gd32_periph_list's member of TimerIndex */
  127. for (j = 0; j < sizeof(gd32_timer_periph_list.TimerIndex) / sizeof(gd32_timer_periph_list.TimerIndex[0]); ++j)
  128. {
  129. if (-1 == gd32_timer_periph_list.TimerIndex[j])
  130. {
  131. break;
  132. }
  133. }
  134. if (j >= sizeof(gd32_timer_periph_list.TimerIndex) / sizeof(gd32_timer_periph_list.TimerIndex[0]))
  135. {
  136. LOG_E("Can not find -1 of gd32_periph_list's member of TimerIndex!\n");
  137. break;
  138. }
  139. /* find the different of TimerIndex */
  140. for (k = 0; k < j; ++k)
  141. {
  142. if (gd32_pwm_obj[i].tim_handle.TimerIndex == gd32_timer_periph_list.TimerIndex[k])
  143. {
  144. break;
  145. }
  146. }
  147. /* if can not find the same TimerIndex */
  148. if (k == j)
  149. {
  150. gd32_timer_periph_list.TimerIndex[j] = gd32_pwm_obj[i].tim_handle.TimerIndex;
  151. }
  152. }
  153. return RT_EOK;
  154. }
  155. static rt_uint32_t index_to_timer(rt_int8_t TimerIndex)
  156. {
  157. switch (TimerIndex)
  158. {
  159. case 0:
  160. return TIMER0;
  161. case 1:
  162. return TIMER1;
  163. case 2:
  164. return TIMER2;
  165. case 3:
  166. return TIMER3;
  167. case 4:
  168. return TIMER4;
  169. case 5:
  170. return TIMER5;
  171. case 6:
  172. return TIMER6;
  173. case 7:
  174. return TIMER7;
  175. case 8:
  176. return TIMER8;
  177. case 9:
  178. return TIMER9;
  179. case 10:
  180. return TIMER10;
  181. case 11:
  182. return TIMER11;
  183. case 12:
  184. return TIMER12;
  185. case 13:
  186. return TIMER13;
  187. default:
  188. LOG_E("Unsport timer periph!\n");
  189. }
  190. return TIMER0;
  191. }
  192. static void gpio_clock_enable(rt_uint32_t Port)
  193. {
  194. switch (Port)
  195. {
  196. case GPIOA:
  197. rcu_periph_clock_enable(RCU_GPIOA);
  198. break;
  199. case GPIOB:
  200. rcu_periph_clock_enable(RCU_GPIOB);
  201. break;
  202. case GPIOC:
  203. rcu_periph_clock_enable(RCU_GPIOC);
  204. break;
  205. case GPIOD:
  206. rcu_periph_clock_enable(RCU_GPIOD);
  207. break;
  208. case GPIOE:
  209. rcu_periph_clock_enable(RCU_GPIOE);
  210. break;
  211. case GPIOF:
  212. rcu_periph_clock_enable(RCU_GPIOF);
  213. break;
  214. case GPIOG:
  215. rcu_periph_clock_enable(RCU_GPIOG);
  216. break;
  217. default:
  218. LOG_E("Unsport gpio port!\n");
  219. }
  220. }
  221. static void timer_clock_enable(rt_int8_t TimerIndex)
  222. {
  223. switch (TimerIndex)
  224. {
  225. case 0:
  226. rcu_periph_clock_enable(RCU_TIMER0);
  227. break;
  228. case 1:
  229. rcu_periph_clock_enable(RCU_TIMER1);
  230. break;
  231. case 2:
  232. rcu_periph_clock_enable(RCU_TIMER2);
  233. break;
  234. case 3:
  235. rcu_periph_clock_enable(RCU_TIMER3);
  236. break;
  237. case 4:
  238. rcu_periph_clock_enable(RCU_TIMER4);
  239. break;
  240. case 5:
  241. rcu_periph_clock_enable(RCU_TIMER5);
  242. break;
  243. case 6:
  244. rcu_periph_clock_enable(RCU_TIMER6);
  245. break;
  246. case 7:
  247. rcu_periph_clock_enable(RCU_TIMER7);
  248. break;
  249. #ifndef GD32F30X_HD
  250. case 8:
  251. rcu_periph_clock_enable(RCU_TIMER8);
  252. break;
  253. case 9:
  254. rcu_periph_clock_enable(RCU_TIMER9);
  255. break;
  256. case 10:
  257. rcu_periph_clock_enable(RCU_TIMER10);
  258. break;
  259. case 11:
  260. rcu_periph_clock_enable(RCU_TIMER11);
  261. break;
  262. case 12:
  263. rcu_periph_clock_enable(RCU_TIMER12);
  264. break;
  265. case 13:
  266. rcu_periph_clock_enable(RCU_TIMER13);
  267. break;
  268. #endif
  269. default:
  270. LOG_E("Unsport timer periph!\n");
  271. }
  272. }
  273. static void rcu_config(void)
  274. {
  275. rt_int16_t i;
  276. for (i = 0; i < sizeof(gd32_timer_periph_list.Port) / sizeof(gd32_timer_periph_list.Port[0]); ++i)
  277. {
  278. if (0 == gd32_timer_periph_list.Port[i])
  279. {
  280. break;
  281. }
  282. /* enable GPIO clock */
  283. gpio_clock_enable(gd32_timer_periph_list.Port[i]);
  284. }
  285. rcu_periph_clock_enable(RCU_AF);
  286. for (i = 0; i < sizeof(gd32_timer_periph_list.TimerIndex) / sizeof(gd32_timer_periph_list.TimerIndex[0]); ++i)
  287. {
  288. if (-1 == gd32_timer_periph_list.TimerIndex[i])
  289. {
  290. break;
  291. }
  292. /* enable timer clock */
  293. timer_clock_enable(gd32_timer_periph_list.TimerIndex[i]);
  294. timer_deinit(index_to_timer(gd32_timer_periph_list.TimerIndex[i]));
  295. }
  296. }
  297. static void gpio_config(void)
  298. {
  299. rt_int16_t i;
  300. /* config the GPIO as analog mode */
  301. for (i = 0; i < sizeof(gd32_pwm_obj) / sizeof(gd32_pwm_obj[0]); ++i)
  302. {
  303. gpio_init(gd32_pwm_obj[i].tim_handle.Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, gd32_pwm_obj[i].tim_handle.pin);
  304. }
  305. }
  306. static void timer_init_para(timer_parameter_struct *initpara)
  307. {
  308. rt_int16_t i;
  309. for (i = 0; i < sizeof(gd32_timer_periph_list.TimerIndex) / sizeof(gd32_timer_periph_list.TimerIndex[0]); ++i)
  310. {
  311. /* config timer */
  312. if (-1 != gd32_timer_periph_list.TimerIndex[i])
  313. {
  314. timer_init(index_to_timer(gd32_timer_periph_list.TimerIndex[i]), initpara);
  315. }
  316. }
  317. }
  318. static void channel_output_config(timer_oc_parameter_struct *ocpara)
  319. {
  320. rt_int16_t i;
  321. rt_uint32_t timer_periph;
  322. /* config the channel config */
  323. for (i = 0; i < sizeof(gd32_pwm_obj) / sizeof(gd32_pwm_obj[0]); ++i)
  324. {
  325. timer_periph = index_to_timer(gd32_pwm_obj[i].tim_handle.TimerIndex);
  326. timer_channel_output_config(timer_periph, gd32_pwm_obj[i].tim_handle.channel, ocpara);
  327. timer_channel_output_pulse_value_config(timer_periph, gd32_pwm_obj[i].tim_handle.channel, 7999);
  328. timer_channel_output_mode_config(timer_periph, gd32_pwm_obj[i].tim_handle.channel, TIMER_OC_MODE_PWM0);
  329. timer_channel_output_shadow_config(timer_periph, gd32_pwm_obj[i].tim_handle.channel, TIMER_OC_SHADOW_DISABLE);
  330. /* auto-reload preload shadow reg enable */
  331. // timer_auto_reload_shadow_enable(timer_periph);
  332. timer_channel_output_state_config(timer_periph, gd32_pwm_obj[i].tim_handle.channel, TIMER_CCX_DISABLE);
  333. }
  334. /* enable timer */
  335. for (i = 0; i < sizeof(gd32_timer_periph_list.TimerIndex) / sizeof(gd32_timer_periph_list.TimerIndex[0]); ++i)
  336. {
  337. if (-1 != gd32_timer_periph_list.TimerIndex[i])
  338. {
  339. timer_periph = index_to_timer(gd32_timer_periph_list.TimerIndex[i]);
  340. timer_enable(timer_periph);
  341. }
  342. }
  343. }
  344. static void timer_config(void)
  345. {
  346. timer_oc_parameter_struct timer_ocintpara;
  347. timer_parameter_struct timer_initpara;
  348. /* TIMER configuration */
  349. timer_initpara.prescaler = 119;
  350. timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
  351. timer_initpara.counterdirection = TIMER_COUNTER_UP;
  352. timer_initpara.period = 15999;
  353. timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
  354. timer_initpara.repetitioncounter = 0;
  355. timer_init_para(&timer_initpara);
  356. /* CHX configuration in PWM mode */
  357. timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
  358. timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
  359. timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
  360. timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
  361. timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
  362. timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
  363. channel_output_config(&timer_ocintpara);
  364. }
  365. static rt_err_t drv_pwm_enable(TIMER_PORT_CHANNEL_MAP_S *pstTimerMap, struct rt_pwm_configuration *configuration,
  366. rt_bool_t enable)
  367. {
  368. if (!enable)
  369. {
  370. timer_channel_output_state_config(index_to_timer(pstTimerMap->TimerIndex), configuration->channel,
  371. TIMER_CCX_DISABLE);
  372. }
  373. else
  374. {
  375. timer_channel_output_state_config(index_to_timer(pstTimerMap->TimerIndex), configuration->channel,
  376. TIMER_CCX_ENABLE);
  377. }
  378. return RT_EOK;
  379. }
  380. static rt_err_t drv_pwm_get(TIMER_PORT_CHANNEL_MAP_S *pstTimerMap, struct rt_pwm_configuration *configuration)
  381. {
  382. rt_uint64_t tim_clock;
  383. rt_uint16_t psc;
  384. rt_uint32_t chxcv;
  385. tim_clock = rcu_clock_freq_get(CK_SYS);
  386. psc = timer_prescaler_read(index_to_timer(pstTimerMap->TimerIndex));
  387. if (psc == TIMER_CKDIV_DIV2)
  388. {
  389. tim_clock = tim_clock / 2;
  390. }
  391. else if (psc == TIMER_CKDIV_DIV4)
  392. {
  393. tim_clock = tim_clock / 4;
  394. }
  395. chxcv = timer_channel_capture_value_register_read(index_to_timer(pstTimerMap->TimerIndex), configuration->channel);
  396. /* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */
  397. tim_clock /= 1000000UL;
  398. configuration->period = (TIMER_CAR(index_to_timer(pstTimerMap->TimerIndex)) + 1) * (psc + 1) * 1000UL / tim_clock;
  399. configuration->pulse = (chxcv + 1) * (psc + 1) * 1000UL / tim_clock;
  400. return RT_EOK;
  401. }
  402. static rt_err_t drv_pwm_set(TIMER_PORT_CHANNEL_MAP_S *pstTimerMap, struct rt_pwm_configuration *configuration)
  403. {
  404. rt_uint32_t period, pulse;
  405. rt_uint64_t tim_clock, psc;
  406. tim_clock = rcu_clock_freq_get(CK_SYS);
  407. /* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */
  408. tim_clock /= 1000000UL;
  409. period = (unsigned long long)configuration->period * tim_clock / 1000ULL;
  410. psc = period / MAX_PERIOD + 1;
  411. period = period / psc;
  412. timer_prescaler_config(index_to_timer(pstTimerMap->TimerIndex), psc - 1, TIMER_PSC_RELOAD_NOW);
  413. if (period < MIN_PERIOD)
  414. {
  415. period = MIN_PERIOD;
  416. }
  417. timer_autoreload_value_config(index_to_timer(pstTimerMap->TimerIndex), period - 1);
  418. pulse = (unsigned long long)configuration->pulse * tim_clock / psc / 1000ULL;
  419. if (pulse < MIN_PULSE)
  420. {
  421. pulse = MIN_PULSE;
  422. }
  423. else if (pulse > period)
  424. {
  425. pulse = period;
  426. }
  427. timer_channel_output_pulse_value_config(index_to_timer(pstTimerMap->TimerIndex), configuration->channel, pulse);
  428. timer_counter_value_config(index_to_timer(pstTimerMap->TimerIndex), 0);
  429. /* Update frequency value */
  430. timer_event_software_generate(index_to_timer(pstTimerMap->TimerIndex), TIMER_EVENT_SRC_UPG);
  431. return RT_EOK;
  432. }
  433. static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  434. {
  435. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  436. TIMER_PORT_CHANNEL_MAP_S *pstTimerMap = (TIMER_PORT_CHANNEL_MAP_S *)device->parent.user_data;
  437. switch (cmd)
  438. {
  439. case PWM_CMD_ENABLE:
  440. return drv_pwm_enable(pstTimerMap, configuration, RT_TRUE);
  441. case PWM_CMD_DISABLE:
  442. return drv_pwm_enable(pstTimerMap, configuration, RT_FALSE);
  443. case PWM_CMD_SET:
  444. return drv_pwm_set(pstTimerMap, configuration);
  445. case PWM_CMD_GET:
  446. return drv_pwm_get(pstTimerMap, configuration);
  447. default:
  448. return RT_EINVAL;
  449. }
  450. }
  451. static struct rt_pwm_ops drv_ops = {drv_pwm_control};
  452. static rt_err_t gd32_hw_pwm_init(void)
  453. {
  454. pwm_find_timer_periph();
  455. rcu_config();
  456. gpio_config();
  457. timer_config();
  458. return RT_EOK;
  459. }
  460. static int gd32_pwm_init(void)
  461. {
  462. int i = 0;
  463. int result = RT_EOK;
  464. /* pwm init */
  465. if (gd32_hw_pwm_init() != RT_EOK)
  466. {
  467. LOG_E("PWM init failed");
  468. result = -RT_ERROR;
  469. goto __exit;
  470. }
  471. LOG_D("PWM init success");
  472. for (i = 0; i < sizeof(gd32_pwm_obj) / sizeof(gd32_pwm_obj[0]); i++)
  473. {
  474. /* register pwm device */
  475. if (rt_device_pwm_register(&gd32_pwm_obj[i].pwm_device, gd32_pwm_obj[i].tim_handle.name, &drv_ops,
  476. &gd32_pwm_obj[i].tim_handle) == RT_EOK)
  477. {
  478. LOG_D("%s register success", gd32_pwm_obj[i].tim_handle.name);
  479. }
  480. else
  481. {
  482. LOG_E("%s register failed", gd32_pwm_obj[i].tim_handle.name);
  483. result = -RT_ERROR;
  484. }
  485. }
  486. __exit:
  487. return result;
  488. }
  489. INIT_DEVICE_EXPORT(gd32_pwm_init);
  490. #endif /* RT_USING_PWM */