mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/mcpwm_trigger_driver_v5.1' into 'release/v5.1'
feature(MCPWM): Add MCPWM trigger driver (v5.1) See merge request espressif/esp-idf!26787
This commit is contained in:
commit
a32f0cf11e
@ -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
|
||||
*/
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
@ -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
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "driver/mcpwm_oper.h"
|
||||
#include "driver/mcpwm_cmpr.h"
|
||||
#include "driver/mcpwm_gen.h"
|
||||
#include "driver/mcpwm_fault.h"
|
||||
#include "driver/mcpwm_sync.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
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_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));
|
||||
}
|
||||
|
@ -696,20 +696,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 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 |= (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 operator_id Operator ID, index from 0 to 2
|
||||
* @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
|
||||
mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
|
||||
|
@ -719,20 +719,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 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 |= (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 operator_id Operator ID, index from 0 to 2
|
||||
* @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
|
||||
mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
|
||||
|
@ -717,20 +717,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 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 |= (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 operator_id Operator ID, index from 0 to 2
|
||||
* @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
|
||||
mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
|
||||
|
@ -708,20 +708,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 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 |= (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 operator_id Operator ID, index from 0 to 2
|
||||
* @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
|
||||
mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
|
||||
|
@ -93,7 +93,7 @@ typedef enum {
|
||||
*/
|
||||
typedef enum {
|
||||
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_operator_brake_mode_t;
|
||||
|
||||
|
@ -311,7 +311,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.
|
||||
|
||||
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:
|
||||
|
Loading…
Reference in New Issue
Block a user