|
5 | 5 | * |
6 | 6 | * Change Logs: |
7 | 7 | * Date Author Notes |
8 | | - * 2024-08-1 hywing Initial version. |
| 8 | + * 2024-12-18 hywing Initial version. |
9 | 9 | */ |
10 | 10 |
|
11 | 11 | #include <rtthread.h> |
12 | 12 | #include <rtdevice.h> |
13 | | -#include "fsl_ctimer.h" |
| 13 | +#include "fsl_pwm.h" |
14 | 14 |
|
15 | 15 | #ifdef RT_USING_PWM |
16 | 16 |
|
| 17 | +#define BOARD_PWM_BASEADDR (FLEXPWM0) |
| 18 | +#define PWM_SRC_CLK_FREQ (CLOCK_GetFreq(kCLOCK_BusClk)) |
| 19 | +#define FLEX_PWM_CLOCK_DEVIDER (kPWM_Prescale_Divide_2) |
| 20 | +#define FLEX_PWM_FAULT_LEVEL true |
| 21 | + |
17 | 22 | typedef struct |
18 | 23 | { |
19 | 24 | struct rt_device_pwm pwm_device; |
20 | | - CTIMER_Type *ct_instance; |
21 | | - uint32_t timerClock; |
22 | | - const ctimer_match_t pwmPeriodChannel; |
23 | | - ctimer_match_t matchChannel; |
| 25 | + pwm_submodule_t submodule; |
| 26 | + pwm_module_control_t control; |
| 27 | + pwm_channels_t channel; |
| 28 | + pwm_clock_prescale_t prescale; |
24 | 29 | char *name; |
25 | 30 | } mcx_pwm_obj_t; |
26 | 31 |
|
27 | 32 | static mcx_pwm_obj_t mcx_pwm_list[]= |
28 | 33 | { |
29 | 34 | #ifdef BSP_USING_PWM0 |
30 | 35 | { |
31 | | - .ct_instance = CTIMER1, |
32 | | - .timerClock = 0, |
33 | | - .pwmPeriodChannel = kCTIMER_Match_3, |
34 | | - .matchChannel = kCTIMER_Match_2, |
| 36 | + .submodule = kPWM_Module_0, |
| 37 | + .control = kPWM_Control_Module_0, |
| 38 | + .channel = kPWM_PwmA, |
| 39 | + .prescale = FLEX_PWM_CLOCK_DEVIDER, |
35 | 40 | .name = "pwm0", |
36 | | - } |
| 41 | + }, |
| 42 | +#endif |
| 43 | +#ifdef BSP_USING_PWM1 |
| 44 | + { |
| 45 | + .submodule = kPWM_Module_1, |
| 46 | + .control = kPWM_Control_Module_1, |
| 47 | + .channel = kPWM_PwmA, |
| 48 | + .prescale = FLEX_PWM_CLOCK_DEVIDER, |
| 49 | + .name = "pwm1", |
| 50 | + }, |
| 51 | +#endif |
| 52 | +#ifdef BSP_USING_PWM2 |
| 53 | + { |
| 54 | + .submodule = kPWM_Module_2, |
| 55 | + .control = kPWM_Control_Module_2, |
| 56 | + .channel = kPWM_PwmA, |
| 57 | + .prescale = FLEX_PWM_CLOCK_DEVIDER, |
| 58 | + .name = "pwm2", |
| 59 | + }, |
37 | 60 | #endif |
38 | 61 | }; |
39 | 62 |
|
40 | | -volatile uint32_t g_pwmPeriod = 0U; |
41 | | -volatile uint32_t g_pulsePeriod = 0U; |
42 | | - |
43 | 63 | static rt_err_t mcx_drv_pwm_get(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration) |
44 | 64 | { |
45 | 65 | return RT_EOK; |
46 | 66 | } |
47 | 67 |
|
48 | | -status_t CTIMER_GetPwmPeriodValue(uint32_t pwmFreqHz, uint8_t dutyCyclePercent, uint32_t timerClock_Hz) |
49 | | -{ |
50 | | - g_pwmPeriod = (timerClock_Hz / pwmFreqHz) - 1U; |
51 | | - g_pulsePeriod = (g_pwmPeriod + 1U) * (100 - dutyCyclePercent) / 100; |
52 | | - return kStatus_Success; |
53 | | -} |
54 | | - |
55 | 68 | static rt_err_t mcx_drv_pwm_set(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration) |
56 | 69 | { |
57 | | - CTIMER_Type *ct = pwm->ct_instance; |
58 | | - uint32_t pwmFreqHz = 1000000000 / configuration->period; |
59 | 70 | uint8_t dutyCyclePercent = configuration->pulse * 100 / configuration->period; |
60 | | - CTIMER_GetPwmPeriodValue(pwmFreqHz, dutyCyclePercent, pwm->timerClock); |
61 | | - CTIMER_SetupPwmPeriod(ct, kCTIMER_Match_3, kCTIMER_Match_2, g_pwmPeriod, g_pulsePeriod, false); |
| 71 | + pwm_signal_param_t pwmSignal[1]; |
| 72 | + uint32_t pwmFrequencyInHz = 1000000000 / configuration->period; |
| 73 | + |
| 74 | + pwmSignal[0].pwmChannel = pwm->channel; |
| 75 | + pwmSignal[0].level = kPWM_HighTrue; |
| 76 | + pwmSignal[0].dutyCyclePercent = dutyCyclePercent; |
| 77 | + pwmSignal[0].deadtimeValue = 0; |
| 78 | + pwmSignal[0].faultState = kPWM_PwmFaultState0; |
| 79 | + pwmSignal[0].pwmchannelenable = true; |
| 80 | + |
| 81 | + PWM_SetupPwm(BOARD_PWM_BASEADDR, pwm->submodule, pwmSignal, 1, kPWM_SignedCenterAligned, pwmFrequencyInHz, PWM_SRC_CLK_FREQ); |
| 82 | + PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, pwm->submodule, pwm->channel, kPWM_SignedCenterAligned, dutyCyclePercent); |
| 83 | + PWM_SetPwmLdok(BOARD_PWM_BASEADDR, pwm->control, true); |
| 84 | + |
62 | 85 | return 0; |
63 | 86 | } |
64 | 87 |
|
65 | 88 | static rt_err_t mcx_drv_pwm_enable(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration) |
66 | 89 | { |
67 | | - CTIMER_StartTimer(pwm->ct_instance); |
| 90 | + PWM_StartTimer(BOARD_PWM_BASEADDR, pwm->control); |
68 | 91 | return 0; |
69 | 92 | } |
70 | 93 |
|
71 | 94 | static rt_err_t mcx_drv_pwm_disable(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration) |
72 | 95 | { |
73 | | - CTIMER_StopTimer(pwm->ct_instance); |
| 96 | + PWM_StopTimer(BOARD_PWM_BASEADDR, pwm->control); |
74 | 97 | return 0; |
75 | 98 | } |
76 | 99 |
|
@@ -108,21 +131,55 @@ static struct rt_pwm_ops mcx_pwm_ops = |
108 | 131 | int mcx_pwm_init(void) |
109 | 132 | { |
110 | 133 | rt_err_t ret; |
111 | | - char name_buf[8]; |
112 | | - |
113 | | - ctimer_config_t config; |
114 | | - CTIMER_GetDefaultConfig(&config); |
115 | | - for (uint8_t i = 0; i < ARRAY_SIZE(mcx_pwm_list); i++) |
| 134 | + pwm_config_t pwmConfig; |
| 135 | + pwm_fault_param_t faultConfig; |
| 136 | + PWM_GetDefaultConfig(&pwmConfig); |
| 137 | + pwmConfig.prescale = FLEX_PWM_CLOCK_DEVIDER; |
| 138 | + pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; |
| 139 | + |
| 140 | + int i; |
| 141 | + for (i = 0; i < sizeof(mcx_pwm_list) / sizeof(mcx_pwm_list[0]); i++) |
116 | 142 | { |
117 | | - mcx_pwm_list[i].timerClock = CLOCK_GetCTimerClkFreq(1U) / (config.prescale + 1); |
118 | | - CTIMER_Init(mcx_pwm_list[i].ct_instance, &config); |
119 | | - ret = rt_device_pwm_register(&mcx_pwm_list[i].pwm_device, mcx_pwm_list[i].name, &mcx_pwm_ops, &mcx_pwm_list[i]); |
120 | | - if (ret != RT_EOK) |
| 143 | + pwm_config_t pwmConfig; |
| 144 | + pwm_fault_param_t faultConfig; |
| 145 | + PWM_GetDefaultConfig(&pwmConfig); |
| 146 | + pwmConfig.prescale = mcx_pwm_list[i].prescale; |
| 147 | + pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; |
| 148 | + if (PWM_Init(BOARD_PWM_BASEADDR, mcx_pwm_list[i].submodule, &pwmConfig) == kStatus_Fail) |
121 | 149 | { |
122 | | - return ret; |
| 150 | + rt_kprintf("PWM Init Failed\n"); |
123 | 151 | } |
| 152 | + ret = rt_device_pwm_register(&mcx_pwm_list[i].pwm_device, mcx_pwm_list[i].name, &mcx_pwm_ops, &mcx_pwm_list[i]); |
124 | 153 | } |
125 | | - return RT_EOK; |
| 154 | + |
| 155 | + /* |
| 156 | + * config->faultClearingMode = kPWM_Automatic; |
| 157 | + * config->faultLevel = false; |
| 158 | + * config->enableCombinationalPath = true; |
| 159 | + * config->recoverMode = kPWM_NoRecovery; |
| 160 | + */ |
| 161 | + PWM_FaultDefaultConfig(&faultConfig); |
| 162 | + faultConfig.faultLevel = FLEX_PWM_FAULT_LEVEL; |
| 163 | + |
| 164 | + /* Sets up the PWM fault protection */ |
| 165 | + PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_0, &faultConfig); |
| 166 | + PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_1, &faultConfig); |
| 167 | + PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_2, &faultConfig); |
| 168 | + PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_3, &faultConfig); |
| 169 | + |
| 170 | + /* Set PWM fault disable mapping for submodule 0/1/2 */ |
| 171 | + PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_faultchannel_0, |
| 172 | + kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3); |
| 173 | + PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_1, kPWM_PwmA, kPWM_faultchannel_0, |
| 174 | + kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3); |
| 175 | + PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_2, kPWM_PwmA, kPWM_faultchannel_0, |
| 176 | + kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3); |
| 177 | + |
| 178 | + |
| 179 | + /* Set the load okay bit for all submodules to load registers from their buffer */ |
| 180 | + PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0 | kPWM_Control_Module_1 | kPWM_Control_Module_2, true); |
| 181 | + |
| 182 | + return ret; |
126 | 183 | } |
127 | 184 |
|
128 | 185 | INIT_DEVICE_EXPORT(mcx_pwm_init); |
|
0 commit comments