drv_pwm.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * Copyright (c) 2006-2024 RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-08-1 hywing Initial version.
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include "fsl_ctimer.h"
  13. #ifdef RT_USING_PWM
  14. typedef struct
  15. {
  16. struct rt_device_pwm pwm_device;
  17. CTIMER_Type *ct_instance;
  18. uint32_t timerClock;
  19. const ctimer_match_t pwmPeriodChannel;
  20. ctimer_match_t matchChannel;
  21. char *name;
  22. } mcx_pwm_obj_t;
  23. static mcx_pwm_obj_t mcx_pwm_list[]=
  24. {
  25. #ifdef BSP_USING_PWM0
  26. {
  27. .ct_instance = CTIMER1,
  28. .timerClock = 0,
  29. .pwmPeriodChannel = kCTIMER_Match_3,
  30. .matchChannel = kCTIMER_Match_2,
  31. .name = "pwm0",
  32. }
  33. #endif
  34. };
  35. volatile uint32_t g_pwmPeriod = 0U;
  36. volatile uint32_t g_pulsePeriod = 0U;
  37. static rt_err_t mcx_drv_pwm_get(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration)
  38. {
  39. return RT_EOK;
  40. }
  41. status_t CTIMER_GetPwmPeriodValue(uint32_t pwmFreqHz, uint8_t dutyCyclePercent, uint32_t timerClock_Hz)
  42. {
  43. g_pwmPeriod = (timerClock_Hz / pwmFreqHz) - 1U;
  44. g_pulsePeriod = (g_pwmPeriod + 1U) * (100 - dutyCyclePercent) / 100;
  45. return kStatus_Success;
  46. }
  47. static rt_err_t mcx_drv_pwm_set(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration)
  48. {
  49. CTIMER_Type *ct = pwm->ct_instance;
  50. uint32_t pwmFreqHz = 1000000000 / configuration->period;
  51. uint8_t dutyCyclePercent = configuration->pulse * 100 / configuration->period;
  52. CTIMER_GetPwmPeriodValue(pwmFreqHz, dutyCyclePercent, pwm->timerClock);
  53. CTIMER_SetupPwmPeriod(ct, kCTIMER_Match_3, kCTIMER_Match_2, g_pwmPeriod, g_pulsePeriod, false);
  54. return 0;
  55. }
  56. static rt_err_t mcx_drv_pwm_enable(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration)
  57. {
  58. CTIMER_StartTimer(pwm->ct_instance);
  59. return 0;
  60. }
  61. static rt_err_t mcx_drv_pwm_disable(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration)
  62. {
  63. CTIMER_StopTimer(pwm->ct_instance);
  64. return 0;
  65. }
  66. static rt_err_t mcx_drv_pwm_control(struct rt_device_pwm *device, int cmd, void *args)
  67. {
  68. mcx_pwm_obj_t *pwm = device->parent.user_data;
  69. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)args;
  70. switch (cmd)
  71. {
  72. case PWM_CMD_ENABLE:
  73. return mcx_drv_pwm_enable(pwm, configuration);
  74. case PWM_CMD_DISABLE:
  75. return mcx_drv_pwm_disable(pwm, configuration);
  76. case PWM_CMD_SET:
  77. return mcx_drv_pwm_set(pwm, configuration);
  78. case PWM_CMD_GET:
  79. return mcx_drv_pwm_get(pwm, configuration);
  80. default:
  81. return -RT_EINVAL;
  82. }
  83. return RT_EOK;
  84. }
  85. static struct rt_pwm_ops mcx_pwm_ops =
  86. {
  87. .control = mcx_drv_pwm_control,
  88. };
  89. int mcx_pwm_init(void)
  90. {
  91. rt_err_t ret;
  92. char name_buf[8];
  93. ctimer_config_t config;
  94. CTIMER_GetDefaultConfig(&config);
  95. for (uint8_t i = 0; i < ARRAY_SIZE(mcx_pwm_list); i++)
  96. {
  97. mcx_pwm_list[i].timerClock = CLOCK_GetCTimerClkFreq(1U) / (config.prescale + 1);
  98. CTIMER_Init(mcx_pwm_list[i].ct_instance, &config);
  99. ret = rt_device_pwm_register(&mcx_pwm_list[i].pwm_device, mcx_pwm_list[i].name, &mcx_pwm_ops, &mcx_pwm_list[i]);
  100. if (ret != RT_EOK)
  101. {
  102. return ret;
  103. }
  104. }
  105. return RT_EOK;
  106. }
  107. INIT_DEVICE_EXPORT(mcx_pwm_init);
  108. #endif /* RT_USING_PWM */