Merge branch 'feature/mcpwm_trigger_driver_v5.0' into 'release/v5.0'

feature(MCPWM): Add MCPWM trigger driver (v5.0)

See merge request espressif/esp-idf!26788
This commit is contained in:
morris 2023-11-23 14:33:20 +08:00
commit 3bb601cee7
8 changed files with 436 additions and 8 deletions

View File

@ -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, ...); 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 * @brief MCPWM dead time configuration structure
*/ */

View File

@ -258,6 +258,60 @@ esp_err_t mcpwm_generator_set_actions_on_brake_event(mcpwm_gen_handle_t gen, mcp
return ESP_OK; 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_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"); ESP_RETURN_ON_FALSE(in_generator && out_generator && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");

View File

@ -93,6 +93,12 @@ struct mcpwm_timer_t {
void *user_data; // user data which would be passed to the timer callbacks 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 { struct mcpwm_oper_t {
int oper_id; // operator ID, index from 0 int oper_id; // operator ID, index from 0
mcpwm_group_t *group; // which group the timer belongs to mcpwm_group_t *group; // which group the timer belongs to
@ -101,6 +107,7 @@ struct mcpwm_oper_t {
intr_handle_t intr; // interrupt handle intr_handle_t intr; // interrupt handle
mcpwm_gen_t *generators[SOC_MCPWM_GENERATORS_PER_OPERATOR]; // mcpwm generator array 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_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_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_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 mcpwm_operator_brake_mode_t brake_mode_on_gpio_fault[SOC_MCPWM_GPIO_FAULTS_PER_GROUP]; // brake mode on GPIO triggered faults

View File

@ -11,6 +11,8 @@
#include "driver/mcpwm_oper.h" #include "driver/mcpwm_oper.h"
#include "driver/mcpwm_cmpr.h" #include "driver/mcpwm_cmpr.h"
#include "driver/mcpwm_gen.h" #include "driver/mcpwm_gen.h"
#include "driver/mcpwm_fault.h"
#include "driver/mcpwm_sync.h"
#include "driver/gpio.h" #include "driver/gpio.h"
TEST_CASE("mcpwm_generator_install_uninstall", "[mcpwm]") TEST_CASE("mcpwm_generator_install_uninstall", "[mcpwm]")
@ -761,3 +763,278 @@ TEST_CASE("mcpwm_duty_empty_full", "[mcpwm]")
TEST_ESP_OK(mcpwm_del_operator(oper)); TEST_ESP_OK(mcpwm_del_operator(oper));
TEST_ESP_OK(mcpwm_del_timer(timer)); TEST_ESP_OK(mcpwm_del_timer(timer));
} }
TEST_CASE("mcpwm_generator_action_on_fault_trigger_event", "[mcpwm]")
{
const int generator_gpio = 0;
const int fault_gpio_num[3] = {2, 4, 5};
printf("create timer and operator\r\n");
mcpwm_timer_config_t timer_config = {
.group_id = 0,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = 1000000,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
.period_ticks = 1000,
};
mcpwm_timer_handle_t timer = NULL;
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
mcpwm_operator_config_t oper_config = {
.group_id = 0,
};
mcpwm_oper_handle_t oper = NULL;
TEST_ESP_OK(mcpwm_new_operator(&oper_config, &oper));
printf("connect timer and operator\r\n");
TEST_ESP_OK(mcpwm_operator_connect_timer(oper, timer));
printf("install gpio faults trigger\r\n");
mcpwm_fault_handle_t gpio_faults[3];
mcpwm_gpio_fault_config_t gpio_fault_config = {
.group_id = 0,
.flags.active_level = 1,
.flags.pull_down = 1,
.flags.pull_up = 0,
.flags.io_loop_back = 1, // so that we can write the GPIO value by GPIO driver
};
for (int i = 0 ; i < 3; i++) {
gpio_fault_config.gpio_num = fault_gpio_num[i];
TEST_ESP_OK(mcpwm_new_gpio_fault(&gpio_fault_config, &gpio_faults[i]));
}
printf("create generator\r\n");
mcpwm_generator_config_t gen_config = {
.gen_gpio_num = generator_gpio,
.flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver
};
mcpwm_gen_handle_t gen = NULL;
TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen));
printf("set generator to output high on trigger0 and low on trigger1\r\n");
TEST_ESP_OK(mcpwm_generator_set_action_on_fault_event(gen,
MCPWM_GEN_FAULT_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, gpio_faults[0], MCPWM_GEN_ACTION_HIGH)));
TEST_ESP_OK(mcpwm_generator_set_action_on_fault_event(gen,
MCPWM_GEN_FAULT_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, gpio_faults[1], MCPWM_GEN_ACTION_LOW)));
// no free trigger
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, mcpwm_generator_set_action_on_fault_event(gen,
MCPWM_GEN_FAULT_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, gpio_faults[2], MCPWM_GEN_ACTION_LOW)));
TEST_ASSERT_EQUAL(0, gpio_get_level(generator_gpio));
gpio_set_level(fault_gpio_num[0], 1);
gpio_set_level(fault_gpio_num[0], 0);
TEST_ASSERT_EQUAL(1, gpio_get_level(generator_gpio));
vTaskDelay(pdMS_TO_TICKS(10));
TEST_ASSERT_EQUAL(1, gpio_get_level(generator_gpio));
gpio_set_level(fault_gpio_num[1], 1);
gpio_set_level(fault_gpio_num[1], 0);
TEST_ASSERT_EQUAL(0, gpio_get_level(generator_gpio));
vTaskDelay(pdMS_TO_TICKS(10));
printf("delete falut trigger, operator, generator\r\n");
TEST_ESP_OK(mcpwm_del_fault(gpio_faults[0]));
TEST_ESP_OK(mcpwm_del_fault(gpio_faults[1]));
TEST_ESP_OK(mcpwm_del_fault(gpio_faults[2]));
TEST_ESP_OK(mcpwm_del_generator(gen));
TEST_ESP_OK(mcpwm_del_operator(oper));
TEST_ESP_OK(mcpwm_del_timer(timer));
}
TEST_CASE("mcpwm_generator_action_on_soft_sync_trigger_event", "[mcpwm]")
{
const int generator_gpio = 0;
printf("create timer and operator\r\n");
mcpwm_timer_config_t timer_config = {
.group_id = 0,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = 1000000,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
.period_ticks = 1000,
};
mcpwm_timer_handle_t timer = NULL;
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
mcpwm_operator_config_t oper_config = {
.group_id = 0,
};
mcpwm_oper_handle_t oper = NULL;
TEST_ESP_OK(mcpwm_new_operator(&oper_config, &oper));
printf("connect timer and operator\r\n");
TEST_ESP_OK(mcpwm_operator_connect_timer(oper, timer));
printf("install soft sync source trigger\r\n");
mcpwm_sync_handle_t soft_sync = NULL;
mcpwm_soft_sync_config_t soft_sync_config = {};
TEST_ESP_OK(mcpwm_new_soft_sync_src(&soft_sync_config, &soft_sync));
mcpwm_timer_sync_phase_config_t sync_phase_config = {
.count_value = 0,
.direction = MCPWM_TIMER_DIRECTION_UP,
.sync_src = soft_sync,
};
TEST_ESP_OK(mcpwm_timer_set_phase_on_sync(timer, &sync_phase_config));
printf("create generator\r\n");
mcpwm_generator_config_t gen_config = {
.gen_gpio_num = generator_gpio,
.flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver
};
mcpwm_gen_handle_t gen = NULL;
TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen));
printf("set generator to output high on soft sync trigger\r\n");
TEST_ESP_OK(mcpwm_generator_set_action_on_sync_event(gen,
MCPWM_GEN_SYNC_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, soft_sync, MCPWM_GEN_ACTION_HIGH)));
//more than 1 sync is not supported
mcpwm_sync_handle_t invalid_soft_sync = NULL;
TEST_ESP_OK(mcpwm_new_soft_sync_src(&soft_sync_config, &invalid_soft_sync));
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_generator_set_action_on_sync_event(gen,
MCPWM_GEN_SYNC_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, invalid_soft_sync, MCPWM_GEN_ACTION_LOW)));
TEST_ASSERT_EQUAL(0, gpio_get_level(generator_gpio));
mcpwm_soft_sync_activate(soft_sync);
TEST_ASSERT_EQUAL(1, gpio_get_level(generator_gpio));
vTaskDelay(pdMS_TO_TICKS(10));
printf("delete soft sync trigger, timer, operator, generator\r\n");
TEST_ESP_OK(mcpwm_del_sync_src(soft_sync));
TEST_ESP_OK(mcpwm_del_sync_src(invalid_soft_sync));
TEST_ESP_OK(mcpwm_del_generator(gen));
TEST_ESP_OK(mcpwm_del_operator(oper));
TEST_ESP_OK(mcpwm_del_timer(timer));
}
TEST_CASE("mcpwm_generator_action_on_timer_sync_trigger_event", "[mcpwm]")
{
const int generator_gpio = 0;
printf("create timer and operator\r\n");
mcpwm_timer_config_t timer_config = {
.group_id = 0,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = 1000000,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
.period_ticks = 1000,
};
mcpwm_timer_handle_t timer = NULL;
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
mcpwm_operator_config_t oper_config = {
.group_id = 0,
};
mcpwm_oper_handle_t oper = NULL;
TEST_ESP_OK(mcpwm_new_operator(&oper_config, &oper));
printf("connect timer and operator\r\n");
TEST_ESP_OK(mcpwm_operator_connect_timer(oper, timer));
printf("install timer sync source trigger\r\n");
mcpwm_sync_handle_t timer_sync = NULL;
mcpwm_timer_sync_src_config_t timer_sync_config = {
.timer_event = MCPWM_TIMER_EVENT_EMPTY,
};
TEST_ESP_OK(mcpwm_new_timer_sync_src(timer, &timer_sync_config, &timer_sync));
mcpwm_timer_sync_phase_config_t sync_phase_config = {
.count_value = 0,
.direction = MCPWM_TIMER_DIRECTION_UP,
.sync_src = timer_sync,
};
TEST_ESP_OK(mcpwm_timer_set_phase_on_sync(timer, &sync_phase_config));
printf("create generator\r\n");
mcpwm_generator_config_t gen_config = {
.gen_gpio_num = generator_gpio,
.flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver
};
mcpwm_gen_handle_t gen = NULL;
TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen));
printf("set generator to output high on timer sync trigger\r\n");
TEST_ESP_OK(mcpwm_generator_set_action_on_sync_event(gen,
MCPWM_GEN_SYNC_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, timer_sync, MCPWM_GEN_ACTION_HIGH)));
TEST_ESP_OK(mcpwm_timer_enable(timer));
TEST_ASSERT_EQUAL(0, gpio_get_level(generator_gpio));
TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_STOP_FULL));
TEST_ASSERT_EQUAL(1, gpio_get_level(generator_gpio));
vTaskDelay(pdMS_TO_TICKS(10));
printf("delete timer sync trigger, timer, operator, generator\r\n");
TEST_ESP_OK(mcpwm_timer_disable(timer));
TEST_ESP_OK(mcpwm_del_sync_src(timer_sync));
TEST_ESP_OK(mcpwm_del_generator(gen));
TEST_ESP_OK(mcpwm_del_operator(oper));
TEST_ESP_OK(mcpwm_del_timer(timer));
}
TEST_CASE("mcpwm_generator_action_on_gpio_sync_trigger_event", "[mcpwm]")
{
const int generator_gpio = 0;
printf("create timer and operator\r\n");
mcpwm_timer_config_t timer_config = {
.group_id = 0,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = 1000000,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
.period_ticks = 1000,
};
mcpwm_timer_handle_t timer = NULL;
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
mcpwm_operator_config_t oper_config = {
.group_id = 0,
};
mcpwm_oper_handle_t oper = NULL;
TEST_ESP_OK(mcpwm_new_operator(&oper_config, &oper));
printf("connect timer and operator\r\n");
TEST_ESP_OK(mcpwm_operator_connect_timer(oper, timer));
printf("install gpio sync source trigger\r\n");
mcpwm_sync_handle_t gpio_sync = NULL;
mcpwm_gpio_sync_src_config_t gpio_sync_config = {
.group_id = 0,
.gpio_num = 2,
.flags.io_loop_back = true, // so that we can use gpio driver to simulate the sync signal
.flags.pull_down = true, // internally pull down
};
TEST_ESP_OK(mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync));
// put the GPIO into initial state
gpio_set_level(gpio_sync_config.gpio_num, 0);
mcpwm_timer_sync_phase_config_t sync_phase_config = {
.count_value = 0,
.direction = MCPWM_TIMER_DIRECTION_UP,
.sync_src = gpio_sync,
};
TEST_ESP_OK(mcpwm_timer_set_phase_on_sync(timer, &sync_phase_config));
printf("create generator\r\n");
mcpwm_generator_config_t gen_config = {
.gen_gpio_num = generator_gpio,
.flags.io_loop_back = 1, // so that we can read the GPIO value by GPIO driver
};
mcpwm_gen_handle_t gen = NULL;
TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen));
printf("set generator to output high on gpio sync trigger\r\n");
TEST_ESP_OK(mcpwm_generator_set_action_on_sync_event(gen,
MCPWM_GEN_SYNC_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, gpio_sync, MCPWM_GEN_ACTION_HIGH)));
TEST_ASSERT_EQUAL(0, gpio_get_level(generator_gpio));
gpio_set_level(gpio_sync_config.gpio_num, 1);
gpio_set_level(gpio_sync_config.gpio_num, 0);
TEST_ASSERT_EQUAL(1, gpio_get_level(generator_gpio));
vTaskDelay(pdMS_TO_TICKS(10));
printf("delete gpio sync trigger, timer, operator, generator\r\n");
TEST_ESP_OK(mcpwm_del_sync_src(gpio_sync));
TEST_ESP_OK(mcpwm_del_generator(gen));
TEST_ESP_OK(mcpwm_del_operator(oper));
TEST_ESP_OK(mcpwm_del_timer(timer));
}

View File

@ -667,20 +667,20 @@ static inline void mcpwm_ll_operator_stop_update_action(mcpwm_dev_t *mcpwm, int
* @param trig_id Trigger ID, index from 0 to 1 * @param trig_id Trigger ID, index from 0 to 1
* @param fault_gpio_id Fault GPIO ID, index from 0 to 3 * @param fault_gpio_id Fault GPIO ID, index from 0 to 3
*/ */
static inline void mcpwm_ll_operator_set_trigger_from_gpio(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_gpio_id) static inline void mcpwm_ll_operator_set_trigger_from_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_gpio_id)
{ {
mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
mcpwm->operators[operator_id].gen_cfg0.val |= (fault_gpio_id << (4 + 3 * trig_id)); mcpwm->operators[operator_id].gen_cfg0.val |= (fault_gpio_id << (4 + 3 * trig_id));
} }
/** /**
* @brief Set trigger from timer sync event (when the timer taken the sync signal) * @brief Set trigger from sync event (when the timer/gpio/soft taken the sync signal)
* *
* @param mcpwm Peripheral instance address * @param mcpwm Peripheral instance address
* @param operator_id Operator ID, index from 0 to 2 * @param operator_id Operator ID, index from 0 to 2
* @param trig_id Trigger ID, index from 0 to 1 * @param trig_id Trigger ID, index from 0 to 1
*/ */
static inline void mcpwm_ll_operator_set_trigger_from_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id) static inline void mcpwm_ll_operator_set_trigger_from_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id)
{ {
// the timer here is not selectable, must be the one connected with the operator // the timer here is not selectable, must be the one connected with the operator
mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));

View File

@ -679,20 +679,20 @@ static inline void mcpwm_ll_operator_stop_update_action(mcpwm_dev_t *mcpwm, int
* @param trig_id Trigger ID, index from 0 to 1 * @param trig_id Trigger ID, index from 0 to 1
* @param fault_gpio_id Fault GPIO ID, index from 0 to 3 * @param fault_gpio_id Fault GPIO ID, index from 0 to 3
*/ */
static inline void mcpwm_ll_operator_set_trigger_from_gpio(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_gpio_id) static inline void mcpwm_ll_operator_set_trigger_from_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_gpio_id)
{ {
mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
mcpwm->operators[operator_id].gen_cfg0.val |= (fault_gpio_id << (4 + 3 * trig_id)); mcpwm->operators[operator_id].gen_cfg0.val |= (fault_gpio_id << (4 + 3 * trig_id));
} }
/** /**
* @brief Set trigger from timer sync event (when the timer taken the sync signal) * @brief Set trigger from sync event (when the timer/gpio/soft taken the sync signal)
* *
* @param mcpwm Peripheral instance address * @param mcpwm Peripheral instance address
* @param operator_id Operator ID, index from 0 to 2 * @param operator_id Operator ID, index from 0 to 2
* @param trig_id Trigger ID, index from 0 to 1 * @param trig_id Trigger ID, index from 0 to 1
*/ */
static inline void mcpwm_ll_operator_set_trigger_from_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id) static inline void mcpwm_ll_operator_set_trigger_from_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id)
{ {
// the timer here is not selectable, must be the one connected with the operator // the timer here is not selectable, must be the one connected with the operator
mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));

View File

@ -93,7 +93,7 @@ typedef enum {
*/ */
typedef enum { typedef enum {
MCPWM_OPER_BRAKE_MODE_CBC, /*!< Brake mode: CBC (cycle by cycle)*/ MCPWM_OPER_BRAKE_MODE_CBC, /*!< Brake mode: CBC (cycle by cycle)*/
MCPWM_OPER_BRAKE_MODE_OST, /*!< Brake mode, OST (one shot) */ MCPWM_OPER_BRAKE_MODE_OST, /*!< Brake mode: OST (one shot) */
MCPWM_OPER_BRAKE_MODE_INVALID, /*!< MCPWM operator invalid brake mode */ MCPWM_OPER_BRAKE_MODE_INVALID, /*!< MCPWM operator invalid brake mode */
} mcpwm_operator_brake_mode_t; } mcpwm_operator_brake_mode_t;

View File

@ -301,7 +301,41 @@ Please note, the argument list of :cpp:func:`mcpwm_generator_set_actions_on_comp
You can also set the compare action one by one by calling :cpp:func:`mcpwm_generator_set_action_on_compare_event` without varargs. You can also set the compare action one by one by calling :cpp:func:`mcpwm_generator_set_action_on_compare_event` without varargs.
Generator Configurations for Classical PWM Waveforms Set Generator Action on Fault Event
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
One generator can set action on fault based trigger events, by calling :cpp:func:`mcpwm_generator_set_action_on_fault_event` with an action configurations. The action configuration is defined in :cpp:type:`mcpwm_gen_fault_event_action_t`:
- :cpp:member:`mcpwm_gen_fault_event_action_t::direction` specifies the timer direction. The supported directions are listed in :cpp:type:`mcpwm_timer_direction_t`.
- :cpp:member:`mcpwm_gen_fault_event_action_t::fault` specifies the fault used for the trigger. See `MCPWM Faults <#mcpwm-faults>`__ for how to allocate a fault.
- :cpp:member:`mcpwm_gen_fault_event_action_t::action` specifies the generator action to be taken. The supported actions are listed in :cpp:type:`mcpwm_generator_action_t`.
When no free trigger slot is left in the operator to which the generator belongs, this function will return the :c:macro:`ESP_ERR_NOT_FOUND` error. [1]_
The trigger only support GPOI fault. when the input is not a GPIO fault, this function will return the :c:macro:`ESP_ERR_NOT_SUPPORTED` error.
There's a helper macro :c:macro:`MCPWM_GEN_FAULT_EVENT_ACTION` to simplify the construction of a trigger event action entry.
Please note, fault event does not have variadic function like :cpp:func:`mcpwm_generator_set_actions_on_fault_event`.
Set Generator Action on Sync Event
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
One generator can set action on sync based trigger events, by calling :cpp:func:`mcpwm_generator_set_action_on_sync_event` with an action configurations. The action configuration is defined in :cpp:type:`mcpwm_gen_sync_event_action_t`:
- :cpp:member:`mcpwm_gen_sync_event_action_t::direction` specifies the timer direction. The supported directions are listed in :cpp:type:`mcpwm_timer_direction_t`.
- :cpp:member:`mcpwm_gen_sync_event_action_t::sync` specifies the sync source used for the trigger. See `MCPWM Sync Sources <#mcpwm-sync-sources>`__ for how to allocate a sync source.
- :cpp:member:`mcpwm_gen_sync_event_action_t::action` specifies the generator action to be taken. The supported actions are listed in :cpp:type:`mcpwm_generator_action_t`.
When no free trigger slot is left in the operator to which the generator belongs, this function will return the :c:macro:`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 :c:macro:`ESP_ERR_INVALID_STATE` error.
There's a helper macro :c:macro:`MCPWM_GEN_SYNC_EVENT_ACTION` to simplify the construction of a trigger event action entry.
Please note, sync event does not have variadic function like :cpp:func:`mcpwm_generator_set_actions_on_sync_event`.
Classical PWM Waveforms and Generator Configurations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This section will demonstrate the classical PWM waveforms that can be generated by the pair of the generators. The code snippet that is used to generate the waveforms is also provided below the diagram. Some general summary: This section will demonstrate the classical PWM waveforms that can be generated by the pair of the generators. The code snippet that is used to generate the waveforms is also provided below the diagram. Some general summary: