1
0

drv_pwm.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-05-16 shelton first version
  9. */
  10. #include "drv_common.h"
  11. #ifdef RT_USING_PWM
  12. #include "drv_pwm.h"
  13. #include <drivers/rt_drv_pwm.h>
  14. //#define DRV_DEBUG
  15. #define LOG_TAG "drv.pwm"
  16. #include <drv_log.h>
  17. #define MAX_PERIOD 65535
  18. struct rt_device_pwm pwm_device;
  19. struct at32_pwm
  20. {
  21. struct rt_device_pwm pwm_device;
  22. tmr_type* tmr_x;
  23. rt_uint8_t channel;
  24. char *name;
  25. };
  26. enum
  27. {
  28. #ifdef BSP_USING_PWM1
  29. PWM1_INDEX,
  30. #endif
  31. #ifdef BSP_USING_PWM2
  32. PWM2_INDEX,
  33. #endif
  34. #ifdef BSP_USING_PWM3
  35. PWM3_INDEX,
  36. #endif
  37. #ifdef BSP_USING_PWM4
  38. PWM4_INDEX,
  39. #endif
  40. #ifdef BSP_USING_PWM5
  41. PWM5_INDEX,
  42. #endif
  43. #ifdef BSP_USING_PWM6
  44. PWM6_INDEX,
  45. #endif
  46. #ifdef BSP_USING_PWM7
  47. PWM7_INDEX,
  48. #endif
  49. #ifdef BSP_USING_PWM8
  50. PWM8_INDEX,
  51. #endif
  52. #ifdef BSP_USING_PWM9
  53. PWM9_INDEX,
  54. #endif
  55. #ifdef BSP_USING_PWM10
  56. PWM10_INDEX,
  57. #endif
  58. #ifdef BSP_USING_PWM11
  59. PWM11_INDEX,
  60. #endif
  61. #ifdef BSP_USING_PWM12
  62. PWM12_INDEX,
  63. #endif
  64. #ifdef BSP_USING_PWM13
  65. PWM13_INDEX,
  66. #endif
  67. };
  68. static struct at32_pwm at32_pwm_obj[] =
  69. {
  70. #ifdef BSP_USING_PWM1
  71. PWM1_CONFIG,
  72. #endif
  73. #ifdef BSP_USING_PWM2
  74. PWM2_CONFIG,
  75. #endif
  76. #ifdef BSP_USING_PWM3
  77. PWM3_CONFIG,
  78. #endif
  79. #ifdef BSP_USING_PWM4
  80. PWM4_CONFIG,
  81. #endif
  82. #ifdef BSP_USING_PWM5
  83. PWM5_CONFIG,
  84. #endif
  85. #ifdef BSP_USING_PWM6
  86. PWM6_CONFIG,
  87. #endif
  88. #ifdef BSP_USING_PWM7
  89. PWM7_CONFIG,
  90. #endif
  91. #ifdef BSP_USING_PWM8
  92. PWM8_CONFIG,
  93. #endif
  94. #ifdef BSP_USING_PWM9
  95. PWM9_CONFIG,
  96. #endif
  97. #ifdef BSP_USING_PWM10
  98. PWM10_CONFIG,
  99. #endif
  100. #ifdef BSP_USING_PWM11
  101. PWM11_CONFIG,
  102. #endif
  103. #ifdef BSP_USING_PWM12
  104. PWM12_CONFIG,
  105. #endif
  106. #ifdef BSP_USING_PWM13
  107. PWM13_CONFIG,
  108. #endif
  109. };
  110. static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg);
  111. static struct rt_pwm_ops drv_ops =
  112. {
  113. drv_pwm_control
  114. };
  115. static void tmr_pclk_get(rt_uint32_t *pclk1_doubler, rt_uint32_t *pclk2_doubler)
  116. {
  117. crm_clocks_freq_type clocks_struct;
  118. *pclk1_doubler = 1;
  119. *pclk2_doubler = 1;
  120. crm_clocks_freq_get(&clocks_struct);
  121. if(clocks_struct.ahb_freq != clocks_struct.apb1_freq)
  122. {
  123. *pclk1_doubler = 2;
  124. }
  125. if(clocks_struct.ahb_freq != clocks_struct.apb2_freq)
  126. {
  127. *pclk2_doubler = 2;
  128. }
  129. }
  130. static rt_err_t drv_pwm_enable(tmr_type* tmr_x, struct rt_pwm_configuration *configuration, rt_bool_t enable)
  131. {
  132. /* get the value of channel */
  133. rt_uint32_t channel = configuration->channel;
  134. if (!configuration->complementary)
  135. {
  136. if (!enable)
  137. {
  138. if(channel == 1)
  139. {
  140. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_1, FALSE);
  141. }
  142. else if(channel == 2)
  143. {
  144. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_2, FALSE);
  145. }
  146. else if(channel == 3)
  147. {
  148. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_3, FALSE);
  149. }
  150. else if(channel == 4)
  151. {
  152. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_4, FALSE);
  153. }
  154. }
  155. else
  156. {
  157. if(channel == 1)
  158. {
  159. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_1, TRUE);
  160. }
  161. else if(channel == 2)
  162. {
  163. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_2, TRUE);
  164. }
  165. else if(channel == 3)
  166. {
  167. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_3, TRUE);
  168. }
  169. else if(channel == 4)
  170. {
  171. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_4, TRUE);
  172. }
  173. }
  174. }
  175. else
  176. {
  177. if (!enable)
  178. {
  179. if(channel == 1)
  180. {
  181. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_1C, FALSE);
  182. }
  183. else if(channel == 2)
  184. {
  185. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_2C, FALSE);
  186. }
  187. else if(channel == 3)
  188. {
  189. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_3C, FALSE);
  190. }
  191. }
  192. else
  193. {
  194. if(channel == 1)
  195. {
  196. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_1C, TRUE);
  197. }
  198. else if(channel == 2)
  199. {
  200. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_2C, TRUE);
  201. }
  202. else if(channel == 3)
  203. {
  204. tmr_channel_enable(tmr_x, TMR_SELECT_CHANNEL_3C, TRUE);
  205. }
  206. }
  207. }
  208. /* tmr_x enable counter */
  209. tmr_counter_enable(tmr_x, TRUE);
  210. return RT_EOK;
  211. }
  212. static rt_err_t drv_pwm_get(tmr_type* tmr_x, struct rt_pwm_configuration *configuration)
  213. {
  214. crm_clocks_freq_type clocks_struct;
  215. rt_uint32_t pr, div, c1dt, c2dt, c3dt, c4dt;
  216. rt_uint32_t pclk1_doubler = 0, pclk2_doubler = 0;
  217. rt_uint32_t channel = configuration->channel;
  218. rt_uint64_t tmr_clock;
  219. pr = tmr_x->pr;
  220. div = tmr_x->div;
  221. c1dt = tmr_x->c1dt;
  222. c2dt = tmr_x->c2dt;
  223. c3dt = tmr_x->c3dt;
  224. c4dt = tmr_x->c4dt;
  225. tmr_pclk_get(&pclk1_doubler, &pclk2_doubler);
  226. crm_clocks_freq_get(&clocks_struct);
  227. if(
  228. #if defined (TMR1)
  229. (tmr_x == TMR1)
  230. #endif
  231. #if defined (TMR8)
  232. || (tmr_x == TMR8)
  233. #endif
  234. #if defined (TMR9)
  235. || (tmr_x == TMR9)
  236. #endif
  237. #if defined (TMR10)
  238. || (tmr_x == TMR10)
  239. #endif
  240. #if defined (TMR11)
  241. || (tmr_x == TMR11)
  242. #endif
  243. )
  244. {
  245. tmr_clock = clocks_struct.apb2_freq * pclk2_doubler;
  246. }
  247. else
  248. {
  249. tmr_clock = clocks_struct.apb1_freq * pclk1_doubler;
  250. }
  251. /* convert nanosecond to frequency and duty cycle. */
  252. tmr_clock /= 1000000UL;
  253. configuration->period = (pr + 1) * (div + 1) * 1000UL / tmr_clock;
  254. if(channel == 1)
  255. configuration->pulse = (c1dt) * (div + 1) * 1000UL / tmr_clock;
  256. if(channel == 2)
  257. configuration->pulse = (c2dt) * (div + 1) * 1000UL / tmr_clock;
  258. if(channel == 3)
  259. configuration->pulse = (c3dt) * (div + 1) * 1000UL / tmr_clock;
  260. if(channel == 4)
  261. configuration->pulse = (c4dt) * (div + 1) * 1000UL / tmr_clock;
  262. return RT_EOK;
  263. }
  264. static rt_err_t drv_pwm_set(tmr_type* tmr_x, struct rt_pwm_configuration *configuration)
  265. {
  266. crm_clocks_freq_type clocks_struct;
  267. tmr_output_config_type tmr_oc_config_struct;
  268. tmr_channel_select_type channel_select;
  269. rt_uint32_t period, pulse, channel, tmr_clock;
  270. rt_uint32_t pclk1_doubler = 0, pclk2_doubler = 0;
  271. rt_uint64_t psc;
  272. /* init timer pin and enable clock */
  273. at32_msp_tmr_init(tmr_x);
  274. tmr_pclk_get(&pclk1_doubler, &pclk2_doubler);
  275. crm_clocks_freq_get(&clocks_struct);
  276. if(
  277. #if defined (TMR1)
  278. (tmr_x == TMR1)
  279. #endif
  280. #if defined (TMR8)
  281. || (tmr_x == TMR8)
  282. #endif
  283. #if defined (TMR9)
  284. || (tmr_x == TMR9)
  285. #endif
  286. #if defined (TMR10)
  287. || (tmr_x == TMR10)
  288. #endif
  289. #if defined (TMR11)
  290. || (tmr_x == TMR11)
  291. #endif
  292. )
  293. {
  294. tmr_clock = clocks_struct.apb2_freq * pclk2_doubler;
  295. }
  296. else
  297. {
  298. tmr_clock = clocks_struct.apb1_freq * pclk1_doubler;
  299. }
  300. /* convert nanosecond to frequency and duty cycle. */
  301. tmr_clock /= 1000000UL;
  302. /* calculate pwm period */
  303. period = (unsigned long long)configuration->period * tmr_clock / 1000ULL;;
  304. psc = period / MAX_PERIOD + 1;
  305. period = period / psc;
  306. /* calculate pulse width */
  307. pulse = (unsigned long long)configuration->pulse * tmr_clock / psc / 1000ULL;
  308. /* get channel parameter */
  309. channel = configuration->channel;
  310. /* tmr base init */
  311. tmr_base_init(tmr_x, period - 1, psc - 1);
  312. tmr_clock_source_div_set(tmr_x, TMR_CLOCK_DIV1);
  313. /* pwm mode configuration */
  314. tmr_output_default_para_init(&tmr_oc_config_struct);
  315. /* config pwm mode */
  316. tmr_oc_config_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  317. if (!configuration->complementary)
  318. {
  319. tmr_oc_config_struct.oc_idle_state = FALSE;
  320. tmr_oc_config_struct.oc_output_state = FALSE;
  321. tmr_oc_config_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  322. }
  323. else
  324. {
  325. tmr_oc_config_struct.occ_idle_state = FALSE;
  326. tmr_oc_config_struct.occ_output_state = FALSE;
  327. tmr_oc_config_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  328. }
  329. if(channel == 1)
  330. {
  331. channel_select = TMR_SELECT_CHANNEL_1;
  332. }
  333. else if(channel == 2)
  334. {
  335. channel_select = TMR_SELECT_CHANNEL_2;
  336. }
  337. else if(channel == 3)
  338. {
  339. channel_select = TMR_SELECT_CHANNEL_3;
  340. }
  341. else if(channel == 4)
  342. {
  343. channel_select = TMR_SELECT_CHANNEL_4;
  344. }
  345. /* config tmr pwm output */
  346. tmr_output_channel_config(tmr_x, channel_select, &tmr_oc_config_struct);
  347. tmr_output_channel_buffer_enable(tmr_x, channel_select, TRUE);
  348. tmr_channel_value_set(tmr_x, channel_select, pulse);
  349. /* enable tmr period buffer */
  350. tmr_period_buffer_enable(tmr_x, TRUE);
  351. /* enable output */
  352. tmr_output_enable(tmr_x, TRUE);
  353. return RT_EOK;
  354. }
  355. static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  356. {
  357. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  358. tmr_type *tmr_x = (tmr_type *)device->parent.user_data;
  359. switch (cmd)
  360. {
  361. case PWMN_CMD_ENABLE:
  362. configuration->complementary = RT_TRUE;
  363. case PWM_CMD_ENABLE:
  364. return drv_pwm_enable(tmr_x, configuration, RT_TRUE);
  365. case PWMN_CMD_DISABLE:
  366. configuration->complementary = RT_FALSE;
  367. case PWM_CMD_DISABLE:
  368. return drv_pwm_enable(tmr_x, configuration, RT_FALSE);
  369. case PWM_CMD_SET:
  370. return drv_pwm_set(tmr_x, configuration);
  371. case PWM_CMD_GET:
  372. return drv_pwm_get(tmr_x, configuration);
  373. default:
  374. return RT_EINVAL;
  375. }
  376. }
  377. static void pwm_get_channel(void)
  378. {
  379. #ifdef BSP_USING_PWM1_CH1
  380. at32_pwm_obj[PWM1_INDEX].channel = 1;
  381. #endif
  382. #ifdef BSP_USING_PWM1_CH2
  383. at32_pwm_obj[PWM1_INDEX].channel = 2;
  384. #endif
  385. #ifdef BSP_USING_PWM1_CH3
  386. at32_pwm_obj[PWM1_INDEX].channel = 3;
  387. #endif
  388. #ifdef BSP_USING_PWM1_CH4
  389. at32_pwm_obj[PWM1_INDEX].channel = 4;
  390. #endif
  391. #ifdef BSP_USING_PWM2_CH1
  392. at32_pwm_obj[PWM2_INDEX].channel = 1;
  393. #endif
  394. #ifdef BSP_USING_PWM2_CH2
  395. at32_pwm_obj[PWM2_INDEX].channel = 2;
  396. #endif
  397. #ifdef BSP_USING_PWM2_CH3
  398. at32_pwm_obj[PWM2_INDEX].channel = 3;
  399. #endif
  400. #ifdef BSP_USING_PWM2_CH4
  401. at32_pwm_obj[PWM2_INDEX].channel = 4;
  402. #endif
  403. #ifdef BSP_USING_PWM3_CH1
  404. at32_pwm_obj[PWM3_INDEX].channel = 1;
  405. #endif
  406. #ifdef BSP_USING_PWM3_CH2
  407. at32_pwm_obj[PWM3_INDEX].channel = 2;
  408. #endif
  409. #ifdef BSP_USING_PWM3_CH3
  410. at32_pwm_obj[PWM3_INDEX].channel = 3;
  411. #endif
  412. #ifdef BSP_USING_PWM3_CH4
  413. at32_pwm_obj[PWM3_INDEX].channel = 4;
  414. #endif
  415. #ifdef BSP_USING_PWM4_CH1
  416. at32_pwm_obj[PWM4_INDEX].channel = 1;
  417. #endif
  418. #ifdef BSP_USING_PWM4_CH2
  419. at32_pwm_obj[PWM4_INDEX].channel = 2;
  420. #endif
  421. #ifdef BSP_USING_PWM4_CH3
  422. at32_pwm_obj[PWM4_INDEX].channel = 3;
  423. #endif
  424. #ifdef BSP_USING_PWM4_CH4
  425. at32_pwm_obj[PWM4_INDEX].channel = 4;
  426. #endif
  427. #ifdef BSP_USING_PWM5_CH1
  428. at32_pwm_obj[PWM5_INDEX].channel = 1;
  429. #endif
  430. #ifdef BSP_USING_PWM5_CH2
  431. at32_pwm_obj[PWM5_INDEX].channel = 2;
  432. #endif
  433. #ifdef BSP_USING_PWM5_CH3
  434. at32_pwm_obj[PWM5_INDEX].channel = 3;
  435. #endif
  436. #ifdef BSP_USING_PWM5_CH4
  437. at32_pwm_obj[PWM5_INDEX].channel = 4;
  438. #endif
  439. #ifdef BSP_USING_PWM6_CH1
  440. at32_pwm_obj[PWM6_INDEX].channel = 1;
  441. #endif
  442. #ifdef BSP_USING_PWM6_CH2
  443. at32_pwm_obj[PWM6_INDEX].channel = 2;
  444. #endif
  445. #ifdef BSP_USING_PWM6_CH3
  446. at32_pwm_obj[PWM6_INDEX].channel = 3;
  447. #endif
  448. #ifdef BSP_USING_PWM6_CH4
  449. at32_pwm_obj[PWM6_INDEX].channel = 4;
  450. #endif
  451. #ifdef BSP_USING_PWM7_CH1
  452. at32_pwm_obj[PWM7_INDEX].channel = 1;
  453. #endif
  454. #ifdef BSP_USING_PWM7_CH2
  455. at32_pwm_obj[PWM7_INDEX].channel = 2;
  456. #endif
  457. #ifdef BSP_USING_PWM7_CH3
  458. at32_pwm_obj[PWM7_INDEX].channel = 3;
  459. #endif
  460. #ifdef BSP_USING_PWM7_CH4
  461. at32_pwm_obj[PWM7_INDEX].channel = 4;
  462. #endif
  463. #ifdef BSP_USING_PWM8_CH1
  464. at32_pwm_obj[PWM8_INDEX].channel = 1;
  465. #endif
  466. #ifdef BSP_USING_PWM8_CH2
  467. at32_pwm_obj[PWM8_INDEX].channel = 2;
  468. #endif
  469. #ifdef BSP_USING_PWM8_CH3
  470. at32_pwm_obj[PWM8_INDEX].channel = 3;
  471. #endif
  472. #ifdef BSP_USING_PWM8_CH4
  473. at32_pwm_obj[PWM8_INDEX].channel = 4;
  474. #endif
  475. #ifdef BSP_USING_PWM9_CH1
  476. at32_pwm_obj[PWM9_INDEX].channel = 1;
  477. #endif
  478. #ifdef BSP_USING_PWM9_CH2
  479. at32_pwm_obj[PWM9_INDEX].channel = 2;
  480. #endif
  481. #ifdef BSP_USING_PWM9_CH3
  482. at32_pwm_obj[PWM9_INDEX].channel = 3;
  483. #endif
  484. #ifdef BSP_USING_PWM9_CH4
  485. at32_pwm_obj[PWM9_INDEX].channel = 4;
  486. #endif
  487. #ifdef BSP_USING_PWM12_CH1
  488. at32_pwm_obj[PWM12_INDEX].channel = 1;
  489. #endif
  490. #ifdef BSP_USING_PWM12_CH2
  491. at32_pwm_obj[PWM12_INDEX].channel = 2;
  492. #endif
  493. }
  494. static int rt_hw_pwm_init(void)
  495. {
  496. int i = 0;
  497. int result = RT_EOK;
  498. pwm_get_channel();
  499. for(i = 0; i < sizeof(at32_pwm_obj) / sizeof(at32_pwm_obj[0]); i++)
  500. {
  501. if(rt_device_pwm_register(&at32_pwm_obj[i].pwm_device, at32_pwm_obj[i].name, &drv_ops, at32_pwm_obj[i].tmr_x) == RT_EOK)
  502. {
  503. LOG_D("%s register success", at32_pwm_obj[i].name);
  504. }
  505. else
  506. {
  507. LOG_D("%s register failed", at32_pwm_obj[i].name);
  508. result = -RT_ERROR;
  509. }
  510. }
  511. return result;
  512. }
  513. INIT_BOARD_EXPORT(rt_hw_pwm_init);
  514. #endif /* RT_USING_PWM */