mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/mcpwm_interrupt_prioity_v5.1' into 'release/v5.1'
feat(MCPWM): Support set interrupt priority(v5.1) See merge request espressif/esp-idf!25573
This commit is contained in:
commit
8da2c57889
@ -132,6 +132,8 @@ esp_err_t mcpwm_capture_timer_set_phase_on_sync(mcpwm_cap_timer_handle_t cap_tim
|
|||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int gpio_num; /*!< GPIO used capturing input signal */
|
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 */
|
uint32_t prescale; /*!< Prescale of input signal, effective frequency = cap_input_clk/prescale */
|
||||||
struct {
|
struct {
|
||||||
uint32_t pos_edge: 1; /*!< Whether to capture on positive edge */
|
uint32_t pos_edge: 1; /*!< Whether to capture on positive edge */
|
||||||
|
@ -19,6 +19,8 @@ extern "C" {
|
|||||||
* @brief MCPWM comparator configuration
|
* @brief MCPWM comparator configuration
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
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 {
|
struct {
|
||||||
uint32_t update_cmp_on_tez: 1; /*!< Whether to update compare value when timer count equals to zero (tez) */
|
uint32_t update_cmp_on_tez: 1; /*!< Whether to update compare value when timer count equals to zero (tez) */
|
||||||
uint32_t update_cmp_on_tep: 1; /*!< Whether to update compare value when timer count equals to peak (tep) */
|
uint32_t update_cmp_on_tep: 1; /*!< Whether to update compare value when timer count equals to peak (tep) */
|
||||||
|
@ -20,8 +20,10 @@ extern "C" {
|
|||||||
* @brief MCPWM GPIO fault configuration structure
|
* @brief MCPWM GPIO fault configuration structure
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int group_id; /*!< In which MCPWM group that the GPIO fault belongs to */
|
int group_id; /*!< In which MCPWM group that the GPIO fault belongs to */
|
||||||
int gpio_num; /*!< GPIO used by the fault signal */
|
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 {
|
struct {
|
||||||
uint32_t active_level: 1; /*!< On which level the fault signal is treated as active */
|
uint32_t active_level: 1; /*!< On which level the fault signal is treated as active */
|
||||||
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
|
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
|
||||||
|
@ -19,7 +19,9 @@ extern "C" {
|
|||||||
* @brief MCPWM operator configuration
|
* @brief MCPWM operator configuration
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int group_id; /*!< Specify from which group to allocate the MCPWM operator */
|
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 {
|
struct {
|
||||||
uint32_t update_gen_action_on_tez: 1; /*!< Whether to update generator action when timer counts to zero */
|
uint32_t update_gen_action_on_tez: 1; /*!< Whether to update generator action when timer counts to zero */
|
||||||
uint32_t update_gen_action_on_tep: 1; /*!< Whether to update generator action when timer counts to peak */
|
uint32_t update_gen_action_on_tep: 1; /*!< Whether to update generator action when timer counts to peak */
|
||||||
|
@ -35,6 +35,8 @@ typedef struct {
|
|||||||
The step size of each count tick equals to (1 / resolution_hz) seconds */
|
The step size of each count tick equals to (1 / resolution_hz) seconds */
|
||||||
mcpwm_timer_count_mode_t count_mode; /*!< Count mode */
|
mcpwm_timer_count_mode_t count_mode; /*!< Count mode */
|
||||||
uint32_t period_ticks; /*!< Number of count ticks within a period */
|
uint32_t period_ticks; /*!< Number of count ticks within a period */
|
||||||
|
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 {
|
struct {
|
||||||
uint32_t update_period_on_empty: 1; /*!< Whether to update period when timer counts to zero */
|
uint32_t update_period_on_empty: 1; /*!< Whether to update period when timer counts to zero */
|
||||||
uint32_t update_period_on_sync: 1; /*!< Whether to update period on sync event */
|
uint32_t update_period_on_sync: 1; /*!< Whether to update period on sync event */
|
||||||
|
@ -247,6 +247,10 @@ esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mc
|
|||||||
mcpwm_cap_channel_t *cap_chan = NULL;
|
mcpwm_cap_channel_t *cap_chan = NULL;
|
||||||
ESP_GOTO_ON_FALSE(cap_timer && config && ret_cap_channel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
ESP_GOTO_ON_FALSE(cap_timer && config && ret_cap_channel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||||
ESP_GOTO_ON_FALSE(config->prescale && config->prescale <= MCPWM_LL_MAX_CAPTURE_PRESCALE, ESP_ERR_INVALID_ARG, err, TAG, "invalid prescale");
|
ESP_GOTO_ON_FALSE(config->prescale && config->prescale <= MCPWM_LL_MAX_CAPTURE_PRESCALE, ESP_ERR_INVALID_ARG, err, TAG, "invalid prescale");
|
||||||
|
if (config->intr_priority) {
|
||||||
|
ESP_RETURN_ON_FALSE(1 << (config->intr_priority) & MCPWM_ALLOW_INTR_PRIORITY_MASK, ESP_ERR_INVALID_ARG,
|
||||||
|
TAG, "invalid interrupt priority:%d", config->intr_priority);
|
||||||
|
}
|
||||||
|
|
||||||
// create instance firstly, then install onto platform
|
// create instance firstly, then install onto platform
|
||||||
cap_chan = calloc(1, sizeof(mcpwm_cap_channel_t));
|
cap_chan = calloc(1, sizeof(mcpwm_cap_channel_t));
|
||||||
@ -257,6 +261,10 @@ esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mc
|
|||||||
mcpwm_hal_context_t *hal = &group->hal;
|
mcpwm_hal_context_t *hal = &group->hal;
|
||||||
int cap_chan_id = cap_chan->cap_chan_id;
|
int cap_chan_id = cap_chan->cap_chan_id;
|
||||||
|
|
||||||
|
// if interrupt priority specified before, it cannot be changed until the group is released
|
||||||
|
// check if the new priority specified consistents with the old one
|
||||||
|
ESP_GOTO_ON_ERROR(mcpwm_check_intr_priority(group, config->intr_priority), err, TAG, "set group intrrupt priority failed");
|
||||||
|
|
||||||
mcpwm_ll_capture_enable_negedge(hal->dev, cap_chan_id, config->flags.neg_edge);
|
mcpwm_ll_capture_enable_negedge(hal->dev, cap_chan_id, config->flags.neg_edge);
|
||||||
mcpwm_ll_capture_enable_posedge(hal->dev, cap_chan_id, config->flags.pos_edge);
|
mcpwm_ll_capture_enable_posedge(hal->dev, cap_chan_id, config->flags.pos_edge);
|
||||||
mcpwm_ll_invert_input(hal->dev, cap_chan_id, config->flags.invert_cap_signal);
|
mcpwm_ll_invert_input(hal->dev, cap_chan_id, config->flags.invert_cap_signal);
|
||||||
@ -368,6 +376,7 @@ esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handl
|
|||||||
if (!cap_channel->intr) {
|
if (!cap_channel->intr) {
|
||||||
ESP_RETURN_ON_FALSE(cap_channel->fsm == MCPWM_CAP_CHAN_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel not in init state");
|
ESP_RETURN_ON_FALSE(cap_channel->fsm == MCPWM_CAP_CHAN_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel not in init state");
|
||||||
int isr_flags = MCPWM_INTR_ALLOC_FLAG;
|
int isr_flags = MCPWM_INTR_ALLOC_FLAG;
|
||||||
|
isr_flags |= mcpwm_get_intr_priority_flag(group);
|
||||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
||||||
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_CAPTURE(cap_chan_id),
|
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_CAPTURE(cap_chan_id),
|
||||||
mcpwm_capture_default_isr, cap_channel, &cap_channel->intr), TAG, "install interrupt service for cap channel failed");
|
mcpwm_capture_default_isr, cap_channel, &cap_channel->intr), TAG, "install interrupt service for cap channel failed");
|
||||||
|
@ -75,6 +75,10 @@ esp_err_t mcpwm_new_comparator(mcpwm_oper_handle_t oper, const mcpwm_comparator_
|
|||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
mcpwm_cmpr_t *cmpr = NULL;
|
mcpwm_cmpr_t *cmpr = NULL;
|
||||||
ESP_GOTO_ON_FALSE(oper && config && ret_cmpr, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
ESP_GOTO_ON_FALSE(oper && config && ret_cmpr, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||||
|
if (config->intr_priority) {
|
||||||
|
ESP_RETURN_ON_FALSE(1 << (config->intr_priority) & MCPWM_ALLOW_INTR_PRIORITY_MASK, ESP_ERR_INVALID_ARG,
|
||||||
|
TAG, "invalid interrupt priority:%d", config->intr_priority);
|
||||||
|
}
|
||||||
|
|
||||||
cmpr = heap_caps_calloc(1, sizeof(mcpwm_cmpr_t), MCPWM_MEM_ALLOC_CAPS);
|
cmpr = heap_caps_calloc(1, sizeof(mcpwm_cmpr_t), MCPWM_MEM_ALLOC_CAPS);
|
||||||
ESP_GOTO_ON_FALSE(cmpr, ESP_ERR_NO_MEM, err, TAG, "no mem for comparator");
|
ESP_GOTO_ON_FALSE(cmpr, ESP_ERR_NO_MEM, err, TAG, "no mem for comparator");
|
||||||
@ -85,6 +89,10 @@ esp_err_t mcpwm_new_comparator(mcpwm_oper_handle_t oper, const mcpwm_comparator_
|
|||||||
int oper_id = oper->oper_id;
|
int oper_id = oper->oper_id;
|
||||||
int cmpr_id = cmpr->cmpr_id;
|
int cmpr_id = cmpr->cmpr_id;
|
||||||
|
|
||||||
|
// if interrupt priority specified before, it cannot be changed until the group is released
|
||||||
|
// check if the new priority specified consistents with the old one
|
||||||
|
ESP_GOTO_ON_ERROR(mcpwm_check_intr_priority(group, config->intr_priority), err, TAG, "set group intrrupt priority failed");
|
||||||
|
|
||||||
mcpwm_ll_operator_enable_update_compare_on_tez(hal->dev, oper_id, cmpr_id, config->flags.update_cmp_on_tez);
|
mcpwm_ll_operator_enable_update_compare_on_tez(hal->dev, oper_id, cmpr_id, config->flags.update_cmp_on_tez);
|
||||||
mcpwm_ll_operator_enable_update_compare_on_tep(hal->dev, oper_id, cmpr_id, config->flags.update_cmp_on_tep);
|
mcpwm_ll_operator_enable_update_compare_on_tep(hal->dev, oper_id, cmpr_id, config->flags.update_cmp_on_tep);
|
||||||
mcpwm_ll_operator_enable_update_compare_on_sync(hal->dev, oper_id, cmpr_id, config->flags.update_cmp_on_sync);
|
mcpwm_ll_operator_enable_update_compare_on_sync(hal->dev, oper_id, cmpr_id, config->flags.update_cmp_on_sync);
|
||||||
@ -162,6 +170,7 @@ esp_err_t mcpwm_comparator_register_event_callbacks(mcpwm_cmpr_handle_t cmpr, co
|
|||||||
if (!cmpr->intr) {
|
if (!cmpr->intr) {
|
||||||
// we want the interrupt service to be enabled after allocation successfully
|
// we want the interrupt service to be enabled after allocation successfully
|
||||||
int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ ESP_INTR_FLAG_INTRDISABLED;
|
int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ ESP_INTR_FLAG_INTRDISABLED;
|
||||||
|
isr_flags |= mcpwm_get_intr_priority_flag(group);
|
||||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
||||||
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_CMP_EQUAL(oper_id, cmpr_id),
|
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_CMP_EQUAL(oper_id, cmpr_id),
|
||||||
mcpwm_comparator_default_isr, cmpr, &cmpr->intr), TAG, "install interrupt service for comparator failed");
|
mcpwm_comparator_default_isr, cmpr, &cmpr->intr), TAG, "install interrupt service for comparator failed");
|
||||||
|
@ -43,6 +43,7 @@ mcpwm_group_t *mcpwm_acquire_group_handle(int group_id)
|
|||||||
new_group = true;
|
new_group = true;
|
||||||
s_platform.groups[group_id] = group;
|
s_platform.groups[group_id] = group;
|
||||||
group->group_id = group_id;
|
group->group_id = group_id;
|
||||||
|
group->intr_priority = -1;
|
||||||
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||||
// enable APB to access MCPWM registers
|
// enable APB to access MCPWM registers
|
||||||
periph_module_enable(mcpwm_periph_signals.groups[group_id].module);
|
periph_module_enable(mcpwm_periph_signals.groups[group_id].module);
|
||||||
@ -96,6 +97,32 @@ void mcpwm_release_group_handle(mcpwm_group_t *group)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t mcpwm_check_intr_priority(mcpwm_group_t *group, int intr_priority)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
bool intr_priority_conflict = false;
|
||||||
|
portENTER_CRITICAL(&group->spinlock);
|
||||||
|
if (group->intr_priority == -1) {
|
||||||
|
group->intr_priority = intr_priority;
|
||||||
|
} else if (intr_priority != 0) {
|
||||||
|
intr_priority_conflict = (group->intr_priority != intr_priority);
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL(&group->spinlock);
|
||||||
|
ESP_RETURN_ON_FALSE(!intr_priority_conflict, ESP_ERR_INVALID_STATE, TAG, "intr_priority conflict, already is %d but attempt to %d", group->intr_priority, intr_priority);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mcpwm_get_intr_priority_flag(mcpwm_group_t *group)
|
||||||
|
{
|
||||||
|
int isr_flags = 0;
|
||||||
|
if (group->intr_priority) {
|
||||||
|
isr_flags |= 1 << (group->intr_priority);
|
||||||
|
} else {
|
||||||
|
isr_flags |= MCPWM_ALLOW_INTR_PRIORITY_MASK;
|
||||||
|
}
|
||||||
|
return isr_flags;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_src)
|
esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_src)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
|
@ -93,6 +93,10 @@ esp_err_t mcpwm_new_gpio_fault(const mcpwm_gpio_fault_config_t *config, mcpwm_fa
|
|||||||
ESP_GOTO_ON_FALSE(config && ret_fault, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
ESP_GOTO_ON_FALSE(config && ret_fault, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||||
ESP_GOTO_ON_FALSE(config->group_id < SOC_MCPWM_GROUPS && config->group_id >= 0, ESP_ERR_INVALID_ARG,
|
ESP_GOTO_ON_FALSE(config->group_id < SOC_MCPWM_GROUPS && config->group_id >= 0, ESP_ERR_INVALID_ARG,
|
||||||
err, TAG, "invalid group ID:%d", config->group_id);
|
err, TAG, "invalid group ID:%d", config->group_id);
|
||||||
|
if (config->intr_priority) {
|
||||||
|
ESP_RETURN_ON_FALSE(1 << (config->intr_priority) & MCPWM_ALLOW_INTR_PRIORITY_MASK, ESP_ERR_INVALID_ARG,
|
||||||
|
TAG, "invalid interrupt priority:%d", config->intr_priority);
|
||||||
|
}
|
||||||
|
|
||||||
fault = heap_caps_calloc(1, sizeof(mcpwm_gpio_fault_t), MCPWM_MEM_ALLOC_CAPS);
|
fault = heap_caps_calloc(1, sizeof(mcpwm_gpio_fault_t), MCPWM_MEM_ALLOC_CAPS);
|
||||||
ESP_GOTO_ON_FALSE(fault, ESP_ERR_NO_MEM, err, TAG, "no mem for gpio fault");
|
ESP_GOTO_ON_FALSE(fault, ESP_ERR_NO_MEM, err, TAG, "no mem for gpio fault");
|
||||||
@ -103,6 +107,10 @@ esp_err_t mcpwm_new_gpio_fault(const mcpwm_gpio_fault_config_t *config, mcpwm_fa
|
|||||||
mcpwm_hal_context_t *hal = &group->hal;
|
mcpwm_hal_context_t *hal = &group->hal;
|
||||||
int fault_id = fault->fault_id;
|
int fault_id = fault->fault_id;
|
||||||
|
|
||||||
|
// if interrupt priority specified before, it cannot be changed until the group is released
|
||||||
|
// check if the new priority specified consistents with the old one
|
||||||
|
ESP_GOTO_ON_ERROR(mcpwm_check_intr_priority(group, config->intr_priority), err, TAG, "set group intrrupt priority failed");
|
||||||
|
|
||||||
// GPIO configuration
|
// GPIO configuration
|
||||||
gpio_config_t gpio_conf = {
|
gpio_config_t gpio_conf = {
|
||||||
.intr_type = GPIO_INTR_DISABLE,
|
.intr_type = GPIO_INTR_DISABLE,
|
||||||
@ -245,6 +253,7 @@ esp_err_t mcpwm_fault_register_event_callbacks(mcpwm_fault_handle_t fault, const
|
|||||||
if (!gpio_fault->intr) {
|
if (!gpio_fault->intr) {
|
||||||
// we want the interrupt service to be enabled after allocation successfully
|
// we want the interrupt service to be enabled after allocation successfully
|
||||||
int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ESP_INTR_FLAG_INTRDISABLED;
|
int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ESP_INTR_FLAG_INTRDISABLED;
|
||||||
|
isr_flags |= mcpwm_get_intr_priority_flag(group);
|
||||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
||||||
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_FAULT_MASK(fault_id),
|
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_FAULT_MASK(fault_id),
|
||||||
mcpwm_gpio_fault_default_isr, gpio_fault, &gpio_fault->intr), TAG, "install interrupt service for gpio fault failed");
|
mcpwm_gpio_fault_default_isr, gpio_fault, &gpio_fault->intr), TAG, "install interrupt service for gpio fault failed");
|
||||||
|
@ -90,6 +90,10 @@ esp_err_t mcpwm_new_operator(const mcpwm_operator_config_t *config, mcpwm_oper_h
|
|||||||
ESP_GOTO_ON_FALSE(config && ret_oper, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
ESP_GOTO_ON_FALSE(config && ret_oper, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||||
ESP_GOTO_ON_FALSE(config->group_id < SOC_MCPWM_GROUPS && config->group_id >= 0, ESP_ERR_INVALID_ARG,
|
ESP_GOTO_ON_FALSE(config->group_id < SOC_MCPWM_GROUPS && config->group_id >= 0, ESP_ERR_INVALID_ARG,
|
||||||
err, TAG, "invalid group ID:%d", config->group_id);
|
err, TAG, "invalid group ID:%d", config->group_id);
|
||||||
|
if (config->intr_priority) {
|
||||||
|
ESP_RETURN_ON_FALSE(1 << (config->intr_priority) & MCPWM_ALLOW_INTR_PRIORITY_MASK, ESP_ERR_INVALID_ARG,
|
||||||
|
TAG, "invalid interrupt priority:%d", config->intr_priority);
|
||||||
|
}
|
||||||
|
|
||||||
oper = heap_caps_calloc(1, sizeof(mcpwm_oper_t), MCPWM_MEM_ALLOC_CAPS);
|
oper = heap_caps_calloc(1, sizeof(mcpwm_oper_t), MCPWM_MEM_ALLOC_CAPS);
|
||||||
ESP_GOTO_ON_FALSE(oper, ESP_ERR_NO_MEM, err, TAG, "no mem for operator");
|
ESP_GOTO_ON_FALSE(oper, ESP_ERR_NO_MEM, err, TAG, "no mem for operator");
|
||||||
@ -100,6 +104,10 @@ esp_err_t mcpwm_new_operator(const mcpwm_operator_config_t *config, mcpwm_oper_h
|
|||||||
mcpwm_hal_context_t *hal = &group->hal;
|
mcpwm_hal_context_t *hal = &group->hal;
|
||||||
int oper_id = oper->oper_id;
|
int oper_id = oper->oper_id;
|
||||||
|
|
||||||
|
// if interrupt priority specified before, it cannot be changed until the group is released
|
||||||
|
// check if the new priority specified consistents with the old one
|
||||||
|
ESP_GOTO_ON_ERROR(mcpwm_check_intr_priority(group, config->intr_priority), err, TAG, "set group intrrupt priority failed");
|
||||||
|
|
||||||
// reset MCPWM operator
|
// reset MCPWM operator
|
||||||
mcpwm_hal_operator_reset(hal, oper_id);
|
mcpwm_hal_operator_reset(hal, oper_id);
|
||||||
|
|
||||||
@ -240,6 +248,7 @@ esp_err_t mcpwm_operator_register_event_callbacks(mcpwm_oper_handle_t oper, cons
|
|||||||
if (!oper->intr) {
|
if (!oper->intr) {
|
||||||
// we want the interrupt service to be enabled after allocation successfully
|
// we want the interrupt service to be enabled after allocation successfully
|
||||||
int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ ESP_INTR_FLAG_INTRDISABLED;
|
int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ ESP_INTR_FLAG_INTRDISABLED;
|
||||||
|
isr_flags |= mcpwm_get_intr_priority_flag(group);
|
||||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
||||||
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_OPER_MASK(oper_id),
|
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_OPER_MASK(oper_id),
|
||||||
mcpwm_operator_default_isr, oper, &oper->intr), TAG, "install interrupt service for operator failed");
|
mcpwm_operator_default_isr, oper, &oper->intr), TAG, "install interrupt service for operator failed");
|
||||||
|
@ -29,11 +29,13 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_MCPWM_ISR_IRAM_SAFE
|
#if CONFIG_MCPWM_ISR_IRAM_SAFE
|
||||||
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM)
|
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM)
|
||||||
#else
|
#else
|
||||||
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
|
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MCPWM_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED
|
||||||
|
|
||||||
#define MCPWM_PERIPH_CLOCK_PRE_SCALE (2)
|
#define MCPWM_PERIPH_CLOCK_PRE_SCALE (2)
|
||||||
#define MCPWM_PM_LOCK_NAME_LEN_MAX 16
|
#define MCPWM_PM_LOCK_NAME_LEN_MAX 16
|
||||||
|
|
||||||
@ -54,6 +56,7 @@ typedef struct mcpwm_cap_channel_t mcpwm_cap_channel_t;
|
|||||||
|
|
||||||
struct mcpwm_group_t {
|
struct mcpwm_group_t {
|
||||||
int group_id; // group ID, index from 0
|
int group_id; // group ID, index from 0
|
||||||
|
int intr_priority; // MCPWM interrupt priority
|
||||||
mcpwm_hal_context_t hal; // HAL instance is at group level
|
mcpwm_hal_context_t hal; // HAL instance is at group level
|
||||||
portMUX_TYPE spinlock; // group level spinlock
|
portMUX_TYPE spinlock; // group level spinlock
|
||||||
uint32_t resolution_hz; // MCPWM group clock resolution
|
uint32_t resolution_hz; // MCPWM group clock resolution
|
||||||
@ -225,6 +228,8 @@ struct mcpwm_cap_channel_t {
|
|||||||
|
|
||||||
mcpwm_group_t *mcpwm_acquire_group_handle(int group_id);
|
mcpwm_group_t *mcpwm_acquire_group_handle(int group_id);
|
||||||
void mcpwm_release_group_handle(mcpwm_group_t *group);
|
void mcpwm_release_group_handle(mcpwm_group_t *group);
|
||||||
|
esp_err_t mcpwm_check_intr_priority(mcpwm_group_t *group, int intr_priority);
|
||||||
|
int mcpwm_get_intr_priority_flag(mcpwm_group_t *group);
|
||||||
esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_src);
|
esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_src);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -91,6 +91,10 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
|
|||||||
ESP_GOTO_ON_FALSE(config && ret_timer, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
ESP_GOTO_ON_FALSE(config && ret_timer, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||||
ESP_GOTO_ON_FALSE(config->group_id < SOC_MCPWM_GROUPS && config->group_id >= 0, ESP_ERR_INVALID_ARG,
|
ESP_GOTO_ON_FALSE(config->group_id < SOC_MCPWM_GROUPS && config->group_id >= 0, ESP_ERR_INVALID_ARG,
|
||||||
err, TAG, "invalid group ID:%d", config->group_id);
|
err, TAG, "invalid group ID:%d", config->group_id);
|
||||||
|
if (config->intr_priority) {
|
||||||
|
ESP_RETURN_ON_FALSE(1 << (config->intr_priority) & MCPWM_ALLOW_INTR_PRIORITY_MASK, ESP_ERR_INVALID_ARG,
|
||||||
|
TAG, "invalid interrupt priority:%d", config->intr_priority);
|
||||||
|
}
|
||||||
|
|
||||||
timer = heap_caps_calloc(1, sizeof(mcpwm_timer_t), MCPWM_MEM_ALLOC_CAPS);
|
timer = heap_caps_calloc(1, sizeof(mcpwm_timer_t), MCPWM_MEM_ALLOC_CAPS);
|
||||||
ESP_GOTO_ON_FALSE(timer, ESP_ERR_NO_MEM, err, TAG, "no mem for timer");
|
ESP_GOTO_ON_FALSE(timer, ESP_ERR_NO_MEM, err, TAG, "no mem for timer");
|
||||||
@ -100,6 +104,11 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
|
|||||||
int group_id = group->group_id;
|
int group_id = group->group_id;
|
||||||
mcpwm_hal_context_t *hal = &group->hal;
|
mcpwm_hal_context_t *hal = &group->hal;
|
||||||
int timer_id = timer->timer_id;
|
int timer_id = timer->timer_id;
|
||||||
|
|
||||||
|
// if interrupt priority specified before, it cannot be changed until the group is released
|
||||||
|
// check if the new priority specified consistents with the old one
|
||||||
|
ESP_GOTO_ON_ERROR(mcpwm_check_intr_priority(group, config->intr_priority), err, TAG, "set group intrrupt priority failed");
|
||||||
|
|
||||||
// select the clock source
|
// select the clock source
|
||||||
mcpwm_timer_clock_source_t clk_src = config->clk_src ? config->clk_src : MCPWM_TIMER_CLK_SRC_DEFAULT;
|
mcpwm_timer_clock_source_t clk_src = config->clk_src ? config->clk_src : MCPWM_TIMER_CLK_SRC_DEFAULT;
|
||||||
ESP_GOTO_ON_ERROR(mcpwm_select_periph_clock(group, (soc_module_clk_t)clk_src), err, TAG, "set group clock failed");
|
ESP_GOTO_ON_ERROR(mcpwm_select_periph_clock(group, (soc_module_clk_t)clk_src), err, TAG, "set group clock failed");
|
||||||
@ -192,6 +201,7 @@ esp_err_t mcpwm_timer_register_event_callbacks(mcpwm_timer_handle_t timer, const
|
|||||||
if (!timer->intr) {
|
if (!timer->intr) {
|
||||||
ESP_RETURN_ON_FALSE(timer->fsm == MCPWM_TIMER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "timer not in init state");
|
ESP_RETURN_ON_FALSE(timer->fsm == MCPWM_TIMER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "timer not in init state");
|
||||||
int isr_flags = MCPWM_INTR_ALLOC_FLAG;
|
int isr_flags = MCPWM_INTR_ALLOC_FLAG;
|
||||||
|
isr_flags |= mcpwm_get_intr_priority_flag(group);
|
||||||
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags,
|
||||||
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_TIMER_MASK(timer_id),
|
(uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_TIMER_MASK(timer_id),
|
||||||
mcpwm_timer_default_isr, timer, &timer->intr), TAG, "install interrupt service for timer failed");
|
mcpwm_timer_default_isr, timer, &timer->intr), TAG, "install interrupt service for timer failed");
|
||||||
|
@ -6,6 +6,7 @@ set(srcs "test_app_main.c"
|
|||||||
"test_mcpwm_oper.c"
|
"test_mcpwm_oper.c"
|
||||||
"test_mcpwm_sync.c"
|
"test_mcpwm_sync.c"
|
||||||
"test_mcpwm_timer.c"
|
"test_mcpwm_timer.c"
|
||||||
|
"test_mcpwm_common.c"
|
||||||
"test_mcpwm_utils.c")
|
"test_mcpwm_utils.c")
|
||||||
|
|
||||||
if(CONFIG_MCPWM_ISR_IRAM_SAFE)
|
if(CONFIG_MCPWM_ISR_IRAM_SAFE)
|
||||||
|
125
components/driver/test_apps/mcpwm/main/test_mcpwm_common.c
Normal file
125
components/driver/test_apps/mcpwm/main/test_mcpwm_common.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "unity.h"
|
||||||
|
#include "esp_private/mcpwm.h"
|
||||||
|
#include "test_mcpwm_utils.h"
|
||||||
|
#include "driver/mcpwm_prelude.h"
|
||||||
|
|
||||||
|
TEST_CASE("mcpwm_set_interrupt_priority", "[mcpwm]")
|
||||||
|
{
|
||||||
|
printf("install timer\r\n");
|
||||||
|
mcpwm_timer_config_t timer_config = {
|
||||||
|
.group_id = 0,
|
||||||
|
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
|
||||||
|
.resolution_hz = 1 * 1000 * 1000,
|
||||||
|
.period_ticks = 20 * 1000,
|
||||||
|
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
|
||||||
|
.intr_priority = 3,
|
||||||
|
};
|
||||||
|
mcpwm_timer_handle_t timer = NULL;
|
||||||
|
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
|
||||||
|
printf("register event callbacks\r\n");
|
||||||
|
mcpwm_timer_event_callbacks_t timer_cbs = {
|
||||||
|
.on_stop = NULL,
|
||||||
|
.on_full = NULL,
|
||||||
|
.on_empty = NULL,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(mcpwm_timer_register_event_callbacks(timer, &timer_cbs, NULL));
|
||||||
|
timer_config.intr_priority = 1;
|
||||||
|
mcpwm_timer_handle_t timer2 = NULL;
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_new_timer(&timer_config, &timer2));
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, mcpwm_timer_register_event_callbacks(timer2, &timer_cbs, NULL));
|
||||||
|
|
||||||
|
printf("install operator\r\n");
|
||||||
|
mcpwm_operator_config_t operator_config = {
|
||||||
|
.group_id = 0,
|
||||||
|
.intr_priority = 0,
|
||||||
|
};
|
||||||
|
mcpwm_oper_handle_t oper = NULL;
|
||||||
|
TEST_ESP_OK(mcpwm_new_operator(&operator_config, &oper));
|
||||||
|
printf("register event callbacks\r\n");
|
||||||
|
mcpwm_operator_event_callbacks_t oper_cbs = {
|
||||||
|
.on_brake_cbc = NULL,
|
||||||
|
.on_brake_ost = NULL,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(mcpwm_operator_register_event_callbacks(oper, &oper_cbs, NULL));
|
||||||
|
operator_config.intr_priority = 1;
|
||||||
|
mcpwm_oper_handle_t oper2 = NULL;
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_new_operator(&operator_config, &oper2));
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, mcpwm_operator_register_event_callbacks(oper2, &oper_cbs, NULL));
|
||||||
|
|
||||||
|
printf("install comparator\r\n");
|
||||||
|
mcpwm_comparator_config_t comparator_config = {
|
||||||
|
.intr_priority = 0,
|
||||||
|
};
|
||||||
|
mcpwm_cmpr_handle_t comparator = NULL;
|
||||||
|
TEST_ESP_OK(mcpwm_new_comparator(oper, &comparator_config, &comparator));
|
||||||
|
TEST_ESP_OK(mcpwm_operator_connect_timer(oper, timer));
|
||||||
|
printf("register event callback\r\n");
|
||||||
|
mcpwm_comparator_event_callbacks_t comparator_cbs = {
|
||||||
|
.on_reach = NULL,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(mcpwm_comparator_register_event_callbacks(comparator, &comparator_cbs, NULL));
|
||||||
|
comparator_config.intr_priority = 1;
|
||||||
|
mcpwm_cmpr_handle_t comparator2 = NULL;
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_new_comparator(oper, &comparator_config, &comparator2));
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, mcpwm_comparator_register_event_callbacks(comparator2, &comparator_cbs, NULL));
|
||||||
|
|
||||||
|
printf("install gpio fault\r\n");
|
||||||
|
const int fault_gpio = 0;
|
||||||
|
mcpwm_fault_handle_t fault = NULL;
|
||||||
|
mcpwm_gpio_fault_config_t gpio_fault_config = {
|
||||||
|
.group_id = 0,
|
||||||
|
.gpio_num = fault_gpio,
|
||||||
|
.intr_priority = 0,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(mcpwm_new_gpio_fault(&gpio_fault_config, &fault));
|
||||||
|
|
||||||
|
printf("register event callback\r\n");
|
||||||
|
mcpwm_fault_event_callbacks_t fault_cbs = {
|
||||||
|
.on_fault_enter = NULL,
|
||||||
|
.on_fault_exit = NULL,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(mcpwm_fault_register_event_callbacks(fault, &fault_cbs, NULL));
|
||||||
|
gpio_fault_config.intr_priority = 1;
|
||||||
|
mcpwm_fault_handle_t fault2 = NULL;
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_new_gpio_fault(&gpio_fault_config, &fault2));
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, mcpwm_fault_register_event_callbacks(fault2, &fault_cbs, NULL));
|
||||||
|
|
||||||
|
printf("install capture timer\r\n");
|
||||||
|
mcpwm_cap_timer_handle_t cap_timer = NULL;
|
||||||
|
mcpwm_capture_timer_config_t cap_timer_config = {
|
||||||
|
.clk_src = MCPWM_CAPTURE_CLK_SRC_DEFAULT,
|
||||||
|
.group_id = 0,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer));
|
||||||
|
printf("install capture\r\n");
|
||||||
|
mcpwm_cap_channel_handle_t cap_channel = NULL;
|
||||||
|
mcpwm_capture_channel_config_t cap_chan_config = {
|
||||||
|
.gpio_num = -1,
|
||||||
|
.prescale = 2,
|
||||||
|
.intr_priority = 3,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &cap_channel));
|
||||||
|
|
||||||
|
printf("register event callback\r\n");
|
||||||
|
mcpwm_capture_event_callbacks_t cap_cbs = {
|
||||||
|
.on_cap = NULL,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(cap_channel, &cap_cbs, NULL));
|
||||||
|
cap_chan_config.intr_priority = 1;
|
||||||
|
mcpwm_cap_channel_handle_t cap_channel2 = NULL;
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &cap_channel2));
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, mcpwm_capture_channel_register_event_callbacks(cap_channel2, &cap_cbs, NULL));
|
||||||
|
|
||||||
|
printf("delete all mcpwm objects\r\n");
|
||||||
|
TEST_ESP_OK(mcpwm_del_comparator(comparator));
|
||||||
|
TEST_ESP_OK(mcpwm_del_operator(oper));
|
||||||
|
TEST_ESP_OK(mcpwm_del_capture_channel(cap_channel));
|
||||||
|
TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer));
|
||||||
|
TEST_ESP_OK(mcpwm_del_timer(timer));
|
||||||
|
TEST_ESP_OK(mcpwm_del_fault(fault));
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -59,6 +59,7 @@ MCPWM Timers
|
|||||||
You can allocate a MCPWM timer object by calling :cpp:func:`mcpwm_new_timer` function, with a configuration structure :cpp:type:`mcpwm_timer_config_t` as the parameter. The configuration structure is defined as:
|
You can allocate a MCPWM timer object by calling :cpp:func:`mcpwm_new_timer` function, with a configuration structure :cpp:type:`mcpwm_timer_config_t` as the parameter. The configuration structure is defined as:
|
||||||
|
|
||||||
- :cpp:member:`mcpwm_timer_config_t::group_id` specifies the MCPWM group ID. The ID should belong to [0, :c:macro:`SOC_MCPWM_GROUPS` - 1] range. Please note, timers located in different groups are totally independent.
|
- :cpp:member:`mcpwm_timer_config_t::group_id` specifies the MCPWM group ID. The ID should belong to [0, :c:macro:`SOC_MCPWM_GROUPS` - 1] range. Please note, timers located in different groups are totally independent.
|
||||||
|
- :cpp:member:`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.
|
||||||
- :cpp:member:`mcpwm_timer_config_t::clk_src` sets the clock source of the timer.
|
- :cpp:member:`mcpwm_timer_config_t::clk_src` sets the clock source of the timer.
|
||||||
- :cpp:member:`mcpwm_timer_config_t::resolution_hz` set the expected resolution of the timer, the driver internally will set a proper divider based on the clock source and the resolution.
|
- :cpp:member:`mcpwm_timer_config_t::resolution_hz` set the expected resolution of the timer, the driver internally will set a proper divider based on the clock source and the resolution.
|
||||||
- :cpp:member:`mcpwm_timer_config_t::count_mode` sets the count mode of the timer.
|
- :cpp:member:`mcpwm_timer_config_t::count_mode` sets the count mode of the timer.
|
||||||
@ -76,6 +77,7 @@ MCPWM Operators
|
|||||||
You can allocate a MCPWM operator object by calling :cpp:func:`mcpwm_new_operator` function, with a configuration structure :cpp:type:`mcpwm_operator_config_t` as the parameter. The configuration structure is defined as:
|
You can allocate a MCPWM operator object by calling :cpp:func:`mcpwm_new_operator` function, with a configuration structure :cpp:type:`mcpwm_operator_config_t` as the parameter. The configuration structure is defined as:
|
||||||
|
|
||||||
- :cpp:member:`mcpwm_operator_config_t::group_id` specifies the MCPWM group ID. The ID should belong to [0, :c:macro:`SOC_MCPWM_GROUPS` - 1] range. Please note, operators located in different groups are totally independent.
|
- :cpp:member:`mcpwm_operator_config_t::group_id` specifies the MCPWM group ID. The ID should belong to [0, :c:macro:`SOC_MCPWM_GROUPS` - 1] range. Please note, operators located in different groups are totally independent.
|
||||||
|
- :cpp:member:`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.
|
||||||
- :cpp:member:`mcpwm_operator_config_t::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 :cpp:func:`mcpwm_operator_connect_timer`.
|
- :cpp:member:`mcpwm_operator_config_t::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 :cpp:func:`mcpwm_operator_connect_timer`.
|
||||||
- :cpp:member:`mcpwm_operator_config_t::update_gen_action_on_tep` sets whether to update the generator action when the timer counts to peak.
|
- :cpp:member:`mcpwm_operator_config_t::update_gen_action_on_tep` sets whether to update the generator action when the timer counts to peak.
|
||||||
- :cpp:member:`mcpwm_operator_config_t::update_gen_action_on_sync` sets whether to update the generator action when the timer takes a sync signal.
|
- :cpp:member:`mcpwm_operator_config_t::update_gen_action_on_sync` sets whether to update the generator action when the timer takes a sync signal.
|
||||||
@ -92,6 +94,7 @@ MCPWM Comparators
|
|||||||
|
|
||||||
You can allocate a MCPWM comparator object by calling :cpp:func:`mcpwm_new_comparator` function, with a MCPWM operator handle and configuration structure :cpp:type:`mcpwm_comparator_config_t` as the parameter. The operator handle is created by :cpp:func:`mcpwm_new_operator`. The configuration structure is defined as:
|
You can allocate a MCPWM comparator object by calling :cpp:func:`mcpwm_new_comparator` function, with a MCPWM operator handle and configuration structure :cpp:type:`mcpwm_comparator_config_t` as the parameter. The operator handle is created by :cpp:func:`mcpwm_new_operator`. The configuration structure is defined as:
|
||||||
|
|
||||||
|
- :cpp:member:`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.
|
||||||
- :cpp:member:`mcpwm_comparator_config_t::update_cmp_on_tez` sets whether to update the compare threshold when the timer counts to zero.
|
- :cpp:member:`mcpwm_comparator_config_t::update_cmp_on_tez` sets whether to update the compare threshold when the timer counts to zero.
|
||||||
- :cpp:member:`mcpwm_comparator_config_t::update_cmp_on_tep` sets whether to update the compare threshold when the timer counts to peak.
|
- :cpp:member:`mcpwm_comparator_config_t::update_cmp_on_tep` sets whether to update the compare threshold when the timer counts to peak.
|
||||||
- :cpp:member:`mcpwm_comparator_config_t::update_cmp_on_sync` sets whether to update the compare threshold when the timer takes a sync signal.
|
- :cpp:member:`mcpwm_comparator_config_t::update_cmp_on_sync` sets whether to update the compare threshold when the timer takes a sync signal.
|
||||||
@ -120,7 +123,10 @@ 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 :cpp:func:`mcpwm_new_gpio_fault` function, with configuration structure :cpp:type:`mcpwm_gpio_fault_config_t` as the parameter. The configuration structure is defined as:
|
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 :cpp:func:`mcpwm_new_gpio_fault` function, with configuration structure :cpp:type:`mcpwm_gpio_fault_config_t` as the parameter. The configuration structure is defined as:
|
||||||
|
|
||||||
- :cpp:member:`mcpwm_gpio_fault_config_t::group_id` sets the MCPWM group ID. The ID should belong to [0, :c:macro:`SOC_MCPWM_GROUPS` - 1] range. Please note, GPIO fault located in different groups are totally independent, i.e. GPIO fault in group 0 can not be detected by the operator in group 1.
|
To allocate a GPIO fault object, you can call the :cpp:func:`mcpwm_new_gpio_fault` function, with the configuration structure :cpp:type:`mcpwm_gpio_fault_config_t` as the parameter. The configuration structure is defined as:
|
||||||
|
|
||||||
|
- :cpp:member:`mcpwm_gpio_fault_config_t::group_id` sets the MCPWM group ID. The ID should belong to [0, :c:macro:`SOC_MCPWM_GROUPS` - 1] range. 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.
|
||||||
|
- :cpp:member:`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.
|
||||||
- :cpp:member:`mcpwm_gpio_fault_config_t::gpio_num` sets the GPIO number used by the fault.
|
- :cpp:member:`mcpwm_gpio_fault_config_t::gpio_num` sets the GPIO number used by the fault.
|
||||||
- :cpp:member:`mcpwm_gpio_fault_config_t::active_level` sets the active level of the fault signal.
|
- :cpp:member:`mcpwm_gpio_fault_config_t::active_level` sets the active level of the fault signal.
|
||||||
- :cpp:member:`mcpwm_gpio_fault_config_t::pull_up` and :cpp:member:`mcpwm_gpio_fault_config_t::pull_down` set whether to pull up and/or pull down the GPIO internally.
|
- :cpp:member:`mcpwm_gpio_fault_config_t::pull_up` and :cpp:member:`mcpwm_gpio_fault_config_t::pull_down` set whether to pull up and/or pull down the GPIO internally.
|
||||||
@ -172,6 +178,7 @@ The :cpp:func:`mcpwm_new_capture_timer` will return a pointer to the allocated c
|
|||||||
|
|
||||||
Next, to allocate a capture channel, you can call :cpp:func:`mcpwm_new_capture_channel` function, with a capture timer handle and configuration structure :cpp:type:`mcpwm_capture_channel_config_t` as the parameter. The configuration structure is defined as:
|
Next, to allocate a capture channel, you can call :cpp:func:`mcpwm_new_capture_channel` function, with a capture timer handle and configuration structure :cpp:type:`mcpwm_capture_channel_config_t` as the parameter. The configuration structure is defined as:
|
||||||
|
|
||||||
|
- :cpp:member:`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.
|
||||||
- :cpp:member:`mcpwm_capture_channel_config_t::gpio_num` sets the GPIO number used by the capture channel.
|
- :cpp:member:`mcpwm_capture_channel_config_t::gpio_num` sets the GPIO number used by the capture channel.
|
||||||
- :cpp:member:`mcpwm_capture_channel_config_t::prescale` sets the prescaler of the input signal.
|
- :cpp:member:`mcpwm_capture_channel_config_t::prescale` sets the prescaler of the input signal.
|
||||||
- :cpp:member:`mcpwm_capture_channel_config_t::pos_edge` and :cpp:member:`mcpwm_capture_channel_config_t::neg_edge` set whether to capture on the positive and/or negative edge of the input signal.
|
- :cpp:member:`mcpwm_capture_channel_config_t::pos_edge` and :cpp:member:`mcpwm_capture_channel_config_t::neg_edge` set whether to capture on the positive and/or negative edge of the input signal.
|
||||||
@ -181,7 +188,19 @@ Next, to allocate a capture channel, you can call :cpp:func:`mcpwm_new_capture_c
|
|||||||
|
|
||||||
The :cpp:func:`mcpwm_new_capture_channel` will return a pointer to the allocated capture channel object if the allocation succeeds. Otherwise, it will return error code. Specifically, when there are no free capture channel left in the capture timer, this function will return :c:macro:`ESP_ERR_NOT_FOUND` error.
|
The :cpp:func:`mcpwm_new_capture_channel` will return a pointer to the allocated capture channel object if the allocation succeeds. Otherwise, it will return error code. Specifically, when there are no free capture channel left in the capture timer, this function will return :c:macro:`ESP_ERR_NOT_FOUND` error.
|
||||||
|
|
||||||
On the contrary, calling :cpp:func:`mcpwm_del_capture_channel` and :cpp:func:`mcpwm_del_capture_timer` function will free the allocated capture channel and timer object accordingly.
|
On the contrary, calling :cpp:func:`mcpwm_del_capture_channel` and :cpp:func:`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.
|
||||||
|
|
||||||
|
|
||||||
|
.. _mcpwm-timer-operations-and-events:
|
||||||
|
|
||||||
Timer Operations and Events
|
Timer Operations and Events
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Loading…
Reference in New Issue
Block a user