Skip to content

Commit

Permalink
Merge branch 'feature/mcpwm_trigger_driver_v5.1' into 'release/v5.1'
Browse files Browse the repository at this point in the history
feature(MCPWM): Add MCPWM trigger driver (v5.1)

See merge request espressif/esp-idf!26787
  • Loading branch information
suda-morris committed Nov 17, 2023
2 parents 472718d + 0ce2683 commit a32f0cf
Show file tree
Hide file tree
Showing 10 changed files with 442 additions and 14 deletions.
56 changes: 56 additions & 0 deletions components/driver/mcpwm/include/driver/mcpwm_gen.h
Expand Up @@ -205,6 +205,62 @@ esp_err_t mcpwm_generator_set_action_on_brake_event(mcpwm_gen_handle_t generator
*/
esp_err_t mcpwm_generator_set_actions_on_brake_event(mcpwm_gen_handle_t generator, mcpwm_gen_brake_event_action_t ev_act, ...);

/**
* @brief Generator action on specific fault event
*/
typedef struct {
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 */
} mcpwm_gen_fault_event_action_t;

/**
* @brief Help macros to construct a mcpwm_gen_fault_event_action_t entry
*/
#define MCPWM_GEN_FAULT_EVENT_ACTION(dir, flt, act) \
(mcpwm_gen_fault_event_action_t) { .direction = dir, .fault = flt, .action = act }

/**
* @brief Set generator action on MCPWM Fault event
*
* @param[in] generator MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] ev_act MCPWM trigger event action, can be constructed by `MCPWM_GEN_FAULT_EVENT_ACTION` helper macro
* @return
* - 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);

/**
* @brief Generator action on specific sync event
*/
typedef struct {
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 */
} mcpwm_gen_sync_event_action_t;

/**
* @brief Help macros to construct a mcpwm_gen_sync_event_action_t entry
*/
#define MCPWM_GEN_SYNC_EVENT_ACTION(dir, syn, act) \
(mcpwm_gen_sync_event_action_t) { .direction = dir, .sync = syn, .action = act }

/**
* @brief 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.
*
* @param[in] generator MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] ev_act MCPWM trigger event action, can be constructed by `MCPWM_GEN_SYNC_EVENT_ACTION` helper macro
* @return
* - 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);

/**
* @brief MCPWM dead time configuration structure
*/
Expand Down
54 changes: 54 additions & 0 deletions components/driver/mcpwm/mcpwm_gen.c
Expand Up @@ -258,6 +258,60 @@ esp_err_t mcpwm_generator_set_actions_on_brake_event(mcpwm_gen_handle_t gen, mcp
return ESP_OK;
}

esp_err_t mcpwm_generator_set_action_on_fault_event(mcpwm_gen_handle_t gen, mcpwm_gen_fault_event_action_t ev_act)
{
ESP_RETURN_ON_FALSE(gen, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
mcpwm_fault_t *fault = ev_act.fault;
ESP_RETURN_ON_FALSE(fault->type == MCPWM_FAULT_TYPE_GPIO, ESP_ERR_NOT_SUPPORTED, TAG, "not supported fault type");
mcpwm_oper_t *oper = gen->oper;
mcpwm_group_t *group = oper->group;
// check the remained triggers
int trigger_id = -1;
portENTER_CRITICAL(&oper->spinlock);
for (int i = 0; i < SOC_MCPWM_TRIGGERS_PER_OPERATOR; i++) {
if (oper->triggers[i] == MCPWM_TRIGGER_NO_ASSIGN) {
trigger_id = i;
oper->triggers[i] = MCPWM_TRIGGER_GPIO_FAULT;
break;
}
}
portEXIT_CRITICAL(&oper->spinlock);
ESP_RETURN_ON_FALSE(trigger_id >= 0, ESP_ERR_NOT_FOUND, TAG, "no free trigger in operator (%d,%d)", group->group_id, oper->oper_id);
mcpwm_gpio_fault_t *gpio_fault = __containerof(fault, mcpwm_gpio_fault_t, base);
mcpwm_ll_operator_set_trigger_from_gpio_fault(group->hal.dev, oper->oper_id, trigger_id, gpio_fault->fault_id);
mcpwm_ll_generator_set_action_on_trigger_event(group->hal.dev, oper->oper_id, gen->gen_id,
ev_act.direction, trigger_id, ev_act.action);
return ESP_OK;
}

esp_err_t mcpwm_generator_set_action_on_sync_event(mcpwm_gen_handle_t gen, mcpwm_gen_sync_event_action_t ev_act)
{
ESP_RETURN_ON_FALSE(gen, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
mcpwm_oper_t *oper = gen->oper;
mcpwm_group_t *group = oper->group;
// check the remained triggers
int trigger_id = -1;
int trigger_sync_used = 0;
portENTER_CRITICAL(&oper->spinlock);
for (int i = 0; i < SOC_MCPWM_TRIGGERS_PER_OPERATOR; i++) {
if (oper->triggers[i] == MCPWM_TRIGGER_SYNC_EVENT) {
trigger_sync_used = 1;
break;
} else if (oper->triggers[i] == MCPWM_TRIGGER_NO_ASSIGN) {
trigger_id = i;
oper->triggers[i] = MCPWM_TRIGGER_SYNC_EVENT;
break;
}
}
portEXIT_CRITICAL(&oper->spinlock);
ESP_RETURN_ON_FALSE(!trigger_sync_used, ESP_ERR_INVALID_STATE, TAG, "only one sync supported");
ESP_RETURN_ON_FALSE(trigger_id >= 0, ESP_ERR_NOT_FOUND, TAG, "no free trigger in operator (%d,%d)", group->group_id, oper->oper_id);
mcpwm_ll_operator_set_trigger_from_sync(group->hal.dev, oper->oper_id, trigger_id);
mcpwm_ll_generator_set_action_on_trigger_event(group->hal.dev, oper->oper_id, gen->gen_id,
ev_act.direction, trigger_id, ev_act.action);
return ESP_OK;
}

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)
{
ESP_RETURN_ON_FALSE(in_generator && out_generator && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
Expand Down
7 changes: 7 additions & 0 deletions components/driver/mcpwm/mcpwm_private.h
Expand Up @@ -94,6 +94,12 @@ struct mcpwm_timer_t {
void *user_data; // user data which would be passed to the timer callbacks
};

typedef enum {
MCPWM_TRIGGER_NO_ASSIGN, //default trigger source
MCPWM_TRIGGER_GPIO_FAULT, //trigger assigned to gpio fault
MCPWM_TRIGGER_SYNC_EVENT, //trigger assigned to sync event
} mcpwm_trigger_source_t;

struct mcpwm_oper_t {
int oper_id; // operator ID, index from 0
mcpwm_group_t *group; // which group the timer belongs to
Expand All @@ -102,6 +108,7 @@ struct mcpwm_oper_t {
intr_handle_t intr; // interrupt handle
mcpwm_gen_t *generators[SOC_MCPWM_GENERATORS_PER_OPERATOR]; // mcpwm generator array
mcpwm_cmpr_t *comparators[SOC_MCPWM_COMPARATORS_PER_OPERATOR]; // mcpwm comparator array
mcpwm_trigger_source_t triggers[SOC_MCPWM_TRIGGERS_PER_OPERATOR]; // mcpwm trigger array, can be either a fault or a sync
mcpwm_soft_fault_t *soft_fault; // mcpwm software fault
mcpwm_operator_brake_mode_t brake_mode_on_soft_fault; // brake mode on software triggered fault
mcpwm_operator_brake_mode_t brake_mode_on_gpio_fault[SOC_MCPWM_GPIO_FAULTS_PER_GROUP]; // brake mode on GPIO triggered faults
Expand Down

0 comments on commit a32f0cf

Please sign in to comment.