drv_pwm_tmra.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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-06-27 lianghongquan first version
  9. */
  10. #include <board.h>
  11. #if (defined RT_USING_PWM) && (defined BSP_USING_PWM_TMRA)
  12. #include "drv_config.h"
  13. #include <drivers/rt_drv_pwm.h>
  14. //#define DRV_DEBUG
  15. #define LOG_TAG "drv.pwm.tmra"
  16. #include <drv_log.h>
  17. #if (!(defined(BSP_USING_PWM_TMRA_1) || defined(BSP_USING_PWM_TMRA_2) || \
  18. defined(BSP_USING_PWM_TMRA_3) || defined(BSP_USING_PWM_TMRA_4) || \
  19. defined(BSP_USING_PWM_TMRA_5) || defined(BSP_USING_PWM_TMRA_6)))
  20. #error "Please define at least one BSP_USING_PWM_TMRA_x"
  21. #endif
  22. enum
  23. {
  24. #ifdef BSP_USING_PWM_TMRA_1
  25. PWM_TMRA_1_INDEX,
  26. #endif
  27. #ifdef BSP_USING_PWM_TMRA_2
  28. PWM_TMRA_2_INDEX,
  29. #endif
  30. #ifdef BSP_USING_PWM_TMRA_3
  31. PWM_TMRA_3_INDEX,
  32. #endif
  33. #ifdef BSP_USING_PWM_TMRA_4
  34. PWM_TMRA_4_INDEX,
  35. #endif
  36. #ifdef BSP_USING_PWM_TMRA_5
  37. PWM_TMRA_5_INDEX,
  38. #endif
  39. #ifdef BSP_USING_PWM_TMRA_6
  40. PWM_TMRA_6_INDEX,
  41. #endif
  42. };
  43. struct hc32_pwm_tmra
  44. {
  45. struct rt_device_pwm pwm_device;
  46. CM_TMRA_TypeDef *instance;
  47. stc_tmra_init_t stcTmraInit;
  48. stc_tmra_pwm_init_t stcPwmInit;
  49. rt_uint8_t channel;
  50. char *name;
  51. };
  52. static struct hc32_pwm_tmra g_pwm_dev_array[] =
  53. {
  54. #ifdef BSP_USING_PWM_TMRA_1
  55. PWM_TMRA_1_CONFIG,
  56. #endif
  57. #ifdef BSP_USING_PWM_TMRA_2
  58. PWM_TMRA_2_CONFIG,
  59. #endif
  60. #ifdef BSP_USING_PWM_TMRA_3
  61. PWM_TMRA_3_CONFIG,
  62. #endif
  63. #ifdef BSP_USING_PWM_TMRA_4
  64. PWM_TMRA_4_CONFIG,
  65. #endif
  66. #ifdef BSP_USING_PWM_TMRA_5
  67. PWM_TMRA_5_CONFIG,
  68. #endif
  69. #ifdef BSP_USING_PWM_TMRA_6
  70. PWM_TMRA_6_CONFIG,
  71. #endif
  72. };
  73. static rt_uint32_t get_tmra_clk_freq_not_div(CM_TMRA_TypeDef *TMRAx)
  74. {
  75. stc_clock_freq_t stcClockFreq;
  76. CLK_GetClockFreq(&stcClockFreq);
  77. return stcClockFreq.u32Pclk1Freq;
  78. }
  79. static rt_uint32_t get_tmra_clk_freq(CM_TMRA_TypeDef *TMRAx)
  80. {
  81. rt_uint32_t u32clkFreq;
  82. uint16_t u16Div;
  83. //
  84. u32clkFreq = get_tmra_clk_freq_not_div(TMRAx);
  85. u16Div = READ_REG16(TMRAx->BCSTR) & TMRA_BCSTR_CKDIV;
  86. switch (u16Div)
  87. {
  88. case (TMRA_CLK_DIV2):
  89. u32clkFreq /= 2;
  90. break;
  91. case (TMRA_CLK_DIV4):
  92. u32clkFreq /= 4;
  93. break;
  94. case (TMRA_CLK_DIV8):
  95. u32clkFreq /= 8;
  96. break;
  97. case (TMRA_CLK_DIV16):
  98. u32clkFreq /= 16;
  99. break;
  100. case (TMRA_CLK_DIV32):
  101. u32clkFreq /= 32;
  102. break;
  103. case (TMRA_CLK_DIV64):
  104. u32clkFreq /= 64;
  105. break;
  106. case (TMRA_CLK_DIV128):
  107. u32clkFreq /= 128;
  108. break;
  109. case (TMRA_CLK_DIV256):
  110. u32clkFreq /= 256;
  111. break;
  112. case (TMRA_CLK_DIV512):
  113. u32clkFreq /= 512;
  114. break;
  115. case (TMRA_CLK_DIV1024):
  116. u32clkFreq /= 1024;
  117. break;
  118. case (TMRA_CLK_DIV1):
  119. default:
  120. break;
  121. }
  122. return u32clkFreq;
  123. }
  124. static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg);
  125. static struct rt_pwm_ops drv_ops =
  126. {
  127. drv_pwm_control
  128. };
  129. static rt_err_t drv_pwm_enable(CM_TMRA_TypeDef *TMRAx, struct rt_pwm_configuration *configuration, rt_bool_t enable)
  130. {
  131. if (RT_TRUE == enable) {TMRA_PWM_OutputCmd(TMRAx, configuration->channel, ENABLE);}
  132. else {TMRA_PWM_OutputCmd(TMRAx, configuration->channel, DISABLE);}
  133. return RT_EOK;
  134. }
  135. static rt_err_t drv_pwm_get(CM_TMRA_TypeDef *TMRAx, struct rt_pwm_configuration *configuration)
  136. {
  137. rt_uint32_t u32clkFreq;
  138. rt_uint64_t u64clk_ns;
  139. u32clkFreq = get_tmra_clk_freq(TMRAx);
  140. u64clk_ns = (rt_uint64_t)1000000000ul / u32clkFreq;
  141. configuration->period = u64clk_ns * TMRA_GetPeriodValue(TMRAx);
  142. configuration->pulse = u64clk_ns * TMRA_GetCompareValue(TMRAx, configuration->channel);
  143. return RT_EOK;
  144. }
  145. static rt_err_t drv_pwm_set(CM_TMRA_TypeDef *TMRAx, struct rt_pwm_configuration *configuration)
  146. {
  147. rt_uint32_t u32clkFreq;
  148. rt_uint64_t u64clk_ns;
  149. rt_uint64_t u64val;
  150. //
  151. u32clkFreq = get_tmra_clk_freq(TMRAx);
  152. u64clk_ns = (rt_uint64_t)1000000000ul / u32clkFreq;
  153. u64val = (rt_uint64_t)configuration->period / u64clk_ns;
  154. if ((configuration->period <= u64clk_ns) || (u64val > 0xFFFF))
  155. {
  156. // clk not match, need change div
  157. uint32_t div_bit;
  158. u32clkFreq = get_tmra_clk_freq_not_div(TMRAx);
  159. u64clk_ns = (rt_uint64_t)1000000000ul / u32clkFreq;
  160. u64val = (rt_uint64_t)configuration->period / u64clk_ns;
  161. for (div_bit=0; div_bit<= 10; div_bit++)
  162. {
  163. if (u64val < 0xFFFF) break;
  164. u64val /= 2;
  165. }
  166. if (div_bit > 10) return -RT_ERROR;
  167. //
  168. TMRA_SetClockDiv(TMRAx, div_bit << TMRA_BCSTR_CKDIV_POS);
  169. u32clkFreq = get_tmra_clk_freq(TMRAx);
  170. u64clk_ns = (rt_uint64_t)1000000000ul / u32clkFreq;
  171. }
  172. TMRA_SetPeriodValue(TMRAx, configuration->period / u64clk_ns);
  173. TMRA_SetCompareValue(TMRAx, configuration->channel, configuration->pulse / u64clk_ns);
  174. return RT_EOK;
  175. }
  176. static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  177. {
  178. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  179. struct hc32_pwm_tmra *pwm;
  180. pwm = rt_container_of(device, struct hc32_pwm_tmra, pwm_device);
  181. CM_TMRA_TypeDef *TMRAx = pwm->instance;
  182. switch (cmd)
  183. {
  184. case PWMN_CMD_ENABLE:
  185. configuration->complementary = RT_TRUE;
  186. case PWM_CMD_ENABLE:
  187. return drv_pwm_enable(TMRAx, configuration, RT_TRUE);
  188. case PWMN_CMD_DISABLE:
  189. configuration->complementary = RT_FALSE;
  190. case PWM_CMD_DISABLE:
  191. return drv_pwm_enable(TMRAx, configuration, RT_FALSE);
  192. case PWM_CMD_SET:
  193. return drv_pwm_set(TMRAx, configuration);
  194. case PWM_CMD_GET:
  195. return drv_pwm_get(TMRAx, configuration);
  196. default:
  197. return -RT_EINVAL;
  198. }
  199. }
  200. static rt_err_t _pwm_tmra_init(struct hc32_pwm_tmra *device)
  201. {
  202. CM_TMRA_TypeDef *TMRAx;
  203. uint32_t i;
  204. //
  205. RT_ASSERT(device != RT_NULL);
  206. TMRAx = device->instance;
  207. TMRA_Init(TMRAx, &device->stcTmraInit);
  208. for (i=0; i<8; i++)
  209. {
  210. if ((device->channel >> i) & 0x01)
  211. {
  212. TMRA_PWM_Init(TMRAx, i, &device->stcPwmInit);
  213. }
  214. }
  215. TMRA_Start(TMRAx);
  216. return RT_EOK;
  217. }
  218. static void pwm_get_channel(void)
  219. {
  220. #ifdef BSP_USING_PWM_TMRA_1
  221. #ifdef BSP_USING_PWM_TMRA_1_CH1
  222. g_pwm_dev_array[PWM_TMRA_1_INDEX].channel |= 1 << 0;
  223. #endif
  224. #ifdef BSP_USING_PWM_TMRA_1_CH2
  225. g_pwm_dev_array[PWM_TMRA_1_INDEX].channel |= 1 << 1;
  226. #endif
  227. #ifdef BSP_USING_PWM_TMRA_1_CH3
  228. g_pwm_dev_array[PWM_TMRA_1_INDEX].channel |= 1 << 2;
  229. #endif
  230. #ifdef BSP_USING_PWM_TMRA_1_CH4
  231. g_pwm_dev_array[PWM_TMRA_1_INDEX].channel |= 1 << 3;
  232. #endif
  233. #ifdef BSP_USING_PWM_TMRA_1_CH5
  234. g_pwm_dev_array[PWM_TMRA_1_INDEX].channel |= 1 << 4;
  235. #endif
  236. #ifdef BSP_USING_PWM_TMRA_1_CH6
  237. g_pwm_dev_array[PWM_TMRA_1_INDEX].channel |= 1 << 5;
  238. #endif
  239. #ifdef BSP_USING_PWM_TMRA_1_CH7
  240. g_pwm_dev_array[PWM_TMRA_1_INDEX].channel |= 1 << 6;
  241. #endif
  242. #ifdef BSP_USING_PWM_TMRA_1_CH8
  243. g_pwm_dev_array[PWM_TMRA_1_INDEX].channel |= 1 << 7;
  244. #endif
  245. #endif
  246. #ifdef BSP_USING_PWM_TMRA_2
  247. #ifdef BSP_USING_PWM_TMRA_2_CH1
  248. g_pwm_dev_array[PWM_TMRA_2_INDEX].channel |= 1 << 0;
  249. #endif
  250. #ifdef BSP_USING_PWM_TMRA_2_CH2
  251. g_pwm_dev_array[PWM_TMRA_2_INDEX].channel |= 1 << 1;
  252. #endif
  253. #ifdef BSP_USING_PWM_TMRA_2_CH3
  254. g_pwm_dev_array[PWM_TMRA_2_INDEX].channel |= 1 << 2;
  255. #endif
  256. #ifdef BSP_USING_PWM_TMRA_2_CH4
  257. g_pwm_dev_array[PWM_TMRA_2_INDEX].channel |= 1 << 3;
  258. #endif
  259. #ifdef BSP_USING_PWM_TMRA_2_CH5
  260. g_pwm_dev_array[PWM_TMRA_2_INDEX].channel |= 1 << 4;
  261. #endif
  262. #ifdef BSP_USING_PWM_TMRA_2_CH6
  263. g_pwm_dev_array[PWM_TMRA_2_INDEX].channel |= 1 << 5;
  264. #endif
  265. #ifdef BSP_USING_PWM_TMRA_2_CH7
  266. g_pwm_dev_array[PWM_TMRA_2_INDEX].channel |= 1 << 6;
  267. #endif
  268. #ifdef BSP_USING_PWM_TMRA_2_CH8
  269. g_pwm_dev_array[PWM_TMRA_2_INDEX].channel |= 1 << 7;
  270. #endif
  271. #endif
  272. #ifdef BSP_USING_PWM_TMRA_3
  273. #ifdef BSP_USING_PWM_TMRA_3_CH1
  274. g_pwm_dev_array[PWM_TMRA_3_INDEX].channel |= 1 << 0;
  275. #endif
  276. #ifdef BSP_USING_PWM_TMRA_3_CH2
  277. g_pwm_dev_array[PWM_TMRA_3_INDEX].channel |= 1 << 1;
  278. #endif
  279. #ifdef BSP_USING_PWM_TMRA_3_CH3
  280. g_pwm_dev_array[PWM_TMRA_3_INDEX].channel |= 1 << 2;
  281. #endif
  282. #ifdef BSP_USING_PWM_TMRA_3_CH4
  283. g_pwm_dev_array[PWM_TMRA_3_INDEX].channel |= 1 << 3;
  284. #endif
  285. #ifdef BSP_USING_PWM_TMRA_3_CH5
  286. g_pwm_dev_array[PWM_TMRA_3_INDEX].channel |= 1 << 4;
  287. #endif
  288. #ifdef BSP_USING_PWM_TMRA_3_CH6
  289. g_pwm_dev_array[PWM_TMRA_3_INDEX].channel |= 1 << 5;
  290. #endif
  291. #ifdef BSP_USING_PWM_TMRA_3_CH7
  292. g_pwm_dev_array[PWM_TMRA_3_INDEX].channel |= 1 << 6;
  293. #endif
  294. #ifdef BSP_USING_PWM_TMRA_3_CH8
  295. g_pwm_dev_array[PWM_TMRA_3_INDEX].channel |= 1 << 7;
  296. #endif
  297. #endif
  298. #ifdef BSP_USING_PWM_TMRA_4
  299. #ifdef BSP_USING_PWM_TMRA_4_CH1
  300. g_pwm_dev_array[PWM_TMRA_4_INDEX].channel |= 1 << 0;
  301. #endif
  302. #ifdef BSP_USING_PWM_TMRA_4_CH2
  303. g_pwm_dev_array[PWM_TMRA_4_INDEX].channel |= 1 << 1;
  304. #endif
  305. #ifdef BSP_USING_PWM_TMRA_4_CH3
  306. g_pwm_dev_array[PWM_TMRA_4_INDEX].channel |= 1 << 2;
  307. #endif
  308. #ifdef BSP_USING_PWM_TMRA_4_CH4
  309. g_pwm_dev_array[PWM_TMRA_4_INDEX].channel |= 1 << 3;
  310. #endif
  311. #ifdef BSP_USING_PWM_TMRA_4_CH5
  312. g_pwm_dev_array[PWM_TMRA_4_INDEX].channel |= 1 << 4;
  313. #endif
  314. #ifdef BSP_USING_PWM_TMRA_4_CH6
  315. g_pwm_dev_array[PWM_TMRA_4_INDEX].channel |= 1 << 5;
  316. #endif
  317. #ifdef BSP_USING_PWM_TMRA_4_CH7
  318. g_pwm_dev_array[PWM_TMRA_4_INDEX].channel |= 1 << 6;
  319. #endif
  320. #ifdef BSP_USING_PWM_TMRA_4_CH8
  321. g_pwm_dev_array[PWM_TMRA_4_INDEX].channel |= 1 << 7;
  322. #endif
  323. #endif
  324. #ifdef BSP_USING_PWM_TMRA_5
  325. #ifdef BSP_USING_PWM_TMRA_5_CH1
  326. g_pwm_dev_array[PWM_TMRA_5_INDEX].channel |= 1 << 0;
  327. #endif
  328. #ifdef BSP_USING_PWM_TMRA_5_CH2
  329. g_pwm_dev_array[PWM_TMRA_5_INDEX].channel |= 1 << 1;
  330. #endif
  331. #ifdef BSP_USING_PWM_TMRA_5_CH3
  332. g_pwm_dev_array[PWM_TMRA_5_INDEX].channel |= 1 << 2;
  333. #endif
  334. #ifdef BSP_USING_PWM_TMRA_5_CH4
  335. g_pwm_dev_array[PWM_TMRA_5_INDEX].channel |= 1 << 3;
  336. #endif
  337. #ifdef BSP_USING_PWM_TMRA_5_CH5
  338. g_pwm_dev_array[PWM_TMRA_5_INDEX].channel |= 1 << 4;
  339. #endif
  340. #ifdef BSP_USING_PWM_TMRA_5_CH6
  341. g_pwm_dev_array[PWM_TMRA_5_INDEX].channel |= 1 << 5;
  342. #endif
  343. #ifdef BSP_USING_PWM_TMRA_5_CH7
  344. g_pwm_dev_array[PWM_TMRA_5_INDEX].channel |= 1 << 6;
  345. #endif
  346. #ifdef BSP_USING_PWM_TMRA_5_CH8
  347. g_pwm_dev_array[PWM_TMRA_5_INDEX].channel |= 1 << 7;
  348. #endif
  349. #endif
  350. #ifdef BSP_USING_PWM_TMRA_6
  351. #ifdef BSP_USING_PWM_TMRA_6_CH1
  352. g_pwm_dev_array[PWM_TMRA_6_INDEX].channel |= 1 << 0;
  353. #endif
  354. #ifdef BSP_USING_PWM_TMRA_6_CH2
  355. g_pwm_dev_array[PWM_TMRA_6_INDEX].channel |= 1 << 1;
  356. #endif
  357. #ifdef BSP_USING_PWM_TMRA_6_CH3
  358. g_pwm_dev_array[PWM_TMRA_6_INDEX].channel |= 1 << 2;
  359. #endif
  360. #ifdef BSP_USING_PWM_TMRA_6_CH4
  361. g_pwm_dev_array[PWM_TMRA_6_INDEX].channel |= 1 << 3;
  362. #endif
  363. #ifdef BSP_USING_PWM_TMRA_6_CH5
  364. g_pwm_dev_array[PWM_TMRA_6_INDEX].channel |= 1 << 4;
  365. #endif
  366. #ifdef BSP_USING_PWM_TMRA_6_CH6
  367. g_pwm_dev_array[PWM_TMRA_6_INDEX].channel |= 1 << 5;
  368. #endif
  369. #ifdef BSP_USING_PWM_TMRA_6_CH7
  370. g_pwm_dev_array[PWM_TMRA_6_INDEX].channel |= 1 << 6;
  371. #endif
  372. #ifdef BSP_USING_PWM_TMRA_6_CH8
  373. g_pwm_dev_array[PWM_TMRA_6_INDEX].channel |= 1 << 7;
  374. #endif
  375. #endif
  376. }
  377. static void _enable_periph_clk(void)
  378. {
  379. #ifdef BSP_USING_PWM_TMRA_1
  380. FCG_Fcg2PeriphClockCmd(FCG2_PERIPH_TMRA_1, ENABLE);
  381. #endif
  382. #ifdef BSP_USING_PWM_TMRA_2
  383. FCG_Fcg2PeriphClockCmd(FCG2_PERIPH_TMRA_2, ENABLE);
  384. #endif
  385. #ifdef BSP_USING_PWM_TMRA_3
  386. FCG_Fcg2PeriphClockCmd(FCG2_PERIPH_TMRA_3, ENABLE);
  387. #endif
  388. #ifdef BSP_USING_PWM_TMRA_4
  389. FCG_Fcg2PeriphClockCmd(FCG2_PERIPH_TMRA_4, ENABLE);
  390. #endif
  391. #ifdef BSP_USING_PWM_TMRA_5
  392. FCG_Fcg2PeriphClockCmd(FCG2_PERIPH_TMRA_5, ENABLE);
  393. #endif
  394. #ifdef BSP_USING_PWM_TMRA_6
  395. FCG_Fcg2PeriphClockCmd(FCG2_PERIPH_TMRA_6, ENABLE);
  396. #endif
  397. }
  398. extern rt_err_t rt_hw_board_pwm_tmra_init(CM_TMRA_TypeDef *TMRAx);
  399. static int rt_hw_pwm_tmra_init(void)
  400. {
  401. int i = 0;
  402. rt_err_t result = RT_EOK;
  403. pwm_get_channel();
  404. _enable_periph_clk();
  405. for (i = 0; i < sizeof(g_pwm_dev_array) / sizeof(g_pwm_dev_array[0]); i++)
  406. {
  407. /* pwm init */
  408. _pwm_tmra_init(&g_pwm_dev_array[i]);
  409. rt_hw_board_pwm_tmra_init(g_pwm_dev_array[i].instance);
  410. /* register UART device */
  411. result = rt_device_pwm_register(&g_pwm_dev_array[i].pwm_device, g_pwm_dev_array[i].name, &drv_ops, &g_pwm_dev_array[i].instance);
  412. RT_ASSERT(result == RT_EOK);
  413. }
  414. return result;
  415. }
  416. INIT_DEVICE_EXPORT(rt_hw_pwm_tmra_init);
  417. #endif /* RT_USING_PWM */