drv_pwm.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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-12-18 hywing Initial version.
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include "fsl_pwm.h"
  13. #ifdef RT_USING_PWM
  14. #define BOARD_PWM_BASEADDR (FLEXPWM0)
  15. #define PWM_SRC_CLK_FREQ (CLOCK_GetFreq(kCLOCK_BusClk))
  16. #define FLEX_PWM_CLOCK_DEVIDER (kPWM_Prescale_Divide_2)
  17. #define FLEX_PWM_FAULT_LEVEL true
  18. typedef struct
  19. {
  20. struct rt_device_pwm pwm_device;
  21. pwm_submodule_t submodule;
  22. pwm_module_control_t control;
  23. pwm_channels_t channel;
  24. pwm_clock_prescale_t prescale;
  25. char *name;
  26. } mcx_pwm_obj_t;
  27. static mcx_pwm_obj_t mcx_pwm_list[]=
  28. {
  29. #ifdef BSP_USING_PWM0
  30. {
  31. .submodule = kPWM_Module_0,
  32. .control = kPWM_Control_Module_0,
  33. .channel = kPWM_PwmA,
  34. .prescale = FLEX_PWM_CLOCK_DEVIDER,
  35. .name = "pwm0",
  36. },
  37. #endif
  38. #ifdef BSP_USING_PWM1
  39. {
  40. .submodule = kPWM_Module_1,
  41. .control = kPWM_Control_Module_1,
  42. .channel = kPWM_PwmA,
  43. .prescale = FLEX_PWM_CLOCK_DEVIDER,
  44. .name = "pwm1",
  45. },
  46. #endif
  47. #ifdef BSP_USING_PWM2
  48. {
  49. .submodule = kPWM_Module_2,
  50. .control = kPWM_Control_Module_2,
  51. .channel = kPWM_PwmA,
  52. .prescale = FLEX_PWM_CLOCK_DEVIDER,
  53. .name = "pwm2",
  54. },
  55. #endif
  56. };
  57. static rt_err_t mcx_drv_pwm_get(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration)
  58. {
  59. return RT_EOK;
  60. }
  61. static rt_err_t mcx_drv_pwm_set(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration)
  62. {
  63. uint8_t dutyCyclePercent = configuration->pulse * 100 / configuration->period;
  64. pwm_signal_param_t pwmSignal[1];
  65. uint32_t pwmFrequencyInHz = 1000000000 / configuration->period;
  66. pwmSignal[0].pwmChannel = pwm->channel;
  67. pwmSignal[0].level = kPWM_HighTrue;
  68. pwmSignal[0].dutyCyclePercent = dutyCyclePercent;
  69. pwmSignal[0].deadtimeValue = 0;
  70. pwmSignal[0].faultState = kPWM_PwmFaultState0;
  71. pwmSignal[0].pwmchannelenable = true;
  72. PWM_SetupPwm(BOARD_PWM_BASEADDR, pwm->submodule, pwmSignal, 1, kPWM_SignedCenterAligned, pwmFrequencyInHz, PWM_SRC_CLK_FREQ);
  73. PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, pwm->submodule, pwm->channel, kPWM_SignedCenterAligned, dutyCyclePercent);
  74. PWM_SetPwmLdok(BOARD_PWM_BASEADDR, pwm->control, true);
  75. return 0;
  76. }
  77. static rt_err_t mcx_drv_pwm_enable(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration)
  78. {
  79. PWM_StartTimer(BOARD_PWM_BASEADDR, pwm->control);
  80. return 0;
  81. }
  82. static rt_err_t mcx_drv_pwm_disable(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration)
  83. {
  84. PWM_StopTimer(BOARD_PWM_BASEADDR, pwm->control);
  85. return 0;
  86. }
  87. static rt_err_t mcx_drv_pwm_control(struct rt_device_pwm *device, int cmd, void *args)
  88. {
  89. mcx_pwm_obj_t *pwm = device->parent.user_data;
  90. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)args;
  91. switch (cmd)
  92. {
  93. case PWM_CMD_ENABLE:
  94. return mcx_drv_pwm_enable(pwm, configuration);
  95. case PWM_CMD_DISABLE:
  96. return mcx_drv_pwm_disable(pwm, configuration);
  97. case PWM_CMD_SET:
  98. return mcx_drv_pwm_set(pwm, configuration);
  99. case PWM_CMD_GET:
  100. return mcx_drv_pwm_get(pwm, configuration);
  101. default:
  102. return -RT_EINVAL;
  103. }
  104. return RT_EOK;
  105. }
  106. static struct rt_pwm_ops mcx_pwm_ops =
  107. {
  108. .control = mcx_drv_pwm_control,
  109. };
  110. int mcx_pwm_init(void)
  111. {
  112. rt_err_t ret;
  113. pwm_config_t pwmConfig;
  114. pwm_fault_param_t faultConfig;
  115. PWM_GetDefaultConfig(&pwmConfig);
  116. pwmConfig.prescale = FLEX_PWM_CLOCK_DEVIDER;
  117. pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;
  118. int i;
  119. for (i = 0; i < sizeof(mcx_pwm_list) / sizeof(mcx_pwm_list[0]); i++)
  120. {
  121. pwm_config_t pwmConfig;
  122. pwm_fault_param_t faultConfig;
  123. PWM_GetDefaultConfig(&pwmConfig);
  124. pwmConfig.prescale = mcx_pwm_list[i].prescale;
  125. pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;
  126. if (PWM_Init(BOARD_PWM_BASEADDR, mcx_pwm_list[i].submodule, &pwmConfig) == kStatus_Fail)
  127. {
  128. rt_kprintf("PWM Init Failed\n");
  129. }
  130. ret = rt_device_pwm_register(&mcx_pwm_list[i].pwm_device, mcx_pwm_list[i].name, &mcx_pwm_ops, &mcx_pwm_list[i]);
  131. }
  132. /*
  133. * config->faultClearingMode = kPWM_Automatic;
  134. * config->faultLevel = false;
  135. * config->enableCombinationalPath = true;
  136. * config->recoverMode = kPWM_NoRecovery;
  137. */
  138. PWM_FaultDefaultConfig(&faultConfig);
  139. faultConfig.faultLevel = FLEX_PWM_FAULT_LEVEL;
  140. /* Sets up the PWM fault protection */
  141. PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_0, &faultConfig);
  142. PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_1, &faultConfig);
  143. PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_2, &faultConfig);
  144. PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_3, &faultConfig);
  145. /* Set PWM fault disable mapping for submodule 0/1/2 */
  146. PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_faultchannel_0,
  147. kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
  148. PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_1, kPWM_PwmA, kPWM_faultchannel_0,
  149. kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
  150. PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_2, kPWM_PwmA, kPWM_faultchannel_0,
  151. kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
  152. /* Set the load okay bit for all submodules to load registers from their buffer */
  153. PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0 | kPWM_Control_Module_1 | kPWM_Control_Module_2, true);
  154. return ret;
  155. }
  156. INIT_DEVICE_EXPORT(mcx_pwm_init);
  157. #endif /* RT_USING_PWM */