mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
mcpwm: can't apply the same delay module to multiple generators
This is a hardware limitation, one delay module can only be used by one generator at one time. Closes https://github.com/espressif/esp-idf/issues/11327
This commit is contained in:
@@ -215,12 +215,17 @@ typedef struct {
|
||||
/**
|
||||
* @brief Set dead time for MCPWM generator
|
||||
*
|
||||
* @note Due to a hardware limitation, you can't set rising edge delay for both MCPWM generator 0 and 1 at the same time,
|
||||
* otherwise, there will be a conflict inside the dead time module. The same goes for the falling edge setting.
|
||||
* But you can set both the rising edge and falling edge delay for the same MCPWM generator.
|
||||
*
|
||||
* @param[in] in_generator MCPWM generator, before adding the dead time
|
||||
* @param[in] out_generator MCPWM generator, after adding the dead time
|
||||
* @param[in] config MCPWM dead time configuration
|
||||
* @return
|
||||
* - ESP_OK: Set dead time for MCPWM generator successfully
|
||||
* - ESP_ERR_INVALID_ARG: Set dead time for MCPWM generator failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Set dead time for MCPWM generator failed because of invalid state (e.g. delay module is already in use by other generator)
|
||||
* - ESP_FAIL: Set dead time for MCPWM generator failed because of other error
|
||||
*/
|
||||
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);
|
||||
|
||||
@@ -268,6 +268,36 @@ esp_err_t mcpwm_generator_set_dead_time(mcpwm_gen_handle_t in_generator, mcpwm_g
|
||||
mcpwm_hal_context_t *hal = &group->hal;
|
||||
int oper_id = oper->oper_id;
|
||||
|
||||
// one delay module can only be used by one generator at a time
|
||||
bool delay_module_conflict = false;
|
||||
portENTER_CRITICAL(&oper->spinlock);
|
||||
if (config->posedge_delay_ticks) {
|
||||
if (oper->posedge_delay_owner && oper->posedge_delay_owner != in_generator) {
|
||||
delay_module_conflict = true;
|
||||
}
|
||||
}
|
||||
if (config->negedge_delay_ticks) {
|
||||
if (oper->negedge_delay_owner && oper->negedge_delay_owner != in_generator) {
|
||||
delay_module_conflict = true;
|
||||
}
|
||||
}
|
||||
if (!delay_module_conflict) {
|
||||
if (config->posedge_delay_ticks) {
|
||||
// set owner if delay module is used
|
||||
oper->posedge_delay_owner = in_generator;
|
||||
} else if (oper->posedge_delay_owner == in_generator) {
|
||||
// clear owner if delay module is previously used by in_generator, but now it is not used
|
||||
oper->posedge_delay_owner = NULL;
|
||||
}
|
||||
if (config->negedge_delay_ticks) {
|
||||
oper->negedge_delay_owner = in_generator;
|
||||
} else if (oper->negedge_delay_owner == in_generator) {
|
||||
oper->negedge_delay_owner = NULL;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&oper->spinlock);
|
||||
ESP_RETURN_ON_FALSE(!delay_module_conflict, ESP_ERR_INVALID_STATE, TAG, "delay module is in use by other generator");
|
||||
|
||||
// Note: to better understand the following code, you should read the deadtime module topology diagram in the TRM
|
||||
// check if we want to bypass the deadtime module
|
||||
bool bypass = (config->negedge_delay_ticks == 0) && (config->posedge_delay_ticks == 0);
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -102,6 +102,8 @@ struct mcpwm_oper_t {
|
||||
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
|
||||
uint32_t deadtime_resolution_hz; // resolution of deadtime submodule
|
||||
mcpwm_gen_t *posedge_delay_owner; // which generator owns the positive edge delay
|
||||
mcpwm_gen_t *negedge_delay_owner; // which generator owns the negative edge delay
|
||||
mcpwm_brake_event_cb_t on_brake_cbc; // callback function which would be invoked when mcpwm operator goes into trip zone
|
||||
mcpwm_brake_event_cb_t on_brake_ost; // callback function which would be invoked when mcpwm operator goes into trip zone
|
||||
void *user_data; // user data which would be passed to the trip zone callback
|
||||
|
||||
@@ -591,6 +591,23 @@ static void redfedb_only_set_dead_time(mcpwm_gen_handle_t gena, mcpwm_gen_handle
|
||||
TEST_ESP_OK(mcpwm_generator_set_dead_time(genb, genb, &dead_time_config));
|
||||
}
|
||||
|
||||
static void invalid_reda_redb_set_dead_time(mcpwm_gen_handle_t gena, mcpwm_gen_handle_t genb)
|
||||
{
|
||||
mcpwm_dead_time_config_t dead_time_config = {
|
||||
.posedge_delay_ticks = 10,
|
||||
};
|
||||
// generator_a adds delay on the posedge
|
||||
TEST_ESP_OK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
|
||||
// generator_b adds delay on the posedge as well, which is not allowed
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_generator_set_dead_time(genb, genb, &dead_time_config));
|
||||
// bypass the delay module for generator_a
|
||||
dead_time_config.posedge_delay_ticks = 0;
|
||||
TEST_ESP_OK(mcpwm_generator_set_dead_time(gena, gena, &dead_time_config));
|
||||
// now generator_b can add delay on the posedge
|
||||
dead_time_config.posedge_delay_ticks = 10;
|
||||
TEST_ESP_OK(mcpwm_generator_set_dead_time(genb, genb, &dead_time_config));
|
||||
}
|
||||
|
||||
TEST_CASE("mcpwm_generator_deadtime_classical_configuration", "[mcpwm]")
|
||||
{
|
||||
printf("Active High Complementary\r\n");
|
||||
@@ -613,6 +630,9 @@ TEST_CASE("mcpwm_generator_deadtime_classical_configuration", "[mcpwm]")
|
||||
|
||||
printf("Bypass A, RED + FED on B\r\n");
|
||||
mcpwm_deadtime_test_template(1000000, 500, 350, 350, 0, 2, redfedb_only_set_generator_actions, redfedb_only_set_dead_time);
|
||||
|
||||
printf("Can't apply one delay module to multiple generators\r\n");
|
||||
mcpwm_deadtime_test_template(1000000, 500, 350, 350, 0, 2, redfedb_only_set_generator_actions, invalid_reda_redb_set_dead_time);
|
||||
}
|
||||
|
||||
TEST_CASE("mcpwm_duty_empty_full", "[mcpwm]")
|
||||
|
||||
Reference in New Issue
Block a user