feature(MCPWM): Add MCPWM trigger driver and test

Each MCPWM operator has two Trigger (named T0 and T1), and they can be
routed to GPIO fault signal or timer sync event.Generator can be set up
to perform different action on Trigger event.
This commit add a trigger driver and a test for the driver.
This commit is contained in:
Chen Jichang
2023-07-25 14:44:41 +08:00
parent 3fca9b778a
commit 5ab755915b
11 changed files with 466 additions and 17 deletions
@@ -202,6 +202,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
*/
+54
View File
@@ -257,6 +257,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");
+7
View File
@@ -90,6 +90,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
@@ -98,6 +104,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