# Motor Control Pulse Width Modulator (MCPWM)

[中文]

The MCPWM peripheral is a versatile PWM generator, which contains various submodules to make it a key element in power electronic applications like motor control, digital power, and so on. Typically, the MCPWM peripheral can be used in the following scenarios:

- Digital motor control, e.g., brushed/brushless DC motor, RC servo motor

- Switch mode-based digital power conversion

- Power DAC, where the duty cycle is equivalent to a DAC analog value

- Calculate external pulse width, and convert it into other analog values like speed, distance

- Generate Space Vector PWM (SVPWM) signals for Field Oriented Control (FOC)

The main submodules are listed in the following diagram:

MCPWM Overview

- MCPWM Timer: The time base of the final PWM signal. It also determines the event timing of other submodules.

- MCPWM Operator: The key module that is responsible for generating the PWM waveforms. It consists of other submodules, like comparator, PWM generator, dead time, and carrier modulator.

- MCPWM Comparator: The compare module takes the time-base count value as input, and continuously compares it to the threshold value configured. When the timer is equal to any of the threshold values, a compare event will be generated and the MCPWM generator can update its level accordingly.

- MCPWM Generator: One MCPWM generator can generate a pair of PWM waves, complementarily or independently, based on various events triggered by other submodules like MCPWM Timer and MCPWM Comparator.

- MCPWM Fault: The fault module is used to detect the fault condition from outside, mainly via the GPIO matrix. Once the fault signal is active, MCPWM Operator will force all the generators into a predefined state to protect the system from damage.

- MCPWM Sync: The sync module is used to synchronize the MCPWM timers, so that the final PWM signals generated by different MCPWM generators can have a fixed phase difference. The sync signal can be routed from the GPIO matrix or from an MCPWM Timer event.

- Dead Time: This submodule is used to insert extra delay to the existing PWM edges generated in the previous steps.

- Carrier Modulation: The carrier submodule can modulate a high-frequency carrier signal into PWM waveforms by the generator and dead time submodules. This capability is mandatory for controlling the power-switching elements.

- Brake: MCPWM operator can set how to brake the generators when a particular fault is detected. You can shut down the PWM output immediately or regulate the PWM output cycle by cycle, depending on how critical the fault is.

- MCPWM Capture: This is a standalone submodule that can work even without the above MCPWM operators. The capture consists one dedicated timer and several independent channels, with each channel connected to the GPIO. A pulse on the GPIO triggers the capture timer to store the time-base count value and then notify you by an interrupt. Using this feature, you can measure a pulse width precisely. What is more, the capture timer can also be synchronized by the MCPWM Sync submodule.

## Functional Overview

Description of the MCPWM functionality is divided into the following sections:

- Resource Allocation and Initialization - covers how to allocate various MCPWM objects, like timers, operators, comparators, generators and so on. These objects are the basis of the following IO setting and control functions.

- Timer Operations and Events - describes control functions and event callbacks supported by the MCPWM timer.

- Comparator Operations and Events - describes control functions and event callbacks supported by the MCPWM comparator.

- Generator Actions on Events - describes how to set actions for MCPWM generators on particular events that are generated by the MCPWM timer and comparators.

- Generator Configurations for Classical PWM Waveforms - demonstrates some classical PWM waveforms that can be achieved by configuring generator actions.

- Dead Time - describes how to set dead time for MCPWM generators.

- Dead Time Configurations for Classical PWM Waveforms - demonstrates some classical PWM waveforms that can be achieved by configuring dead time.

- Carrier Modulation - describes how to set and modulate a high frequency onto the final PWM waveforms.

- Faults and Brake Actions - describes how to set brake actions for MCPWM operators on particular fault events.

- Generator Force Actions - describes how to control the generator output level asynchronously in a forceful way.

- Synchronization - describes how to synchronize the MCPWM timers and get a fixed phase difference between the generated PWM signals.

- Capture - describes how to use the MCPWM capture module to measure the pulse width of a signal.

- Power Management - describes how different source clocks affects power consumption.

- Resolution Configuration - describes the resolution configuration rules for the MCPWM submodule.

- IRAM Safe - describes tips on how to make the RMT interrupt work better along with a disabled cache.

- Thread Safety - lists which APIs are guaranteed to be thread-safe by the driver.

- Kconfig Options - lists the supported Kconfig options that can bring different effects to the driver.

### Resource Allocation and Initialization

As displayed in the diagram above, the MCPWM peripheral consists of several submodules. Each submodule has its own resource allocation, which is described in the following sections.

#### MCPWM Timers

You can allocate a MCPWM timer object by calling `mcpwm_new_timer()` function, with a configuration structure `mcpwm_timer_config_t` as the parameter. The configuration structure is defined as:

- `mcpwm_timer_config_t::group_id` specifies the MCPWM group ID. The ID should belong to [0, `MCPWM_GROUP_NUM` - 1] range, where `MCPWM_GROUP_NUM` is the number of MCPWM groups available on the chip. Please note, timers located in different groups are totally independent.

Note

For the number of MCPWM groups available on the chip, please refer to ESP32 Technical Reference Manual > Motor Control PWM (MCPWM) [PDF].

- `mcpwm_timer_config_t::intr_priority` sets the priority of the interrupt. If it is set to `0`, the driver will allocate an interrupt with a default priority. Otherwise, the driver will use the given priority.

- `mcpwm_timer_config_t::clk_src` sets the clock source of the timer.

- `mcpwm_timer_config_t::resolution_hz` sets the expected resolution of the timer. The driver internally sets a proper divider based on the clock source and the resolution.

- `mcpwm_timer_config_t::count_mode` sets the count mode of the timer.

- `mcpwm_timer_config_t::period_ticks` sets the period of the timer, in ticks (the tick resolution is set in the `mcpwm_timer_config_t::resolution_hz`).

- `mcpwm_timer_config_t::flags::update_period_on_empty` sets whether to update the period value when the timer counts to zero.

- `mcpwm_timer_config_t::flags::update_period_on_sync` sets whether to update the period value when the timer takes a sync signal.

The `mcpwm_new_timer()` will return a pointer to the allocated timer object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free timers in the MCPWM group, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

On the contrary, calling the `mcpwm_del_timer()` function will free the allocated timer object.

Note

The prescale for the MCPWM group will be calculated with the resolution of the first timer, and the driver will find the appropriate prescale from low to high. If there is a prescale conflict when allocating multiple timers, allocate timers in order of their target resolution, either from highest to lowest or lowest to highest. For more information, please refer to Resolution Configuration.

#### MCPWM Operators

You can allocate a MCPWM operator object by calling `mcpwm_new_operator()()` function, with a configuration structure `mcpwm_operator_config_t` as the parameter. The configuration structure is defined as:

- `mcpwm_operator_config_t::group_id` specifies the MCPWM group ID. The ID should belong to [0, `MCPWM_GROUP_NUM` - 1] range, where `MCPWM_GROUP_NUM` is the number of MCPWM groups available on the chip. Please note, operators located in different groups are totally independent.

- `mcpwm_operator_config_t::intr_priority` sets the priority of the interrupt. If it is set to `0`, the driver will allocate an interrupt with a default priority. Otherwise, the driver will use the given priority.

- `mcpwm_operator_config_t::flags::update_gen_action_on_tez` sets whether to update the generator action when the timer counts to zero. Here and below, the timer refers to the one that is connected to the operator by `mcpwm_operator_connect_timer()`.

- `mcpwm_operator_config_t::flags::update_gen_action_on_tep` sets whether to update the generator action when the timer counts to peak.

- `mcpwm_operator_config_t::flags::update_gen_action_on_sync` sets whether to update the generator action when the timer takes a sync signal.

- `mcpwm_operator_config_t::flags::update_dead_time_on_tez` sets whether to update the dead time when the timer counts to zero.

- `mcpwm_operator_config_t::flags::update_dead_time_on_tep` sets whether to update the dead time when the timer counts to the peak.

- `mcpwm_operator_config_t::flags::update_dead_time_on_sync` sets whether to update the dead time when the timer takes a sync signal.

The `mcpwm_new_operator()()` will return a pointer to the allocated operator object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free operators in the MCPWM group, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

On the contrary, calling `mcpwm_del_operator()()` function will free the allocated operator object.

#### MCPWM Comparators

You can allocate a MCPWM comparator object by calling the `mcpwm_new_comparator()` function, with a MCPWM operator handle and configuration structure `mcpwm_comparator_config_t` as the parameter. The operator handle is created by `mcpwm_new_operator()()`. The configuration structure is defined as:

- `mcpwm_comparator_config_t::intr_priority` sets the priority of the interrupt. If it is set to `0`, the driver will allocate an interrupt with a default priority. Otherwise, the driver will use the given priority.

- `mcpwm_comparator_config_t::flags::update_cmp_on_tez` sets whether to update the compare threshold when the timer counts to zero.

- `mcpwm_comparator_config_t::flags::update_cmp_on_tep` sets whether to update the compare threshold when the timer counts to the peak.

- `mcpwm_comparator_config_t::flags::update_cmp_on_sync` sets whether to update the compare threshold when the timer takes a sync signal.

The `mcpwm_new_comparator()` will return a pointer to the allocated comparator object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free comparators in the MCPWM operator, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

On the contrary, calling the `mcpwm_del_comparator()` function will free the allocated comparator object.

#### MCPWM Generators

You can allocate a MCPWM generator object by calling the `mcpwm_new_generator()` function, with a MCPWM operator handle and configuration structure `mcpwm_generator_config_t` as the parameter. The operator handle is created by `mcpwm_new_operator()()`. The configuration structure is defined as:

- `mcpwm_generator_config_t::gen_gpio_num` sets the GPIO number used by the generator.

- `mcpwm_generator_config_t::flags::invert_pwm` sets whether to invert the PWM signal.

- `mcpwm_generator_config_t::pull_up` and `mcpwm_generator_config_t::pull_down` controls whether to enable the internal pull-up and pull-down resistors accordingly.

The `mcpwm_new_generator()` will return a pointer to the allocated generator object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free generators in the MCPWM operator, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

On the contrary, calling the `mcpwm_del_generator()` function will free the allocated generator object.

#### MCPWM Faults

There are two types of faults: A fault signal reflected from the GPIO and a fault generated by software.

To allocate a GPIO fault object, you can call the `mcpwm_new_gpio_fault()` function, with the configuration structure `mcpwm_gpio_fault_config_t` as the parameter. The configuration structure is defined as:

- `mcpwm_gpio_fault_config_t::group_id` sets the MCPWM group ID. The ID should belong to [0, `MCPWM_GROUP_NUM` - 1] range, where `MCPWM_GROUP_NUM` is the number of MCPWM groups available on the chip. Please note, GPIO faults located in different groups are totally independent, i.e., GPIO faults in group 0 can not be detected by the operator in group 1.

- `mcpwm_gpio_fault_config_t::intr_priority` sets the priority of the interrupt. If it is set to `0`, the driver will allocate an interrupt with a default priority. Otherwise, the driver will use the given priority.

- `mcpwm_gpio_fault_config_t::gpio_num` sets the GPIO number used by the fault.

- `mcpwm_gpio_fault_config_t::flags::active_level` sets the active level of the fault signal.

- `mcpwm_gpio_fault_config_t::pull_up` and `mcpwm_gpio_fault_config_t::pull_down` set whether to pull up and/or pull down the GPIO internally.

The `mcpwm_new_gpio_fault()` will return a pointer to the allocated fault object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free GPIO faults in the MCPWM group, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

Software fault object can be used to trigger a fault by calling the function `mcpwm_soft_fault_activate()` instead of waiting for a real fault signal on the GPIO. A software fault object can be allocated by calling the `mcpwm_new_soft_fault()` function, with configuration structure `mcpwm_soft_fault_config_t` as the parameter. Currently, this configuration structure is left for future purposes.

The `mcpwm_new_soft_fault()` function will return a pointer to the allocated fault object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there is no memory left for the fault object, this function will return the `ESP_ERR_NO_MEM` error. Although the software fault and GPIO fault are of different types, the returned fault handle is of the same type.

On the contrary, calling the `mcpwm_del_fault()` function will free the allocated fault object, this function works for both software and GPIO fault.

#### MCPWM Sync Sources

The sync source is what can be used to synchronize the MCPWM timer and MCPWM capture timer. There are three types of sync sources: a sync source reflected from the GPIO, a sync source generated by software, and a sync source generated by an MCPWM timer event.

To allocate a GPIO sync source, you can call the `mcpwm_new_gpio_sync_src()` function, with configuration structure `mcpwm_gpio_sync_src_config_t` as the parameter. The configuration structure is defined as:

- `mcpwm_gpio_sync_src_config_t::group_id` sets the MCPWM group ID. The ID should belong to [0, `MCPWM_GROUP_NUM` - 1] range, where `MCPWM_GROUP_NUM` is the number of MCPWM groups available on the chip. Please note, the GPIO sync sources located in different groups are totally independent, i.e., GPIO sync source in group 0 can not be detected by the timers in group 1.

- `mcpwm_gpio_sync_src_config_t::gpio_num` sets the GPIO number used by the sync source.

- `mcpwm_gpio_sync_src_config_t::flags::active_neg` sets whether the sync signal is active on falling edges.

- `mcpwm_gpio_sync_src_config_t::pull_up` and `mcpwm_gpio_sync_src_config_t::pull_down` set whether to pull up and/or pull down the GPIO internally.

The `mcpwm_new_gpio_sync_src()` will return a pointer to the allocated sync source object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there are no more free GPIO sync sources in the MCPWM group, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

To allocate a timer event sync source, you can call the `mcpwm_new_timer_sync_src()` function, with configuration structure `mcpwm_timer_sync_src_config_t` as the parameter. The configuration structure is defined as:

- `mcpwm_timer_sync_src_config_t::timer_event` specifies on what timer event to generate the sync signal.

- `mcpwm_timer_sync_src_config_t::propagate_input_sync` sets whether to propagate the input sync signal (i.e., the input sync signal will be routed to its sync output).

The `mcpwm_new_timer_sync_src()` will return a pointer to the allocated sync source object if the allocation succeeds. Otherwise, it will return an error code. Specifically, if a sync source has been allocated from the same timer before, this function will return the `ESP_ERR_INVALID_STATE` error.

Last but not least, to allocate a software sync source, you can call the `mcpwm_new_soft_sync_src()` function, with configuration structure `mcpwm_soft_sync_config_t` as the parameter. Currently, this configuration structure is left for future purposes.

`mcpwm_new_soft_sync_src()` will return a pointer to the allocated sync source object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there is no memory left for the sync source object, this function will return the `ESP_ERR_NO_MEM` error. Please note, to make a software sync source take effect, do not forget to call `mcpwm_soft_sync_activate()`.

On the contrary, calling the `mcpwm_del_sync_src()` function will free the allocated sync source object. This function works for all types of sync sources.

#### MCPWM Capture Timer and Channels

The MCPWM group has a dedicated timer which is used to capture the timestamp when a specific event occurred. The capture timer is connected to several independent channels, each channel is assigned a GPIO.

To allocate a capture timer, you can call the `mcpwm_new_capture_timer()` function, with configuration structure `mcpwm_capture_timer_config_t` as the parameter. The configuration structure is defined as:

- `mcpwm_capture_timer_config_t::group_id` sets the MCPWM group ID. The ID should belong to [0, `MCPWM_GROUP_NUM` - 1] range, where `MCPWM_GROUP_NUM` is the number of MCPWM groups available on the chip.

- `mcpwm_capture_timer_config_t::clk_src` sets the clock source of the capture timer.

- `mcpwm_capture_timer_config_t::resolution_hz` The driver internally will set a proper divider based on the clock source and the resolution. If it is set to `0`, the driver will pick an appropriate resolution on its own, and you can subsequently view the current timer resolution via `mcpwm_capture_timer_get_resolution()`.

Note

In ESP32, `mcpwm_capture_timer_config_t::resolution_hz` parameter is invalid, the capture timer resolution is always equal to the `MCPWM_CAPTURE_CLK_SRC_APB`.

The `mcpwm_new_capture_timer()` will return a pointer to the allocated capture timer object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there is no free capture timer left in the MCPWM group, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

Next, to allocate a capture channel, you can call the `mcpwm_new_capture_channel()` function, with a capture timer handle and configuration structure `mcpwm_capture_channel_config_t` as the parameter. The configuration structure is defined as:

- `mcpwm_capture_channel_config_t::intr_priority` sets the priority of the interrupt. If it is set to `0`, the driver will allocate an interrupt with a default priority. Otherwise, the driver will use the given priority.

- `mcpwm_capture_channel_config_t::gpio_num` sets the GPIO number used by the capture channel.

- `mcpwm_capture_channel_config_t::prescale` sets the prescaler of the input signal.

- `mcpwm_capture_channel_config_t::extra_capture_channel_flags::pos_edge` and `mcpwm_capture_channel_config_t::extra_capture_channel_flags::neg_edge` set whether to capture on the positive and/or falling edge of the input signal.

- `mcpwm_capture_channel_config_t::extra_capture_channel_flags::pull_up` and `mcpwm_capture_channel_config_t::extra_capture_channel_flags::pull_down` set whether to pull up and/or pull down the GPIO internally.

- `mcpwm_capture_channel_config_t::extra_capture_channel_flags::invert_cap_signal` sets whether to invert the capture signal.

The `mcpwm_new_capture_channel()` will return a pointer to the allocated capture channel object if the allocation succeeds. Otherwise, it will return an error code. Specifically, when there is no free capture channel left in the capture timer, this function will return the `ESP_ERR_NOT_FOUND` error.

On the contrary, calling `mcpwm_del_capture_channel()` and `mcpwm_del_capture_timer()` will free the allocated capture channel and timer object accordingly.

#### MCPWM Interrupt Priority

MCPWM allows configuring interrupts separately for timer, operator, comparator, fault, and capture events. The interrupt priority is determined by the respective `config_t::intr_priority`. Additionally, events within the same MCPWM group share a common interrupt source. When registering multiple interrupt events, the interrupt priorities need to remain consistent.

Note

When registering multiple interrupt events within an MCPWM group, the driver will use the interrupt priority of the first registered event as the MCPWM group's interrupt priority.

### Timer Operations and Events

#### Update Period

The timer period is initialized by the `mcpwm_timer_config_t::period_ticks` parameter in `mcpwm_timer_config_t`. You can update the period at runtime by calling `mcpwm_timer_set_period()` function. The new period will take effect based on how you set the `mcpwm_timer_config_t::flags::update_period_on_empty` and `mcpwm_timer_config_t::flags::update_period_on_sync` parameters in `mcpwm_timer_config_t`. If none of them are set, the timer period will take effect immediately.

#### Register Timer Event Callbacks

The MCPWM timer can generate different events at runtime. If you have some function that should be called when a particular event happens, you should hook your function to the interrupt service routine by calling `mcpwm_timer_register_event_callbacks()`. The callback function prototype is declared in `mcpwm_timer_event_cb_t`. All supported event callbacks are listed in the `mcpwm_timer_event_callbacks_t`:

- `mcpwm_timer_event_callbacks_t::on_full` sets the callback function for the timer when it counts to peak value.

- `mcpwm_timer_event_callbacks_t::on_empty` sets the callback function for the timer when it counts to zero.

- `mcpwm_timer_event_callbacks_t::on_stop` sets the callback function for the timer when it is stopped.

The callback functions above are called within the ISR context, so they should not attempt to block. For example, you may make sure that only FreeRTOS APIs with the `ISR` suffix are called within the function.

The parameter `user_data` of the `mcpwm_timer_register_event_callbacks()` function is used to save your own context. It is passed to each callback function directly.

This function will lazy the install interrupt service for the MCPWM timer without enabling it. It is only allowed to be called before `mcpwm_timer_enable()`, otherwise the `ESP_ERR_INVALID_STATE` error will be returned. See also Enable and Disable Timer for more information.

#### Enable and Disable Timer

Before doing IO control to the timer, you need to enable the timer first, by calling `mcpwm_timer_enable()`. This function:

- switches the timer state from init to enable.

- enables the interrupt service if it has been lazy installed by `mcpwm_timer_register_event_callbacks()`.

- acquire a proper power management lock if a specific clock source (e.g., PLL_160M clock) is selected. See also Power Management for more information.

On the contrary, calling `mcpwm_timer_disable()` will put the timer driver back to the init state, disable the interrupt service and release the power management lock.

#### Start and Stop Timer

The basic IO operation of a timer is to start and stop. Calling `mcpwm_timer_start_stop()` with different `mcpwm_timer_start_stop_cmd_t` commands can start the timer immediately or stop the timer at a specific event. What is more, you can even start the timer for only one round, which means, the timer will count to peak value or zero, and then stop itself.

#### Connect Timer with Operator

The allocated MCPWM timer should be connected with an MCPWM operator by calling `mcpwm_operator_connect_timer()`, so that the operator can take that timer as its time base, and generate the required PWM waves. Please make sure the MCPWM timer and operator are in the same group. Otherwise, this function will return the `ESP_ERR_INVALID_ARG` error.

### Comparator Operations and Events

#### Register Comparator Event Callbacks

The MCPWM comparator can inform you when the timer counter equals the compare value. If you have some function that should be called when this event happens, you should hook your function to the interrupt service routine by calling `mcpwm_comparator_register_event_callbacks()`. The callback function prototype is declared in `mcpwm_compare_event_cb_t`. All supported event callbacks are listed in the `mcpwm_comparator_event_callbacks_t`:

- `mcpwm_comparator_event_callbacks_t::on_reach` sets the callback function for the comparator when the timer counter equals the compare value.

The callback function provides event-specific data of type `mcpwm_compare_event_data_t` to you. The callback function is called within the ISR context, so it should not attempt to block. For example, you may make sure that only FreeRTOS APIs with the `ISR` suffix are called within the function.

The parameter `user_data` of `mcpwm_comparator_register_event_callbacks()` function is used to save your own context. It is passed to the callback function directly.

This function will lazy the installation of interrupt service for the MCPWM comparator, whereas the service can only be removed in `mcpwm_del_comparator`.

#### Set Compare Value

You can set the compare value for the MCPWM comparator at runtime by calling `mcpwm_comparator_set_compare_value()`. There are a few points to note:

- A new compare value might not take effect immediately. The update time for the compare value is set by `mcpwm_comparator_config_t::flags::update_cmp_on_tez` or `mcpwm_comparator_config_t::flags::update_cmp_on_tep` or `mcpwm_comparator_config_t::flags::update_cmp_on_sync`.

- Make sure the operator has connected to one MCPWM timer already by `mcpwm_operator_connect_timer()`. Otherwise, it will return the error code `ESP_ERR_INVALID_STATE`.

- The compare value should not exceed the timer's count peak, otherwise, the compare event will never get triggered.

### Generator Actions on Events

#### Set Generator Action on Timer Event

A single generator can be configured to perform multiple actions in response to different timer events. To achieve this, invoke `mcpwm_generator_set_action_on_timer_event()` for each desired event-action pair. The details of each action are specified using the `mcpwm_gen_timer_event_action_t` structure.

- `mcpwm_gen_timer_event_action_t::direction` specifies the timer direction. The supported directions are listed in `mcpwm_timer_direction_t`.

- `mcpwm_gen_timer_event_action_t::event` specifies the timer event. The supported timer events are listed in `mcpwm_timer_event_t`.

- `mcpwm_gen_timer_event_action_t::action` specifies the generator action to be taken. The supported actions are listed in `mcpwm_generator_action_t`.

There is a helper macro `MCPWM_GEN_TIMER_EVENT_ACTION` to simplify the construction of a timer event action entry.

#### Set Generator Action on Compare Event

A single generator can be configured to perform multiple actions in response to different compare events. To achieve this, invoke `mcpwm_generator_set_action_on_compare_event()` for each desired compare event and action pair. The specific action settings are encapsulated in the `mcpwm_gen_compare_event_action_t` structure.

- `mcpwm_gen_compare_event_action_t::direction` specifies the timer direction. The supported directions are listed in `mcpwm_timer_direction_t`.

- `mcpwm_gen_compare_event_action_t::comparator` specifies the comparator handle. See MCPWM Comparators for how to allocate a comparator.

- `mcpwm_gen_compare_event_action_t::action` specifies the generator action to be taken. The supported actions are listed in `mcpwm_generator_action_t`.

There is a helper macro `MCPWM_GEN_COMPARE_EVENT_ACTION` to simplify the construction of a compare event action entry.

#### Set Generator Action on Fault Event

A single generator can be configured to perform multiple actions in response to fault events. To achieve this, invoke `mcpwm_generator_set_action_on_fault_event()` for each desired action. The specific actions to be taken are described by the `mcpwm_gen_fault_event_action_t` structure.

- `mcpwm_gen_fault_event_action_t::direction` specifies the timer direction. The supported directions are listed in `mcpwm_timer_direction_t`.

- `mcpwm_gen_fault_event_action_t::fault` specifies the fault used for the trigger. See MCPWM Faults for how to allocate a fault.

- `mcpwm_gen_fault_event_action_t::action` specifies the generator action to be taken. The supported actions are listed in `mcpwm_generator_action_t`.

When no free trigger slot is left in the operator to which the generator belongs, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

The trigger only support GPIO fault. when the input is not a GPIO fault, this function will return the `ESP_ERR_NOT_SUPPORTED` error.

There is a helper macro `MCPWM_GEN_FAULT_EVENT_ACTION` to simplify the construction of a trigger event action entry.

#### Set Generator Action on Sync Event

A single generator can be configured to perform multiple actions in response to different synchronization events. This is achieved by invoking `mcpwm_generator_set_action_on_sync_event()` for each desired event-action pair. The specific action to be taken for each synchronization event is described by the `mcpwm_gen_sync_event_action_t` structure.

- `mcpwm_gen_sync_event_action_t::direction` specifies the timer direction. The supported directions are listed in `mcpwm_timer_direction_t`.

- `mcpwm_gen_sync_event_action_t::sync` specifies the sync source used for the trigger. See MCPWM Sync Sources for how to allocate a sync source.

- `mcpwm_gen_sync_event_action_t::action` specifies the generator action to be taken. The supported actions are listed in `mcpwm_generator_action_t`.

When no free trigger slot is left in the operator to which the generator belongs, this function will return the `ESP_ERR_NOT_FOUND` error. [1]

The trigger only support one sync action, regardless of the kinds. When set sync actions more than once, this function will return the `ESP_ERR_INVALID_STATE` error.

There is a helper macro `MCPWM_GEN_SYNC_EVENT_ACTION` to simplify the construction of a trigger event action entry.

### Generator Configurations for Classical PWM Waveforms

This section will demonstrate the classical PWM waveforms that can be generated by the pair of generators. The code snippet that is used to generate the waveforms is also provided below the diagram. Some general summary:

- The Symmetric or Asymmetric of the waveforms is determined by the count mode of the MCPWM timer.

- The active level of the waveform pair is determined by the level of the PWM with a smaller duty cycle.

- The period of the PWM waveform is determined by the timer's period and count mode.

- The duty cycle of the PWM waveform is determined by the generator's various action combinations.

#### Single Edge Asymmetric Waveform - Active High

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(genb,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpb, MCPWM_GEN_ACTION_LOW)));
    }

#### Single Edge Asymmetric Waveform - Active Low

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(genb,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpb, MCPWM_GEN_ACTION_HIGH)));
    }

#### Pulse Placement Asymmetric Waveform

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpb, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(genb,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_TOGGLE)));
    }

#### Dual Edge Asymmetric Waveform - Active Low

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, cmpb, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(genb,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(genb,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_GEN_ACTION_HIGH)));
    }

#### Dual Edge Symmetric Waveform - Active Low

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, cmpa, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpb, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, cmpb, MCPWM_GEN_ACTION_LOW)));
    }

#### Dual Edge Symmetric Waveform - Complementary

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, cmpa, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpb, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, cmpb, MCPWM_GEN_ACTION_HIGH)));
    }

### Dead Time

In power electronics, the rectifier and inverter are commonly used. This requires the use of a rectifier bridge and an inverter bridge. Each bridge arm has two power electronic devices, such as MOSFET, IGBT, etc. The two MOSFETs on the same arm can not conduct at the same time, otherwise there will be a short circuit. The fact is that, although the PWM wave shows it is turning off the switch, the MOSFET still needs a small time window to make that happen. This requires an extra delay to be added to the existing PWM wave generated by setting Generator Actions on Events.

The dead time driver works like a decorator. This is also reflected in the function parameters of `mcpwm_generator_set_dead_time()`, where it takes the primary generator handle (`in_generator`), and returns a new generator (`out_generator`) after applying the dead time. Please note, if the `out_generator` and `in_generator` are the same, it means you are adding the time delay to the PWM waveform in an "in-place" fashion. In turn, if the `out_generator` and `in_generator` are different, it means you are deriving a new PWM waveform from the existing `in_generator`.

Dead time specific configuration is listed in the `mcpwm_dead_time_config_t` structure:

- `mcpwm_dead_time_config_t::posedge_delay_ticks` and `mcpwm_dead_time_config_t::negedge_delay_ticks` set the number of ticks to delay the PWM waveform on the rising and falling edge. Specifically, setting both of them to zero means bypassing the dead time module. The resolution of the dead time tick is the same as the timer that is connected with the operator by `mcpwm_operator_connect_timer()`.

- `mcpwm_dead_time_config_t::invert_output` sets whether to invert the signal after applying the dead time, which can be used to control the delay edge polarity.

Warning

Due to the hardware limitation, one delay module (either `posedge delay` or `negedge delay`) can not be applied to multiple MCPWM generators at the same time. e.g., the following configuration is invalid:

    mcpwm_dead_time_config_t dt_config = {
        .posedge_delay_ticks = 10,
    };
    // Set posedge delay to generator A
    mcpwm_generator_set_dead_time(mcpwm_gen_a, mcpwm_gen_a, &dt_config);
    // NOTE: This is invalid, you can not apply the posedge delay to another generator
    mcpwm_generator_set_dead_time(mcpwm_gen_b, mcpwm_gen_b, &dt_config);

However, you can apply `posedge delay` to generator A and `negedge delay` to generator B. You can also set both `posedge delay` and `negedge delay` for generator B, while letting generator A bypass the dead time module. Note that if `negedge delay` and `posedge delay` are both set for generator A, generator B will not be available. Where generator A is the first generator requested through the operator handle and generator B is the second generator requested through an operator handle.

Note

It is also possible to generate the required dead time by setting Generator Actions on Events, especially by controlling edge placement using different comparators. However, if the more classical edge delay-based dead time with polarity control is required, then the dead time submodule should be used.

### Dead Time Configurations for Classical PWM Waveforms

This section demonstrates the classical PWM waveforms that can be generated by the dead time submodule. The code snippet that is used to generate the waveforms is also provided below the diagram.

#### Active High Complementary

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW)));
    }

    static void dead_time_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb)
    {
        mcpwm_dead_time_config_t dead_time_config = {
            .posedge_delay_ticks = 50,
            .negedge_delay_ticks = 0
        };
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
        dead_time_config.posedge_delay_ticks = 0;
        dead_time_config.negedge_delay_ticks = 100;
        dead_time_config.flags.invert_output = true;
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, genb, &dead_time_config));
    }

#### Active Low Complementary

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW)));
    }

    static void dead_time_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb)
    {
        mcpwm_dead_time_config_t dead_time_config = {
            .posedge_delay_ticks = 50,
            .negedge_delay_ticks = 0,
            .flags.invert_output = true
        };
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
        dead_time_config.posedge_delay_ticks = 0;
        dead_time_config.negedge_delay_ticks = 100;
        dead_time_config.flags.invert_output = false;
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, genb, &dead_time_config));
    }

#### Active High

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW)));
    }

    static void dead_time_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb)
    {
        mcpwm_dead_time_config_t dead_time_config = {
            .posedge_delay_ticks = 50,
            .negedge_delay_ticks = 0,
        };
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
        dead_time_config.posedge_delay_ticks = 0;
        dead_time_config.negedge_delay_ticks = 100;
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, genb, &dead_time_config));
    }

#### Active Low

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW)));
    }

    static void dead_time_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb)
    {
        mcpwm_dead_time_config_t dead_time_config = {
            .posedge_delay_ticks = 50,
            .negedge_delay_ticks = 0,
            .flags.invert_output = true
        };
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
        dead_time_config.posedge_delay_ticks = 0;
        dead_time_config.negedge_delay_ticks = 100;
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, genb, &dead_time_config));
    }

#### Rising Delay on PWMA and Bypass Dead Time for PWMB

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(genb,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpb, MCPWM_GEN_ACTION_LOW)));
    }

    static void dead_time_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb)
    {
        mcpwm_dead_time_config_t dead_time_config = {
            .posedge_delay_ticks = 50,
            .negedge_delay_ticks = 0,
        };
        // apply deadtime to generator_a
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
        // bypass deadtime module for generator_b
        dead_time_config.posedge_delay_ticks = 0;
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(genb, genb, &dead_time_config));
    }

#### Falling Delay on PWMB and Bypass Dead Time for PWMA

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(genb,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpb, MCPWM_GEN_ACTION_LOW)));
    }

    static void dead_time_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb)
    {
        mcpwm_dead_time_config_t dead_time_config = {
            .posedge_delay_ticks = 0,
            .negedge_delay_ticks = 0,
        };
        // generator_a bypass the deadtime module (no delay)
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
        // apply dead time to generator_b
        dead_time_config.negedge_delay_ticks = 50;
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(genb, genb, &dead_time_config));

    }

#### Rising and Falling Delay on PWMB and Bypass Dead Time for PWMA

    static void gen_action_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb, mcpwm_cmpr_handle_t cmpa, mcpwm_cmpr_handle_t cmpb)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(gena,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(gena,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(genb,
                        MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(genb,
                        MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, cmpb, MCPWM_GEN_ACTION_LOW)));
    }

    static void dead_time_config(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb)
    {
        mcpwm_dead_time_config_t dead_time_config = {
            .posedge_delay_ticks = 0,
            .negedge_delay_ticks = 0,
        };
        // generator_a bypass the deadtime module (no delay)
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
        // apply dead time on both edge for generator_b
        dead_time_config.negedge_delay_ticks = 50;
        dead_time_config.posedge_delay_ticks = 50;
        ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(genb, genb, &dead_time_config));
    }

### Carrier Modulation

The MCPWM operator has a carrier submodule that can be used if galvanic isolation from the motor driver is required (e.g., isolated digital power application) by passing the PWM output signals through transformers. Any of the PWM output signals may be at 100% duty and not changing whenever a motor is required to run steadily at the full load. Coupling with non-alternating signals with a transformer is problematic, so the signals are modulated by the carrier submodule to create an AC waveform, to make the coupling possible.

To configure the carrier submodule, you can call `mcpwm_operator_apply_carrier()`, and provide configuration structure `mcpwm_carrier_config_t`:

- `mcpwm_carrier_config_t::clk_src` sets the clock source of the carrier.

- `mcpwm_carrier_config_t::frequency_hz` indicates carrier frequency in Hz. For more information, please refer to Resolution Configuration.

- `mcpwm_carrier_config_t::duty_cycle` indicates the duty cycle of the carrier. Note that, there are only 7 supported duty cycles: 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875.

- `mcpwm_carrier_config_t::first_pulse_duration_us` indicates the duration of the first pulse in microseconds. The resolution of the first pulse duration is determined by the carrier frequency you set in the `mcpwm_carrier_config_t::frequency_hz`. The first pulse duration can not be zero, and it has to be at least one period of the carrier. A longer pulse width can help conduct the inductance quicker.

- `mcpwm_carrier_config_t::invert_before_modulate` and `mcpwm_carrier_config_t::invert_after_modulate` set whether to invert the carrier output before and after modulation.

Specifically, the carrier submodule can be disabled by calling `mcpwm_operator_apply_carrier()` with a `NULL` configuration.

### Faults and Brake Actions

The MCPWM operator is able to sense external signals with information about the failure of the motor, the power driver or any other device connected. These failure signals are encapsulated into MCPWM fault objects.

You should determine possible failure modes of the motor and what action should be performed on detection of a particular fault, e.g., drive all outputs low for a brushed motor, lock current state for a stepper motor, etc. Because of this action, the motor should be put into a safe state to reduce the likelihood of damage caused by the fault.

#### Set Operator Brake Mode on Fault

The way that MCPWM operator reacts to the fault is called Brake. The MCPWM operator can be configured to perform different brake modes for each fault object by calling `mcpwm_operator_set_brake_on_fault()`. Specific brake configuration is passed as a structure `mcpwm_brake_config_t`:

- `mcpwm_brake_config_t::fault` sets which fault the operator should react to.

- `mcpwm_brake_config_t::brake_mode` sets the brake mode that should be used for the fault. The supported brake modes are listed in the `mcpwm_operator_brake_mode_t`. For `MCPWM_OPER_BRAKE_MODE_CBC` mode, the operator recovers itself automatically as long as the fault disappears. You can specify the recovery time in `mcpwm_brake_config_t::cbc_recover_on_tez` and `mcpwm_brake_config_t::cbc_recover_on_tep`. For `MCPWM_OPER_BRAKE_MODE_OST` mode, the operator can not recover even though the fault disappears. You have to call `mcpwm_operator_recover_from_fault()` to manually recover it.

#### Set Generator Action on Brake Event

A single generator can be configured to perform multiple actions in response to brake events. To achieve this, invoke `mcpwm_generator_set_action_on_brake_event()` for each desired action. The specific actions available for configuration are defined in `mcpwm_gen_brake_event_action_t`.

- `mcpwm_gen_brake_event_action_t::direction` specifies the timer direction. The supported directions are listed in `mcpwm_timer_direction_t`.

- `mcpwm_gen_brake_event_action_t::brake_mode` specifies the brake mode. The supported brake modes are listed in the `mcpwm_operator_brake_mode_t`.

- `mcpwm_gen_brake_event_action_t::action` specifies the generator action to be taken. The supported actions are listed in `mcpwm_generator_action_t`.

There is a helper macro `MCPWM_GEN_BRAKE_EVENT_ACTION` to simplify the construction of a brake event action entry.

#### Register Fault Event Callbacks

The MCPWM fault detector can inform you when it detects a valid fault or a fault signal disappears. If you have some function that should be called when such an event happens, you should hook your function to the interrupt service routine by calling `mcpwm_fault_register_event_callbacks()`. The callback function prototype is declared in `mcpwm_fault_event_cb_t`. All supported event callbacks are listed in the `mcpwm_fault_event_callbacks_t`:

- `mcpwm_fault_event_callbacks_t::on_fault_enter` sets the callback function that will be called when a fault is detected.

- `mcpwm_fault_event_callbacks_t::on_fault_exit` sets the callback function that will be called when a fault is cleared.

The callback function is called within the ISR context, so it should not attempt to block. For example, you may make sure that only FreeRTOS APIs with the `ISR` suffix are called within the function.

The parameter `user_data` of `mcpwm_fault_register_event_callbacks()` function is used to save your own context. It is passed to the callback function directly.

This function will lazy the install interrupt service for the MCPWM fault, whereas the service can only be removed in `mcpwm_del_fault`.

#### Register Brake Event Callbacks

The MCPWM operator can inform you when it is going to take a brake action. If you have some function that should be called when this event happens, you should hook your function to the interrupt service routine by calling `mcpwm_operator_register_event_callbacks()`. The callback function prototype is declared in `mcpwm_brake_event_cb_t`. All supported event callbacks are listed in the `mcpwm_operator_event_callbacks_t`:

- `mcpwm_operator_event_callbacks_t::on_brake_cbc` sets the callback function that will be called when the operator is going to take a CBC action.

- `mcpwm_operator_event_callbacks_t::on_brake_ost` sets the callback function that will be called when the operator is going to take an OST action.

The callback function is called within the ISR context, so it should not attempt to block. For example, you may make sure that only FreeRTOS APIs with the `ISR` suffix are called within the function.

The parameter `user_data` of the `mcpwm_operator_register_event_callbacks()` function is used to save your own context. It will be passed to the callback function directly.

This function will lazy the install interrupt service for the MCPWM operator, whereas the service can only be removed in `mcpwm_del_operator`.

### Generator Force Actions

Software can override generator output level at runtime, by calling `mcpwm_generator_set_force_level()`. The software force level always has a higher priority than other event actions set in e.g., `mcpwm_generator_set_action_on_timer_event()`.

- Set the `level` to -1 means to disable the force action, and the generator's output level will be controlled by the event actions again.

- Set the `hold_on` to true, and the force output level will keep alive until it is removed by assigning `level` to -1.

- Set the `hole_on` to false, the force output level will only be active for a short time, and any upcoming event can override it.

### Synchronization

When a sync signal is taken by the MCPWM timer, the timer will be forced into a predefined phase, where the phase is determined by count value and count direction. You can set the sync phase by calling `mcpwm_timer_set_phase_on_sync()`. The sync phase configuration is defined in `mcpwm_timer_sync_phase_config_t` structure:

- `mcpwm_timer_sync_phase_config_t::sync_src` sets the sync signal source. See MCPWM Sync Sources for how to create a sync source object. Specifically, if this is set to `NULL`, the driver will disable the sync feature for the MCPWM timer.

- `mcpwm_timer_sync_phase_config_t::count_value` sets the count value to load when the sync signal is taken.

- `mcpwm_timer_sync_phase_config_t::direction` sets the count direction when the sync signal is taken.

Note

When the MCPWM timer is working in `MCPWM_TIMER_COUNT_MODE_UP_DOWN` mode, special attention needs to be taken. In this mode, counter range `[0 -> peak-1]` belongs to the increment phase, and counter range `[peak -> 1]` belongs to the decrement phase. Thus if you set the `mcpwm_timer_sync_phase_config_t::count_value` to zero, you may also want to set the `mcpwm_timer_sync_phase_config_t::direction` to `MCPWM_TIMER_DIRECTION_UP`. Otherwise, the timer will be continue with the decrement phase, and the count value underflows to `peak`.

Likewise, the MCPWM Capture Timer can be synced as well. You can set the sync phase for the capture timer by calling `mcpwm_capture_timer_set_phase_on_sync()`. The sync phase configuration is defined in `mcpwm_capture_timer_sync_phase_config_t` structure:

- `mcpwm_capture_timer_sync_phase_config_t::sync_src` sets the sync signal source. See MCPWM Sync Sources for how to create a sync source object. Specifically, if this is set to `NULL`, the driver will disable the sync feature for the MCPWM capture timer.

- `mcpwm_capture_timer_sync_phase_config_t::count_value` sets the count value to load when the sync signal is taken.

- `mcpwm_capture_timer_sync_phase_config_t::direction` sets the count direction when the sync signal is taken. Note that, different from MCPWM Timer, the capture timer can only support one count direction: `MCPWM_TIMER_DIRECTION_UP`.

#### Sync Timers by GPIO

GPIO Sync All MCPWM Timers

    static void example_setup_sync_strategy(mcpwm_timer_handle_t timers[])
    {
        mcpwm_sync_handle_t gpio_sync_source = NULL;
        mcpwm_gpio_sync_src_config_t gpio_sync_config = {
            .group_id = 0,              // GPIO fault should be in the same group of the above timers
            .gpio_num = EXAMPLE_SYNC_GPIO,
            .flags.active_neg = false,  // By default, a posedge pulse can trigger a sync event
        };
        ESP_ERROR_CHECK(mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync_source));

        mcpwm_timer_sync_phase_config_t sync_phase_config = {
            .count_value = 0,                      // sync phase: target count value
            .direction = MCPWM_TIMER_DIRECTION_UP, // sync phase: count direction
            .sync_src = gpio_sync_source,          // sync source
        };
        for (int i = 0; i < 3; i++) {
            ESP_ERROR_CHECK(mcpwm_timer_set_phase_on_sync(timers[i], &sync_phase_config));
        }
    }

### Capture

The basic functionality of MCPWM capture is to record the time when any pulse edge of the capture signal turns active. Then you can get the pulse width and convert it into other physical quantities like distance or speed in the capture callback function. For example, in the BLDC (Brushless DC, see figure below) scenario, you can use the capture submodule to sense the rotor position from the Hall sensor.

MCPWM BLDC with Hall Sensor

The capture timer is usually connected to several capture channels. Please refer to MCPWM Capture Timer and Channels for more information about resource allocation.

#### Register Capture Event Callbacks

The MCPWM capture channel can inform you when there is a valid edge detected on the signal. You have to register a callback function to get the timer count value of the captured moment, by calling `mcpwm_capture_channel_register_event_callbacks()`. The callback function prototype is declared in `mcpwm_capture_event_cb_t`. All supported capture callbacks are listed in the `mcpwm_capture_event_callbacks_t`:

- `mcpwm_capture_event_callbacks_t::on_cap` sets the callback function for the capture channel when a valid edge is detected.

The callback function provides event-specific data of type `mcpwm_capture_event_data_t`, so that you can get the edge of the capture signal in `mcpwm_capture_event_data_t::cap_edge` and the count value of that moment in `mcpwm_capture_event_data_t::cap_value`. To convert the capture count into a timestamp, you need to know the resolution of the capture timer by calling `mcpwm_capture_timer_get_resolution()`.

The callback function is called within the ISR context, so it should not attempt to block. For example, you may make sure that only FreeRTOS APIs with the `ISR` suffix are called within the function.

The parameter `user_data` of `mcpwm_capture_channel_register_event_callbacks()` function is used to save your context. It is passed to the callback function directly.

This function will lazy install interrupt service for the MCPWM capture channel, whereas the service can only be removed in `mcpwm_del_capture_channel`.

#### Enable and Disable Capture Channel

The capture channel is not enabled after allocation by `mcpwm_new_capture_channel()`. You should call `mcpwm_capture_channel_enable()` and `mcpwm_capture_channel_disable()` accordingly to enable or disable the channel. If the interrupt service is lazy installed during registering event callbacks for the channel in `mcpwm_capture_channel_register_event_callbacks()`, `mcpwm_capture_channel_enable()` will enable the interrupt service as well.

#### Enable and Disable Capture Timer

Before doing IO control to the capture timer, you need to enable the timer first, by calling `mcpwm_capture_timer_enable()`. Internally, this function:

- switches the capture timer state from init to enable.

- acquires a proper power management lock if a specific clock source (e.g., APB clock) is selected. See also Power Management for more information.

On the contrary, calling `mcpwm_capture_timer_disable()` will put the timer driver back to init state, and release the power management lock.

#### Start and Stop Capture Timer

The basic IO operation of a capture timer is to start and stop. Calling `mcpwm_capture_timer_start()` can start the timer and calling `mcpwm_capture_timer_stop()` can stop the timer immediately.

#### Trigger a Software Capture Event

Sometimes, the software also wants to trigger a "fake" capture event. The `mcpwm_capture_channel_trigger_soft_catch()` is provided for that purpose. Please note that, even though it is a "fake" capture event, it can still cause an interrupt, thus your capture event callback function gets invoked as well.

#### Get the Last Captured Value

If you don't want to process the captured value in the capture event callback function, but want to process it in other places, you can call `mcpwm_capture_get_latched_value()` to get the last captured value.

### Power Management

When power management is enabled (i.e., CONFIG_PM_ENABLE is on), the system will adjust the PLL and APB frequency before going into Light-sleep, thus potentially changing the period of an MCPWM timers' counting step and leading to inaccurate time-keeping.

However, the driver can prevent the system from going into Light-sleep by acquiring a power management lock of type `ESP_PM_NO_LIGHT_SLEEP`. Whenever the driver creates an MCPWM timer instance that has selected PLL as its clock source, the driver guarantees that the power management lock is acquired when enabling the timer by `mcpwm_timer_enable()`. On the contrary, the driver releases the lock when `mcpwm_timer_disable()` is called for that timer.

Likewise, whenever the driver creates an MCPWM capture timer instance, the driver guarantees that the power management lock is acquired when enabling the timer by `mcpwm_capture_timer_enable()`. And releases the lock in `mcpwm_capture_timer_disable()`.

### Resolution Configuration

The MCPWM group has clock dividers and some sub-modules will have their own clock dividers. The final clock frequency of the sub-module depends on the group clock divider and its own divider (if any). The group clock divider affects all submodules. When configuring the clock frequency (also called resolution) of an MCPWM submodule, the driver sets the divider according to the following rules:

1. If the clock frequency of the submodule can be divisible by the clock source, the frequency of the submodule is prioritized to ensure the accuracy of the submodule.

2. If it cannot be divisible by the clock source, the group clock is guaranteed to have the highest frequency possible, and the submodule frequency is adjusted to the closest frequency that can be divisible by the clock source.

When multiple MCPWM submodules coexist, you need to consider whether there is a clock divider conflict. When there is a group clock divider conflict, try adjusting the submodule allocation order. See [TRM] for details on group frequency divider and submodule frequency divider ranges.

### IRAM Safe

By default, the MCPWM interrupt will be deferred when the Cache is disabled for reasons like writing/erasing Flash. Thus the event callback functions will not get executed in time, which is not expected in a real-time application.

There is a Kconfig option CONFIG_MCPWM_ISR_CACHE_SAFE that:

- enables the interrupt to be serviced even when the cache is disabled

- places all functions used by the ISR into IRAM [2]

- places the driver object into DRAM (in case it is mapped to PSRAM by accident)

This allows the interrupt to run while the cache is disabled but comes at the cost of increased IRAM consumption.

There is another Kconfig option CONFIG_MCPWM_CTRL_FUNC_IN_IRAM that can put commonly used IO control functions into IRAM as well. So, these functions can also be executable when the cache is disabled. The IO control function is as follows:

- `mcpwm_comparator_set_compare_value()`

- `mcpwm_timer_set_period()`

### Thread Safety

The factory functions like `mcpwm_new_timer()` are guaranteed to be thread-safe by the driver, which means, you can call it from different RTOS tasks without protection by extra locks.

The following function is allowed to run under the ISR context, as the driver uses a critical section to prevent them from being called concurrently in the task and ISR.

- `mcpwm_comparator_set_compare_value()`

- `mcpwm_timer_set_period()`

Other functions that are not related to Resource Allocation and Initialization, are not thread-safe. Thus, you should avoid calling them in different tasks without mutex protection.

### Kconfig Options

- CONFIG_MCPWM_ISR_CACHE_SAFE controls whether the default ISR handler can work when the cache is disabled, see IRAM Safe for more information.

- CONFIG_MCPWM_CTRL_FUNC_IN_IRAM controls where to place the MCPWM control functions (IRAM or flash), see IRAM Safe for more information.

- CONFIG_MCPWM_ENABLE_DEBUG_LOG is used to enable the debug log output. Enabling this option will increase the firmware binary size.

## Application Examples

- peripherals/mcpwm/mcpwm_bdc_speed_control demonstrates how to drive a brushed DC motor using two specific PWM signals, measure the motor speed with a photoelectric encoder, and maintain a stable motor speed using a simple PID algorithm.

- peripherals/mcpwm/mcpwm_bldc_hall_control demonstrates how to use the MCPWM peripheral to control a BLDC motor using a six-step commutation scheme, with the motor's spin direction and speed being adjusted based on the readings from a Hall sensor.

- peripherals/mcpwm/mcpwm_capture_hc_sr04 demonstrates how to use the MCPWM peripheral's capture module to decode the pulse width signals from an HC-SR04 sonar sensor, which can measure distance based on the width of the pulse.

- peripherals/mcpwm/mcpwm_foc_svpwm_open_loop demonstrates how to use the MCPWM peripheral to generate three pairs of PWM signals for Field-Oriented Control (FOC), which can be used to drive a BLDC or PMSM motor, or a three-phase power inverter, using an open-loop FOC algorithm.

- peripherals/mcpwm/mcpwm_servo_control demonstrates how to control a typical RC Servo by sending a PWM signal using the MCPWM driver, with the servo rotating from -60° to 60° and then turning back again.

- peripherals/mcpwm/mcpwm_sync demonstrates how to generate three PWMs in perfect synchronization using MCPWM timers, with options to synchronize the timers via GPIO, Timer TEZ, or software.

## API Reference

MCPWM APIs are divided into the following sections:

- Timer API

- Operator API

- Comparator API

- Generator API

- Fault API

- Sync API

- Capture API

- ETM API

- Driver Types

- HAL Types

### Timer API

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_timer.h

- This header file can be included with:

  >     #include "driver/mcpwm_timer.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Functions

esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle_t *ret_timer)

  Create MCPWM timer.

  Parameters:

    - config -- [in] MCPWM timer configuration

    - ret_timer -- [out] Returned MCPWM timer handle

  Returns:

    - ESP_OK: Create MCPWM timer successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM timer failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM timer failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM timer failed because all hardware timers are used up and no more free one

    - ESP_FAIL: Create MCPWM timer failed because of other error

esp_err_t mcpwm_del_timer(mcpwm_timer_handle_t timer)

  Delete MCPWM timer.

  Parameters:

    timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer()`

  Returns:

    - ESP_OK: Delete MCPWM timer successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM timer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Delete MCPWM timer failed because timer is not in init state

    - ESP_FAIL: Delete MCPWM timer failed because of other error

esp_err_t mcpwm_timer_set_period(mcpwm_timer_handle_t timer, uint32_t period_ticks)

  Set a new period for MCPWM timer.

  Note

  If `mcpwm_timer_config_t::update_period_on_empty` and `mcpwm_timer_config_t::update_period_on_sync` are not set, the new period will take effect immediately. Otherwise, the new period will take effect when timer counts to zero or on sync event.

  Note

  You may need to use `mcpwm_comparator_set_compare_value` to set a new compare value for MCPWM comparator in order to keep the same PWM duty cycle.

  Parameters:

    - timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer`

    - period_ticks -- [in] New period in count ticks

  Returns:

    - ESP_OK: Set new period for MCPWM timer successfully

    - ESP_ERR_INVALID_ARG: Set new period for MCPWM timer failed because of invalid argument

    - ESP_FAIL: Set new period for MCPWM timer failed because of other error

esp_err_t mcpwm_timer_enable(mcpwm_timer_handle_t timer)

  Enable MCPWM timer.

  Parameters:

    timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer()`

  Returns:

    - ESP_OK: Enable MCPWM timer successfully

    - ESP_ERR_INVALID_ARG: Enable MCPWM timer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Enable MCPWM timer failed because timer is enabled already

    - ESP_FAIL: Enable MCPWM timer failed because of other error

esp_err_t mcpwm_timer_disable(mcpwm_timer_handle_t timer)

  Disable MCPWM timer.

  Parameters:

    timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer()`

  Returns:

    - ESP_OK: Disable MCPWM timer successfully

    - ESP_ERR_INVALID_ARG: Disable MCPWM timer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Disable MCPWM timer failed because timer is disabled already

    - ESP_FAIL: Disable MCPWM timer failed because of other error

esp_err_t mcpwm_timer_start_stop(mcpwm_timer_handle_t timer, mcpwm_timer_start_stop_cmd_t command)

  Send specific start/stop commands to MCPWM timer.

  Parameters:

    - timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer()`

    - command -- [in] Supported command list for MCPWM timer

  Returns:

    - ESP_OK: Start or stop MCPWM timer successfully

    - ESP_ERR_INVALID_ARG: Start or stop MCPWM timer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Start or stop MCPWM timer failed because timer is not enabled

    - ESP_FAIL: Start or stop MCPWM timer failed because of other error

esp_err_t mcpwm_timer_register_event_callbacks(mcpwm_timer_handle_t timer, const mcpwm_timer_event_callbacks_t *cbs, void *user_data)

  Set event callbacks for MCPWM timer.

  Note

  The first call to this function needs to be before the call to `mcpwm_timer_enable`

  Note

  User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.

  Parameters:

    - timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer()`

    - cbs -- [in] Group of callback functions

    - user_data -- [in] User data, which will be passed to callback functions directly

  Returns:

    - ESP_OK: Set event callbacks successfully

    - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Set event callbacks failed because timer is not in init state

    - ESP_FAIL: Set event callbacks failed because of other error

esp_err_t mcpwm_timer_set_phase_on_sync(mcpwm_timer_handle_t timer, const mcpwm_timer_sync_phase_config_t *config)

  Set sync phase for MCPWM timer.

  Parameters:

    - timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer()`

    - config -- [in] MCPWM timer sync phase configuration

  Returns:

    - ESP_OK: Set sync phase for MCPWM timer successfully

    - ESP_ERR_INVALID_ARG: Set sync phase for MCPWM timer failed because of invalid argument

    - ESP_FAIL: Set sync phase for MCPWM timer failed because of other error

### Structures

struct mcpwm_timer_event_callbacks_t

  Group of supported MCPWM timer event callbacks.

  Note

  The callbacks are all running under ISR environment

  Public Members

  mcpwm_timer_event_cb_t on_full

    callback function when MCPWM timer counts to peak value

  mcpwm_timer_event_cb_t on_empty

    callback function when MCPWM timer counts to zero

  mcpwm_timer_event_cb_t on_stop

    callback function when MCPWM timer stops

struct mcpwm_timer_config_t

  MCPWM timer configuration.

  Public Members

  int group_id

    Specify from which group to allocate the MCPWM timer

  mcpwm_timer_clock_source_t clk_src

    MCPWM timer clock source

  uint32_t resolution_hz

    Counter resolution in Hz The step size of each count tick equals to (1 / resolution_hz) seconds

  mcpwm_timer_count_mode_t count_mode

    Count mode

  uint32_t period_ticks

    Number of count ticks within a period. For up-down mode, the timer peak value is half of the period_ticks

  int intr_priority

    MCPWM timer interrupt priority, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)

  struct mcpwm_timer_config_t::extra_mcpwm_timer_flags flags

    Extra configuration flags for timer

  struct extra_mcpwm_timer_flags

    Extra configuration flags for MCPWM timer.

    Public Members

    uint32_t update_period_on_empty

      Whether to update period when timer counts to zero

    uint32_t update_period_on_sync

      Whether to update period on sync event

    uint32_t allow_pd

      Set to allow power down. When this flag set, the driver will backup/restore the MCPWM registers before/after entering/exist sleep mode. By this approach, the system can power off MCPWM's power domain. This can save power, but at the expense of more RAM being consumed.

struct mcpwm_timer_sync_phase_config_t

  MCPWM Timer sync phase configuration.

  Public Members

  mcpwm_sync_handle_t sync_src

    The sync event source. Set to NULL will disable the timer being synced by others

  uint32_t count_value

    The count value that should lock to upon sync event

  mcpwm_timer_direction_t direction

    The count direction that should lock to upon sync event

### Operator API

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_oper.h

- This header file can be included with:

  >     #include "driver/mcpwm_oper.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Functions

esp_err_t mcpwm_new_operator(const mcpwm_operator_config_t *config, mcpwm_oper_handle_t *ret_oper)

  Create MCPWM operator.

  Parameters:

    - config -- [in] MCPWM operator configuration

    - ret_oper -- [out] Returned MCPWM operator handle

  Returns:

    - ESP_OK: Create MCPWM operator successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM operator failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM operator failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM operator failed because can't find free resource

    - ESP_FAIL: Create MCPWM operator failed because of other error

esp_err_t mcpwm_del_operator(mcpwm_oper_handle_t oper)

  Delete MCPWM operator.

  Parameters:

    oper -- [in] MCPWM operator, allocated by `mcpwm_new_operator()`

  Returns:

    - ESP_OK: Delete MCPWM operator successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM operator failed because of invalid argument

    - ESP_FAIL: Delete MCPWM operator failed because of other error

esp_err_t mcpwm_operator_connect_timer(mcpwm_oper_handle_t oper, mcpwm_timer_handle_t timer)

  Connect MCPWM operator and timer, so that the operator can be driven by the timer.

  Parameters:

    - oper -- [in] MCPWM operator handle, allocated by `mcpwm_new_operator()`

    - timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer()`

  Returns:

    - ESP_OK: Connect MCPWM operator and timer successfully

    - ESP_ERR_INVALID_ARG: Connect MCPWM operator and timer failed because of invalid argument

    - ESP_FAIL: Connect MCPWM operator and timer failed because of other error

esp_err_t mcpwm_operator_set_brake_on_fault(mcpwm_oper_handle_t oper, const mcpwm_brake_config_t *config)

  Set brake method for MCPWM operator.

  Parameters:

    - oper -- [in] MCPWM operator, allocated by `mcpwm_new_operator()`

    - config -- [in] MCPWM brake configuration

  Returns:

    - ESP_OK: Set trip for operator successfully

    - ESP_ERR_INVALID_ARG: Set trip for operator failed because of invalid argument

    - ESP_FAIL: Set trip for operator failed because of other error

esp_err_t mcpwm_operator_recover_from_fault(mcpwm_oper_handle_t oper, mcpwm_fault_handle_t fault)

  Try to make the operator recover from fault.

  Note

  To recover from fault or escape from trip, you make sure the fault signal has disappeared already. Otherwise the recovery can't succeed.

  Parameters:

    - oper -- [in] MCPWM operator, allocated by `mcpwm_new_operator()`

    - fault -- [in] MCPWM fault handle

  Returns:

    - ESP_OK: Recover from fault successfully

    - ESP_ERR_INVALID_ARG: Recover from fault failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Recover from fault failed because the fault source is still active

    - ESP_FAIL: Recover from fault failed because of other error

esp_err_t mcpwm_operator_register_event_callbacks(mcpwm_oper_handle_t oper, const mcpwm_operator_event_callbacks_t *cbs, void *user_data)

  Set event callbacks for MCPWM operator.

  Note

  User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.

  Parameters:

    - oper -- [in] MCPWM operator handle, allocated by `mcpwm_new_operator()`

    - cbs -- [in] Group of callback functions

    - user_data -- [in] User data, which will be passed to callback functions directly

  Returns:

    - ESP_OK: Set event callbacks successfully

    - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument

    - ESP_FAIL: Set event callbacks failed because of other error

esp_err_t mcpwm_operator_apply_carrier(mcpwm_oper_handle_t oper, const mcpwm_carrier_config_t *config)

  Apply carrier feature for MCPWM operator.

  Parameters:

    - oper -- [in] MCPWM operator, allocated by `mcpwm_new_operator()`

    - config -- [in] MCPWM carrier specific configuration

  Returns:

    - ESP_OK: Set carrier for operator successfully

    - ESP_ERR_INVALID_ARG: Set carrier for operator failed because of invalid argument

    - ESP_FAIL: Set carrier for operator failed because of other error

### Structures

struct mcpwm_operator_config_t

  MCPWM operator configuration.

  Public Members

  int group_id

    Specify from which group to allocate the MCPWM operator

  int intr_priority

    MCPWM operator interrupt priority, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)

  struct mcpwm_operator_config_t::extra_mcpwm_operator_flags flags

    Extra configuration flags for operator

  struct extra_mcpwm_operator_flags

    Extra configuration flags for operator.

    Public Members

    uint32_t update_gen_action_on_tez

      Whether to update generator action when timer counts to zero

    uint32_t update_gen_action_on_tep

      Whether to update generator action when timer counts to peak

    uint32_t update_gen_action_on_sync

      Whether to update generator action on sync event

    uint32_t update_dead_time_on_tez

      Whether to update dead time when timer counts to zero

    uint32_t update_dead_time_on_tep

      Whether to update dead time when timer counts to peak

    uint32_t update_dead_time_on_sync

      Whether to update dead time on sync event

struct mcpwm_brake_config_t

  MCPWM brake configuration structure.

  Public Members

  mcpwm_fault_handle_t fault

    Which fault causes the operator to brake

  mcpwm_operator_brake_mode_t brake_mode

    Brake mode

  uint32_t cbc_recover_on_tez

    Recovery CBC brake state on tez event

  uint32_t cbc_recover_on_tep

    Recovery CBC brake state on tep event

  struct mcpwm_brake_config_t flags

    Extra flags for brake configuration

struct mcpwm_operator_event_callbacks_t

  Group of supported MCPWM operator event callbacks.

  Note

  The callbacks are all running under ISR environment

  Public Members

  mcpwm_brake_event_cb_t on_brake_cbc

    callback function when mcpwm operator brakes in CBC

  mcpwm_brake_event_cb_t on_brake_ost

    callback function when mcpwm operator brakes in OST

struct mcpwm_carrier_config_t

  MCPWM carrier configuration structure.

  Public Members

  mcpwm_carrier_clock_source_t clk_src

    MCPWM carrier clock source

  uint32_t frequency_hz

    Carrier frequency in Hz

  uint32_t first_pulse_duration_us

    The duration of the first PWM pulse, in us

  float duty_cycle

    Carrier duty cycle

  uint32_t invert_before_modulate

    Invert the raw signal

  uint32_t invert_after_modulate

    Invert the modulated signal

  struct mcpwm_carrier_config_t flags

    Extra flags for carrier configuration

### Comparator API

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_cmpr.h

- This header file can be included with:

  >     #include "driver/mcpwm_cmpr.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Functions

esp_err_t mcpwm_new_comparator(mcpwm_oper_handle_t oper, const mcpwm_comparator_config_t *config, mcpwm_cmpr_handle_t *ret_cmpr)

  Create MCPWM comparator.

  Parameters:

    - oper -- [in] MCPWM operator, allocated by `mcpwm_new_operator()`, the new comparator will be allocated from this operator

    - config -- [in] MCPWM comparator configuration

    - ret_cmpr -- [out] Returned MCPWM comparator

  Returns:

    - ESP_OK: Create MCPWM comparator successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM comparator failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM comparator failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM comparator failed because can't find free resource

    - ESP_FAIL: Create MCPWM comparator failed because of other error

esp_err_t mcpwm_del_comparator(mcpwm_cmpr_handle_t cmpr)

  Delete MCPWM comparator.

  Parameters:

    cmpr -- [in] MCPWM comparator handle, allocated by `mcpwm_new_comparator()`

  Returns:

    - ESP_OK: Delete MCPWM comparator successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM comparator failed because of invalid argument

    - ESP_FAIL: Delete MCPWM comparator failed because of other error

esp_err_t mcpwm_comparator_register_event_callbacks(mcpwm_cmpr_handle_t cmpr, const mcpwm_comparator_event_callbacks_t *cbs, void *user_data)

  Set event callbacks for MCPWM comparator.

  Note

  User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.

  Parameters:

    - cmpr -- [in] MCPWM comparator handle, allocated by `mcpwm_new_comparator()`

    - cbs -- [in] Group of callback functions

    - user_data -- [in] User data, which will be passed to callback functions directly

  Returns:

    - ESP_OK: Set event callbacks successfully

    - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument

    - ESP_FAIL: Set event callbacks failed because of other error

esp_err_t mcpwm_comparator_set_compare_value(mcpwm_cmpr_handle_t cmpr, uint32_t cmp_ticks)

  Set MCPWM comparator's compare value.

  Parameters:

    - cmpr -- [in] MCPWM comparator handle, allocated by `mcpwm_new_comparator()`

    - cmp_ticks -- [in] The new compare value

  Returns:

    - ESP_OK: Set MCPWM compare value successfully

    - ESP_ERR_INVALID_ARG: Set MCPWM compare value failed because of invalid argument (e.g. the cmp_ticks is out of range)

    - ESP_ERR_INVALID_STATE: Set MCPWM compare value failed because the operator doesn't have a timer connected

    - ESP_FAIL: Set MCPWM compare value failed because of other error

### Structures

struct mcpwm_comparator_config_t

  MCPWM comparator configuration.

  Public Members

  int intr_priority

    MCPWM comparator interrupt priority, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)

  struct mcpwm_comparator_config_t::extra_mcpwm_comparator_flags flags

    Extra configuration flags for comparator

  struct extra_mcpwm_comparator_flags

    Extra configuration flags for comparator.

    Public Members

    uint32_t update_cmp_on_tez

      Whether to update compare value when timer count equals to zero (tez)

    uint32_t update_cmp_on_tep

      Whether to update compare value when timer count equals to peak (tep)

    uint32_t update_cmp_on_sync

      Whether to update compare value on sync event

struct mcpwm_comparator_event_callbacks_t

  Group of supported MCPWM compare event callbacks.

  Note

  The callbacks are all running under ISR environment

  Public Members

  mcpwm_compare_event_cb_t on_reach

    ISR callback function which would be invoked when counter reaches compare value

### Generator API

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_gen.h

- This header file can be included with:

  >     #include "driver/mcpwm_gen.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Functions

esp_err_t mcpwm_new_generator(mcpwm_oper_handle_t oper, const mcpwm_generator_config_t *config, mcpwm_gen_handle_t *ret_gen)

  Allocate MCPWM generator from given operator.

  Parameters:

    - oper -- [in] MCPWM operator, allocated by `mcpwm_new_operator()`

    - config -- [in] MCPWM generator configuration

    - ret_gen -- [out] Returned MCPWM generator

  Returns:

    - ESP_OK: Create MCPWM generator successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM generator failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM generator failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM generator failed because can't find free resource

    - ESP_FAIL: Create MCPWM generator failed because of other error

esp_err_t mcpwm_del_generator(mcpwm_gen_handle_t gen)

  Delete MCPWM generator.

  Parameters:

    gen -- [in] MCPWM generator handle, allocated by `mcpwm_new_generator()`

  Returns:

    - ESP_OK: Delete MCPWM generator successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM generator failed because of invalid argument

    - ESP_FAIL: Delete MCPWM generator failed because of other error

esp_err_t mcpwm_generator_set_force_level(mcpwm_gen_handle_t gen, int level, bool hold_on)

  Set force level for MCPWM generator.

  Note

  The force level will be applied to the generator immediately, regardless any other events that would change the generator's behaviour.

  Note

  If the `hold_on` is true, the force level will retain forever, until user removes the force level by setting the force level to `-1`.

  Note

  If the `hold_on` is false, the force level can be overridden by the next event action.

  Note

  The force level set by this function can be inverted by GPIO matrix or dead-time module. So the level set here doesn't equal to the final output level.

  Parameters:

    - gen -- [in] MCPWM generator handle, allocated by `mcpwm_new_generator()`

    - level -- [in] GPIO level to be applied to MCPWM generator, specially, -1 means to remove the force level

    - hold_on -- [in] Whether the forced PWM level should retain (i.e. will remain unchanged until manually remove the force level)

  Returns:

    - ESP_OK: Set force level for MCPWM generator successfully

    - ESP_ERR_INVALID_ARG: Set force level for MCPWM generator failed because of invalid argument

    - ESP_FAIL: Set force level for MCPWM generator failed because of other error

esp_err_t mcpwm_generator_set_action_on_timer_event(mcpwm_gen_handle_t gen, mcpwm_gen_timer_event_action_t ev_act)

  Set generator action on MCPWM timer event.

  Parameters:

    - gen -- [in] MCPWM generator handle, allocated by `mcpwm_new_generator()`

    - ev_act -- [in] MCPWM timer event action, can be constructed by `MCPWM_GEN_TIMER_EVENT_ACTION` helper macro

  Returns:

    - ESP_OK: Set generator action successfully

    - ESP_ERR_INVALID_ARG: Set generator action failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Set generator action failed because of timer is not connected to operator

    - ESP_FAIL: Set generator action failed because of other error

esp_err_t mcpwm_generator_set_action_on_compare_event(mcpwm_gen_handle_t generator, mcpwm_gen_compare_event_action_t ev_act)

  Set generator action on MCPWM compare event.

  Parameters:

    - generator -- [in] MCPWM generator handle, allocated by `mcpwm_new_generator()`

    - ev_act -- [in] MCPWM compare event action, can be constructed by `MCPWM_GEN_COMPARE_EVENT_ACTION` helper macro

  Returns:

    - ESP_OK: Set generator action successfully

    - ESP_ERR_INVALID_ARG: Set generator action failed because of invalid argument

    - ESP_FAIL: Set generator action failed because of other error

esp_err_t mcpwm_generator_set_action_on_brake_event(mcpwm_gen_handle_t generator, mcpwm_gen_brake_event_action_t ev_act)

  Set generator action on MCPWM brake event.

  Parameters:

    - generator -- [in] MCPWM generator handle, allocated by `mcpwm_new_generator()`

    - ev_act -- [in] MCPWM brake event action, can be constructed by `MCPWM_GEN_BRAKE_EVENT_ACTION` helper macro

  Returns:

    - ESP_OK: Set generator action successfully

    - ESP_ERR_INVALID_ARG: Set generator action failed because of invalid argument

    - ESP_FAIL: Set generator action failed because of other error

esp_err_t mcpwm_generator_set_action_on_fault_event(mcpwm_gen_handle_t generator, mcpwm_gen_fault_event_action_t ev_act)

  Set generator action on MCPWM Fault event.

  Parameters:

    - generator -- [in] MCPWM generator handle, allocated by `mcpwm_new_generator()`

    - ev_act -- [in] MCPWM trigger event action, can be constructed by `MCPWM_GEN_FAULT_EVENT_ACTION` helper macro

  Returns:

    - ESP_OK: Set generator action successfully

    - ESP_ERR_INVALID_ARG: Set generator action failed because of invalid argument

    - ESP_FAIL: Set generator action failed because of other error

esp_err_t mcpwm_generator_set_action_on_sync_event(mcpwm_gen_handle_t generator, mcpwm_gen_sync_event_action_t ev_act)

  Set generator action on MCPWM Sync event.

  Note

  The trigger only support one sync action, regardless of the kinds. Should not call this function more than once.

  Parameters:

    - generator -- [in] MCPWM generator handle, allocated by `mcpwm_new_generator()`

    - ev_act -- [in] MCPWM trigger event action, can be constructed by `MCPWM_GEN_SYNC_EVENT_ACTION` helper macro

  Returns:

    - ESP_OK: Set generator action successfully

    - ESP_ERR_INVALID_ARG: Set generator action failed because of invalid argument

    - ESP_FAIL: Set generator action failed because of other error

esp_err_t mcpwm_generator_set_dead_time(mcpwm_gen_handle_t in_generator, mcpwm_gen_handle_t out_generator, const mcpwm_dead_time_config_t *config)

  Set dead time for MCPWM generator.

  Note

  Due to a hardware limitation, you can't set rising edge delay for both MCPWM generator 0 and 1 at the same time, otherwise, there will be a conflict inside the dead time module. The same goes for the falling edge setting. But you can set both the rising edge and falling edge delay for the same MCPWM generator.

  Parameters:

    - in_generator -- [in] MCPWM generator, before adding the dead time

    - out_generator -- [in] MCPWM generator, after adding the dead time

    - config -- [in] MCPWM dead time configuration

  Returns:

    - ESP_OK: Set dead time for MCPWM generator successfully

    - ESP_ERR_INVALID_ARG: Set dead time for MCPWM generator failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Set dead time for MCPWM generator failed because of invalid state (e.g. delay module is already in use by other generator)

    - ESP_FAIL: Set dead time for MCPWM generator failed because of other error

### Structures

struct mcpwm_generator_config_t

  MCPWM generator configuration.

  Public Members

  int gen_gpio_num

    The GPIO number used to output the PWM signal

  struct mcpwm_generator_config_t::extra_mcpwm_generator_flags flags

    Extra configuration flags for generator

  struct extra_mcpwm_generator_flags

    Extra configuration flags for generator.

    Public Members

    uint32_t invert_pwm

      Whether to invert the PWM signal (done by GPIO matrix)

struct mcpwm_gen_timer_event_action_t

  Generator action on specific timer event.

  Public Members

  mcpwm_timer_direction_t direction

    Timer direction

  mcpwm_timer_event_t event

    Timer event

  mcpwm_generator_action_t action

    Generator action should perform

struct mcpwm_gen_compare_event_action_t

  Generator action on specific comparator event.

  Public Members

  mcpwm_timer_direction_t direction

    Timer direction

  mcpwm_cmpr_handle_t comparator

    Comparator handle

  mcpwm_generator_action_t action

    Generator action should perform

struct mcpwm_gen_brake_event_action_t

  Generator action on specific brake event.

  Public Members

  mcpwm_timer_direction_t direction

    Timer direction

  mcpwm_operator_brake_mode_t brake_mode

    Brake mode

  mcpwm_generator_action_t action

    Generator action should perform

struct mcpwm_gen_fault_event_action_t

  Generator action on specific fault event.

  Public Members

  mcpwm_timer_direction_t direction

    Timer direction

  mcpwm_fault_handle_t fault

    Which fault as the trigger. Only support GPIO fault

  mcpwm_generator_action_t action

    Generator action should perform

struct mcpwm_gen_sync_event_action_t

  Generator action on specific sync event.

  Public Members

  mcpwm_timer_direction_t direction

    Timer direction

  mcpwm_sync_handle_t sync

    Which sync as the trigger

  mcpwm_generator_action_t action

    Generator action should perform

struct mcpwm_dead_time_config_t

  MCPWM dead time configuration structure.

  Public Members

  uint32_t posedge_delay_ticks

    delay time applied to rising edge, 0 means no rising delay time

  uint32_t negedge_delay_ticks

    delay time applied to falling edge, 0 means no falling delay time

  uint32_t invert_output

    Invert the signal after applied the dead time

  struct mcpwm_dead_time_config_t flags

    Extra flags for dead time configuration

### Macros

MCPWM_GEN_TIMER_EVENT_ACTION(dir, ev, act)

  Help macros to construct a mcpwm_gen_timer_event_action_t entry.

MCPWM_GEN_COMPARE_EVENT_ACTION(dir, cmp, act)

  Help macros to construct a mcpwm_gen_compare_event_action_t entry.

MCPWM_GEN_BRAKE_EVENT_ACTION(dir, mode, act)

  Help macros to construct a mcpwm_gen_brake_event_action_t entry.

MCPWM_GEN_FAULT_EVENT_ACTION(dir, flt, act)

  Help macros to construct a mcpwm_gen_fault_event_action_t entry.

MCPWM_GEN_SYNC_EVENT_ACTION(dir, syn, act)

  Help macros to construct a mcpwm_gen_sync_event_action_t entry.

### Fault API

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_fault.h

- This header file can be included with:

  >     #include "driver/mcpwm_fault.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Functions

esp_err_t mcpwm_new_gpio_fault(const mcpwm_gpio_fault_config_t *config, mcpwm_fault_handle_t *ret_fault)

  Create MCPWM GPIO fault.

  Parameters:

    - config -- [in] MCPWM GPIO fault configuration

    - ret_fault -- [out] Returned GPIO fault handle

  Returns:

    - ESP_OK: Create MCPWM GPIO fault successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM GPIO fault failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM GPIO fault failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM GPIO fault failed because can't find free resource

    - ESP_FAIL: Create MCPWM GPIO fault failed because of other error

esp_err_t mcpwm_new_soft_fault(const mcpwm_soft_fault_config_t *config, mcpwm_fault_handle_t *ret_fault)

  Create MCPWM software fault.

  Parameters:

    - config -- [in] MCPWM software fault configuration

    - ret_fault -- [out] Returned software fault handle

  Returns:

    - ESP_OK: Create MCPWM software fault successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM software fault failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM software fault failed because out of memory

    - ESP_FAIL: Create MCPWM software fault failed because of other error

esp_err_t mcpwm_del_fault(mcpwm_fault_handle_t fault)

  Delete MCPWM fault.

  Parameters:

    fault -- [in] MCPWM fault handle allocated by `mcpwm_new_gpio_fault()` or `mcpwm_new_soft_fault()`

  Returns:

    - ESP_OK: Delete MCPWM fault successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM fault failed because of invalid argument

    - ESP_FAIL: Delete MCPWM fault failed because of other error

esp_err_t mcpwm_soft_fault_activate(mcpwm_fault_handle_t fault)

  Activate the software fault, trigger the fault event for once.

  Parameters:

    fault -- [in] MCPWM soft fault, allocated by `mcpwm_new_soft_fault()`

  Returns:

    - ESP_OK: Trigger MCPWM software fault event successfully

    - ESP_ERR_INVALID_ARG: Trigger MCPWM software fault event failed because of invalid argument

    - ESP_FAIL: Trigger MCPWM software fault event failed because of other error

esp_err_t mcpwm_fault_register_event_callbacks(mcpwm_fault_handle_t fault, const mcpwm_fault_event_callbacks_t *cbs, void *user_data)

  Set event callbacks for MCPWM fault.

  Note

  User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.

  Parameters:

    - fault -- [in] MCPWM GPIO fault handle, allocated by `mcpwm_new_gpio_fault()`

    - cbs -- [in] Group of callback functions

    - user_data -- [in] User data, which will be passed to callback functions directly

  Returns:

    - ESP_OK: Set event callbacks successfully

    - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument

    - ESP_FAIL: Set event callbacks failed because of other error

### Structures

struct mcpwm_gpio_fault_config_t

  MCPWM GPIO fault configuration structure.

  Public Members

  int group_id

    In which MCPWM group that the GPIO fault belongs to

  int intr_priority

    MCPWM GPIO fault interrupt priority, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)

  int gpio_num

    GPIO used by the fault signal

  struct mcpwm_gpio_fault_config_t::extra_mcpwm_gpio_fault_flags flags

    Extra configuration flags for GPIO fault

  struct extra_mcpwm_gpio_fault_flags

    Extra configuration flags for GPIO fault.

    Public Members

    uint32_t active_level

      On which level the fault signal is treated as active

struct mcpwm_soft_fault_config_t

  MCPWM software fault configuration structure.

struct mcpwm_fault_event_callbacks_t

  Group of supported MCPWM fault event callbacks.

  Note

  The callbacks are all running under ISR environment

  Public Members

  mcpwm_fault_event_cb_t on_fault_enter

    ISR callback function that would be invoked when fault signal becomes active

  mcpwm_fault_event_cb_t on_fault_exit

    ISR callback function that would be invoked when fault signal becomes inactive

### Sync API

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_sync.h

- This header file can be included with:

  >     #include "driver/mcpwm_sync.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Functions

esp_err_t mcpwm_new_timer_sync_src(mcpwm_timer_handle_t timer, const mcpwm_timer_sync_src_config_t *config, mcpwm_sync_handle_t *ret_sync)

  Create MCPWM timer sync source.

  Parameters:

    - timer -- [in] MCPWM timer handle, allocated by `mcpwm_new_timer()`

    - config -- [in] MCPWM timer sync source configuration

    - ret_sync -- [out] Returned MCPWM sync handle

  Returns:

    - ESP_OK: Create MCPWM timer sync source successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM timer sync source failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM timer sync source failed because out of memory

    - ESP_ERR_INVALID_STATE: Create MCPWM timer sync source failed because the timer has created a sync source before

    - ESP_FAIL: Create MCPWM timer sync source failed because of other error

esp_err_t mcpwm_new_gpio_sync_src(const mcpwm_gpio_sync_src_config_t *config, mcpwm_sync_handle_t *ret_sync)

  Create MCPWM GPIO sync source.

  Parameters:

    - config -- [in] MCPWM GPIO sync source configuration

    - ret_sync -- [out] Returned MCPWM GPIO sync handle

  Returns:

    - ESP_OK: Create MCPWM GPIO sync source successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM GPIO sync source failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM GPIO sync source failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM GPIO sync source failed because can't find free resource

    - ESP_FAIL: Create MCPWM GPIO sync source failed because of other error

esp_err_t mcpwm_new_soft_sync_src(const mcpwm_soft_sync_config_t *config, mcpwm_sync_handle_t *ret_sync)

  Create MCPWM software sync source.

  Parameters:

    - config -- [in] MCPWM software sync source configuration

    - ret_sync -- [out] Returned software sync handle

  Returns:

    - ESP_OK: Create MCPWM software sync successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM software sync failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM software sync failed because out of memory

    - ESP_FAIL: Create MCPWM software sync failed because of other error

esp_err_t mcpwm_del_sync_src(mcpwm_sync_handle_t sync)

  Delete MCPWM sync source.

  Parameters:

    sync -- [in] MCPWM sync handle, allocated by `mcpwm_new_timer_sync_src()` or `mcpwm_new_gpio_sync_src()` or `mcpwm_new_soft_sync_src()`

  Returns:

    - ESP_OK: Delete MCPWM sync source successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM sync source failed because of invalid argument

    - ESP_FAIL: Delete MCPWM sync source failed because of other error

esp_err_t mcpwm_soft_sync_activate(mcpwm_sync_handle_t sync)

  Activate the software sync, trigger the sync event for once.

  Parameters:

    sync -- [in] MCPWM soft sync handle, allocated by `mcpwm_new_soft_sync_src()`

  Returns:

    - ESP_OK: Trigger MCPWM software sync event successfully

    - ESP_ERR_INVALID_ARG: Trigger MCPWM software sync event failed because of invalid argument

    - ESP_FAIL: Trigger MCPWM software sync event failed because of other error

### Structures

struct mcpwm_timer_sync_src_config_t

  MCPWM timer sync source configuration.

  Public Members

  mcpwm_timer_event_t timer_event

    Timer event, upon which MCPWM timer will generate the sync signal

  struct mcpwm_timer_sync_src_config_t::extra_mcpwm_timer_sync_src_flags flags

    Extra configuration flags for timer sync source

  struct extra_mcpwm_timer_sync_src_flags

    Extra configuration flags for timer sync source.

    Public Members

    uint32_t propagate_input_sync

      The input sync signal would be routed to its sync output

struct mcpwm_gpio_sync_src_config_t

  MCPWM GPIO sync source configuration.

  Public Members

  int group_id

    MCPWM group ID

  int gpio_num

    GPIO used by sync source

  struct mcpwm_gpio_sync_src_config_t::extra_mcpwm_gpio_sync_src_flags flags

    Extra configuration flags for GPIO sync source

  struct extra_mcpwm_gpio_sync_src_flags

    Extra configuration flags for GPIO sync source.

    Public Members

    uint32_t active_neg

      Whether the sync signal is active on negedge, by default, the sync signal's posedge is treated as active

struct mcpwm_soft_sync_config_t

  MCPWM software sync configuration structure.

### Capture API

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_cap.h

- This header file can be included with:

  >     #include "driver/mcpwm_cap.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Functions

esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mcpwm_cap_timer_handle_t *ret_cap_timer)

  Create MCPWM capture timer.

  Parameters:

    - config -- [in] MCPWM capture timer configuration

    - ret_cap_timer -- [out] Returned MCPWM capture timer handle

  Returns:

    - ESP_OK: Create MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM capture timer failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM capture timer failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM capture timer failed because can't find free resource

    - ESP_FAIL: Create MCPWM capture timer failed because of other error

esp_err_t mcpwm_del_capture_timer(mcpwm_cap_timer_handle_t cap_timer)

  Delete MCPWM capture timer.

  Parameters:

    cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

  Returns:

    - ESP_OK: Delete MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM capture timer failed because of invalid argument

    - ESP_FAIL: Delete MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_enable(mcpwm_cap_timer_handle_t cap_timer)

  Enable MCPWM capture timer.

  Parameters:

    cap_timer -- [in] MCPWM capture timer handle, allocated by `mcpwm_new_capture_timer()`

  Returns:

    - ESP_OK: Enable MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Enable MCPWM capture timer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Enable MCPWM capture timer failed because timer is enabled already

    - ESP_FAIL: Enable MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_disable(mcpwm_cap_timer_handle_t cap_timer)

  Disable MCPWM capture timer.

  Parameters:

    cap_timer -- [in] MCPWM capture timer handle, allocated by `mcpwm_new_capture_timer()`

  Returns:

    - ESP_OK: Disable MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Disable MCPWM capture timer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Disable MCPWM capture timer failed because timer is disabled already

    - ESP_FAIL: Disable MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_start(mcpwm_cap_timer_handle_t cap_timer)

  Start MCPWM capture timer.

  Parameters:

    cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

  Returns:

    - ESP_OK: Start MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Start MCPWM capture timer failed because of invalid argument

    - ESP_FAIL: Start MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_stop(mcpwm_cap_timer_handle_t cap_timer)

  Stop MCPWM capture timer.

  Parameters:

    cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

  Returns:

    - ESP_OK: Stop MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Stop MCPWM capture timer failed because of invalid argument

    - ESP_FAIL: Stop MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_get_resolution(mcpwm_cap_timer_handle_t cap_timer, uint32_t *out_resolution)

  Get MCPWM capture timer resolution, in Hz.

  Parameters:

    - cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

    - out_resolution -- [out] Returned capture timer resolution, in Hz

  Returns:

    - ESP_OK: Get capture timer resolution successfully

    - ESP_ERR_INVALID_ARG: Get capture timer resolution failed because of invalid argument

    - ESP_FAIL: Get capture timer resolution failed because of other error

esp_err_t mcpwm_capture_timer_set_phase_on_sync(mcpwm_cap_timer_handle_t cap_timer, const mcpwm_capture_timer_sync_phase_config_t *config)

  Set sync phase for MCPWM capture timer.

  Parameters:

    - cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

    - config -- [in] MCPWM capture timer sync phase configuration

  Returns:

    - ESP_OK: Set sync phase for MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Set sync phase for MCPWM capture timer failed because of invalid argument

    - ESP_FAIL: Set sync phase for MCPWM capture timer failed because of other error

esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mcpwm_capture_channel_config_t *config, mcpwm_cap_channel_handle_t *ret_cap_channel)

  Create MCPWM capture channel.

  Note

  The created capture channel won't be enabled until calling `mcpwm_capture_channel_enable`

  Parameters:

    - cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`, will be connected to the new capture channel

    - config -- [in] MCPWM capture channel configuration

    - ret_cap_channel -- [out] Returned MCPWM capture channel

  Returns:

    - ESP_OK: Create MCPWM capture channel successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM capture channel failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM capture channel failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM capture channel failed because can't find free resource

    - ESP_FAIL: Create MCPWM capture channel failed because of other error

esp_err_t mcpwm_del_capture_channel(mcpwm_cap_channel_handle_t cap_channel)

  Delete MCPWM capture channel.

  Parameters:

    cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

  Returns:

    - ESP_OK: Delete MCPWM capture channel successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM capture channel failed because of invalid argument

    - ESP_FAIL: Delete MCPWM capture channel failed because of other error

esp_err_t mcpwm_capture_channel_enable(mcpwm_cap_channel_handle_t cap_channel)

  Enable MCPWM capture channel.

  Note

  This function will transit the channel state from init to enable.

  Note

  This function will enable the interrupt service, if it's lazy installed in `mcpwm_capture_channel_register_event_callbacks()`.

  Parameters:

    cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

  Returns:

    - ESP_OK: Enable MCPWM capture channel successfully

    - ESP_ERR_INVALID_ARG: Enable MCPWM capture channel failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Enable MCPWM capture channel failed because the channel is already enabled

    - ESP_FAIL: Enable MCPWM capture channel failed because of other error

esp_err_t mcpwm_capture_channel_disable(mcpwm_cap_channel_handle_t cap_channel)

  Disable MCPWM capture channel.

  Parameters:

    cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

  Returns:

    - ESP_OK: Disable MCPWM capture channel successfully

    - ESP_ERR_INVALID_ARG: Disable MCPWM capture channel failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Disable MCPWM capture channel failed because the channel is not enabled yet

    - ESP_FAIL: Disable MCPWM capture channel failed because of other error

esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_callbacks_t *cbs, void *user_data)

  Set event callbacks for MCPWM capture channel.

  Note

  The first call to this function needs to be before the call to `mcpwm_capture_channel_enable`

  Note

  User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.

  Parameters:

    - cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

    - cbs -- [in] Group of callback functions

    - user_data -- [in] User data, which will be passed to callback functions directly

  Returns:

    - ESP_OK: Set event callbacks successfully

    - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Set event callbacks failed because the channel is not in init state

    - ESP_FAIL: Set event callbacks failed because of other error

esp_err_t mcpwm_capture_channel_trigger_soft_catch(mcpwm_cap_channel_handle_t cap_channel)

  Trigger a catch by software.

  Parameters:

    cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

  Returns:

    - ESP_OK: Trigger software catch successfully

    - ESP_ERR_INVALID_ARG: Trigger software catch failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Trigger software catch failed because the channel is not enabled yet

    - ESP_FAIL: Trigger software catch failed because of other error

esp_err_t mcpwm_capture_get_latched_value(mcpwm_cap_channel_handle_t cap_channel, uint32_t *value)

  Get the last captured value of the MCPWM capture channel.

  Note

  To convert the count value to a time, user can use `mcpwm_capture_timer_get_resolution` to get the resolution of the capture timer.

  Parameters:

    - cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

    - value -- [out] Returned capture value

  Returns:

    - ESP_OK: Get capture value successfully

    - ESP_ERR_INVALID_ARG: Get capture value failed because of invalid argument

    - ESP_FAIL: Get capture value failed because of other error

### Structures

struct mcpwm_capture_timer_config_t

  MCPWM capture timer configuration structure.

  Public Members

  int group_id

    Specify from which group to allocate the capture timer

  mcpwm_capture_clock_source_t clk_src

    MCPWM capture timer clock source

  uint32_t resolution_hz

    Resolution of capture timer

  struct mcpwm_capture_timer_config_t::extra_mcpwm_capture_timer_flags flags

    Extra configuration flags for timer

  struct extra_mcpwm_capture_timer_flags

    Extra configuration flags for capture timer.

    Public Members

    uint32_t allow_pd

      Set to allow power down. When this flag set, the driver will backup/restore the MCPWM registers before/after entering/exist sleep mode. By this approach, the system can power off MCPWM's power domain. This can save power, but at the expense of more RAM being consumed.

struct mcpwm_capture_timer_sync_phase_config_t

  MCPWM Capture timer sync phase configuration.

  Public Members

  mcpwm_sync_handle_t sync_src

    The sync event source

  uint32_t count_value

    The count value that should lock to upon sync event

  mcpwm_timer_direction_t direction

    The count direction that should lock to upon sync event

struct mcpwm_capture_channel_config_t

  MCPWM capture channel configuration structure.

  Public Members

  int gpio_num

    GPIO used capturing input signal

  int intr_priority

    MCPWM capture interrupt priority, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)

  uint32_t prescale

    Prescale of input signal, effective frequency = cap_input_clk/prescale

  struct mcpwm_capture_channel_config_t::extra_capture_channel_flags flags

    Extra configuration flags for capture channel

  struct extra_capture_channel_flags

    Extra configuration flags for capture channel.

    Public Members

    uint32_t pos_edge

      Whether to capture on positive edge

    uint32_t neg_edge

      Whether to capture on negative edge

    uint32_t invert_cap_signal

      Invert the input capture signal

struct mcpwm_capture_event_callbacks_t

  Group of supported MCPWM capture event callbacks.

  Note

  The callbacks are all running under ISR environment

  Public Members

  mcpwm_capture_event_cb_t on_cap

    Callback function that would be invoked when capture event occurred

### ETM API

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_etm.h

- This header file can be included with:

  >     #include "driver/mcpwm_etm.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Functions

esp_err_t mcpwm_comparator_new_etm_event(mcpwm_cmpr_handle_t cmpr, const mcpwm_cmpr_etm_event_config_t *config, esp_etm_event_handle_t *out_event)

  Get the ETM event for MCPWM comparator.

  Note

  The created ETM event object can be deleted later by calling `esp_etm_del_event`

  Parameters:

    - cmpr -- [in] MCPWM comparator, allocated by `mcpwm_new_comparator()` or `mcpwm_new_event_comparator()`

    - config -- [in] MCPWM ETM comparator event configuration

    - out_event -- [out] Returned ETM event handle

  Returns:

    - ESP_OK: Get ETM event successfully

    - ESP_ERR_INVALID_ARG: Get ETM event failed because of invalid argument

    - ESP_FAIL: Get ETM event failed because of other error

esp_err_t mcpwm_timer_new_etm_event(mcpwm_timer_handle_t timer, const mcpwm_timer_etm_event_config_t *config, esp_etm_event_handle_t *out_event)

  Get the ETM event for MCPWM timer.

  Note

  The created ETM event object can be deleted later by calling `esp_etm_del_event`

  Parameters:

    - timer -- [in] MCPWM timer, allocated by `mcpwm_new_timer()`

    - config -- [in] MCPWM ETM timer event configuration

    - out_event -- [out] Returned ETM event handle

  Returns:

    - ESP_OK: Get ETM event successfully

    - ESP_ERR_INVALID_ARG: Get ETM event failed because of invalid argument

    - ESP_FAIL: Get ETM event failed because of other error

### Structures

struct mcpwm_cmpr_etm_event_config_t

  MCPWM event comparator ETM event configuration.

  Public Members

  mcpwm_comparator_etm_event_type_t event_type

    MCPWM comparator ETM event type

struct mcpwm_timer_etm_event_config_t

  MCPWM timer ETM event configuration.

  Public Members

  mcpwm_timer_etm_event_type_t event_type

    MCPWM timer ETM event type

### Driver Types

### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_types.h

- This header file can be included with:

  >     #include "driver/mcpwm_types.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

### Structures

struct mcpwm_timer_event_data_t

  MCPWM timer event data.

  Public Members

  uint32_t count_value

    MCPWM timer count value

  mcpwm_timer_direction_t direction

    MCPWM timer count direction

struct mcpwm_brake_event_data_t

  MCPWM brake event data.

struct mcpwm_fault_event_data_t

  MCPWM fault event data.

struct mcpwm_compare_event_data_t

  MCPWM compare event data.

  Public Members

  uint32_t compare_ticks

    Compare value

  mcpwm_timer_direction_t direction

    Count direction

struct mcpwm_capture_event_data_t

  MCPWM capture event data.

  Public Members

  uint32_t cap_value

    Captured value

  mcpwm_capture_edge_t cap_edge

    Capture edge

### Type Definitions

typedef struct mcpwm_timer_t *mcpwm_timer_handle_t

  Type of MCPWM timer handle.

typedef struct mcpwm_oper_t *mcpwm_oper_handle_t

  Type of MCPWM operator handle.

typedef struct mcpwm_cmpr_t *mcpwm_cmpr_handle_t

  Type of MCPWM comparator handle.

typedef struct mcpwm_gen_t *mcpwm_gen_handle_t

  Type of MCPWM generator handle.

typedef struct mcpwm_fault_t *mcpwm_fault_handle_t

  Type of MCPWM fault handle.

typedef struct mcpwm_sync_t *mcpwm_sync_handle_t

  Type of MCPWM sync handle.

typedef struct mcpwm_cap_timer_t *mcpwm_cap_timer_handle_t

  Type of MCPWM capture timer handle.

typedef struct mcpwm_cap_channel_t *mcpwm_cap_channel_handle_t

  Type of MCPWM capture channel handle.

typedef bool (*mcpwm_timer_event_cb_t)(mcpwm_timer_handle_t timer, const mcpwm_timer_event_data_t *edata, void *user_ctx)

  MCPWM timer event callback function.

  Param timer:

    [in] MCPWM timer handle

  Param edata:

    [in] MCPWM timer event data, fed by driver

  Param user_ctx:

    [in] User data, set in `mcpwm_timer_register_event_callbacks()`

  Return:

    Whether a high priority task has been waken up by this function

typedef bool (*mcpwm_brake_event_cb_t)(mcpwm_oper_handle_t oper, const mcpwm_brake_event_data_t *edata, void *user_ctx)

  MCPWM operator brake event callback function.

  Param oper:

    [in] MCPWM operator handle

  Param edata:

    [in] MCPWM brake event data, fed by driver

  Param user_ctx:

    [in] User data, set in `mcpwm_operator_register_event_callbacks()`

  Return:

    Whether a high priority task has been waken up by this function

typedef bool (*mcpwm_fault_event_cb_t)(mcpwm_fault_handle_t fault, const mcpwm_fault_event_data_t *edata, void *user_ctx)

  MCPWM fault event callback function.

  Param fault:

    MCPWM fault handle

  Param edata:

    MCPWM fault event data, fed by driver

  Param user_ctx:

    User data, set in `mcpwm_fault_register_event_callbacks()`

  Return:

    whether a task switch is needed after the callback returns

typedef bool (*mcpwm_compare_event_cb_t)(mcpwm_cmpr_handle_t comparator, const mcpwm_compare_event_data_t *edata, void *user_ctx)

  MCPWM comparator event callback function.

  Param comparator:

    MCPWM comparator handle

  Param edata:

    MCPWM comparator event data, fed by driver

  Param user_ctx:

    User data, set in `mcpwm_comparator_register_event_callbacks()`

  Return:

    Whether a high priority task has been waken up by this function

typedef bool (*mcpwm_capture_event_cb_t)(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_data_t *edata, void *user_ctx)

  MCPWM capture event callback function.

  Param cap_channel:

    MCPWM capture channel handle

  Param edata:

    MCPWM capture event data, fed by driver

  Param user_ctx:

    User data, set in `mcpwm_capture_channel_register_event_callbacks()`

  Return:

    Whether a high priority task has been waken up by this function

### HAL Types

### Header File

- components/esp_hal_mcpwm/include/hal/mcpwm_types.h

- This header file can be included with:

  >     #include "hal/mcpwm_types.h"

- This header file is a part of the API provided by the `esp_hal_mcpwm` component. To declare that your component depends on `esp_hal_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_hal_mcpwm

  > or

  >     PRIV_REQUIRES esp_hal_mcpwm

### Type Definitions

typedef soc_periph_mcpwm_timer_clk_src_t mcpwm_timer_clock_source_t

  MCPWM timer clock source.

typedef soc_periph_mcpwm_capture_clk_src_t mcpwm_capture_clock_source_t

  MCPWM capture clock source.

typedef soc_periph_mcpwm_carrier_clk_src_t mcpwm_carrier_clock_source_t

  MCPWM carrier clock source.

### Enumerations

enum mcpwm_timer_direction_t

  MCPWM timer count direction.

  Values:

  enumerator MCPWM_TIMER_DIRECTION_UP

    Counting direction: Increase

  enumerator MCPWM_TIMER_DIRECTION_DOWN

    Counting direction: Decrease

enum mcpwm_timer_event_t

  MCPWM timer events.

  Values:

  enumerator MCPWM_TIMER_EVENT_EMPTY

    MCPWM timer counts to zero (i.e. counter is empty)

  enumerator MCPWM_TIMER_EVENT_FULL

    MCPWM timer counts to peak (i.e. counter is full)

  enumerator MCPWM_TIMER_EVENT_INVALID

    MCPWM timer invalid event

enum mcpwm_timer_count_mode_t

  MCPWM timer count modes.

  Values:

  enumerator MCPWM_TIMER_COUNT_MODE_PAUSE

    MCPWM timer paused

  enumerator MCPWM_TIMER_COUNT_MODE_UP

    MCPWM timer counting up

  enumerator MCPWM_TIMER_COUNT_MODE_DOWN

    MCPWM timer counting down

  enumerator MCPWM_TIMER_COUNT_MODE_UP_DOWN

    MCPWM timer counting up and down

enum mcpwm_timer_start_stop_cmd_t

  MCPWM timer commands, specify the way to start or stop the timer.

  Values:

  enumerator MCPWM_TIMER_STOP_EMPTY

    MCPWM timer stops when next count reaches zero

  enumerator MCPWM_TIMER_STOP_FULL

    MCPWM timer stops when next count reaches peak

  enumerator MCPWM_TIMER_START_NO_STOP

    MCPWM timer starts counting, and don't stop until received stop command

  enumerator MCPWM_TIMER_START_STOP_EMPTY

    MCPWM timer starts counting and stops when next count reaches zero

  enumerator MCPWM_TIMER_START_STOP_FULL

    MCPWM timer starts counting and stops when next count reaches peak

enum mcpwm_generator_action_t

  MCPWM generator actions.

  Values:

  enumerator MCPWM_GEN_ACTION_KEEP

    Generator action: Keep the same level

  enumerator MCPWM_GEN_ACTION_LOW

    Generator action: Force to low level

  enumerator MCPWM_GEN_ACTION_HIGH

    Generator action: Force to high level

  enumerator MCPWM_GEN_ACTION_TOGGLE

    Generator action: Toggle level

enum mcpwm_operator_brake_mode_t

  MCPWM operator brake mode.

  Values:

  enumerator MCPWM_OPER_BRAKE_MODE_CBC

    Brake mode: CBC (cycle by cycle)

  enumerator MCPWM_OPER_BRAKE_MODE_OST

    Brake mode: OST (one shot)

  enumerator MCPWM_OPER_BRAKE_MODE_INVALID

    MCPWM operator invalid brake mode

enum mcpwm_capture_edge_t

  MCPWM capture edge.

  Values:

  enumerator MCPWM_CAP_EDGE_POS

    Capture on the positive edge

  enumerator MCPWM_CAP_EDGE_NEG

    Capture on the negative edge

enum mcpwm_timer_etm_event_type_t

  MCPWM timer specific events that supported by the ETM module.

  Values:

  enumerator MCPWM_TIMER_ETM_EVENT_TEZ

    The timer reaches zero

  enumerator MCPWM_TIMER_ETM_EVENT_TEP

    The timer reaches peak

  enumerator MCPWM_TIMER_ETM_EVENT_MAX

    Maximum number of timer events

enum mcpwm_comparator_etm_event_type_t

  MCPWM comparator specific events that supported by the ETM module.

  Values:

  enumerator MCPWM_CMPR_ETM_EVENT_EQUAL

    The count value equals the value of comparator

  enumerator MCPWM_CMPR_ETM_EVENT_MAX

    Maximum number of comparator events

[1] (1,2,3,4,5,6,7,8,9)

Different ESP chip series might have a different number of MCPWM resources (e.g., groups, timers, comparators, operators, generators, triggers and so on). Please refer to the [TRM] for details. The driver does not forbid you from applying for more MCPWM resources, but it returns an error when there are no hardware resources available. Please always check the return value when doing Resource Allocation and Initialization.

[2]

The callback function and the sub-functions invoked by itself should also be placed in IRAM. You need to take care of this by yourself.

Was this page helpful?

- Thank you! We received your feedback.
- If you have any comments, fill in Espressif Documentation Feedback Form.

- We value your feedback.
- Let us know how we can improve this page by filling in Espressif Documentation Feedback Form.