1 /*
2 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "sdkconfig.h"
8 #include "freertos/FreeRTOS.h"
9 #include "freertos/task.h"
10 #include "esp_log.h"
11 #include "esp_err.h"
12 #include "esp_check.h"
13 #include "esp_rom_gpio.h"
14 #include "esp_intr_alloc.h"
15 #include "soc/mcpwm_periph.h"
16 #include "hal/mcpwm_hal.h"
17 #include "hal/gpio_hal.h"
18 #include "hal/mcpwm_ll.h"
19 #include "driver/mcpwm_types_legacy.h"
20 #include "driver/gpio.h"
21 #include "esp_private/periph_ctrl.h"
22 #include "esp_clk_tree.h"
23 #include "esp_private/esp_clk.h"
24
25 static const char *TAG = "mcpwm(legacy)";
26
27 _Static_assert(MCPWM_UNIT_MAX == SOC_MCPWM_GROUPS, "MCPWM unit number not equal to chip capabilities");
28
29 #define MCPWM_DRIVER_INIT_ERROR "MCPWM DRIVER NOT INITIALIZED"
30 #define MCPWM_GROUP_NUM_ERROR "MCPWM GROUP NUM ERROR"
31 #define MCPWM_PRESCALE_ERROR "MCPWM PRESCALE ERROR"
32 #define MCPWM_TIMER_ERROR "MCPWM TIMER NUM ERROR"
33 #define MCPWM_CAPTURE_ERROR "MCPWM CAPTURE NUM ERROR"
34 #define MCPWM_PARAM_ADDR_ERROR "MCPWM PARAM ADDR ERROR"
35 #define MCPWM_DUTY_TYPE_ERROR "MCPWM DUTY TYPE ERROR"
36 #define MCPWM_GPIO_ERROR "MCPWM GPIO NUM ERROR"
37 #define MCPWM_GEN_ERROR "MCPWM GENERATOR ERROR"
38 #define MCPWM_DT_ERROR "MCPWM DEADTIME TYPE ERROR"
39 #define MCPWM_CAP_EXIST_ERROR "MCPWM USER CAP INT SERVICE ALREADY EXISTS"
40
41 #ifdef CONFIG_MCPWM_ISR_IRAM_SAFE
42 #define MCPWM_ISR_ATTR IRAM_ATTR
43 #define MCPWM_INTR_FLAG ESP_INTR_FLAG_IRAM
44 #else
45 #define MCPWM_ISR_ATTR
46 #define MCPWM_INTR_FLAG 0
47 #endif
48
49 // Note: we can't modify the default MCPWM group resolution once it's determined
50 // otherwise we may break user's existing code which configures the dead-time based on this resolution, see `mcpwm_deadtime_enable`
51 #if CONFIG_IDF_TARGET_ESP32H2
52 #define MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ (12 * 1000 * 1000)
53 #else
54 #define MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ (10 * 1000 * 1000)
55 #endif
56
57 // Preset MCPWM Timer clock resolution (1MHz)
58 #define MCPWM_DEFAULT_TIMER_CLK_RESOLUTION_HZ (1 * 1000 * 1000)
59
60 ESP_STATIC_ASSERT(SOC_MCPWM_OPERATORS_PER_GROUP >= SOC_MCPWM_TIMERS_PER_GROUP, "This driver assumes the timer num equals to the operator num.");
61 ESP_STATIC_ASSERT(SOC_MCPWM_COMPARATORS_PER_OPERATOR >= SOC_MCPWM_GENERATORS_PER_OPERATOR, "This driver assumes the generator num equals to the generator num.");
62 ESP_STATIC_ASSERT(SOC_MCPWM_GENERATORS_PER_OPERATOR == 2, "This driver assumes the generator num equals to 2.");
63
64 #define MCPWM_TIMER_ID_CHECK(mcpwm_num, timer_num) \
65 do { \
66 ESP_RETURN_ON_FALSE((mcpwm_num) < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR); \
67 ESP_RETURN_ON_FALSE((timer_num) < SOC_MCPWM_TIMERS_PER_GROUP, ESP_ERR_INVALID_ARG, TAG, MCPWM_TIMER_ERROR); \
68 } while (0)
69
70 #define MCPWM_TIMER_CHECK(mcpwm_num, timer_num) \
71 do { \
72 MCPWM_TIMER_ID_CHECK(mcpwm_num, timer_num); \
73 ESP_RETURN_ON_FALSE(context[mcpwm_num].hal.dev, ESP_ERR_INVALID_STATE, TAG, MCPWM_DRIVER_INIT_ERROR); \
74 } while (0)
75
76 #define MCPWM_GEN_CHECK(mcpwm_num, timer_num, gen) \
77 do { \
78 MCPWM_TIMER_CHECK(mcpwm_num, timer_num); \
79 ESP_RETURN_ON_FALSE((gen) < MCPWM_GEN_MAX, ESP_ERR_INVALID_ARG, TAG, MCPWM_GEN_ERROR); \
80 } while (0)
81
82 typedef struct {
83 cap_isr_cb_t fn; // isr function
84 void *args; // isr function args
85 } cap_isr_func_t;
86
87 typedef struct {
88 mcpwm_hal_context_t hal;
89 portMUX_TYPE spinlock;
90 _lock_t mutex_lock;
91 const int group_id;
92 int group_resolution_hz;
93 int timer_resolution_hz[SOC_MCPWM_TIMERS_PER_GROUP];
94 intr_handle_t mcpwm_intr_handle; // handler for ISR register, one per MCPWM group
95 cap_isr_func_t cap_isr_func[SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER]; // handler for ISR callback, one for each cap ch
96 } mcpwm_context_t;
97
98 static mcpwm_context_t context[SOC_MCPWM_GROUPS] = {
99 [0] = {
100 .hal = {MCPWM_LL_GET_HW(0)},
101 .spinlock = portMUX_INITIALIZER_UNLOCKED,
102 .group_id = 0,
103 },
104 #if SOC_MCPWM_GROUPS > 1
105 [1] = {
106 .hal = {MCPWM_LL_GET_HW(1)},
107 .spinlock = portMUX_INITIALIZER_UNLOCKED,
108 .group_id = 1,
109 },
110 #endif
111 };
112
113 typedef void (*mcpwm_ll_gen_set_event_action_t)(mcpwm_dev_t *mcpwm, int op, int gen, int action);
114
mcpwm_critical_enter(mcpwm_unit_t mcpwm_num)115 static inline void mcpwm_critical_enter(mcpwm_unit_t mcpwm_num)
116 {
117 portENTER_CRITICAL(&context[mcpwm_num].spinlock);
118 }
119
mcpwm_critical_exit(mcpwm_unit_t mcpwm_num)120 static inline void mcpwm_critical_exit(mcpwm_unit_t mcpwm_num)
121 {
122 portEXIT_CRITICAL(&context[mcpwm_num].spinlock);
123 }
124
mcpwm_mutex_lock(mcpwm_unit_t mcpwm_num)125 static inline void mcpwm_mutex_lock(mcpwm_unit_t mcpwm_num)
126 {
127 _lock_acquire(&context[mcpwm_num].mutex_lock);
128 }
129
mcpwm_mutex_unlock(mcpwm_unit_t mcpwm_num)130 static inline void mcpwm_mutex_unlock(mcpwm_unit_t mcpwm_num)
131 {
132 _lock_release(&context[mcpwm_num].mutex_lock);
133 }
134
mcpwm_gpio_init(mcpwm_unit_t mcpwm_num,mcpwm_io_signals_t io_signal,int gpio_num)135 esp_err_t mcpwm_gpio_init(mcpwm_unit_t mcpwm_num, mcpwm_io_signals_t io_signal, int gpio_num)
136 {
137 if (gpio_num < 0) { // ignore on minus gpio number
138 return ESP_OK;
139 }
140
141 ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR);
142 ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, MCPWM_GPIO_ERROR);
143
144 if (io_signal <= MCPWM2B) { // Generator output signal
145 ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, MCPWM_GPIO_ERROR);
146 gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
147 int operator_id = io_signal / 2;
148 int generator_id = io_signal % 2;
149 esp_rom_gpio_connect_out_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].operators[operator_id].generators[generator_id].pwm_sig, 0, 0);
150 } else if (io_signal <= MCPWM_SYNC_2) { // External sync input signal
151 gpio_set_direction(gpio_num, GPIO_MODE_INPUT);
152 int gpio_sync_id = io_signal - MCPWM_SYNC_0;
153 esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].gpio_synchros[gpio_sync_id].sync_sig, 0);
154 } else if (io_signal <= MCPWM_FAULT_2) { // Fault input signal
155 gpio_set_direction(gpio_num, GPIO_MODE_INPUT);
156 int fault_id = io_signal - MCPWM_FAULT_0;
157 esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].gpio_faults[fault_id].fault_sig, 0);
158 } else if (io_signal >= MCPWM_CAP_0 && io_signal <= MCPWM_CAP_2) { // Capture input signal
159 gpio_set_direction(gpio_num, GPIO_MODE_INPUT);
160 int capture_id = io_signal - MCPWM_CAP_0;
161 esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].captures[capture_id].cap_sig, 0);
162 }
163 gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
164 return ESP_OK;
165 }
166
mcpwm_set_pin(mcpwm_unit_t mcpwm_num,const mcpwm_pin_config_t * mcpwm_pin)167 esp_err_t mcpwm_set_pin(mcpwm_unit_t mcpwm_num, const mcpwm_pin_config_t *mcpwm_pin)
168 {
169 ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR);
170 mcpwm_gpio_init(mcpwm_num, MCPWM0A, mcpwm_pin->mcpwm0a_out_num); //MCPWM0A
171 mcpwm_gpio_init(mcpwm_num, MCPWM0B, mcpwm_pin->mcpwm0b_out_num); //MCPWM0B
172 mcpwm_gpio_init(mcpwm_num, MCPWM1A, mcpwm_pin->mcpwm1a_out_num); //MCPWM1A
173 mcpwm_gpio_init(mcpwm_num, MCPWM1B, mcpwm_pin->mcpwm1b_out_num); //MCPWM1B
174 mcpwm_gpio_init(mcpwm_num, MCPWM2A, mcpwm_pin->mcpwm2a_out_num); //MCPWM2A
175 mcpwm_gpio_init(mcpwm_num, MCPWM2B, mcpwm_pin->mcpwm2b_out_num); //MCPWM2B
176 mcpwm_gpio_init(mcpwm_num, MCPWM_SYNC_0, mcpwm_pin->mcpwm_sync0_in_num); //SYNC0
177 mcpwm_gpio_init(mcpwm_num, MCPWM_SYNC_1, mcpwm_pin->mcpwm_sync1_in_num); //SYNC1
178 mcpwm_gpio_init(mcpwm_num, MCPWM_SYNC_2, mcpwm_pin->mcpwm_sync2_in_num); //SYNC2
179 mcpwm_gpio_init(mcpwm_num, MCPWM_FAULT_0, mcpwm_pin->mcpwm_fault0_in_num); //FAULT0
180 mcpwm_gpio_init(mcpwm_num, MCPWM_FAULT_1, mcpwm_pin->mcpwm_fault1_in_num); //FAULT1
181 mcpwm_gpio_init(mcpwm_num, MCPWM_FAULT_2, mcpwm_pin->mcpwm_fault2_in_num); //FAULT2
182 mcpwm_gpio_init(mcpwm_num, MCPWM_CAP_0, mcpwm_pin->mcpwm_cap0_in_num); //CAP0
183 mcpwm_gpio_init(mcpwm_num, MCPWM_CAP_1, mcpwm_pin->mcpwm_cap1_in_num); //CAP1
184 mcpwm_gpio_init(mcpwm_num, MCPWM_CAP_2, mcpwm_pin->mcpwm_cap2_in_num); //CAP2
185 return ESP_OK;
186 }
187
mcpwm_start(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)188 esp_err_t mcpwm_start(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
189 {
190 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
191
192 mcpwm_critical_enter(mcpwm_num);
193 mcpwm_ll_timer_set_start_stop_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_START_NO_STOP);
194 mcpwm_critical_exit(mcpwm_num);
195 return ESP_OK;
196 }
197
mcpwm_stop(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)198 esp_err_t mcpwm_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
199 {
200 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
201
202 mcpwm_critical_enter(mcpwm_num);
203 mcpwm_ll_timer_set_start_stop_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_STOP_EMPTY);
204 mcpwm_critical_exit(mcpwm_num);
205 return ESP_OK;
206 }
207
mcpwm_group_get_resolution(mcpwm_unit_t mcpwm_num)208 static inline uint32_t mcpwm_group_get_resolution(mcpwm_unit_t mcpwm_num)
209 {
210 if (context[mcpwm_num].group_resolution_hz == 0) {
211 context[mcpwm_num].group_resolution_hz = MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ;
212 }
213 return context[mcpwm_num].group_resolution_hz;
214 }
215
mcpwm_timer_get_resolution(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)216 static inline uint32_t mcpwm_timer_get_resolution(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
217 {
218 if (context[mcpwm_num].timer_resolution_hz[timer_num] == 0) {
219 context[mcpwm_num].timer_resolution_hz[timer_num] = MCPWM_DEFAULT_TIMER_CLK_RESOLUTION_HZ;
220 }
221 return context[mcpwm_num].timer_resolution_hz[timer_num];
222 }
223
mcpwm_group_set_resolution(mcpwm_unit_t mcpwm_num,uint32_t resolution)224 esp_err_t mcpwm_group_set_resolution(mcpwm_unit_t mcpwm_num, uint32_t resolution)
225 {
226 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
227 uint32_t clk_src_hz = 0;
228 esp_clk_tree_src_get_freq_hz(MCPWM_TIMER_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_hz);
229
230 int pre_scale_temp = clk_src_hz / resolution;
231 ESP_RETURN_ON_FALSE(pre_scale_temp >= 1, ESP_ERR_INVALID_ARG, TAG, "invalid resolution");
232 context[mcpwm_num].group_resolution_hz = clk_src_hz / pre_scale_temp;
233
234 mcpwm_critical_enter(mcpwm_num);
235 mcpwm_ll_group_set_clock_prescale(hal->dev, pre_scale_temp);
236 mcpwm_critical_exit(mcpwm_num);
237 return ESP_OK;
238 }
239
mcpwm_timer_set_resolution(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,uint32_t resolution)240 esp_err_t mcpwm_timer_set_resolution(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, uint32_t resolution)
241 {
242 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
243
244 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
245 uint32_t group_resolution = mcpwm_group_get_resolution(mcpwm_num);
246
247 int pre_scale_temp = group_resolution / resolution;
248 ESP_RETURN_ON_FALSE(pre_scale_temp >= 1, ESP_ERR_INVALID_ARG, TAG, "invalid resolution");
249 context[mcpwm_num].timer_resolution_hz[timer_num] = context[mcpwm_num].group_resolution_hz / pre_scale_temp;
250
251 mcpwm_critical_enter(mcpwm_num);
252 mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_num, pre_scale_temp);
253 mcpwm_critical_exit(mcpwm_num);
254 return ESP_OK;
255 }
256
mcpwm_set_frequency(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,uint32_t frequency)257 esp_err_t mcpwm_set_frequency(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, uint32_t frequency)
258 {
259 //the driver currently always use the timer x for operator x
260 const int op = timer_num;
261 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
262 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
263
264 mcpwm_critical_enter(mcpwm_num);
265
266 mcpwm_ll_timer_update_period_at_once(hal->dev, timer_num);
267 uint32_t previous_peak = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false);
268 uint32_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
269 uint32_t new_peak = timer_resolution / frequency;
270 mcpwm_ll_timer_set_peak(hal->dev, timer_num, new_peak, false);
271 // keep the duty cycle unchanged
272 float scale = ((float)new_peak) / previous_peak;
273 // the driver currently always use the comparator A for PWMxA output, and comparator B for PWMxB output
274 uint32_t previous_cmp_a = mcpwm_ll_operator_get_compare_value(hal->dev, op, 0);
275 uint32_t previous_cmp_b = mcpwm_ll_operator_get_compare_value(hal->dev, op, 1);
276 // update compare value immediately
277 mcpwm_ll_operator_update_compare_at_once(hal->dev, op, 0);
278 mcpwm_ll_operator_update_compare_at_once(hal->dev, op, 1);
279 mcpwm_ll_operator_set_compare_value(hal->dev, op, 0, (uint32_t)(previous_cmp_a * scale));
280 mcpwm_ll_operator_set_compare_value(hal->dev, op, 1, (uint32_t)(previous_cmp_b * scale));
281
282 mcpwm_critical_exit(mcpwm_num);
283 return ESP_OK;
284 }
285
mcpwm_set_duty(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_generator_t gen,float duty)286 esp_err_t mcpwm_set_duty(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_generator_t gen, float duty)
287 {
288 //the driver currently always use the timer x for operator x
289 const int op = timer_num;
290 //the driver currently always use the comparator A for PWMxA output, and comparator B for PWMxB output
291 const int cmp = gen;
292 MCPWM_GEN_CHECK(mcpwm_num, timer_num, gen);
293 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
294
295 mcpwm_critical_enter(mcpwm_num);
296 uint32_t set_duty = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false) * duty / 100;
297 mcpwm_ll_operator_set_compare_value(hal->dev, op, cmp, set_duty);
298 mcpwm_ll_operator_enable_update_compare_on_tez(hal->dev, op, cmp, true);
299 mcpwm_ll_operator_enable_update_compare_on_tep(hal->dev, op, cmp, true);
300 mcpwm_critical_exit(mcpwm_num);
301 return ESP_OK;
302 }
303
mcpwm_set_duty_in_us(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_generator_t gen,uint32_t duty_in_us)304 esp_err_t mcpwm_set_duty_in_us(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_generator_t gen, uint32_t duty_in_us)
305 {
306 //the driver currently always use the timer x for operator x
307 const int op = timer_num;
308 //the driver currently always use the comparator A for PWMxA output, and comparator B for PWMxB output
309 const int cmp = gen;
310 MCPWM_GEN_CHECK(mcpwm_num, timer_num, gen);
311 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
312
313 mcpwm_critical_enter(mcpwm_num);
314 // to avid multiplication overflow, use uint64_t here
315 uint64_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
316 uint64_t compare_val = timer_resolution * duty_in_us / 1000000;
317 mcpwm_ll_operator_set_compare_value(hal->dev, op, cmp, (uint32_t)compare_val);
318 mcpwm_ll_operator_enable_update_compare_on_tez(hal->dev, op, cmp, true);
319 mcpwm_ll_operator_enable_update_compare_on_tep(hal->dev, op, cmp, true);
320 mcpwm_critical_exit(mcpwm_num);
321 return ESP_OK;
322 }
323
mcpwm_set_duty_type(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_generator_t gen,mcpwm_duty_type_t duty_type)324 esp_err_t mcpwm_set_duty_type(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_generator_t gen,
325 mcpwm_duty_type_t duty_type)
326 {
327 //the driver currently always use the timer x for operator x
328 const int op = timer_num;
329 MCPWM_GEN_CHECK(mcpwm_num, timer_num, gen);
330 ESP_RETURN_ON_FALSE(duty_type < MCPWM_DUTY_MODE_MAX, ESP_ERR_INVALID_ARG, TAG, MCPWM_DUTY_TYPE_ERROR);
331 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
332
333 //the driver currently always use the comparator A for PWMxA output, and comparator B for PWMxB output
334 mcpwm_critical_enter(mcpwm_num);
335 switch (mcpwm_ll_timer_get_count_mode(hal->dev, timer_num)) {
336 case MCPWM_TIMER_COUNT_MODE_UP:
337 if (duty_type == MCPWM_DUTY_MODE_0) {
338 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH);
339 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_GEN_ACTION_KEEP);
340 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_LOW);
341 } else if (duty_type == MCPWM_DUTY_MODE_1) {
342 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_LOW);
343 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_NO_CHANGE);
344 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_HIGH);
345 } else if (duty_type == MCPWM_DUTY_MODE_FORCE_LOW) {
346 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW);
347 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW);
348 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_LOW);
349 } else if (duty_type == MCPWM_DUTY_MODE_FORCE_HIGH) {
350 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH);
351 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH);
352 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_HIGH);
353 }
354 break;
355 case MCPWM_TIMER_COUNT_MODE_DOWN:
356 if (duty_type == MCPWM_DUTY_MODE_0) {
357 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW);
358 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_NO_CHANGE);
359 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_HIGH);
360 } else if (duty_type == MCPWM_DUTY_MODE_1) {
361 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH);
362 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_NO_CHANGE);
363 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_LOW);
364 } else if (duty_type == MCPWM_DUTY_MODE_FORCE_LOW) {
365 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW);
366 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW);
367 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_LOW);
368 } else if (duty_type == MCPWM_DUTY_MODE_FORCE_HIGH) {
369 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH);
370 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH);
371 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_HIGH);
372 }
373 break;
374 case MCPWM_TIMER_COUNT_MODE_UP_DOWN:
375 if (duty_type == MCPWM_DUTY_MODE_0) {
376 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH);
377 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_LOW);
378 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_HIGH);
379 } else if (duty_type == MCPWM_DUTY_MODE_1) {
380 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW);
381 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_HIGH);
382 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_LOW);
383 } else if (duty_type == MCPWM_DUTY_MODE_FORCE_LOW) {
384 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW);
385 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW);
386 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW);
387 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW);
388 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_LOW);
389 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_LOW);
390 } else if (duty_type == MCPWM_DUTY_MODE_FORCE_HIGH) {
391 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH);
392 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH);
393 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH);
394 mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH);
395 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_HIGH);
396 mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_HIGH);
397 }
398 break;
399 default:
400 break;
401 }
402 mcpwm_critical_exit(mcpwm_num);
403 return ESP_OK;
404 }
405
mcpwm_init(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,const mcpwm_config_t * mcpwm_conf)406 esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpwm_config_t *mcpwm_conf)
407 {
408 const int op = timer_num;
409 MCPWM_TIMER_ID_CHECK(mcpwm_num, op);
410 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
411 periph_module_enable(mcpwm_periph_signals.groups[mcpwm_num].module);
412 mcpwm_hal_init_config_t config = {
413 .group_id = mcpwm_num
414 };
415 mcpwm_hal_init(hal, &config);
416
417 uint32_t clk_src_hz = 0;
418 esp_clk_tree_src_get_freq_hz(MCPWM_TIMER_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_hz);
419 uint32_t group_resolution = mcpwm_group_get_resolution(mcpwm_num);
420 uint32_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
421 uint32_t group_pre_scale = clk_src_hz / group_resolution;
422 uint32_t timer_pre_scale = group_resolution / timer_resolution;
423
424 mcpwm_critical_enter(mcpwm_num);
425 mcpwm_ll_group_enable_clock(hal->dev, true);
426 mcpwm_ll_group_set_clock_source(hal->dev, (soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT);
427 mcpwm_ll_group_set_clock_prescale(hal->dev, group_pre_scale);
428 mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_num, timer_pre_scale);
429 mcpwm_ll_timer_set_count_mode(hal->dev, timer_num, mcpwm_conf->counter_mode);
430 mcpwm_ll_timer_update_period_at_once(hal->dev, timer_num);
431 mcpwm_ll_timer_set_peak(hal->dev, timer_num, timer_resolution / mcpwm_conf->frequency, false);
432 mcpwm_ll_operator_connect_timer(hal->dev, timer_num, timer_num); //the driver currently always use the timer x for operator x
433 mcpwm_critical_exit(mcpwm_num);
434
435 mcpwm_set_duty(mcpwm_num, timer_num, 0, mcpwm_conf->cmpr_a);
436 mcpwm_set_duty(mcpwm_num, timer_num, 1, mcpwm_conf->cmpr_b);
437 mcpwm_set_duty_type(mcpwm_num, timer_num, 0, mcpwm_conf->duty_mode);
438 mcpwm_set_duty_type(mcpwm_num, timer_num, 1, mcpwm_conf->duty_mode);
439 mcpwm_start(mcpwm_num, timer_num);
440
441 return ESP_OK;
442 }
443
mcpwm_get_frequency(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)444 uint32_t mcpwm_get_frequency(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
445 {
446 if (mcpwm_num >= MCPWM_UNIT_MAX || timer_num >= MCPWM_TIMER_MAX) {
447 ESP_LOGE(TAG, "Invalid MCPWM timer instance");
448 return 0;
449 }
450
451 uint32_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
452
453 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
454 mcpwm_critical_enter(mcpwm_num);
455 uint32_t peak = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false);
456 uint32_t freq = timer_resolution / peak;
457 mcpwm_critical_exit(mcpwm_num);
458 return freq;
459 }
460
mcpwm_get_duty(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_generator_t gen)461 float mcpwm_get_duty(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_generator_t gen)
462 {
463 if (mcpwm_num >= MCPWM_UNIT_MAX || timer_num >= MCPWM_TIMER_MAX || gen >= MCPWM_GEN_MAX) {
464 ESP_LOGE(TAG, "Invalid MCPWM generator instance");
465 return 0;
466 }
467 //the driver currently always use the timer x for operator x
468 const int op = timer_num;
469 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
470 mcpwm_critical_enter(mcpwm_num);
471 float duty = 100.0 * mcpwm_ll_operator_get_compare_value(hal->dev, op, gen) / mcpwm_ll_timer_get_peak(hal->dev, timer_num, false);
472 mcpwm_critical_exit(mcpwm_num);
473 return duty;
474 }
475
mcpwm_get_duty_in_us(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_operator_t gen)476 uint32_t mcpwm_get_duty_in_us(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_operator_t gen)
477 {
478 if (mcpwm_num >= MCPWM_UNIT_MAX || timer_num >= MCPWM_TIMER_MAX || gen >= MCPWM_GEN_MAX) {
479 ESP_LOGE(TAG, "Invalid MCPWM generator instance");
480 return 0;
481 }
482
483 uint32_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
484
485 //the driver currently always use the timer x for operator x
486 const int op = timer_num;
487 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
488 mcpwm_critical_enter(mcpwm_num);
489 uint32_t duty = mcpwm_ll_operator_get_compare_value(hal->dev, op, gen) * (1000000.0 / timer_resolution);
490 mcpwm_critical_exit(mcpwm_num);
491 return duty;
492 }
493
mcpwm_set_signal_high(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_generator_t gen)494 esp_err_t mcpwm_set_signal_high(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_generator_t gen)
495 {
496 //the driver currently always use the timer x for operator x
497 return mcpwm_set_duty_type(mcpwm_num, timer_num, gen, MCPWM_DUTY_MODE_FORCE_HIGH);
498 }
499
mcpwm_set_signal_low(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_generator_t gen)500 esp_err_t mcpwm_set_signal_low(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_generator_t gen)
501 {
502 //the driver currently always use the timer x for operator x
503 return mcpwm_set_duty_type(mcpwm_num, timer_num, gen, MCPWM_DUTY_MODE_FORCE_LOW);
504 }
505
mcpwm_carrier_enable(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)506 esp_err_t mcpwm_carrier_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
507 {
508 //the driver currently always use the timer x for operator x
509 const int op = timer_num;
510 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
511
512 mcpwm_critical_enter(mcpwm_num);
513 mcpwm_ll_carrier_enable(context[mcpwm_num].hal.dev, op, true);
514 mcpwm_critical_exit(mcpwm_num);
515 return ESP_OK;
516 }
517
mcpwm_carrier_disable(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)518 esp_err_t mcpwm_carrier_disable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
519 {
520 //the driver currently always use the timer x for operator x
521 const int op = timer_num;
522 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
523
524 mcpwm_critical_enter(mcpwm_num);
525 mcpwm_ll_carrier_enable(context[mcpwm_num].hal.dev, op, false);
526 mcpwm_critical_exit(mcpwm_num);
527 return ESP_OK;
528 }
529
mcpwm_carrier_set_period(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,uint8_t carrier_period)530 esp_err_t mcpwm_carrier_set_period(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, uint8_t carrier_period)
531 {
532 //the driver currently always use the timer x for operator x
533 const int op = timer_num;
534 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
535
536 mcpwm_critical_enter(mcpwm_num);
537 mcpwm_ll_carrier_set_prescale(context[mcpwm_num].hal.dev, op, carrier_period + 1);
538 mcpwm_critical_exit(mcpwm_num);
539 return ESP_OK;
540 }
541
mcpwm_carrier_set_duty_cycle(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,uint8_t carrier_duty)542 esp_err_t mcpwm_carrier_set_duty_cycle(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, uint8_t carrier_duty)
543 {
544 //the driver currently always use the timer x for operator x
545 const int op = timer_num;
546 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
547
548 mcpwm_critical_enter(mcpwm_num);
549 mcpwm_ll_carrier_set_duty(context[mcpwm_num].hal.dev, op, carrier_duty);
550 mcpwm_critical_exit(mcpwm_num);
551 return ESP_OK;
552 }
553
mcpwm_carrier_oneshot_mode_enable(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,uint8_t pulse_width)554 esp_err_t mcpwm_carrier_oneshot_mode_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, uint8_t pulse_width)
555 {
556 //the driver currently always use the timer x for operator x
557 const int op = timer_num;
558 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
559
560 mcpwm_critical_enter(mcpwm_num);
561 mcpwm_ll_carrier_set_first_pulse_width(context[mcpwm_num].hal.dev, op, pulse_width + 1);
562 mcpwm_critical_exit(mcpwm_num);
563 return ESP_OK;
564 }
565
mcpwm_carrier_output_invert(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_carrier_out_ivt_t carrier_ivt_mode)566 esp_err_t mcpwm_carrier_output_invert(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num,
567 mcpwm_carrier_out_ivt_t carrier_ivt_mode)
568 {
569 //the driver currently always use the timer x for operator x
570 const int op = timer_num;
571 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
572
573 mcpwm_critical_enter(mcpwm_num);
574 mcpwm_ll_carrier_out_invert(context[mcpwm_num].hal.dev, op, carrier_ivt_mode);
575 mcpwm_critical_exit(mcpwm_num);
576 return ESP_OK;
577 }
578
mcpwm_carrier_init(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,const mcpwm_carrier_config_t * carrier_conf)579 esp_err_t mcpwm_carrier_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpwm_carrier_config_t *carrier_conf)
580 {
581 //the driver currently always use the timer x for operator x
582 const int op = timer_num;
583 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
584 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
585
586 mcpwm_carrier_enable(mcpwm_num, timer_num);
587 mcpwm_carrier_set_period(mcpwm_num, timer_num, carrier_conf->carrier_period);
588 mcpwm_carrier_set_duty_cycle(mcpwm_num, timer_num, carrier_conf->carrier_duty);
589 mcpwm_carrier_oneshot_mode_enable(mcpwm_num, timer_num, carrier_conf->pulse_width_in_os);
590 mcpwm_carrier_output_invert(mcpwm_num, timer_num, carrier_conf->carrier_ivt_mode);
591
592 mcpwm_critical_enter(mcpwm_num);
593 mcpwm_ll_carrier_in_invert(hal->dev, op, false);
594 mcpwm_critical_exit(mcpwm_num);
595
596 return ESP_OK;
597 }
598
mcpwm_deadtime_enable(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_deadtime_type_t dt_mode,uint32_t red,uint32_t fed)599 esp_err_t mcpwm_deadtime_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_deadtime_type_t dt_mode,
600 uint32_t red, uint32_t fed)
601 {
602 //the driver currently always use the timer x for operator x
603 const int op = timer_num;
604 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
605 ESP_RETURN_ON_FALSE(dt_mode < MCPWM_DEADTIME_TYPE_MAX, ESP_ERR_INVALID_ARG, TAG, MCPWM_DT_ERROR);
606 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
607
608 mcpwm_critical_enter(mcpwm_num);
609 mcpwm_ll_deadtime_enable_update_delay_on_tez(hal->dev, op, true);
610 // The dead time delay unit equals to MCPWM group resolution
611 mcpwm_ll_operator_set_deadtime_clock_src(hal->dev, op, MCPWM_LL_DEADTIME_CLK_SRC_GROUP);
612 mcpwm_ll_deadtime_set_rising_delay(hal->dev, op, red + 1);
613 mcpwm_ll_deadtime_set_falling_delay(hal->dev, op, fed + 1);
614 switch (dt_mode) {
615 case MCPWM_BYPASS_RED:
616 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0
617 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, true); // S1=1
618 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2=0
619 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0
620 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0
621 mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0
622 break;
623 case MCPWM_BYPASS_FED:
624 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, true); // S0=1
625 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0
626 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2=0
627 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0
628 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0
629 mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0
630 break;
631 case MCPWM_ACTIVE_HIGH_MODE:
632 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0
633 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0
634 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2=0
635 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0
636 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0
637 mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0
638 break;
639 case MCPWM_ACTIVE_LOW_MODE:
640 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0
641 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0
642 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, true); // S2=1
643 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, true); // S3=1
644 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0
645 mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0
646 break;
647 case MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE:
648 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0
649 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0
650 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2=0
651 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, true); // S3=1
652 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0
653 mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0
654 break;
655 case MCPWM_ACTIVE_LOW_COMPLIMENT_MODE:
656 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0
657 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0
658 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, true); // S2=1
659 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0
660 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0
661 mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0
662 break;
663 case MCPWM_ACTIVE_RED_FED_FROM_PWMXA:
664 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0
665 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0
666 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0
667 mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 0, true); // S6=1
668 mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 1, false); // S7=0
669 mcpwm_ll_deadtime_enable_deb(hal->dev, op, true); // S8=1
670 break;
671 case MCPWM_ACTIVE_RED_FED_FROM_PWMXB:
672 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0
673 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0
674 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 1); // S4=1
675 mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 0, true); // S6=1
676 mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 1, false); // S7=0
677 mcpwm_ll_deadtime_enable_deb(hal->dev, op, true); // S8=1
678 break;
679 default :
680 break;
681 }
682 mcpwm_critical_exit(mcpwm_num);
683 return ESP_OK;
684 }
685
mcpwm_deadtime_disable(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)686 esp_err_t mcpwm_deadtime_disable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
687 {
688 //the driver currently always use the timer x for operator x
689 const int op = timer_num;
690 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
691 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
692
693 mcpwm_critical_enter(mcpwm_num);
694 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, true); // S0
695 mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, true); // S1
696 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2
697 mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3
698 mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4
699 mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5
700 mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 0, false); // S6
701 mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 1, false); // S7
702 mcpwm_ll_deadtime_enable_deb(hal->dev, op, false); // S8
703 mcpwm_critical_exit(mcpwm_num);
704 return ESP_OK;
705 }
706
mcpwm_fault_init(mcpwm_unit_t mcpwm_num,mcpwm_fault_input_level_t intput_level,mcpwm_fault_signal_t fault_sig)707 esp_err_t mcpwm_fault_init(mcpwm_unit_t mcpwm_num, mcpwm_fault_input_level_t intput_level, mcpwm_fault_signal_t fault_sig)
708 {
709 ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR);
710 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
711
712 mcpwm_critical_enter(mcpwm_num);
713 mcpwm_ll_fault_enable_detection(hal->dev, fault_sig, true);
714 mcpwm_ll_fault_set_active_level(hal->dev, fault_sig, intput_level);
715 mcpwm_critical_exit(mcpwm_num);
716 return ESP_OK;
717 }
718
mcpwm_fault_deinit(mcpwm_unit_t mcpwm_num,mcpwm_fault_signal_t fault_sig)719 esp_err_t mcpwm_fault_deinit(mcpwm_unit_t mcpwm_num, mcpwm_fault_signal_t fault_sig)
720 {
721 ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR);
722 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
723
724 mcpwm_critical_enter(mcpwm_num);
725 mcpwm_ll_fault_enable_detection(hal->dev, fault_sig, false);
726 for (int i = 0; i < SOC_MCPWM_OPERATORS_PER_GROUP; i++) {
727 mcpwm_ll_brake_clear_ost(hal->dev, i); // make sure operator has exit the ost fault state totally
728 }
729 mcpwm_critical_exit(mcpwm_num);
730 return ESP_OK;
731 }
732
mcpwm_fault_set_cyc_mode(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_fault_signal_t fault_sig,mcpwm_output_action_t action_on_pwmxa,mcpwm_output_action_t action_on_pwmxb)733 esp_err_t mcpwm_fault_set_cyc_mode(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_fault_signal_t fault_sig,
734 mcpwm_output_action_t action_on_pwmxa, mcpwm_output_action_t action_on_pwmxb)
735 {
736 //the driver currently always use the timer x for operator x
737 const int op = timer_num;
738 MCPWM_TIMER_CHECK(mcpwm_num, op);
739 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
740
741 mcpwm_critical_enter(mcpwm_num);
742 mcpwm_ll_brake_enable_cbc_mode(hal->dev, op, fault_sig, true);
743 mcpwm_ll_brake_enable_cbc_refresh_on_tez(hal->dev, op, true);
744 mcpwm_ll_brake_enable_oneshot_mode(hal->dev, op, fault_sig, false);
745 mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_OPER_BRAKE_MODE_CBC, action_on_pwmxa);
746 mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, action_on_pwmxa);
747 mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_OPER_BRAKE_MODE_CBC, action_on_pwmxb);
748 mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, action_on_pwmxb);
749 mcpwm_critical_exit(mcpwm_num);
750 return ESP_OK;
751 }
752
mcpwm_fault_set_oneshot_mode(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_fault_signal_t fault_sig,mcpwm_action_on_pwmxa_t action_on_pwmxa,mcpwm_action_on_pwmxb_t action_on_pwmxb)753 esp_err_t mcpwm_fault_set_oneshot_mode(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_fault_signal_t fault_sig,
754 mcpwm_action_on_pwmxa_t action_on_pwmxa, mcpwm_action_on_pwmxb_t action_on_pwmxb)
755 {
756 //the driver currently always use the timer x for operator x
757 const int op = timer_num;
758 MCPWM_TIMER_CHECK(mcpwm_num, op);
759 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
760
761 mcpwm_critical_enter(mcpwm_num);
762 mcpwm_ll_brake_clear_ost(hal->dev, op);
763 mcpwm_ll_brake_enable_oneshot_mode(hal->dev, op, fault_sig, true);
764 mcpwm_ll_brake_enable_cbc_mode(hal->dev, op, fault_sig, false);
765 mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_OPER_BRAKE_MODE_OST, action_on_pwmxa);
766 mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_OST, action_on_pwmxa);
767 mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_OPER_BRAKE_MODE_OST, action_on_pwmxb);
768 mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_OST, action_on_pwmxb);
769 mcpwm_critical_exit(mcpwm_num);
770 return ESP_OK;
771 }
772
mcpwm_default_isr_handler(void * arg)773 static void MCPWM_ISR_ATTR mcpwm_default_isr_handler(void *arg)
774 {
775 mcpwm_context_t *curr_context = (mcpwm_context_t *) arg;
776 uint32_t intr_status = mcpwm_ll_intr_get_capture_status(curr_context->hal.dev);
777 mcpwm_ll_intr_clear_capture_status(curr_context->hal.dev, intr_status);
778 bool need_yield = false;
779 for (int i = 0; i < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER; ++i) {
780 if ((intr_status >> i) & 0x1) {
781 if (curr_context->cap_isr_func[i].fn != NULL) {
782 cap_event_data_t edata;
783 edata.cap_edge = mcpwm_ll_capture_get_edge(curr_context->hal.dev, i) == MCPWM_CAP_EDGE_NEG ? MCPWM_NEG_EDGE
784 : MCPWM_POS_EDGE;
785 edata.cap_value = mcpwm_ll_capture_get_value(curr_context->hal.dev, i);
786 if (curr_context->cap_isr_func[i].fn(curr_context->group_id, i, &edata,
787 curr_context->cap_isr_func[i].args)) {
788 need_yield = true;
789 }
790 }
791 }
792 }
793 if (need_yield) {
794 portYIELD_FROM_ISR();
795 }
796 }
797
mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num,mcpwm_capture_channel_id_t cap_channel,const mcpwm_capture_config_t * cap_conf)798 esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_channel_id_t cap_channel, const mcpwm_capture_config_t *cap_conf)
799 {
800 ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR);
801 ESP_RETURN_ON_FALSE(cap_channel < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR);
802 ESP_RETURN_ON_FALSE(context[mcpwm_num].cap_isr_func[cap_channel].fn == NULL, ESP_ERR_INVALID_STATE, TAG,
803 MCPWM_CAP_EXIST_ERROR);
804 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
805
806 // enable MCPWM module incase user don't use `mcpwm_init` at all. always increase reference count
807 periph_module_enable(mcpwm_periph_signals.groups[mcpwm_num].module);
808
809 mcpwm_hal_init_config_t init_config = {
810 .group_id = mcpwm_num
811 };
812 mcpwm_hal_init(hal, &init_config);
813
814 uint32_t clk_src_hz = 0;
815 esp_clk_tree_src_get_freq_hz(MCPWM_TIMER_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_hz);
816 uint32_t group_resolution = mcpwm_group_get_resolution(mcpwm_num);
817 uint32_t group_pre_scale = clk_src_hz / group_resolution;
818
819 mcpwm_critical_enter(mcpwm_num);
820 mcpwm_ll_group_enable_clock(hal->dev, true);
821 mcpwm_ll_group_set_clock_source(hal->dev, (soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT);
822 mcpwm_ll_group_set_clock_prescale(hal->dev, group_pre_scale);
823 mcpwm_ll_capture_enable_timer(hal->dev, true);
824 mcpwm_ll_capture_enable_channel(hal->dev, cap_channel, true);
825 mcpwm_ll_capture_enable_negedge(hal->dev, cap_channel, cap_conf->cap_edge & MCPWM_NEG_EDGE);
826 mcpwm_ll_capture_enable_posedge(hal->dev, cap_channel, cap_conf->cap_edge & MCPWM_POS_EDGE);
827 mcpwm_ll_capture_set_prescale(hal->dev, cap_channel, cap_conf->cap_prescale);
828 // capture feature should be used with interrupt, so enable it by default
829 mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_channel), true);
830 mcpwm_ll_intr_clear_capture_status(hal->dev, 1 << cap_channel);
831 mcpwm_critical_exit(mcpwm_num);
832
833 mcpwm_mutex_lock(mcpwm_num);
834 context[mcpwm_num].cap_isr_func[cap_channel].fn = cap_conf->capture_cb;
835 context[mcpwm_num].cap_isr_func[cap_channel].args = cap_conf->user_data;
836 esp_err_t ret = ESP_OK;
837 if (context[mcpwm_num].mcpwm_intr_handle == NULL) {
838 ret = esp_intr_alloc(mcpwm_periph_signals.groups[mcpwm_num].irq_id, MCPWM_INTR_FLAG,
839 mcpwm_default_isr_handler,
840 (void *) (context + mcpwm_num), &(context[mcpwm_num].mcpwm_intr_handle));
841 }
842 mcpwm_mutex_unlock(mcpwm_num);
843
844 return ret;
845 }
846
mcpwm_capture_disable_channel(mcpwm_unit_t mcpwm_num,mcpwm_capture_channel_id_t cap_channel)847 esp_err_t mcpwm_capture_disable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_channel_id_t cap_channel)
848 {
849 ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR);
850 ESP_RETURN_ON_FALSE(cap_channel < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR);
851
852 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
853
854 mcpwm_critical_enter(mcpwm_num);
855 mcpwm_ll_capture_enable_channel(hal->dev, cap_channel, false);
856 mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_channel), false);
857 mcpwm_critical_exit(mcpwm_num);
858
859 mcpwm_mutex_lock(mcpwm_num);
860 context[mcpwm_num].cap_isr_func[cap_channel].fn = NULL;
861 context[mcpwm_num].cap_isr_func[cap_channel].args = NULL;
862 // if all user defined ISR callback is disabled, free the handle
863 bool should_free_handle = true;
864 for (int i = 0; i < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER; ++i) {
865 if (context[mcpwm_num].cap_isr_func[i].fn != NULL) {
866 should_free_handle = false;
867 break;
868 }
869 }
870 esp_err_t ret = ESP_OK;
871 if (should_free_handle) {
872 ret = esp_intr_free(context[mcpwm_num].mcpwm_intr_handle);
873 if (ret != ESP_OK) {
874 ESP_LOGE(TAG, "failed to free interrupt handle");
875 }
876 context[mcpwm_num].mcpwm_intr_handle = NULL;
877 }
878 mcpwm_mutex_unlock(mcpwm_num);
879
880 // always decrease reference count
881 periph_module_disable(mcpwm_periph_signals.groups[mcpwm_num].module);
882 return ret;
883 }
884
mcpwm_capture_signal_get_value(mcpwm_unit_t mcpwm_num,mcpwm_capture_signal_t cap_sig)885 uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_value(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig)
886 {
887 if (mcpwm_num >= MCPWM_UNIT_MAX || cap_sig >= SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER) {
888 return 0;
889 }
890 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
891 return mcpwm_ll_capture_get_value(hal->dev, cap_sig);
892 }
893
mcpwm_capture_get_resolution(mcpwm_unit_t mcpwm_num)894 uint32_t mcpwm_capture_get_resolution(mcpwm_unit_t mcpwm_num)
895 {
896 if (mcpwm_num >= MCPWM_UNIT_MAX) {
897 ESP_LOGE(TAG, "Invalid MCPWM instance");
898 return 0;
899 }
900 #if SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
901 return mcpwm_group_get_resolution(mcpwm_num);
902 #else
903 return esp_clk_apb_freq();
904 #endif
905 }
906
mcpwm_capture_signal_get_edge(mcpwm_unit_t mcpwm_num,mcpwm_capture_signal_t cap_sig)907 uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_edge(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig)
908 {
909 if (mcpwm_num >= MCPWM_UNIT_MAX || cap_sig >= SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER) {
910 return 0;
911 }
912 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
913 return mcpwm_ll_capture_get_edge(hal->dev, cap_sig) == MCPWM_CAP_EDGE_NEG ? 2 : 1;
914 }
915
mcpwm_sync_configure(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,const mcpwm_sync_config_t * sync_conf)916 esp_err_t mcpwm_sync_configure(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpwm_sync_config_t *sync_conf)
917 {
918 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
919 ESP_RETURN_ON_FALSE(sync_conf->sync_sig <= MCPWM_SELECT_GPIO_SYNC2, ESP_ERR_INVALID_ARG, TAG, "invalid sync_sig");
920 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
921
922 mcpwm_critical_enter(mcpwm_num);
923 mcpwm_ll_timer_set_sync_phase_direction(hal->dev, timer_num, sync_conf->count_direction);
924 // sync TEP with current setting
925 uint32_t set_phase = 0;
926 set_phase = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false) * sync_conf->timer_val / 1000;
927 mcpwm_ll_timer_set_sync_phase_value(hal->dev, timer_num, set_phase);
928 if (sync_conf->sync_sig == MCPWM_SELECT_NO_INPUT) {
929 mcpwm_ll_timer_clear_sync_input(hal->dev, timer_num);
930 } else if (sync_conf->sync_sig <= MCPWM_SELECT_TIMER2_SYNC) {
931 mcpwm_ll_timer_set_timer_sync_input(hal->dev, timer_num, sync_conf->sync_sig - MCPWM_SELECT_TIMER0_SYNC);
932 } else {
933 mcpwm_ll_timer_set_gpio_sync_input(hal->dev, timer_num, sync_conf->sync_sig - MCPWM_SELECT_GPIO_SYNC0);
934 }
935 mcpwm_ll_timer_enable_sync_input(hal->dev, timer_num, true);
936 mcpwm_critical_exit(mcpwm_num);
937 return ESP_OK;
938 }
939
mcpwm_sync_disable(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)940 esp_err_t mcpwm_sync_disable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
941 {
942 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
943 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
944
945 mcpwm_critical_enter(mcpwm_num);
946 mcpwm_ll_timer_enable_sync_input(hal->dev, timer_num, false);
947 mcpwm_critical_exit(mcpwm_num);
948 return ESP_OK;
949 }
950
mcpwm_timer_trigger_soft_sync(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num)951 esp_err_t mcpwm_timer_trigger_soft_sync(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
952 {
953 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
954
955 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
956 mcpwm_critical_enter(mcpwm_num);
957 mcpwm_ll_timer_trigger_soft_sync(hal->dev, timer_num);
958 mcpwm_critical_exit(mcpwm_num);
959
960 return ESP_OK;
961 }
962
mcpwm_sync_invert_gpio_synchro(mcpwm_unit_t mcpwm_num,mcpwm_sync_signal_t sync_sig,bool invert)963 esp_err_t mcpwm_sync_invert_gpio_synchro(mcpwm_unit_t mcpwm_num, mcpwm_sync_signal_t sync_sig, bool invert)
964 {
965 ESP_RETURN_ON_FALSE(sync_sig >= MCPWM_SELECT_GPIO_SYNC0 && sync_sig <= MCPWM_SELECT_GPIO_SYNC2,
966 ESP_ERR_INVALID_ARG, TAG, "invalid sync sig");
967
968 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
969 mcpwm_critical_enter(mcpwm_num);
970 mcpwm_ll_invert_gpio_sync_input(hal->dev, sync_sig - MCPWM_SELECT_GPIO_SYNC0, invert);
971 mcpwm_critical_exit(mcpwm_num);
972
973 return ESP_OK;
974 }
975
mcpwm_set_timer_sync_output(mcpwm_unit_t mcpwm_num,mcpwm_timer_t timer_num,mcpwm_timer_sync_trigger_t trigger)976 esp_err_t mcpwm_set_timer_sync_output(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_timer_sync_trigger_t trigger)
977 {
978 MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
979
980 mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
981 mcpwm_critical_enter(mcpwm_num);
982 switch (trigger) {
983 case MCPWM_SWSYNC_SOURCE_SYNCIN:
984 mcpwm_ll_timer_propagate_input_sync(hal->dev, timer_num);
985 break;
986 case MCPWM_SWSYNC_SOURCE_TEZ:
987 mcpwm_ll_timer_sync_out_on_timer_event(hal->dev, timer_num, MCPWM_TIMER_EVENT_EMPTY);
988 break;
989 case MCPWM_SWSYNC_SOURCE_TEP:
990 mcpwm_ll_timer_sync_out_on_timer_event(hal->dev, timer_num, MCPWM_TIMER_EVENT_FULL);
991 break;
992 case MCPWM_SWSYNC_SOURCE_DISABLED:
993 default:
994 mcpwm_ll_timer_disable_sync_out(hal->dev, timer_num);
995 break;
996 }
997 mcpwm_critical_exit(mcpwm_num);
998 return ESP_OK;
999 }
1000
1001 /**
1002 * @brief This function will be called during start up, to check that this legacy mcpwm driver is not running along with the new MCPWM driver
1003 */
1004 __attribute__((constructor))
check_mcpwm_driver_conflict(void)1005 static void check_mcpwm_driver_conflict(void)
1006 {
1007 // This function was declared as weak here. The new MCPWM driver has the implementation.
1008 // So if the new MCPWM driver is not linked in, then `mcpwm_acquire_group_handle()` should be NULL at runtime.
1009 extern __attribute__((weak)) void *mcpwm_acquire_group_handle(int group_id);
1010 if ((void *)mcpwm_acquire_group_handle != NULL) {
1011 ESP_EARLY_LOGE(TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
1012 abort();
1013 }
1014 ESP_EARLY_LOGW(TAG, "legacy driver is deprecated, please migrate to `driver/mcpwm_prelude.h`");
1015 }
1016