From f7ff7ac4d08f93fed5b22e096954c81104cd379c Mon Sep 17 00:00:00 2001 From: morris Date: Sat, 28 May 2022 16:59:59 +0800 Subject: [PATCH 1/3] mcpwm: clean up hal driver and add doc --- components/driver/mcpwm.c | 158 +- components/hal/esp32/include/hal/mcpwm_ll.h | 2321 +++++++++++------ components/hal/esp32s3/include/hal/mcpwm_ll.h | 1311 +++++++--- components/hal/include/hal/mcpwm_hal.h | 74 +- components/hal/include/hal/mcpwm_types.h | 88 +- components/hal/mcpwm_hal.c | 65 +- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 - .../soc/esp32/include/soc/clk_tree_defs.h | 28 + .../soc/esp32/include/soc/mcpwm_struct.h | 4 +- components/soc/esp32/include/soc/soc_caps.h | 1 - components/soc/esp32/mcpwm_periph.c | 18 +- .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 - .../soc/esp32s3/include/soc/clk_tree_defs.h | 28 + .../soc/esp32s3/include/soc/mcpwm_struct.h | 4 +- components/soc/esp32s3/include/soc/soc_caps.h | 1 - components/soc/esp32s3/mcpwm_periph.c | 18 +- components/soc/include/soc/mcpwm_periph.h | 18 +- tools/ci/check_copyright_ignore.txt | 6 - 18 files changed, 2733 insertions(+), 1418 deletions(-) diff --git a/components/driver/mcpwm.c b/components/driver/mcpwm.c index e780de19c9..4142db246d 100644 --- a/components/driver/mcpwm.c +++ b/components/driver/mcpwm.c @@ -187,7 +187,7 @@ esp_err_t mcpwm_start(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) MCPWM_TIMER_CHECK(mcpwm_num, timer_num); mcpwm_critical_enter(mcpwm_num); - mcpwm_ll_timer_set_execute_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_START_NO_STOP); + mcpwm_ll_timer_set_start_stop_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_START_NO_STOP); mcpwm_critical_exit(mcpwm_num); return ESP_OK; } @@ -197,7 +197,7 @@ esp_err_t mcpwm_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) MCPWM_TIMER_CHECK(mcpwm_num, timer_num); mcpwm_critical_enter(mcpwm_num); - mcpwm_ll_timer_set_execute_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_STOP_AT_ZERO); + mcpwm_ll_timer_set_start_stop_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_STOP_EMPTY); mcpwm_critical_exit(mcpwm_num); return ESP_OK; } @@ -307,63 +307,63 @@ esp_err_t mcpwm_set_duty_type(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, m switch (mcpwm_ll_timer_get_count_mode(hal->dev, timer_num)) { case MCPWM_TIMER_COUNT_MODE_UP: if (duty_type == MCPWM_DUTY_MODE_0) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_GEN_ACTION_HIGH); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_GEN_ACTION_KEEP); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_GEN_ACTION_KEEP); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_LOW); } else if (duty_type == MCPWM_DUTY_MODE_1) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_GEN_ACTION_LOW); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_NO_CHANGE); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_NO_CHANGE); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_HIGH); } else if (duty_type == MCPWM_HAL_GENERATOR_MODE_FORCE_LOW) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_LOW); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_LOW); } else if (duty_type == MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_HIGH); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_HIGH); } break; case MCPWM_TIMER_COUNT_MODE_DOWN: if (duty_type == MCPWM_DUTY_MODE_0) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_LOW); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_NO_CHANGE); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_NO_CHANGE); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_HIGH); } else if (duty_type == MCPWM_DUTY_MODE_1) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_HIGH); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_NO_CHANGE); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_NO_CHANGE); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_LOW); } else if (duty_type == MCPWM_HAL_GENERATOR_MODE_FORCE_LOW) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_LOW); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_LOW); } else if (duty_type == MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_HIGH); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_HIGH); } break; case MCPWM_TIMER_COUNT_MODE_UP_DOWN: if (duty_type == MCPWM_DUTY_MODE_0) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_LOW); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_HIGH); } else if (duty_type == MCPWM_DUTY_MODE_1) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_HIGH); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_LOW); } else if (duty_type == MCPWM_HAL_GENERATOR_MODE_FORCE_LOW) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_LOW); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_LOW); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_LOW); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_LOW); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_LOW); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_LOW); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_LOW); } else if (duty_type == MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH) { - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_HIGH); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_HIGH); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_HIGH); - mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_ACTION_FORCE_HIGH); + mcpwm_ll_generator_set_action_on_timer_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_FULL, MCPWM_ACTION_FORCE_HIGH); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_DOWN, gen, MCPWM_ACTION_FORCE_HIGH); mcpwm_ll_generator_set_action_on_compare_event(hal->dev, op, gen, MCPWM_TIMER_DIRECTION_UP, gen, MCPWM_ACTION_FORCE_HIGH); } @@ -382,14 +382,12 @@ esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpw mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; periph_module_enable(mcpwm_periph_signals.groups[mcpwm_num].module); mcpwm_hal_init_config_t config = { - .host_id = mcpwm_num + .group_id = mcpwm_num }; mcpwm_hal_init(hal, &config); mcpwm_critical_enter(mcpwm_num); mcpwm_ll_group_set_clock_prescale(hal->dev, context[mcpwm_num].group_pre_scale); - mcpwm_ll_group_enable_shadow_mode(hal->dev); - mcpwm_ll_group_flush_shadow(hal->dev); mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_num, context[mcpwm_num].timer_pre_scale[timer_num]); mcpwm_ll_timer_set_count_mode(hal->dev, timer_num, mcpwm_conf->counter_mode); mcpwm_ll_timer_update_period_at_once(hal->dev, timer_num); @@ -397,7 +395,7 @@ esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpw unsigned long int real_timer_clk_hz = SOC_MCPWM_BASE_CLK_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); mcpwm_ll_timer_set_peak(hal->dev, timer_num, real_timer_clk_hz / mcpwm_conf->frequency, false); - mcpwm_ll_operator_select_timer(hal->dev, timer_num, timer_num); //the driver currently always use the timer x for operator x + mcpwm_ll_operator_connect_timer(hal->dev, timer_num, timer_num); //the driver currently always use the timer x for operator x mcpwm_critical_exit(mcpwm_num); mcpwm_set_duty(mcpwm_num, timer_num, 0, mcpwm_conf->cmpr_a); @@ -516,7 +514,7 @@ esp_err_t mcpwm_carrier_oneshot_mode_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_ MCPWM_TIMER_CHECK(mcpwm_num, timer_num); mcpwm_critical_enter(mcpwm_num); - mcpwm_ll_carrier_set_oneshot_width(context[mcpwm_num].hal.dev, op, pulse_width + 1); + mcpwm_ll_carrier_set_first_pulse_width(context[mcpwm_num].hal.dev, op, pulse_width + 1); mcpwm_critical_exit(mcpwm_num); return ESP_OK; } @@ -575,7 +573,7 @@ esp_err_t mcpwm_deadtime_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_critical_enter(mcpwm_num); mcpwm_ll_deadtime_enable_update_delay_on_tez(hal->dev, op, true); // The dead time delay unit equals to MCPWM group resolution - mcpwm_ll_deadtime_resolution_to_timer(hal->dev, op, false); + mcpwm_ll_operator_set_deadtime_clock_src(hal->dev, op, MCPWM_LL_DEADTIME_CLK_SRC_GROUP); mcpwm_ll_deadtime_set_rising_delay(hal->dev, op, red + 1); mcpwm_ll_deadtime_set_falling_delay(hal->dev, op, fed + 1); switch (dt_mode) { @@ -691,7 +689,7 @@ esp_err_t mcpwm_fault_deinit(mcpwm_unit_t mcpwm_num, mcpwm_fault_signal_t fault_ mcpwm_critical_enter(mcpwm_num); mcpwm_ll_fault_enable_detection(hal->dev, fault_sig, false); for (int i = 0; i < SOC_MCPWM_OPERATORS_PER_GROUP; i++) { - mcpwm_ll_fault_clear_ost(hal->dev, i); // make sure operator has exit the ost fault state totally + mcpwm_ll_brake_clear_ost(hal->dev, i); // make sure operator has exit the ost fault state totally } mcpwm_critical_exit(mcpwm_num); return ESP_OK; @@ -706,13 +704,13 @@ esp_err_t mcpwm_fault_set_cyc_mode(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_n mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; mcpwm_critical_enter(mcpwm_num); - mcpwm_ll_fault_enable_cbc_mode(hal->dev, op, fault_sig, true); - mcpwm_ll_fault_enable_cbc_refresh_on_tez(hal->dev, op, true); - mcpwm_ll_fault_enable_oneshot_mode(hal->dev, op, fault_sig, false); - mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TRIP_TYPE_CBC, action_on_pwmxa); - mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_TRIP_TYPE_CBC, action_on_pwmxa); - mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TRIP_TYPE_CBC, action_on_pwmxb); - mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_TRIP_TYPE_CBC, action_on_pwmxb); + mcpwm_ll_brake_enable_cbc_mode(hal->dev, op, fault_sig, true); + mcpwm_ll_brake_enable_cbc_refresh_on_tez(hal->dev, op, true); + mcpwm_ll_brake_enable_oneshot_mode(hal->dev, op, fault_sig, false); + mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_OPER_BRAKE_MODE_CBC, action_on_pwmxa); + mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, action_on_pwmxa); + mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_OPER_BRAKE_MODE_CBC, action_on_pwmxb); + mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, action_on_pwmxb); mcpwm_critical_exit(mcpwm_num); return ESP_OK; } @@ -726,18 +724,19 @@ esp_err_t mcpwm_fault_set_oneshot_mode(mcpwm_unit_t mcpwm_num, mcpwm_timer_t tim mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; mcpwm_critical_enter(mcpwm_num); - mcpwm_ll_fault_clear_ost(hal->dev, op); - mcpwm_ll_fault_enable_oneshot_mode(hal->dev, op, fault_sig, true); - mcpwm_ll_fault_enable_cbc_mode(hal->dev, op, fault_sig, false); - mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TRIP_TYPE_OST, action_on_pwmxa); - mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_TRIP_TYPE_OST, action_on_pwmxa); - mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TRIP_TYPE_OST, action_on_pwmxb); - mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_TRIP_TYPE_OST, action_on_pwmxb); + mcpwm_ll_brake_clear_ost(hal->dev, op); + mcpwm_ll_brake_enable_oneshot_mode(hal->dev, op, fault_sig, true); + mcpwm_ll_brake_enable_cbc_mode(hal->dev, op, fault_sig, false); + mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_OPER_BRAKE_MODE_OST, action_on_pwmxa); + mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_OST, action_on_pwmxa); + mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_OPER_BRAKE_MODE_OST, action_on_pwmxb); + mcpwm_ll_generator_set_action_on_brake_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_OST, action_on_pwmxb); mcpwm_critical_exit(mcpwm_num); return ESP_OK; } -static void MCPWM_ISR_ATTR mcpwm_default_isr_handler(void *arg) { +static void MCPWM_ISR_ATTR mcpwm_default_isr_handler(void *arg) +{ mcpwm_context_t *curr_context = (mcpwm_context_t *) arg; uint32_t intr_status = mcpwm_ll_intr_get_capture_status(curr_context->hal.dev); mcpwm_ll_intr_clear_capture_status(curr_context->hal.dev, intr_status); @@ -746,11 +745,11 @@ static void MCPWM_ISR_ATTR mcpwm_default_isr_handler(void *arg) { if ((intr_status >> i) & 0x1) { if (curr_context->cap_isr_func[i].fn != NULL) { cap_event_data_t edata; - edata.cap_edge = mcpwm_ll_capture_is_negedge(curr_context->hal.dev, i) ? MCPWM_NEG_EDGE - : MCPWM_POS_EDGE; + edata.cap_edge = mcpwm_ll_capture_get_edge(curr_context->hal.dev, i) == MCPWM_CAP_EDGE_NEG ? MCPWM_NEG_EDGE + : MCPWM_POS_EDGE; edata.cap_value = mcpwm_ll_capture_get_value(curr_context->hal.dev, i); if (curr_context->cap_isr_func[i].fn(curr_context->group_id, i, &edata, - curr_context->cap_isr_func[i].args)) { + curr_context->cap_isr_func[i].args)) { need_yield = true; } } @@ -773,7 +772,7 @@ esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_cha periph_module_enable(mcpwm_periph_signals.groups[mcpwm_num].module); mcpwm_hal_init_config_t init_config = { - .host_id = mcpwm_num + .group_id = mcpwm_num }; mcpwm_hal_init(hal, &init_config); mcpwm_critical_enter(mcpwm_num); @@ -784,7 +783,7 @@ esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_cha mcpwm_ll_capture_enable_posedge(hal->dev, cap_channel, cap_conf->cap_edge & MCPWM_POS_EDGE); mcpwm_ll_capture_set_prescale(hal->dev, cap_channel, cap_conf->cap_prescale); // capture feature should be used with interupt, so enable it by default - mcpwm_ll_intr_enable_capture(hal->dev, cap_channel, true); + mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_channel), true); mcpwm_ll_intr_clear_capture_status(hal->dev, 1 << cap_channel); mcpwm_critical_exit(mcpwm_num); @@ -794,8 +793,8 @@ esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_cha esp_err_t ret = ESP_OK; if (context[mcpwm_num].mcpwm_intr_handle == NULL) { ret = esp_intr_alloc(mcpwm_periph_signals.groups[mcpwm_num].irq_id, MCPWM_INTR_FLAG, - mcpwm_default_isr_handler, - (void *) (context + mcpwm_num), &(context[mcpwm_num].mcpwm_intr_handle)); + mcpwm_default_isr_handler, + (void *) (context + mcpwm_num), &(context[mcpwm_num].mcpwm_intr_handle)); } mcpwm_mutex_unlock(mcpwm_num); @@ -811,7 +810,7 @@ esp_err_t mcpwm_capture_disable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_ch mcpwm_critical_enter(mcpwm_num); mcpwm_ll_capture_enable_channel(hal->dev, cap_channel, false); - mcpwm_ll_intr_enable_capture(hal->dev, cap_channel, false); + mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_channel), false); mcpwm_critical_exit(mcpwm_num); mcpwm_mutex_lock(mcpwm_num); @@ -828,7 +827,7 @@ esp_err_t mcpwm_capture_disable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_ch esp_err_t ret = ESP_OK; if (should_free_handle) { ret = esp_intr_free(context[mcpwm_num].mcpwm_intr_handle); - if (ret != ESP_OK){ + if (ret != ESP_OK) { ESP_LOGE(TAG, "failed to free interrupt handle"); } context[mcpwm_num].mcpwm_intr_handle = NULL; @@ -853,7 +852,7 @@ uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_edge(mcpwm_unit_t mcpwm_num, mc ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR); ESP_RETURN_ON_FALSE(cap_sig < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR); mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; - return mcpwm_ll_capture_is_negedge(hal->dev, cap_sig) ? 2 : 1; + return mcpwm_ll_capture_get_edge(hal->dev, cap_sig) == MCPWM_CAP_EDGE_NEG ? 2 : 1; } esp_err_t mcpwm_sync_configure(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpwm_sync_config_t *sync_conf) @@ -868,12 +867,12 @@ esp_err_t mcpwm_sync_configure(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, uint32_t set_phase = 0; set_phase = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false) * sync_conf->timer_val / 1000; mcpwm_ll_timer_set_sync_phase_value(hal->dev, timer_num, set_phase); - if (sync_conf->sync_sig == MCPWM_SELECT_NO_INPUT){ - mcpwm_ll_timer_set_soft_synchro(hal->dev, timer_num); + if (sync_conf->sync_sig == MCPWM_SELECT_NO_INPUT) { + mcpwm_ll_timer_clear_sync_input(hal->dev, timer_num); } else if (sync_conf->sync_sig <= MCPWM_SELECT_TIMER2_SYNC) { - mcpwm_ll_timer_set_timer_synchro(hal->dev, timer_num, sync_conf->sync_sig - MCPWM_SELECT_TIMER0_SYNC); + mcpwm_ll_timer_set_timer_sync_input(hal->dev, timer_num, sync_conf->sync_sig - MCPWM_SELECT_TIMER0_SYNC); } else { - mcpwm_ll_timer_set_gpio_synchro(hal->dev, timer_num, sync_conf->sync_sig - MCPWM_SELECT_GPIO_SYNC0); + mcpwm_ll_timer_set_gpio_sync_input(hal->dev, timer_num, sync_conf->sync_sig - MCPWM_SELECT_GPIO_SYNC0); } mcpwm_ll_timer_enable_sync_input(hal->dev, timer_num, true); mcpwm_critical_exit(mcpwm_num); @@ -903,13 +902,14 @@ esp_err_t mcpwm_timer_trigger_soft_sync(mcpwm_unit_t mcpwm_num, mcpwm_timer_t ti return ESP_OK; } -esp_err_t mcpwm_sync_invert_gpio_synchro(mcpwm_unit_t mcpwm_num, mcpwm_sync_signal_t sync_sig, bool invert){ +esp_err_t mcpwm_sync_invert_gpio_synchro(mcpwm_unit_t mcpwm_num, mcpwm_sync_signal_t sync_sig, bool invert) +{ ESP_RETURN_ON_FALSE(sync_sig >= MCPWM_SELECT_GPIO_SYNC0 && sync_sig <= MCPWM_SELECT_GPIO_SYNC2, ESP_ERR_INVALID_ARG, TAG, "invalid sync sig"); mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; mcpwm_critical_enter(mcpwm_num); - mcpwm_ll_invert_gpio_synchro(hal->dev, sync_sig - MCPWM_SELECT_GPIO_SYNC0, invert); + mcpwm_ll_invert_gpio_sync_input(hal->dev, sync_sig - MCPWM_SELECT_GPIO_SYNC0, invert); mcpwm_critical_exit(mcpwm_num); return ESP_OK; @@ -922,19 +922,19 @@ esp_err_t mcpwm_set_timer_sync_output(mcpwm_unit_t mcpwm_num, mcpwm_timer_t time mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; mcpwm_critical_enter(mcpwm_num); switch (trigger) { - case MCPWM_SWSYNC_SOURCE_SYNCIN: - mcpwm_ll_timer_sync_out_penetrate(hal->dev, timer_num); - break; - case MCPWM_SWSYNC_SOURCE_TEZ: - mcpwm_ll_timer_sync_out_on_timer_event(hal->dev, timer_num, MCPWM_TIMER_EVENT_ZERO); - break; - case MCPWM_SWSYNC_SOURCE_TEP: - mcpwm_ll_timer_sync_out_on_timer_event(hal->dev, timer_num, MCPWM_TIMER_EVENT_PEAK); - break; - case MCPWM_SWSYNC_SOURCE_DISABLED: - default: - mcpwm_ll_timer_disable_sync_out(hal->dev, timer_num); - break; + case MCPWM_SWSYNC_SOURCE_SYNCIN: + mcpwm_ll_timer_propagate_input_sync(hal->dev, timer_num); + break; + case MCPWM_SWSYNC_SOURCE_TEZ: + mcpwm_ll_timer_sync_out_on_timer_event(hal->dev, timer_num, MCPWM_TIMER_EVENT_EMPTY); + break; + case MCPWM_SWSYNC_SOURCE_TEP: + mcpwm_ll_timer_sync_out_on_timer_event(hal->dev, timer_num, MCPWM_TIMER_EVENT_FULL); + break; + case MCPWM_SWSYNC_SOURCE_DISABLED: + default: + mcpwm_ll_timer_disable_sync_out(hal->dev, timer_num); + break; } mcpwm_critical_exit(mcpwm_num); return ESP_OK; diff --git a/components/hal/esp32/include/hal/mcpwm_ll.h b/components/hal/esp32/include/hal/mcpwm_ll.h index 44c19c85d7..4eba4eb6df 100644 --- a/components/hal/esp32/include/hal/mcpwm_ll.h +++ b/components/hal/esp32/include/hal/mcpwm_ll.h @@ -15,292 +15,213 @@ #pragma once #include -#include "hal/misc.h" #include "soc/soc_caps.h" #include "soc/mcpwm_struct.h" #include "hal/mcpwm_types.h" +#include "hal/misc.h" #include "hal/assert.h" #ifdef __cplusplus extern "C" { #endif -/// Get the address of peripheral registers -#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : &MCPWM1) -#define MCPWM_LL_MAX_CAPTURE_PRESCALE 255 -#define MCPWM_LL_MAX_COMPARE_VALUE 65535 -#define MCPWM_LL_MAX_DEAD_DELAY 65535 -#define MCPWM_LL_MAX_PHASE_VALUE 65535 +// Get MCPWM group register base address +#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : &MCPWM1) -/********************* Group registers *******************/ +// MCPWM interrupt event mask +#define MCPWM_LL_EVENT_TIMER_STOP(timer) (1 << (timer)) +#define MCPWM_LL_EVENT_TIMER_EMPTY(timer) (1 << ((timer) + 3)) +#define MCPWM_LL_EVENT_TIMER_FULL(timer) (1 << ((timer) + 6)) +#define MCPWM_LL_EVENT_TIMER_MASK(timer) (MCPWM_LL_EVENT_TIMER_STOP(timer) | MCPWM_LL_EVENT_TIMER_EMPTY(timer) | MCPWM_LL_EVENT_TIMER_FULL(timer)) +#define MCPWM_LL_EVENT_FAULT_ENTER(fault) (1 << ((fault) + 9)) +#define MCPWM_LL_EVENT_FAULT_EXIT(fault) (1 << ((fault) + 12)) +#define MCPWM_LL_EVENT_FAULT_MASK(fault) (MCPWM_LL_EVENT_FAULT_ENTER(fault) | MCPWM_LL_EVENT_FAULT_EXIT(fault)) +#define MCPWM_LL_EVENT_CMP_EQUAL(oper, cmp) (1 << ((oper) + (cmp) * 3 + 15)) +#define MCPWM_LL_EVENT_OPER_BRAKE_CBC(oper) (1 << ((oper) + 21)) +#define MCPWM_LL_EVENT_OPER_BRAKE_OST(oper) (1 << ((oper) + 24)) +#define MCPWM_LL_EVENT_OPER_MASK(oper) (MCPWM_LL_EVENT_OPER_BRAKE_CBC(oper) | MCPWM_LL_EVENT_OPER_BRAKE_OST(oper)) +#define MCPWM_LL_EVENT_CAPTURE(cap) (1 << ((cap) + 27)) -// Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1) +// Maximum values due to limited register bit width +#define MCPWM_LL_MAX_CARRIER_ONESHOT 16 +#define MCPWM_LL_MAX_CAPTURE_PRESCALE 256 +#define MCPWM_LL_MAX_DEAD_DELAY 65536 +#define MCPWM_LL_MAX_COUNT_VALUE 65536 + +// translate the HAL types into register values +#define MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) ((uint8_t[]) {0, 1}[(event)]) +#define MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) ((uint8_t[]) {0, 1, 2, 3}[(action)]) +#define MCPWM_LL_BRAKE_MODE_TO_REG_VAL(mode) ((uint8_t[]) {0, 1}[(mode)]) + +/** + * @brief The dead time module's clock source + */ +typedef enum { + MCPWM_LL_DEADTIME_CLK_SRC_GROUP, + MCPWM_LL_DEADTIME_CLK_SRC_TIMER, +} mcpwm_ll_deadtime_clock_src_t; + +////////////////////////////////////////MCPWM Group Specific//////////////////////////////////////////////////////////// + +/** + * @brief Set the MCPWM group clock prescale + * + * @param mcpwm Peripheral instance address + * @param pre_scale Prescale value + */ static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale) { + // group clock: PWM_clk = CLK_160M / (prescale + 1) HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale, pre_scale - 1); } -static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale) + 1; -} - +/** + * @brief Enable update MCPWM active registers from shadow registers + * + * @param mcpwm Peripheral instance address + */ static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm) { mcpwm->update_cfg.global_up_en = 1; - // updating of active registers in MCPWM operators should be enabled mcpwm->update_cfg.op0_up_en = 1; mcpwm->update_cfg.op1_up_en = 1; mcpwm->update_cfg.op2_up_en = 1; } +/** + * @brief Flush shadow registers to active registers + * + * @param mcpwm Peripheral instance address + */ static inline void mcpwm_ll_group_flush_shadow(mcpwm_dev_t *mcpwm) { // a toggle can trigger a forced update of all active registers in MCPWM, i.e. shadow->active - mcpwm->update_cfg.global_force_up = ~mcpwm->update_cfg.global_force_up; + mcpwm->update_cfg.global_force_up = 1; + mcpwm->update_cfg.global_force_up = 0; } -/********************* Interrupt registers *******************/ +//////////////////////////////////////////Interrupt Specific//////////////////////////////////////////////////////////// +/** + * @brief Get interrupt status register address + * + * @param mcpwm Peripheral instance address + * @return Register address + */ +static inline volatile void *mcpwm_ll_intr_get_status_reg(mcpwm_dev_t *mcpwm) +{ + return &mcpwm->int_st; +} + +/** + * @brief Enable MCPWM interrupt for specific event mask + * + * @param mcpwm Peripheral instance address + * @param mask Event mask + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_intr_enable(mcpwm_dev_t *mcpwm, uint32_t mask, bool enable) +{ + if (enable) { + mcpwm->int_ena.val |= mask; + } else { + mcpwm->int_ena.val &= ~mask; + } +} + +/** + * @brief Get MCPWM interrupt status + * + * @param mcpwm Peripheral instance address + * @return Interrupt status + */ +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_intr_get_status(mcpwm_dev_t *mcpwm) { return mcpwm->int_st.val; } -static inline void mcpwm_ll_intr_clear_status(mcpwm_dev_t *mcpwm, uint32_t intr_mask) -{ - mcpwm->int_clr.val = intr_mask; -} - -static inline void mcpwm_ll_intr_disable_all(mcpwm_dev_t *mcpwm) -{ - mcpwm->int_ena.val = 0; -} - -//////////// get interrupt status for each event //////////////// - -static inline uint32_t mcpwm_ll_intr_get_timer_stop_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 0) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_timer_tez_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 3) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_timer_tep_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 6) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_fault_enter_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 9) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_fault_exit_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 12) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_compare_status(mcpwm_dev_t *mcpwm, uint32_t cmp_id) -{ - return (mcpwm->int_st.val >> (15 + cmp_id * 3)) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_trip_cbc_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 21) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_trip_ost_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 24) & 0x07; -} - +/** + * @brief Clear MCPWM interrupt status by mask + * + * @param mcpwm Peripheral instance address + * @param mask Interupt status mask + */ __attribute__((always_inline)) -static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm) +static inline void mcpwm_ll_intr_clear_status(mcpwm_dev_t *mcpwm, uint32_t mask) { - return (mcpwm->int_st.val >> 27) & 0x07; + mcpwm->int_clr.val = mask; } -//////////// clear interrupt status for each event //////////////// - -static inline void mcpwm_ll_intr_clear_timer_stop_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask) -{ - mcpwm->int_clr.val = (timer_mask & 0x07) << 0; -} - -static inline void mcpwm_ll_intr_clear_timer_tez_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask) -{ - mcpwm->int_clr.val = (timer_mask & 0x07) << 3; -} - -static inline void mcpwm_ll_intr_clear_timer_tep_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask) -{ - mcpwm->int_clr.val = (timer_mask & 0x07) << 6; -} - -static inline void mcpwm_ll_intr_clear_fault_enter_status(mcpwm_dev_t *mcpwm, uint32_t fault_mask) -{ - mcpwm->int_clr.val = (fault_mask & 0x07) << 9; -} - -static inline void mcpwm_ll_intr_clear_fault_exit_status(mcpwm_dev_t *mcpwm, uint32_t fault_mask) -{ - mcpwm->int_clr.val = (fault_mask & 0x07) << 12; -} - -static inline void mcpwm_ll_intr_clear_compare_status(mcpwm_dev_t *mcpwm, uint32_t operator_mask, uint32_t cmp_id) -{ - mcpwm->int_clr.val = (operator_mask & 0x07) << (15 + cmp_id * 3); -} - -static inline void mcpwm_ll_intr_clear_trip_cbc_status(mcpwm_dev_t *mcpwm, uint32_t cbc_mask) -{ - mcpwm->int_clr.val = (cbc_mask & 0x07) << 21; -} - -static inline void mcpwm_ll_intr_clear_trip_ost_status(mcpwm_dev_t *mcpwm, uint32_t ost_mask) -{ - mcpwm->int_clr.val = (ost_mask & 0x07) << 24; -} - -__attribute__((always_inline)) -static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask) -{ - mcpwm->int_clr.val = (capture_mask & 0x07) << 27; -} - -//////////// enable interrupt for each event //////////////// - -static inline void mcpwm_ll_intr_enable_timer_stop(mcpwm_dev_t *mcpwm, uint32_t timer_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (timer_id + 0); - } else { - mcpwm->int_ena.val &= ~(1 << (timer_id + 0)); - } -} - -static inline void mcpwm_ll_intr_enable_timer_tez(mcpwm_dev_t *mcpwm, uint32_t timer_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (timer_id + 3); - } else { - mcpwm->int_ena.val &= ~(1 << (timer_id + 3)); - } -} - -static inline void mcpwm_ll_intr_enable_timer_tep(mcpwm_dev_t *mcpwm, uint32_t timer_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (timer_id + 6); - } else { - mcpwm->int_ena.val &= ~(1 << (timer_id + 6)); - } -} - -static inline void mcpwm_ll_intr_enable_fault_enter(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (9 + fault_id); // enter fault interrupt - } else { - mcpwm->int_ena.val &= ~(1 << (9 + fault_id)); - } -} - -static inline void mcpwm_ll_intr_enable_fault_exit(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (12 + fault_id); // exit fault interrupt - } else { - mcpwm->int_ena.val &= ~(1 << (12 + fault_id)); - } -} - -static inline void mcpwm_ll_intr_enable_compare(mcpwm_dev_t *mcpwm, uint32_t operator_id, uint32_t cmp_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= (1 << (15 + cmp_id * 3 + operator_id)); - } else { - mcpwm->int_ena.val &= ~(1 << (15 + cmp_id * 3 + operator_id)); - } -} - -static inline void mcpwm_ll_intr_enable_trip_cbc(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= (1 << (21 + operator_id)); - } else { - mcpwm->int_ena.val &= ~(1 << (21 + operator_id)); - } -} - -static inline void mcpwm_ll_intr_enable_trip_ost(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= (1 << (24 + operator_id)); - } else { - mcpwm->int_ena.val &= ~(1 << (24 + operator_id)); - } -} - -static inline void mcpwm_ll_intr_enable_capture(mcpwm_dev_t *mcpwm, uint32_t capture_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (27 + capture_id); - } else { - mcpwm->int_ena.val &= ~(1 << (27 + capture_id)); - } -} - -/********************* Timer registers *******************/ +////////////////////////////////////////MCPWM Timer Specific//////////////////////////////////////////////////////////// +/** + * @brief Set MCPWM timer prescale + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param prescale Prescale value + */ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id, uint32_t prescale) { + HAL_ASSERT(prescale <= 256 && prescale > 0); HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_prescale, prescale - 1); } -static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_prescale) + 1; -} - +/** + * @brief Set peak value for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param peak Peak value + * @param symmetric True to set symmetric peak value, False to set asymmetric peak value + */ static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) { if (!symmetric) { // in asymmetric mode, period = [0,peak-1] + HAL_ASSERT(peak > 0 && peak <= MCPWM_LL_MAX_COUNT_VALUE); HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1); } else { // in symmetric mode, period = [0,peak-1] + [peak,1] + HAL_ASSERT(peak < MCPWM_LL_MAX_COUNT_VALUE); HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak); } } -static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, bool symmetric) -{ - // asymmetric mode - if (!symmetric) { - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1; - } - // symmetric mode - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period); -} - +/** + * @brief Update MCPWM period immediately + * @note When period value is updated in the shadow register, it will be flushed to active register immediately. + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod = 0; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod = 0; } +/** + * @brief Enable to update MCPWM period upon TEZ event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_timer_enable_update_period_on_tez(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x01; } else { - mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x01; } } +/** + * @brief Enable to update MCPWM period upon sync event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { @@ -310,6 +231,13 @@ static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpw } } +/** + * @brief Set MCPWM timer count mode + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param mode Timer count mode + */ static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_count_mode_t mode) { switch (mode) { @@ -325,9 +253,1315 @@ static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_i case MCPWM_TIMER_COUNT_MODE_UP_DOWN: mcpwm->timer[timer_id].timer_cfg1.timer_mod = 3; break; + default: + HAL_ASSERT(false); + break; } } +/** + * @brief Execute MCPWM timer start/stop command + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param cmd Timer start/stop command + */ +static inline void mcpwm_ll_timer_set_start_stop_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_start_stop_cmd_t cmd) +{ + switch (cmd) { + case MCPWM_TIMER_STOP_EMPTY: + mcpwm->timer[timer_id].timer_cfg1.timer_start = 0; + break; + case MCPWM_TIMER_STOP_FULL: + mcpwm->timer[timer_id].timer_cfg1.timer_start = 1; + break; + case MCPWM_TIMER_START_NO_STOP: + mcpwm->timer[timer_id].timer_cfg1.timer_start = 2; + break; + case MCPWM_TIMER_START_STOP_EMPTY: + mcpwm->timer[timer_id].timer_cfg1.timer_start = 3; + break; + case MCPWM_TIMER_START_STOP_FULL: + mcpwm->timer[timer_id].timer_cfg1.timer_start = 4; + break; + default: + HAL_ASSERT(false); + break;; + } +} + +/** + * @brief Get timer count value + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @return Timer count value + */ +__attribute__((always_inline)) +static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id) +{ + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value); +} + +/** + * @brief Get timer count direction + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @return Timer count direction + */ +__attribute__((always_inline)) +static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) +{ + return mcpwm->timer[timer_id].timer_status.timer_direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; +} + +/** + * @brief Enable sync input for timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable) +{ + mcpwm->timer[timer_id].timer_sync.timer_synci_en = enable; +} + +/** + * @brief Use the input sync signal as the output sync signal (i.e. propagate the input sync signal) + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_propagate_input_sync(mcpwm_dev_t *mcpwm, int timer_id) +{ + // sync_out is selected to sync_in + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 0; +} + +/** + * @brief Set the sync output signal to one of the timer event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param event Timer event + */ +static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_event_t event) +{ + switch (event) { + case MCPWM_TIMER_EVENT_EMPTY: + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 1; + break; + case MCPWM_TIMER_EVENT_FULL: + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 2; + break; + default: + HAL_ASSERT(false); + break; + } +} + +/** + * @brief Disable sync output for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id) +{ + // sync_out will always be zero + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 3; +} + +/** + * @brief Trigger MCPWM timer software sync event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id) +{ + mcpwm->timer[timer_id].timer_sync.timer_sync_sw = ~mcpwm->timer[timer_id].timer_sync.timer_sync_sw; +} + +/** + * @brief Set sync count value for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param phase_value Sync phase value + */ +static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_sync, timer_phase, phase_value); +} + +/** + * @brief Set sync phase direction for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param direction Sync phase direction + */ +static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) +{ + mcpwm->timer[timer_id].timer_sync.timer_phase_direction = direction; +} + +/** + * @brief Select which GPIO sync input to use + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + * @param gpio_sync_id GPIO sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_set_gpio_sync_input(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) +{ + mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); + mcpwm->timer_synci_cfg.val |= (gpio_sync_id + 4) << (timer * 3); +} + +/** + * @brief Select which timer sync input to use + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + * @param timer_sync_id Timer sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_set_timer_sync_input(mcpwm_dev_t *mcpwm, int timer, int timer_sync_id) +{ + mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); + mcpwm->timer_synci_cfg.val |= (timer_sync_id + 1) << (timer * 3); +} + +/** + * @brief Clear timer sync input selection + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_clear_sync_input(mcpwm_dev_t *mcpwm, int timer) +{ + // no sync input is selected, but software sync can still work + mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); +} + +/** + * @brief Invert the GPIO sync input signal + * + * @param mcpwm Peripheral instance address + * @param sync_id GPIO sync ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_invert_gpio_sync_input(mcpwm_dev_t *mcpwm, int sync_id, bool invert) +{ + if (invert) { + mcpwm->timer_synci_cfg.val |= 1 << (sync_id + 9); + } else { + mcpwm->timer_synci_cfg.val &= ~(1 << (sync_id + 9)); + } +} + +////////////////////////////////////////MCPWM Operator Specific///////////////////////////////////////////////////////// + +/** + * @brief Flush operator shadow registers to active registers + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_operator_flush_shadow(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->update_cfg.val ^= (1 << (2 * operator_id + 3)); +} + +/** + * @brief Connect operator and timer by ID + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_operator_connect_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) +{ + mcpwm->operator_timersel.val &= ~(0x03 << (2 * operator_id)); + mcpwm->operator_timersel.val |= (timer_id << (2 * operator_id)); +} + +/** + * @brief Update the compare value immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + */ +static inline void mcpwm_ll_operator_update_compare_at_once(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) +{ + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~(0x0F << (4 * compare_id)); +} + +/** + * @brief Enable to update the compare value upon TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 0) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 0) << (4 * compare_id)); + } +} + +/** + * @brief Enable to update the compare value upon TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 1) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 1) << (4 * compare_id)); + } +} + +/** + * @brief Enable to update the compare value upon sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 2) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 2) << (4 * compare_id)); + } +} + +/** + * @brief Stop updating the compare value + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param stop_or_not True to stop, False to not stop + */ +static inline void mcpwm_ll_operator_stop_update_compare(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool stop_or_not) +{ + if (stop_or_not) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 3) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 3) << (4 * compare_id)); + } +} + +/** + * @brief Set compare value for comparator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param compare_value Compare value + */ +__attribute__((always_inline)) +static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen, compare_value); +} + +/** + * @brief Update operator actions immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod = 0; +} + +/** + * @brief Enable update actions on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 0; + } else { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 0); + } +} + +/** + * @brief Enable update actions on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 1; + } else { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 1); + } +} + +/** + * @brief Enable update actions on sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 2; + } else { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 2); + } +} + +/** + * @brief Stop updating actions + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param stop_or_not True to stop, False to not stop + */ +static inline void mcpwm_ll_operator_stop_update_action(mcpwm_dev_t *mcpwm, int operator_id, bool stop_or_not) +{ + if (stop_or_not) { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 3; + } else { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 3); + } +} + +/** + * @brief Set trigger from GPIO (reuse the fault GPIO) + * + * @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 + * @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) +{ + 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) + * + * @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) +{ + // 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 |= (3 << (4 + 3 * trig_id)); +} + +////////////////////////////////////////MCPWM Generator Specific//////////////////////////////////////////////////////// + +/** + * @brief Reset actions for the generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) +{ + mcpwm->operators[operator_id].generator[generator_id].val = 0; +} + +/** + * @brief Set generator action on timer event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param event Timer event + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_timer_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, mcpwm_timer_event_t event, mcpwm_generator_action_t action) +{ + // empty: 0, full: 1 + if (direction == MCPWM_TIMER_DIRECTION_UP) { // utez, utep + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtez, dtep + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2 + 12)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2 + 12); + } +} + +/** + * @brief Set generator action on compare event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param comp_id Compare ID, index from 0 to 1 + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_compare_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, int cmp_id, int action) +{ + if (direction == MCPWM_TIMER_DIRECTION_UP) { // utea, uteb + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (cmp_id * 2 + 4); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtea, dteb + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (cmp_id * 2 + 16); + } +} + +/** + * @brief Set generator action on trigger event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param trig_id Trigger ID, index from 0 to 1 + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, int trig_id, int action) +{ + if (direction == MCPWM_TIMER_DIRECTION_UP) { // ut0, ut1 + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (trig_id * 2 + 8); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dt0, dt1 + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (trig_id * 2 + 20); + } +} + +/** + * @brief Set generator action on brake event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param brake_mode Brake mode + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_brake_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, mcpwm_operator_brake_mode_t brake_mode, int action) +{ + // the following bit operation is highly depend on the register bit layout. + // the priority comes: generator ID > brake mode > direction + if (direction == MCPWM_TIMER_DIRECTION_UP) { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode) + 2)); + mcpwm->operators[operator_id].fh_cfg0.val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode) + 2); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode))); + mcpwm->operators[operator_id].fh_cfg0.val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode)); + } +} + +/** + * @brief Trigger non-continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) +{ + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.gen_a_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_a_nciforce; + } else { + mcpwm->operators[operator_id].gen_force.gen_b_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_b_nciforce; + } +} + +/** + * @brief Disable continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) +{ + mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = 0; + } else { + mcpwm->operators[operator_id].gen_force.gen_b_cntuforce_mode = 0; + } +} + +/** + * @brief Disable non-continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) +{ + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.gen_a_nciforce_mode = 0; + } else { + mcpwm->operators[operator_id].gen_force.gen_b_nciforce_mode = 0; + } +} + +/** + * @brief Set continue force level for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param level Force level to set + */ +static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) +{ + mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = level + 1; + } else { + mcpwm->operators[operator_id].gen_force.gen_b_cntuforce_mode = level + 1; + } +} + +/** + * @brief Set non-continue force level for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param level Force level to set + */ +static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) +{ + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.gen_a_nciforce_mode = level + 1; + } else { + mcpwm->operators[operator_id].gen_force.gen_b_nciforce_mode = level + 1; + } +} + +////////////////////////////////////////MCPWM Dead Time Specific//////////////////////////////////////////////////////// + +/** + * @brief Set clock source for dead time submodule + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param src Clock source for dead time submodule + */ +static inline void mcpwm_ll_operator_set_deadtime_clock_src(mcpwm_dev_t *mcpwm, int operator_id, mcpwm_ll_deadtime_clock_src_t src) +{ + switch (src) { + case MCPWM_LL_DEADTIME_CLK_SRC_GROUP: + mcpwm->operators[operator_id].dt_cfg.dt_clk_sel = 0; + break; + case MCPWM_LL_DEADTIME_CLK_SRC_TIMER: + mcpwm->operators[operator_id].dt_cfg.dt_clk_sel = 1; + break;; + default: + HAL_ASSERT(false); + } +} + +/** + * @brief Select the generator for RED block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_deadtime_red_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) +{ + mcpwm->operators[operator_id].dt_cfg.dt_red_insel = generator; +} + +/** + * @brief Select the generator for FED block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_deadtime_fed_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) +{ + mcpwm->operators[operator_id].dt_cfg.dt_fed_insel = generator; +} + +/** + * @brief Set which path to bypass in the deadtime submodule + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to bypass, index from 0 to 1 + * @param bypass True to bypass, False to not bypass + */ +static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool bypass) +{ + if (bypass) { + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 15); + } else { + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 15)); + } +} + +/** + * @brief Invert the output path + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to invert, index from 0 to 1 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int operator_id, int path, bool invert) +{ + if (invert) { + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 13); + } else { + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 13)); + } +} + +/** + * @brief Swap the output path + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to swap, index from 0 to 1 + * @param swap True to swap, False to not swap + */ +static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool swap) +{ + if (swap) { + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 9); + } else { + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 9)); + } +} + +/** + * @brief Enable the DEB block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + mcpwm->operators[operator_id].dt_cfg.dt_deb_mode = enable; +} + +/** + * @brief Get the deadtime switch topology + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return Dead time submodule's switch topology, each bit represents one switch on/off status + */ +static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id) +{ + return (mcpwm->operators[operator_id].dt_cfg.dt_deb_mode << 8) | (mcpwm->operators[operator_id].dt_cfg.dt_b_outswap << 7) | + (mcpwm->operators[operator_id].dt_cfg.dt_a_outswap << 6) | (mcpwm->operators[operator_id].dt_cfg.dt_fed_insel << 5) | + (mcpwm->operators[operator_id].dt_cfg.dt_red_insel << 4) | (mcpwm->operators[operator_id].dt_cfg.dt_fed_outinvert << 3) | + (mcpwm->operators[operator_id].dt_cfg.dt_red_outinvert << 2) | (mcpwm->operators[operator_id].dt_cfg.dt_a_outbypass << 1) | + (mcpwm->operators[operator_id].dt_cfg.dt_b_outbypass << 0); +} + +/** + * @brief Set falling edge delay duration + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fed Delay duration, in deadtime submodule's clock cycles + */ +static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed, fed - 1); +} + +/** + * @brief Set rising edge delay duration + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param red Delay duration, in deadtime submodule's clock cycles + */ +static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red, red - 1); +} + +/** + * @brief Update deadtime immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod = 0; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod = 0; +} + +/** + * @brief Enable to update deadtime on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 0; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 0; + } else { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 0); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 0); + } +} + +/** + * @brief Enable to update deadtime on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 1; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 1; + } else { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 1); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 1); + } +} + +/** + * @brief Enable to update deadtime on sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 2; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 2; + } else { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 2); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 2); + } +} + +/** + * @brief Stop updating deadtime + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param stop_or_not True to stop, False to continue + */ +static inline void mcpwm_ll_deadtime_stop_update_delay(mcpwm_dev_t *mcpwm, int operator_id, bool stop_or_not) +{ + if (stop_or_not) { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 3; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 3; + } else { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 3); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 3); + } +} + +////////////////////////////////////////MCPWM Carrier Specific////////////////////////////////////////////////////////// + +/** + * @brief Enable carrier for MCPWM operator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + mcpwm->operators[operator_id].carrier_cfg.carrier_en = enable; +} + +/** + * @brief Set prescale for MCPWM carrier source clock + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param prescale Prescale value + */ +static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int operator_id, uint8_t prescale) +{ + HAL_ASSERT(prescale > 0 && prescale <= 16); + mcpwm->operators[operator_id].carrier_cfg.carrier_prescale = prescale - 1; +} + +/** + * @brief Set duty cycle of MCPWM carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param carrier_duty Duty cycle value + */ +static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int operator_id, uint8_t carrier_duty) +{ + mcpwm->operators[operator_id].carrier_cfg.carrier_duty = carrier_duty; +} + +/** + * @brief Invert the signal after the carrier is applied + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) +{ + mcpwm->operators[operator_id].carrier_cfg.carrier_out_invert = invert; +} + +/** + * @brief Invert the signal before applying the carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_carrier_in_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) +{ + mcpwm->operators[operator_id].carrier_cfg.carrier_in_invert = invert; +} + +/** + * @brief Set the first pulse width of the carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param pulse_width Pulse width + */ +static inline void mcpwm_ll_carrier_set_first_pulse_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) +{ + HAL_ASSERT(pulse_width >= 1); + mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth = pulse_width - 1; +} + +////////////////////////////////////////MCPWM Fault Specific//////////////////////////////////////////////////////////// + +/** + * @brief Enable GPIO fault detection + * + * @param mcpwm Peripheral instance address + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_fault_enable_detection(mcpwm_dev_t *mcpwm, int fault_sig, bool enable) +{ + if (enable) { + mcpwm->fault_detect.val |= 1 << fault_sig; + } else { + mcpwm->fault_detect.val &= ~(1 << fault_sig); + } +} + +/** + * @brief Set fault polarity (i.e. which level is treated as an active fault) + * + * @param mcpwm Peripheral instance address + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param level Active level, 0 for low, 1 for high + */ +static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault_sig, bool level) +{ + if (level) { + mcpwm->fault_detect.val |= 1 << (fault_sig + 3); + } else { + mcpwm->fault_detect.val &= ~(1 << (fault_sig + 3)); + } +} + +/** + * @brief Clear the OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) +{ + // a posedge can clear the ost fault status + mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 0; + mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 1; +} + +/** + * @brief Enable the OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].fh_cfg0.val |= (1 << (7 - fault_sig)); + } else { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); + } +} + +/** + * @brief Enable the CBC brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); + } else { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); + } +} + +/** + * @brief Enable refresh the CBC brake on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 1; + } else { + mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 1); + } +} + +/** + * @brief Enable refresh the CBC brake on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 2; + } else { + mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 2); + } +} + +/** + * @brief Enable software CBC brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_soft_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + mcpwm->operators[operator_id].fh_cfg0.fh_sw_cbc = enable; +} + +/** + * @brief Enable software OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_soft_ost(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + mcpwm->operators[operator_id].fh_cfg0.fh_sw_ost = enable; +} + +/** + * @brief Trigger software CBC brake for once + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_trigger_soft_cbc(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc; +} + +/** + * @brief Trigger software OST brake for once + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_trigger_soft_ost(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->operators[operator_id].fh_cfg1.fh_force_ost = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_ost; +} + +/** + * @brief Whether the OST brake is still active + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return True if active, False if not + */ +static inline bool mcpwm_ll_ost_brake_active(mcpwm_dev_t *mcpwm, int operator_id) +{ + return mcpwm->operators[operator_id].fh_status.fh_ost_on; +} + +/** + * @brief Whether the CBC brake is still active + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return True if active, False if not + */ +static inline bool mcpwm_ll_cbc_brake_active(mcpwm_dev_t *mcpwm, int operator_id) +{ + return mcpwm->operators[operator_id].fh_status.fh_cbc_on; +} + +////////////////////////////////////////MCPWM Capture Specific////////////////////////////////////////////////////////// + +/** + * @brief Enable capture timer + * + * @param mcpwm Peripheral instance address + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_timer(mcpwm_dev_t *mcpwm, bool enable) +{ + mcpwm->cap_timer_cfg.cap_timer_en = enable; +} + +/** + * @brief Enable capture channel + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int channel, bool enable) +{ + mcpwm->cap_chn_cfg[channel].capn_en = enable; +} + +/** + * @brief Set sync phase for capture timer + * + * @param mcpwm Peripheral instance address + * @param phase_value Phase value + */ +static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value) +{ + mcpwm->cap_timer_phase.cap_timer_phase = phase_value; +} + +/** + * @brief Enable sync for capture timer + * + * @param mcpwm Peripheral instance address + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool enable) +{ + mcpwm->cap_timer_cfg.cap_synci_en = enable; +} + +/** + * @brief Set the timer sync source for MCPWM capture timer + * + * @param mcpwm Peripheral instance address + * @param sync_out_timer MCPWM Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_capture_set_timer_sync(mcpwm_dev_t *mcpwm, int sync_out_timer) +{ + mcpwm->cap_timer_cfg.cap_synci_sel = sync_out_timer + 1; +} + +/** + * @brief Set the GPIO sync source for MCPWM capture timer + * + * @param mcpwm Peripheral instance address + * @param gpio_sync GPIO sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_capture_set_gpio_sync(mcpwm_dev_t *mcpwm, int gpio_sync) +{ + mcpwm->cap_timer_cfg.cap_synci_sel = gpio_sync + 4; +} + +/** + * @brief Trigger a software sync for capture timer + * + * @param mcpwm Peripheral instance address + */ +static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm) +{ + mcpwm->cap_timer_cfg.cap_sync_sw = 1; // auto clear +} + +/** + * @brief Enable capture on positive edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int channel, bool enable) +{ + if (enable) { + mcpwm->cap_chn_cfg[channel].val |= 1 << 2; + } else { + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 2); + } +} + +/** + * @brief Enable capture on negative edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int channel, bool enable) +{ + if (enable) { + mcpwm->cap_chn_cfg[channel].val |= 1 << 1; + } else { + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 1); + } +} + +/** + * @brief Invert the capture input signal + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_invert_input(mcpwm_dev_t *mcpwm, int channel, bool invert) +{ + mcpwm->cap_chn_cfg[channel].capn_in_invert = invert; +} + +/** + * @brief Trigger the software capture for once + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + */ +static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel) +{ + mcpwm->cap_chn_cfg[channel].capn_sw = 1; // auto clear +} + +/** + * @brief Get the captured value + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @return Captured value + */ +__attribute__((always_inline)) +static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) +{ + return mcpwm->cap_chn[channel].capn_value; +} + +/** + * @brief Get the captured edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @return Captured edge + */ +__attribute__((always_inline)) +static inline mcpwm_capture_edge_t mcpwm_ll_capture_get_edge(mcpwm_dev_t *mcpwm, int channel) +{ + return mcpwm->cap_status.val & (1 << channel) ? MCPWM_CAP_EDGE_NEG : MCPWM_CAP_EDGE_POS; +} + +/** + * @brief Set the prescale of the input capture signal + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param prescale Prescale value + */ +static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) +{ + HAL_ASSERT(prescale > 0); + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale, prescale - 1); +} + +//////////////////////////////////////////Deprecated Functions////////////////////////////////////////////////////////// +/////////////////////////////The following functions are only used by the legacy driver///////////////////////////////// +/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) +{ + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale) + 1; +} + +static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) +{ + mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; + return cfg0.timer_prescale + 1; +} + +static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, bool symmetric) +{ + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + (symmetric ? 0 : 1); +} + static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t *mcpwm, int timer_id) { switch (mcpwm->timer[timer_id].timer_cfg1.timer_mod) { @@ -343,656 +1577,21 @@ static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t } } -static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_execute_cmd_t cmd) -{ - switch (cmd) { - case MCPWM_TIMER_STOP_AT_ZERO: - mcpwm->timer[timer_id].timer_cfg1.timer_start = 0; - break; - case MCPWM_TIMER_STOP_AT_PEAK: - mcpwm->timer[timer_id].timer_cfg1.timer_start = 1; - break; - case MCPWM_TIMER_START_NO_STOP: - mcpwm->timer[timer_id].timer_cfg1.timer_start = 2; - break; - case MCPWM_TIMER_START_STOP_AT_ZERO: - mcpwm->timer[timer_id].timer_cfg1.timer_start = 3; - break; - case MCPWM_TIMER_START_STOP_AT_PEAK: - mcpwm->timer[timer_id].timer_cfg1.timer_start = 4; - break; - } -} - -static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value); -} - -static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) -{ - return mcpwm->timer[timer_id].timer_status.timer_direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; -} - -static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable) -{ - mcpwm->timer[timer_id].timer_sync.timer_synci_en = enable; -} - -static inline void mcpwm_ll_timer_sync_out_penetrate(mcpwm_dev_t *mcpwm, int timer_id) -{ - // sync_out is selected to sync_in - mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 0; -} - -static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_event_t event) -{ - if (event == MCPWM_TIMER_EVENT_ZERO) { - mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 1; - } else if (event == MCPWM_TIMER_EVENT_PEAK) { - mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 2; - } else { - HAL_ASSERT(false && "unknown sync out event"); - } -} - -static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id) -{ - // sync_out will always be zero - mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 3; -} - -static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id) -{ - mcpwm->timer[timer_id].timer_sync.timer_sync_sw = ~mcpwm->timer[timer_id].timer_sync.timer_sync_sw; -} - -static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) -{ - HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_sync, timer_phase, phase_value); -} - -static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) -{ - mcpwm->timer[timer_id].timer_sync.timer_phase_direction = direction; -} - -static inline void mcpwm_ll_timer_set_gpio_synchro(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) -{ - mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); - mcpwm->timer_synci_cfg.val |= (gpio_sync_id + 4) << (timer * 3); -} - -static inline void mcpwm_ll_timer_set_timer_synchro(mcpwm_dev_t *mcpwm, int timer, int timer_sync_id) -{ - mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); - mcpwm->timer_synci_cfg.val |= (timer_sync_id + 1) << (timer * 3); -} - -static inline void mcpwm_ll_timer_set_soft_synchro(mcpwm_dev_t *mcpwm, int timer) -{ - // no sync input is selected, but software sync can still work - mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); -} - -static inline void mcpwm_ll_invert_gpio_synchro(mcpwm_dev_t *mcpwm, int sync_id, bool invert) -{ - if (invert) { - mcpwm->timer_synci_cfg.val |= 1 << (sync_id + 9); - } else { - mcpwm->timer_synci_cfg.val &= ~(1 << (sync_id + 9)); - } -} - -/********************* Operator registers *******************/ - -static inline void mcpwm_ll_operator_flush_shadow(mcpwm_dev_t *mcpwm, int operator_id) -{ - mcpwm->update_cfg.val ^= (1 << (2 * operator_id + 3)); -} - -static inline void mcpwm_ll_operator_select_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) -{ - if (operator_id == 0) { - mcpwm->operator_timersel.operator0_timersel = timer_id; - } else if (operator_id == 1) { - mcpwm->operator_timersel.operator1_timersel = timer_id; - } else { - mcpwm->operator_timersel.operator2_timersel = timer_id; - } -} - -static inline void mcpwm_ll_operator_update_compare_at_once(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) -{ - mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~(0x0F << (4 * compare_id)); -} - -static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 0) << (4 * compare_id); - } else { - mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 0) << (4 * compare_id)); - } -} - -static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 1) << (4 * compare_id); - } else { - mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 1) << (4 * compare_id)); - } -} - -static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 2) << (4 * compare_id); - } else { - mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 2) << (4 * compare_id)); - } -} - -static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) -{ - HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen, compare_value); -} - static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen); } -static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) +__attribute__((always_inline)) +static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm) { - mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod = 0; -} - -static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 0; - } else { - mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 0); - } -} - -static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 1; - } else { - mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 1); - } -} - -static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 2; - } else { - mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 2); - } -} - -static inline void mcpwm_ll_operator_set_trigger_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_id) -{ - mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->operators[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); -} - -static inline void mcpwm_ll_operator_set_trigger_timer_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)); - mcpwm->operators[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); -} - -/********************* Generator registers *******************/ - -static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) -{ - mcpwm->operators[operator_id].generator[generator_id].val = 0; -} - -static inline void mcpwm_ll_generator_set_action_on_timer_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, - mcpwm_timer_direction_t direction, mcpwm_timer_event_t event, mcpwm_generator_action_t action) -{ - if (direction == MCPWM_TIMER_DIRECTION_UP) { // utez, utep - mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (event * 2); - } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtez, dtep - mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (event * 2 + 12); - } -} - -static inline void mcpwm_ll_generator_set_action_on_compare_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, - mcpwm_timer_direction_t direction, int cmp_id, int action) -{ - if (direction == MCPWM_TIMER_DIRECTION_UP) { // utea, uteb - mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); - } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtea, dteb - mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); - } -} - -static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, - mcpwm_timer_direction_t direction, int trig_id, int action) -{ - if (direction == MCPWM_TIMER_DIRECTION_UP) { // ut0, ut1 - mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); - } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dt0, dt1 - mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); - } -} - -static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) -{ - if (generator_id == 0) { - mcpwm->operators[operator_id].gen_force.gen_a_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_a_nciforce; - } else { - mcpwm->operators[operator_id].gen_force.gen_b_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_b_nciforce; - } -} - -static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) -{ - mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately - if (generator_id == 0) { - mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = 0; - } else { - mcpwm->operators[operator_id].gen_force.gen_b_cntuforce_mode = 0; - } -} - -static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) -{ - if (generator_id == 0) { - mcpwm->operators[operator_id].gen_force.gen_a_nciforce_mode = 0; - } else { - mcpwm->operators[operator_id].gen_force.gen_b_nciforce_mode = 0; - } -} - -static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) -{ - mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately - if (generator_id == 0) { - mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = level + 1; - } else { - mcpwm->operators[operator_id].gen_force.gen_b_cntuforce_mode = level + 1; - } -} - -static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) -{ - if (generator_id == 0) { - mcpwm->operators[operator_id].gen_force.gen_a_nciforce_mode = level + 1; - } else { - mcpwm->operators[operator_id].gen_force.gen_b_nciforce_mode = level + 1; - } -} - -/********************* Dead time registers *******************/ - -static inline void mcpwm_ll_deadtime_resolution_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same) -{ - // whether to make the resolution of dead time delay module the same to the timer connected with operator - mcpwm->operators[operator_id].dt_cfg.dt_clk_sel = same; -} - -static inline void mcpwm_ll_deadtime_red_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) -{ - mcpwm->operators[operator_id].dt_cfg.dt_red_insel = generator; -} - -static inline void mcpwm_ll_deadtime_fed_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) -{ - mcpwm->operators[operator_id].dt_cfg.dt_fed_insel = generator; -} - -static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool bypass) -{ - if (bypass) { - mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 15); - } else { - mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 15)); - } -} - -static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int operator_id, int path, bool invert) -{ - if (invert) { - mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 13); - } else { - mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 13)); - } -} - -static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool swap) -{ - if (swap) { - mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 9); - } else { - mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 9)); - } -} - -static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - mcpwm->operators[operator_id].dt_cfg.dt_deb_mode = enable; -} - -static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id) -{ - return (mcpwm->operators[operator_id].dt_cfg.dt_deb_mode << 8) | (mcpwm->operators[operator_id].dt_cfg.dt_b_outswap << 7) | - (mcpwm->operators[operator_id].dt_cfg.dt_a_outswap << 6) | (mcpwm->operators[operator_id].dt_cfg.dt_fed_insel << 5) | - (mcpwm->operators[operator_id].dt_cfg.dt_red_insel << 4) | (mcpwm->operators[operator_id].dt_cfg.dt_fed_outinvert << 3) | - (mcpwm->operators[operator_id].dt_cfg.dt_red_outinvert << 2) | (mcpwm->operators[operator_id].dt_cfg.dt_a_outbypass << 1) | - (mcpwm->operators[operator_id].dt_cfg.dt_b_outbypass << 0); -} - -static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) -{ - HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed, fed - 1); -} - -static inline uint32_t mcpwm_ll_deadtime_get_falling_delay(mcpwm_dev_t *mcpwm, int operator_id) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed) + 1; -} - -static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) -{ - HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red, red - 1); -} - -static inline uint32_t mcpwm_ll_deadtime_get_rising_delay(mcpwm_dev_t *mcpwm, int operator_id) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red) + 1; -} - -static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) -{ - mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod = 0; - mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod = 0; -} - -static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 0; - mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 0; - } else { - mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 0); - mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 0); - } -} - -static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 1; - mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 1; - } else { - mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 1); - mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 1); - } -} - -static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 2; - mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 2; - } else { - mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 2); - mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 2); - } -} - -/********************* Carrier registers *******************/ - -static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - mcpwm->operators[operator_id].carrier_cfg.carrier_en = enable; -} - -static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int operator_id, uint8_t prescale) -{ - mcpwm->operators[operator_id].carrier_cfg.carrier_prescale = prescale - 1; -} - -static inline uint8_t mcpwm_ll_carrier_get_prescale(mcpwm_dev_t *mcpwm, int operator_id) -{ - return mcpwm->operators[operator_id].carrier_cfg.carrier_prescale + 1; -} - -static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int operator_id, uint8_t carrier_duty) -{ - mcpwm->operators[operator_id].carrier_cfg.carrier_duty = carrier_duty; -} - -static inline uint8_t mcpwm_ll_carrier_get_duty(mcpwm_dev_t *mcpwm, int operator_id) -{ - return mcpwm->operators[operator_id].carrier_cfg.carrier_duty; -} - -static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) -{ - mcpwm->operators[operator_id].carrier_cfg.carrier_out_invert = invert; -} - -static inline void mcpwm_ll_carrier_in_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) -{ - mcpwm->operators[operator_id].carrier_cfg.carrier_in_invert = invert; -} - -static inline void mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) -{ - mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth = pulse_width - 1; -} - -static inline uint8_t mcpwm_ll_carrier_get_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id) -{ - return mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth + 1; -} - -/********************* Fault detector registers *******************/ - -static inline void mcpwm_ll_fault_enable_detection(mcpwm_dev_t *mcpwm, int fault_sig, bool enable) -{ - if (enable) { - mcpwm->fault_detect.val |= 1 << fault_sig; - } else { - mcpwm->fault_detect.val &= ~(1 << fault_sig); - } -} - -static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault_sig, bool level) -{ - if (level) { - mcpwm->fault_detect.val |= 1 << (fault_sig + 3); - } else { - mcpwm->fault_detect.val &= ~(1 << (fault_sig + 3)); - } -} - -static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) -{ - // a posedge can clear the ost fault status - mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 0; - mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 1; -} - -static inline void mcpwm_ll_fault_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) -{ - mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); - mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (7 - fault_sig)); -} - -static inline void mcpwm_ll_fault_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) -{ - mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); - mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); -} - -static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 1; - } else { - mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 1); - } -} - -static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - if (enable) { - mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 2; - } else { - mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 2); - } -} - -static inline void mcpwm_ll_fault_enable_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - mcpwm->operators[operator_id].fh_cfg0.fh_sw_cbc = enable; -} - -static inline void mcpwm_ll_fault_enable_sw_oneshot(mcpwm_dev_t *mcpwm, int operator_id, bool enable) -{ - mcpwm->operators[operator_id].fh_cfg0.fh_sw_ost = enable; -} - -static inline void mcpwm_ll_fault_trigger_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id) -{ - mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc; -} - -static inline void mcpwm_ll_fault_trigger_sw_ost(mcpwm_dev_t *mcpwm, int operator_id) -{ - mcpwm->operators[operator_id].fh_cfg1.fh_force_ost = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_ost; -} - -static inline void mcpwm_ll_generator_set_action_on_trip_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, - mcpwm_timer_direction_t direction, mcpwm_trip_type_t trip, int action) -{ - if (direction == MCPWM_TIMER_DIRECTION_UP) { - mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); - mcpwm->operators[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); - } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { - mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); - mcpwm->operators[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); - } -} - -static inline bool mcpwm_ll_fault_is_ost_on(mcpwm_dev_t *mcpwm, int op) -{ - return mcpwm->operators[op].fh_status.fh_ost_on; -} - -static inline bool mcpwm_ll_fault_is_cbc_on(mcpwm_dev_t *mcpwm, int op) -{ - return mcpwm->operators[op].fh_status.fh_cbc_on; -} - -/********************* Capture registers *******************/ - -static inline void mcpwm_ll_capture_enable_timer(mcpwm_dev_t *mcpwm, bool enable) -{ - mcpwm->cap_timer_cfg.cap_timer_en = enable; -} - -static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int channel, bool enable) -{ - mcpwm->cap_chn_cfg[channel].capn_en = enable; -} - -static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value) -{ - mcpwm->cap_timer_phase.cap_timer_phase = phase_value; -} - -static inline uint32_t mcpwm_ll_capture_get_sync_phase_value(mcpwm_dev_t *mcpwm) -{ - return mcpwm->cap_timer_phase.cap_timer_phase; -} - -static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool enable) -{ - mcpwm->cap_timer_cfg.cap_synci_en = enable; -} - -static inline void mcpwm_ll_capture_set_internal_timer_synchro(mcpwm_dev_t *mcpwm, int sync_out_timer) -{ - mcpwm->cap_timer_cfg.cap_synci_sel = sync_out_timer + 1; -} - -static inline void mcpwm_ll_capture_set_external_synchro(mcpwm_dev_t *mcpwm, int extern_synchro) -{ - mcpwm->cap_timer_cfg.cap_synci_sel = extern_synchro + 4; -} - -static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm) -{ - mcpwm->cap_timer_cfg.cap_sync_sw = 1; // auto clear -} - -static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int channel, bool enable) -{ - if (enable) { - mcpwm->cap_chn_cfg[channel].val |= 1 << 2; - } else { - mcpwm->cap_chn_cfg[channel].val &= ~(1 << 2); - } -} - -static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int channel, bool enable) -{ - if (enable) { - mcpwm->cap_chn_cfg[channel].val |= 1 << 1; - } else { - mcpwm->cap_chn_cfg[channel].val &= ~(1 << 1); - } -} - -static inline void mcpwm_ll_invert_input(mcpwm_dev_t *mcpwm, int channel, bool invert) -{ - mcpwm->cap_chn_cfg[channel].capn_in_invert = invert; -} - -static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel) -{ - mcpwm->cap_chn_cfg[channel].capn_sw = 1; // auto clear + return (mcpwm->int_st.val >> 27) & 0x07; } __attribute__((always_inline)) -static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) +static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask) { - return mcpwm->cap_chn[channel].capn_value; -} - -__attribute__((always_inline)) -static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) -{ - return mcpwm->cap_status.val & (1 << channel) ? true : false; -} - -static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) -{ - HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale, prescale - 1); -} - -static inline uint32_t mcpwm_ll_capture_get_prescale(mcpwm_dev_t *mcpwm, int channel) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale) + 1; + mcpwm->int_clr.val = (capture_mask & 0x07) << 27; } #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/mcpwm_ll.h b/components/hal/esp32s3/include/hal/mcpwm_ll.h index 4f3305798e..10e2cc1f63 100644 --- a/components/hal/esp32s3/include/hal/mcpwm_ll.h +++ b/components/hal/esp32s3/include/hal/mcpwm_ll.h @@ -15,302 +15,213 @@ #pragma once #include -#include "hal/misc.h" #include "soc/soc_caps.h" #include "soc/mcpwm_struct.h" #include "hal/mcpwm_types.h" +#include "hal/misc.h" #include "hal/assert.h" #ifdef __cplusplus extern "C" { #endif -/// Get the address of peripheral registers -#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : &MCPWM1) -#define MCPWM_LL_MAX_CAPTURE_PRESCALE 255 -#define MCPWM_LL_MAX_COMPARE_VALUE 65535 -#define MCPWM_LL_MAX_DEAD_DELAY 65535 -#define MCPWM_LL_MAX_PHASE_VALUE 65535 +// Get MCPWM group register base address +#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : &MCPWM1) -/********************* Group registers *******************/ +// MCPWM interrupt event mask +#define MCPWM_LL_EVENT_TIMER_STOP(timer) (1 << (timer)) +#define MCPWM_LL_EVENT_TIMER_EMPTY(timer) (1 << ((timer) + 3)) +#define MCPWM_LL_EVENT_TIMER_FULL(timer) (1 << ((timer) + 6)) +#define MCPWM_LL_EVENT_TIMER_MASK(timer) (MCPWM_LL_EVENT_TIMER_STOP(timer) | MCPWM_LL_EVENT_TIMER_EMPTY(timer) | MCPWM_LL_EVENT_TIMER_FULL(timer)) +#define MCPWM_LL_EVENT_FAULT_ENTER(fault) (1 << ((fault) + 9)) +#define MCPWM_LL_EVENT_FAULT_EXIT(fault) (1 << ((fault) + 12)) +#define MCPWM_LL_EVENT_FAULT_MASK(fault) (MCPWM_LL_EVENT_FAULT_ENTER(fault) | MCPWM_LL_EVENT_FAULT_EXIT(fault)) +#define MCPWM_LL_EVENT_CMP_EQUAL(oper, cmp) (1 << ((oper) + (cmp) * 3 + 15)) +#define MCPWM_LL_EVENT_OPER_BRAKE_CBC(oper) (1 << ((oper) + 21)) +#define MCPWM_LL_EVENT_OPER_BRAKE_OST(oper) (1 << ((oper) + 24)) +#define MCPWM_LL_EVENT_OPER_MASK(oper) (MCPWM_LL_EVENT_OPER_BRAKE_CBC(oper) | MCPWM_LL_EVENT_OPER_BRAKE_OST(oper)) +#define MCPWM_LL_EVENT_CAPTURE(cap) (1 << ((cap) + 27)) -// Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1) +// Maximum values due to limited register bit width +#define MCPWM_LL_MAX_CARRIER_ONESHOT 16 +#define MCPWM_LL_MAX_CAPTURE_PRESCALE 256 +#define MCPWM_LL_MAX_DEAD_DELAY 65536 +#define MCPWM_LL_MAX_COUNT_VALUE 65536 + +// translate the HAL types into register values +#define MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) ((uint8_t[]) {0, 1}[(event)]) +#define MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) ((uint8_t[]) {0, 1, 2, 3}[(action)]) +#define MCPWM_LL_BRAKE_MODE_TO_REG_VAL(mode) ((uint8_t[]) {0, 1}[(mode)]) + +/** + * @brief The dead time module's clock source + */ +typedef enum { + MCPWM_LL_DEADTIME_CLK_SRC_GROUP, + MCPWM_LL_DEADTIME_CLK_SRC_TIMER, +} mcpwm_ll_deadtime_clock_src_t; + +////////////////////////////////////////MCPWM Group Specific//////////////////////////////////////////////////////////// + +/** + * @brief Set the MCPWM group clock prescale + * + * @param mcpwm Peripheral instance address + * @param pre_scale Prescale value + */ static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale) { - // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) - // We take care of the "read-modify-write" procedure by ourselves. - mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; - clkcfg.clk_prescale = pre_scale - 1; - mcpwm->clk_cfg = clkcfg; -} - -static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) -{ - mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; - return clkcfg.clk_prescale + 1; + // group clock: PWM_clk = CLK_160M / (prescale + 1) + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale, pre_scale - 1); } +/** + * @brief Enable update MCPWM active registers from shadow registers + * + * @param mcpwm Peripheral instance address + */ static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm) { mcpwm->update_cfg.global_up_en = 1; - // updating of active registers in MCPWM operators should be enabled mcpwm->update_cfg.op0_up_en = 1; mcpwm->update_cfg.op1_up_en = 1; mcpwm->update_cfg.op2_up_en = 1; } +/** + * @brief Flush shadow registers to active registers + * + * @param mcpwm Peripheral instance address + */ static inline void mcpwm_ll_group_flush_shadow(mcpwm_dev_t *mcpwm) { // a toggle can trigger a forced update of all active registers in MCPWM, i.e. shadow->active - mcpwm->update_cfg.global_force_up = ~mcpwm->update_cfg.global_force_up; + mcpwm->update_cfg.global_force_up = 1; + mcpwm->update_cfg.global_force_up = 0; } -/********************* Interrupt registers *******************/ +//////////////////////////////////////////Interrupt Specific//////////////////////////////////////////////////////////// +/** + * @brief Get interrupt status register address + * + * @param mcpwm Peripheral instance address + * @return Register address + */ +static inline volatile void *mcpwm_ll_intr_get_status_reg(mcpwm_dev_t *mcpwm) +{ + return &mcpwm->int_st; +} + +/** + * @brief Enable MCPWM interrupt for specific event mask + * + * @param mcpwm Peripheral instance address + * @param mask Event mask + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_intr_enable(mcpwm_dev_t *mcpwm, uint32_t mask, bool enable) +{ + if (enable) { + mcpwm->int_ena.val |= mask; + } else { + mcpwm->int_ena.val &= ~mask; + } +} + +/** + * @brief Get MCPWM interrupt status + * + * @param mcpwm Peripheral instance address + * @return Interrupt status + */ +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_intr_get_status(mcpwm_dev_t *mcpwm) { return mcpwm->int_st.val; } -static inline void mcpwm_ll_intr_clear_status(mcpwm_dev_t *mcpwm, uint32_t intr_mask) -{ - mcpwm->int_clr.val = intr_mask; -} - -static inline void mcpwm_ll_intr_disable_all(mcpwm_dev_t *mcpwm) -{ - mcpwm->int_ena.val = 0; -} - -//////////// get interrupt status for each event //////////////// - -static inline uint32_t mcpwm_ll_intr_get_timer_stop_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 0) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_timer_tez_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 3) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_timer_tep_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 6) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_fault_enter_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 9) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_fault_exit_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 12) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_compare_status(mcpwm_dev_t *mcpwm, uint32_t cmp_id) -{ - return (mcpwm->int_st.val >> (15 + cmp_id * 3)) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_trip_cbc_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 21) & 0x07; -} - -static inline uint32_t mcpwm_ll_intr_get_trip_ost_status(mcpwm_dev_t *mcpwm) -{ - return (mcpwm->int_st.val >> 24) & 0x07; -} - +/** + * @brief Clear MCPWM interrupt status by mask + * + * @param mcpwm Peripheral instance address + * @param mask Interupt status mask + */ __attribute__((always_inline)) -static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm) +static inline void mcpwm_ll_intr_clear_status(mcpwm_dev_t *mcpwm, uint32_t mask) { - return (mcpwm->int_st.val >> 27) & 0x07; + mcpwm->int_clr.val = mask; } -//////////// clear interrupt status for each event //////////////// - -static inline void mcpwm_ll_intr_clear_timer_stop_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask) -{ - mcpwm->int_clr.val = (timer_mask & 0x07) << 0; -} - -static inline void mcpwm_ll_intr_clear_timer_tez_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask) -{ - mcpwm->int_clr.val = (timer_mask & 0x07) << 3; -} - -static inline void mcpwm_ll_intr_clear_timer_tep_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask) -{ - mcpwm->int_clr.val = (timer_mask & 0x07) << 6; -} - -static inline void mcpwm_ll_intr_clear_fault_enter_status(mcpwm_dev_t *mcpwm, uint32_t fault_mask) -{ - mcpwm->int_clr.val = (fault_mask & 0x07) << 9; -} - -static inline void mcpwm_ll_intr_clear_fault_exit_status(mcpwm_dev_t *mcpwm, uint32_t fault_mask) -{ - mcpwm->int_clr.val = (fault_mask & 0x07) << 12; -} - -static inline void mcpwm_ll_intr_clear_compare_status(mcpwm_dev_t *mcpwm, uint32_t operator_mask, uint32_t cmp_id) -{ - mcpwm->int_clr.val = (operator_mask & 0x07) << (15 + cmp_id * 3); -} - -static inline void mcpwm_ll_intr_clear_trip_cbc_status(mcpwm_dev_t *mcpwm, uint32_t cbc_mask) -{ - mcpwm->int_clr.val = (cbc_mask & 0x07) << 21; -} - -static inline void mcpwm_ll_intr_clear_trip_ost_status(mcpwm_dev_t *mcpwm, uint32_t ost_mask) -{ - mcpwm->int_clr.val = (ost_mask & 0x07) << 24; -} - -__attribute__((always_inline)) -static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask) -{ - mcpwm->int_clr.val = (capture_mask & 0x07) << 27; -} - -//////////// enable interrupt for each event //////////////// - -static inline void mcpwm_ll_intr_enable_timer_stop(mcpwm_dev_t *mcpwm, uint32_t timer_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (timer_id + 0); - } else { - mcpwm->int_ena.val &= ~(1 << (timer_id + 0)); - } -} - -static inline void mcpwm_ll_intr_enable_timer_tez(mcpwm_dev_t *mcpwm, uint32_t timer_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (timer_id + 3); - } else { - mcpwm->int_ena.val &= ~(1 << (timer_id + 3)); - } -} - -static inline void mcpwm_ll_intr_enable_timer_tep(mcpwm_dev_t *mcpwm, uint32_t timer_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (timer_id + 6); - } else { - mcpwm->int_ena.val &= ~(1 << (timer_id + 6)); - } -} - -static inline void mcpwm_ll_intr_enable_fault_enter(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (9 + fault_id); // enter fault interrupt - } else { - mcpwm->int_ena.val &= ~(1 << (9 + fault_id)); - } -} - -static inline void mcpwm_ll_intr_enable_fault_exit(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (12 + fault_id); // exit fault interrupt - } else { - mcpwm->int_ena.val &= ~(1 << (12 + fault_id)); - } -} - -static inline void mcpwm_ll_intr_enable_compare(mcpwm_dev_t *mcpwm, uint32_t operator_id, uint32_t cmp_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= (1 << (15 + cmp_id * 3 + operator_id)); - } else { - mcpwm->int_ena.val &= ~(1 << (15 + cmp_id * 3 + operator_id)); - } -} - -static inline void mcpwm_ll_intr_enable_trip_cbc(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= (1 << (21 + operator_id)); - } else { - mcpwm->int_ena.val &= ~(1 << (21 + operator_id)); - } -} - -static inline void mcpwm_ll_intr_enable_trip_ost(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= (1 << (24 + operator_id)); - } else { - mcpwm->int_ena.val &= ~(1 << (24 + operator_id)); - } -} - -static inline void mcpwm_ll_intr_enable_capture(mcpwm_dev_t *mcpwm, uint32_t capture_id, bool enable) -{ - if (enable) { - mcpwm->int_ena.val |= 1 << (27 + capture_id); - } else { - mcpwm->int_ena.val &= ~(1 << (27 + capture_id)); - } -} - -/********************* Timer registers *******************/ +////////////////////////////////////////MCPWM Timer Specific//////////////////////////////////////////////////////////// +/** + * @brief Set MCPWM timer prescale + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param prescale Prescale value + */ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id, uint32_t prescale) { - // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) - // We take care of the "read-modify-write" procedure by ourselves. - mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; - cfg0.timer_prescale = prescale - 1; - mcpwm->timer[timer_id].timer_cfg0 = cfg0; -} - -static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) -{ - mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; - return cfg0.timer_prescale + 1; + HAL_ASSERT(prescale <= 256 && prescale > 0); + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_prescale, prescale - 1); } +/** + * @brief Set peak value for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param peak Peak value + * @param symmetric True to set symmetric peak value, False to set asymmetric peak value + */ static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) { if (!symmetric) { // in asymmetric mode, period = [0,peak-1] + HAL_ASSERT(peak > 0 && peak <= MCPWM_LL_MAX_COUNT_VALUE); HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1); } else { // in symmetric mode, period = [0,peak-1] + [peak,1] + HAL_ASSERT(peak < MCPWM_LL_MAX_COUNT_VALUE); HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak); } } -static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, bool symmetric) -{ - // asymmetric mode - if (!symmetric) { - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1; - } - // symmetric mode - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period); -} - +/** + * @brief Update MCPWM period immediately + * @note When period value is updated in the shadow register, it will be flushed to active register immediately. + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod = 0; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod = 0; } +/** + * @brief Enable to update MCPWM period upon TEZ event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_timer_enable_update_period_on_tez(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x01; } else { - mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x01; } } +/** + * @brief Enable to update MCPWM period upon sync event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { @@ -320,6 +231,13 @@ static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpw } } +/** + * @brief Set MCPWM timer count mode + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param mode Timer count mode + */ static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_count_mode_t mode) { switch (mode) { @@ -335,45 +253,51 @@ static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_i case MCPWM_TIMER_COUNT_MODE_UP_DOWN: mcpwm->timer[timer_id].timer_cfg1.timer_mod = 3; break; - } -} - -static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t *mcpwm, int timer_id) -{ - switch (mcpwm->timer[timer_id].timer_cfg1.timer_mod) { - case 1: - return MCPWM_TIMER_COUNT_MODE_UP; - case 2: - return MCPWM_TIMER_COUNT_MODE_DOWN; - case 3: - return MCPWM_TIMER_COUNT_MODE_UP_DOWN; - case 0: default: - return MCPWM_TIMER_COUNT_MODE_PAUSE; + HAL_ASSERT(false); + break; } } -static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_execute_cmd_t cmd) +/** + * @brief Execute MCPWM timer start/stop command + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param cmd Timer start/stop command + */ +static inline void mcpwm_ll_timer_set_start_stop_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_start_stop_cmd_t cmd) { switch (cmd) { - case MCPWM_TIMER_STOP_AT_ZERO: + case MCPWM_TIMER_STOP_EMPTY: mcpwm->timer[timer_id].timer_cfg1.timer_start = 0; break; - case MCPWM_TIMER_STOP_AT_PEAK: + case MCPWM_TIMER_STOP_FULL: mcpwm->timer[timer_id].timer_cfg1.timer_start = 1; break; case MCPWM_TIMER_START_NO_STOP: mcpwm->timer[timer_id].timer_cfg1.timer_start = 2; break; - case MCPWM_TIMER_START_STOP_AT_ZERO: + case MCPWM_TIMER_START_STOP_EMPTY: mcpwm->timer[timer_id].timer_cfg1.timer_start = 3; break; - case MCPWM_TIMER_START_STOP_AT_PEAK: + case MCPWM_TIMER_START_STOP_FULL: mcpwm->timer[timer_id].timer_cfg1.timer_start = 4; break; + default: + HAL_ASSERT(false); + break;; } } +/** + * @brief Get timer count value + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @return Timer count value + */ +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id) { // status.value saves the "next count value", so need an extra round up here to get the current count value according to count mode @@ -391,73 +315,158 @@ static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int ti (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1); } +/** + * @brief Get timer count direction + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @return Timer count direction + */ +__attribute__((always_inline)) static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) { return mcpwm->timer[timer_id].timer_status.timer_direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; } +/** + * @brief Enable sync input for timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { mcpwm->timer[timer_id].timer_sync.timer_synci_en = enable; } -static inline void mcpwm_ll_timer_sync_out_penetrate(mcpwm_dev_t *mcpwm, int timer_id) +/** + * @brief Use the input sync signal as the output sync signal (i.e. propagate the input sync signal) + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_propagate_input_sync(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out is selected to sync_in mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 0; } +/** + * @brief Set the sync output signal to one of the timer event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param event Timer event + */ static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_event_t event) { - if (event == MCPWM_TIMER_EVENT_ZERO) { + switch (event) { + case MCPWM_TIMER_EVENT_EMPTY: mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 1; - } else if (event == MCPWM_TIMER_EVENT_PEAK) { + break; + case MCPWM_TIMER_EVENT_FULL: mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 2; - } else { - HAL_ASSERT(false && "unknown sync out event"); + break; + default: + HAL_ASSERT(false); + break; } } +/** + * @brief Disable sync output for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out will always be zero mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 3; } +/** + * @brief Trigger MCPWM timer software sync event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id) { mcpwm->timer[timer_id].timer_sync.timer_sync_sw = ~mcpwm->timer[timer_id].timer_sync.timer_sync_sw; } +/** + * @brief Set sync count value for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param phase_value Sync phase value + */ static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) { HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_sync, timer_phase, phase_value); } +/** + * @brief Set sync phase direction for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param direction Sync phase direction + */ static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) { mcpwm->timer[timer_id].timer_sync.timer_phase_direction = direction; } -static inline void mcpwm_ll_timer_set_gpio_synchro(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) +/** + * @brief Select which GPIO sync input to use + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + * @param gpio_sync_id GPIO sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_set_gpio_sync_input(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) { mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); mcpwm->timer_synci_cfg.val |= (gpio_sync_id + 4) << (timer * 3); } -static inline void mcpwm_ll_timer_set_timer_synchro(mcpwm_dev_t *mcpwm, int timer, int timer_sync_id) +/** + * @brief Select which timer sync input to use + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + * @param timer_sync_id Timer sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_set_timer_sync_input(mcpwm_dev_t *mcpwm, int timer, int timer_sync_id) { mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); mcpwm->timer_synci_cfg.val |= (timer_sync_id + 1) << (timer * 3); } -static inline void mcpwm_ll_timer_set_soft_synchro(mcpwm_dev_t *mcpwm, int timer) +/** + * @brief Clear timer sync input selection + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_clear_sync_input(mcpwm_dev_t *mcpwm, int timer) { // no sync input is selected, but software sync can still work mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); } -static inline void mcpwm_ll_invert_gpio_synchro(mcpwm_dev_t *mcpwm, int sync_id, bool invert) +/** + * @brief Invert the GPIO sync input signal + * + * @param mcpwm Peripheral instance address + * @param sync_id GPIO sync ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_invert_gpio_sync_input(mcpwm_dev_t *mcpwm, int sync_id, bool invert) { if (invert) { mcpwm->timer_synci_cfg.val |= 1 << (sync_id + 9); @@ -466,29 +475,52 @@ static inline void mcpwm_ll_invert_gpio_synchro(mcpwm_dev_t *mcpwm, int sync_id, } } -/********************* Operator registers *******************/ +////////////////////////////////////////MCPWM Operator Specific///////////////////////////////////////////////////////// +/** + * @brief Flush operator shadow registers to active registers + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ static inline void mcpwm_ll_operator_flush_shadow(mcpwm_dev_t *mcpwm, int operator_id) { mcpwm->update_cfg.val ^= (1 << (2 * operator_id + 3)); } -static inline void mcpwm_ll_operator_select_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) +/** + * @brief Connect operator and timer by ID + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_operator_connect_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) { - if (operator_id == 0) { - mcpwm->operator_timersel.operator0_timersel = timer_id; - } else if (operator_id == 1) { - mcpwm->operator_timersel.operator1_timersel = timer_id; - } else { - mcpwm->operator_timersel.operator2_timersel = timer_id; - } + mcpwm->operator_timersel.val &= ~(0x03 << (2 * operator_id)); + mcpwm->operator_timersel.val |= (timer_id << (2 * operator_id)); } +/** + * @brief Update the compare value immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + */ static inline void mcpwm_ll_operator_update_compare_at_once(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~(0x0F << (4 * compare_id)); } +/** + * @brief Enable to update the compare value upon TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { @@ -498,6 +530,14 @@ static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *m } } +/** + * @brief Enable to update the compare value upon TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { @@ -507,6 +547,14 @@ static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *m } } +/** + * @brief Enable to update the compare value upon sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { @@ -516,21 +564,55 @@ static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t * } } +/** + * @brief Stop updating the compare value + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param stop_or_not True to stop, False to not stop + */ +static inline void mcpwm_ll_operator_stop_update_compare(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool stop_or_not) +{ + if (stop_or_not) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 3) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 3) << (4 * compare_id)); + } +} + +/** + * @brief Set compare value for comparator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param compare_value Compare value + */ +__attribute__((always_inline)) static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) { HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen, compare_value); } -static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen); -} - +/** + * @brief Update operator actions immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) { mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod = 0; } +/** + * @brief Enable update actions on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { @@ -540,6 +622,13 @@ static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mc } } +/** + * @brief Enable update actions on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { @@ -549,6 +638,13 @@ static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mc } } +/** + * @brief Enable update actions on sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { @@ -558,62 +654,162 @@ static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *m } } -static inline void mcpwm_ll_operator_set_trigger_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_id) +/** + * @brief Stop updating actions + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param stop_or_not True to stop, False to not stop + */ +static inline void mcpwm_ll_operator_stop_update_action(mcpwm_dev_t *mcpwm, int operator_id, bool stop_or_not) { - mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->operators[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); + if (stop_or_not) { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 3; + } else { + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 3); + } } -static inline void mcpwm_ll_operator_set_trigger_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id) +/** + * @brief Set trigger from GPIO (reuse the fault GPIO) + * + * @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 + * @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) +{ + 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) + * + * @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) { // 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 |= (3 << (4 + 3 * trig_id)); } -/********************* Generator registers *******************/ +////////////////////////////////////////MCPWM Generator Specific//////////////////////////////////////////////////////// +/** + * @brief Reset actions for the generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { mcpwm->operators[operator_id].generator[generator_id].val = 0; } +/** + * @brief Set generator action on timer event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param event Timer event + * @param action Action to set + */ static inline void mcpwm_ll_generator_set_action_on_timer_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_timer_event_t event, mcpwm_generator_action_t action) { + // empty: 0, full: 1 if (direction == MCPWM_TIMER_DIRECTION_UP) { // utez, utep - mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (event * 2); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtez, dtep - mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (event * 2 + 12); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2 + 12)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2 + 12); } } +/** + * @brief Set generator action on compare event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param comp_id Compare ID, index from 0 to 1 + * @param action Action to set + */ static inline void mcpwm_ll_generator_set_action_on_compare_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, int cmp_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utea, uteb mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (cmp_id * 2 + 4); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtea, dteb mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (cmp_id * 2 + 16); } } +/** + * @brief Set generator action on trigger event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param trig_id Trigger ID, index from 0 to 1 + * @param action Action to set + */ static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, int trig_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // ut0, ut1 mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (trig_id * 2 + 8); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dt0, dt1 mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); - mcpwm->operators[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (trig_id * 2 + 20); } } +/** + * @brief Set generator action on brake event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param brake_mode Brake mode + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_brake_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, mcpwm_operator_brake_mode_t brake_mode, int action) +{ + // the following bit operation is highly depend on the register bit layout. + // the priority comes: generator ID > brake mode > direction + if (direction == MCPWM_TIMER_DIRECTION_UP) { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode) + 2)); + mcpwm->operators[operator_id].fh_cfg0.val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode) + 2); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode))); + mcpwm->operators[operator_id].fh_cfg0.val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode)); + } +} + +/** + * @brief Trigger non-continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { @@ -623,6 +819,13 @@ static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mc } } +/** + * @brief Disable continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately @@ -633,6 +836,13 @@ static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm } } +/** + * @brief Disable non-continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { @@ -642,6 +852,14 @@ static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mc } } +/** + * @brief Set continue force level for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param level Force level to set + */ static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately @@ -652,6 +870,14 @@ static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int } } +/** + * @brief Set non-continue force level for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param level Force level to set + */ static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { if (generator_id == 0) { @@ -661,24 +887,61 @@ static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, } } -/********************* Dead time registers *******************/ +////////////////////////////////////////MCPWM Dead Time Specific//////////////////////////////////////////////////////// -static inline void mcpwm_ll_deadtime_resolution_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same) +/** + * @brief Set clock source for dead time submodule + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param src Clock source for dead time submodule + */ +static inline void mcpwm_ll_operator_set_deadtime_clock_src(mcpwm_dev_t *mcpwm, int operator_id, mcpwm_ll_deadtime_clock_src_t src) { - // whether to make the resolution of dead time delay module the same to the timer connected with operator - mcpwm->operators[operator_id].dt_cfg.dt_clk_sel = same; + switch (src) { + case MCPWM_LL_DEADTIME_CLK_SRC_GROUP: + mcpwm->operators[operator_id].dt_cfg.dt_clk_sel = 0; + break; + case MCPWM_LL_DEADTIME_CLK_SRC_TIMER: + mcpwm->operators[operator_id].dt_cfg.dt_clk_sel = 1; + break;; + default: + HAL_ASSERT(false); + } } +/** + * @brief Select the generator for RED block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator Generator ID, index from 0 to 1 + */ static inline void mcpwm_ll_deadtime_red_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { mcpwm->operators[operator_id].dt_cfg.dt_red_insel = generator; } +/** + * @brief Select the generator for FED block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator Generator ID, index from 0 to 1 + */ static inline void mcpwm_ll_deadtime_fed_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { mcpwm->operators[operator_id].dt_cfg.dt_fed_insel = generator; } +/** + * @brief Set which path to bypass in the deadtime submodule + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to bypass, index from 0 to 1 + * @param bypass True to bypass, False to not bypass + */ static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool bypass) { if (bypass) { @@ -688,6 +951,14 @@ static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operato } } +/** + * @brief Invert the output path + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to invert, index from 0 to 1 + * @param invert True to invert, False to not invert + */ static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int operator_id, int path, bool invert) { if (invert) { @@ -697,6 +968,14 @@ static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int oper } } +/** + * @brief Swap the output path + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to swap, index from 0 to 1 + * @param swap True to swap, False to not swap + */ static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool swap) { if (swap) { @@ -706,11 +985,25 @@ static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int opera } } +/** + * @brief Enable the DEB block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { mcpwm->operators[operator_id].dt_cfg.dt_deb_mode = enable; } +/** + * @brief Get the deadtime switch topology + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return Dead time submodule's switch topology, each bit represents one switch on/off status + */ static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id) { return (mcpwm->operators[operator_id].dt_cfg.dt_deb_mode << 8) | (mcpwm->operators[operator_id].dt_cfg.dt_b_outswap << 7) | @@ -720,32 +1013,49 @@ static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, (mcpwm->operators[operator_id].dt_cfg.dt_b_outbypass << 0); } +/** + * @brief Set falling edge delay duration + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fed Delay duration, in deadtime submodule's clock cycles + */ static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) { HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed, fed - 1); } -static inline uint32_t mcpwm_ll_deadtime_get_falling_delay(mcpwm_dev_t *mcpwm, int operator_id) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed) + 1; -} - +/** + * @brief Set rising edge delay duration + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param red Delay duration, in deadtime submodule's clock cycles + */ static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) { HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red, red - 1); } -static inline uint32_t mcpwm_ll_deadtime_get_rising_delay(mcpwm_dev_t *mcpwm, int operator_id) -{ - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red) + 1; -} - +/** + * @brief Update deadtime immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) { mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod = 0; mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod = 0; } +/** + * @brief Enable to update deadtime on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { @@ -757,6 +1067,13 @@ static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcp } } +/** + * @brief Enable to update deadtime on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { @@ -768,6 +1085,13 @@ static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcp } } +/** + * @brief Enable to update deadtime on sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { @@ -779,55 +1103,109 @@ static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mc } } -/********************* Carrier registers *******************/ +/** + * @brief Stop updating deadtime + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param stop_or_not True to stop, False to continue + */ +static inline void mcpwm_ll_deadtime_stop_update_delay(mcpwm_dev_t *mcpwm, int operator_id, bool stop_or_not) +{ + if (stop_or_not) { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 3; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 3; + } else { + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 3); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 3); + } +} +////////////////////////////////////////MCPWM Carrier Specific////////////////////////////////////////////////////////// + +/** + * @brief Enable carrier for MCPWM operator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { mcpwm->operators[operator_id].carrier_cfg.carrier_en = enable; } +/** + * @brief Set prescale for MCPWM carrier source clock + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param prescale Prescale value + */ static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int operator_id, uint8_t prescale) { + HAL_ASSERT(prescale > 0 && prescale <= 16); mcpwm->operators[operator_id].carrier_cfg.carrier_prescale = prescale - 1; } -static inline uint8_t mcpwm_ll_carrier_get_prescale(mcpwm_dev_t *mcpwm, int operator_id) -{ - return mcpwm->operators[operator_id].carrier_cfg.carrier_prescale + 1; -} - +/** + * @brief Set duty cycle of MCPWM carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param carrier_duty Duty cycle value + */ static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int operator_id, uint8_t carrier_duty) { mcpwm->operators[operator_id].carrier_cfg.carrier_duty = carrier_duty; } -static inline uint8_t mcpwm_ll_carrier_get_duty(mcpwm_dev_t *mcpwm, int operator_id) -{ - return mcpwm->operators[operator_id].carrier_cfg.carrier_duty; -} - +/** + * @brief Invert the signal after the carrier is applied + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { mcpwm->operators[operator_id].carrier_cfg.carrier_out_invert = invert; } +/** + * @brief Invert the signal before applying the carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ static inline void mcpwm_ll_carrier_in_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { mcpwm->operators[operator_id].carrier_cfg.carrier_in_invert = invert; } -static inline void mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) +/** + * @brief Set the first pulse width of the carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param pulse_width Pulse width + */ +static inline void mcpwm_ll_carrier_set_first_pulse_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) { + HAL_ASSERT(pulse_width >= 1); mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth = pulse_width - 1; } -static inline uint8_t mcpwm_ll_carrier_get_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id) -{ - return mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth + 1; -} - -/********************* Fault detector registers *******************/ +////////////////////////////////////////MCPWM Fault Specific//////////////////////////////////////////////////////////// +/** + * @brief Enable GPIO fault detection + * + * @param mcpwm Peripheral instance address + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_fault_enable_detection(mcpwm_dev_t *mcpwm, int fault_sig, bool enable) { if (enable) { @@ -837,6 +1215,13 @@ static inline void mcpwm_ll_fault_enable_detection(mcpwm_dev_t *mcpwm, int fault } } +/** + * @brief Set fault polarity (i.e. which level is treated as an active fault) + * + * @param mcpwm Peripheral instance address + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param level Active level, 0 for low, 1 for high + */ static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault_sig, bool level) { if (level) { @@ -846,26 +1231,61 @@ static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault } } -static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) +/** + * @brief Clear the OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) { // a posedge can clear the ost fault status mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 0; mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 1; } -static inline void mcpwm_ll_fault_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) +/** + * @brief Enable the OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); - mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (7 - fault_sig)); + if (enable) { + mcpwm->operators[operator_id].fh_cfg0.val |= (1 << (7 - fault_sig)); + } else { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); + } } -static inline void mcpwm_ll_fault_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) +/** + * @brief Enable the CBC brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); - mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); + if (enable) { + mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); + } else { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); + } } -static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +/** + * @brief Enable refresh the CBC brake on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 1; @@ -874,6 +1294,13 @@ static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, } } +/** + * @brief Enable refresh the CBC brake on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { @@ -883,90 +1310,162 @@ static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, } } -static inline void mcpwm_ll_fault_enable_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +/** + * @brief Enable software CBC brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_soft_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { mcpwm->operators[operator_id].fh_cfg0.fh_sw_cbc = enable; } -static inline void mcpwm_ll_fault_enable_sw_oneshot(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +/** + * @brief Enable software OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_soft_ost(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { mcpwm->operators[operator_id].fh_cfg0.fh_sw_ost = enable; } -static inline void mcpwm_ll_fault_trigger_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id) +/** + * @brief Trigger software CBC brake for once + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_trigger_soft_cbc(mcpwm_dev_t *mcpwm, int operator_id) { mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc; } -static inline void mcpwm_ll_fault_trigger_sw_ost(mcpwm_dev_t *mcpwm, int operator_id) +/** + * @brief Trigger software OST brake for once + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_trigger_soft_ost(mcpwm_dev_t *mcpwm, int operator_id) { mcpwm->operators[operator_id].fh_cfg1.fh_force_ost = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_ost; } -static inline void mcpwm_ll_generator_set_action_on_trip_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, - mcpwm_timer_direction_t direction, mcpwm_trip_type_t trip, int action) +/** + * @brief Whether the OST brake is still active + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return True if active, False if not + */ +static inline bool mcpwm_ll_ost_brake_active(mcpwm_dev_t *mcpwm, int operator_id) { - if (direction == MCPWM_TIMER_DIRECTION_UP) { - mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); - mcpwm->operators[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); - } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { - mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); - mcpwm->operators[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); - } + return mcpwm->operators[operator_id].fh_status.fh_ost_on; } -static inline bool mcpwm_ll_fault_is_ost_on(mcpwm_dev_t *mcpwm, int op) +/** + * @brief Whether the CBC brake is still active + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return True if active, False if not + */ +static inline bool mcpwm_ll_cbc_brake_active(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->operators[op].fh_status.fh_ost_on; + return mcpwm->operators[operator_id].fh_status.fh_cbc_on; } -static inline bool mcpwm_ll_fault_is_cbc_on(mcpwm_dev_t *mcpwm, int op) -{ - return mcpwm->operators[op].fh_status.fh_cbc_on; -} - -/********************* Capture registers *******************/ +////////////////////////////////////////MCPWM Capture Specific////////////////////////////////////////////////////////// +/** + * @brief Enable capture timer + * + * @param mcpwm Peripheral instance address + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_capture_enable_timer(mcpwm_dev_t *mcpwm, bool enable) { mcpwm->cap_timer_cfg.cap_timer_en = enable; } +/** + * @brief Enable capture channel + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int channel, bool enable) { mcpwm->cap_chn_cfg[channel].capn_en = enable; } +/** + * @brief Set sync phase for capture timer + * + * @param mcpwm Peripheral instance address + * @param phase_value Phase value + */ static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value) { mcpwm->cap_timer_phase.cap_timer_phase = phase_value; } -static inline uint32_t mcpwm_ll_capture_get_sync_phase_value(mcpwm_dev_t *mcpwm) -{ - return mcpwm->cap_timer_phase.cap_timer_phase; -} - +/** + * @brief Enable sync for capture timer + * + * @param mcpwm Peripheral instance address + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool enable) { mcpwm->cap_timer_cfg.cap_synci_en = enable; } -static inline void mcpwm_ll_capture_set_internal_timer_synchro(mcpwm_dev_t *mcpwm, int sync_out_timer) +/** + * @brief Set the timer sync source for MCPWM capture timer + * + * @param mcpwm Peripheral instance address + * @param sync_out_timer MCPWM Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_capture_set_timer_sync(mcpwm_dev_t *mcpwm, int sync_out_timer) { mcpwm->cap_timer_cfg.cap_synci_sel = sync_out_timer + 1; } -static inline void mcpwm_ll_capture_set_external_synchro(mcpwm_dev_t *mcpwm, int extern_synchro) +/** + * @brief Set the GPIO sync source for MCPWM capture timer + * + * @param mcpwm Peripheral instance address + * @param gpio_sync GPIO sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_capture_set_gpio_sync(mcpwm_dev_t *mcpwm, int gpio_sync) { - mcpwm->cap_timer_cfg.cap_synci_sel = extern_synchro + 4; + mcpwm->cap_timer_cfg.cap_synci_sel = gpio_sync + 4; } +/** + * @brief Trigger a software sync for capture timer + * + * @param mcpwm Peripheral instance address + */ static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm) { mcpwm->cap_timer_cfg.cap_sync_sw = 1; // auto clear } +/** + * @brief Enable capture on positive edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { @@ -976,6 +1475,13 @@ static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int chann } } +/** + * @brief Enable capture on negative edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { @@ -985,36 +1491,119 @@ static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int chann } } +/** + * @brief Invert the capture input signal + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ static inline void mcpwm_ll_invert_input(mcpwm_dev_t *mcpwm, int channel, bool invert) { mcpwm->cap_chn_cfg[channel].capn_in_invert = invert; } +/** + * @brief Trigger the software capture for once + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + */ static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel) { mcpwm->cap_chn_cfg[channel].capn_sw = 1; // auto clear } +/** + * @brief Get the captured value + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @return Captured value + */ __attribute__((always_inline)) static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) { return mcpwm->cap_chn[channel].capn_value; } +/** + * @brief Get the captured edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @return Captured edge + */ __attribute__((always_inline)) -static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) +static inline mcpwm_capture_edge_t mcpwm_ll_capture_get_edge(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_status.val & (1 << channel) ? true : false; + return mcpwm->cap_status.val & (1 << channel) ? MCPWM_CAP_EDGE_NEG : MCPWM_CAP_EDGE_POS; } +/** + * @brief Set the prescale of the input capture signal + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param prescale Prescale value + */ static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) { + HAL_ASSERT(prescale > 0); HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale, prescale - 1); } -static inline uint32_t mcpwm_ll_capture_get_prescale(mcpwm_dev_t *mcpwm, int channel) +//////////////////////////////////////////Deprecated Functions////////////////////////////////////////////////////////// +/////////////////////////////The following functions are only used by the legacy driver///////////////////////////////// +/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) { - return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale) + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale) + 1; +} + +static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) +{ + mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; + return cfg0.timer_prescale + 1; +} + +static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, bool symmetric) +{ + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + (symmetric ? 0 : 1); +} + +static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t *mcpwm, int timer_id) +{ + switch (mcpwm->timer[timer_id].timer_cfg1.timer_mod) { + case 1: + return MCPWM_TIMER_COUNT_MODE_UP; + case 2: + return MCPWM_TIMER_COUNT_MODE_DOWN; + case 3: + return MCPWM_TIMER_COUNT_MODE_UP_DOWN; + case 0: + default: + return MCPWM_TIMER_COUNT_MODE_PAUSE; + } +} + +static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) +{ + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen); +} + +__attribute__((always_inline)) +static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm) +{ + return (mcpwm->int_st.val >> 27) & 0x07; +} + +__attribute__((always_inline)) +static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask) +{ + mcpwm->int_clr.val = (capture_mask & 0x07) << 27; } #ifdef __cplusplus diff --git a/components/hal/include/hal/mcpwm_hal.h b/components/hal/include/hal/mcpwm_hal.h index 982d5d3abf..752603a568 100644 --- a/components/hal/include/hal/mcpwm_hal.h +++ b/components/hal/include/hal/mcpwm_hal.h @@ -1,16 +1,8 @@ -// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /******************************************************************************* * NOTICE @@ -18,18 +10,28 @@ * See readme.md in hal/include/hal/readme.md ******************************************************************************/ -// The HAL layer for MCPWM (common part) - #pragma once -#include "soc/mcpwm_struct.h" +#include +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mcpwm_dev_t *mcpwm_soc_handle_t; // MCPWM SOC layer handle + +/** + * @brief HAL layer configuration + */ typedef struct { - int host_id; ///< Which MCPWM peripheral to use, 0-1. + int group_id; // Indicate the MCPWM hardware group } mcpwm_hal_init_config_t; +/** + * Context that should be maintained by both the driver and the HAL + */ typedef struct { - mcpwm_dev_t *dev; ///< Beginning address of the peripheral registers of a single MCPWM unit. Call `mcpwm_hal_init` to initialize it. + mcpwm_soc_handle_t dev; // MCPWM SOC layer handle } mcpwm_hal_context_t; /** @@ -39,3 +41,39 @@ typedef struct { * @param init_config Configuration for the HAL to be used only once. */ void mcpwm_hal_init(mcpwm_hal_context_t *hal, const mcpwm_hal_init_config_t *init_config); + +/** + * @brief Deinitialize the HAL driver. + * + * @param hal Context of the HAL layer. + */ +void mcpwm_hal_deinit(mcpwm_hal_context_t *hal); + +/** + * @brief Reset MCPWM timer + * + * @param hal Context of the HAL layer. + * @param timer_id Timer ID + */ +void mcpwm_hal_timer_reset(mcpwm_hal_context_t *hal, int timer_id); + +/** + * @brief Reset MCPWM operator + * + * @param hal Context of the HAL layer. + * @param oper_id Operator ID + */ +void mcpwm_hal_operator_reset(mcpwm_hal_context_t *hal, int oper_id); + +/** + * @brief Reset MCPWM generator + * + * @param hal Context of the HAL layer. + * @param oper_id Operator ID + * @param gen_id Generator ID + */ +void mcpwm_hal_generator_reset(mcpwm_hal_context_t *hal, int oper_id, int gen_id); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/mcpwm_types.h b/components/hal/include/hal/mcpwm_types.h index b9c37315bc..b31824b0fe 100644 --- a/components/hal/include/hal/mcpwm_types.h +++ b/components/hal/include/hal/mcpwm_types.h @@ -1,29 +1,47 @@ -// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once +#include "soc/clk_tree_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief MCPWM timer clock source + */ +typedef soc_periph_mcpwm_timer_clk_src_t mcpwm_timer_clock_source_t; + +/** + * @brief MCPWM capture clock source + */ +typedef soc_periph_mcpwm_capture_clk_src_t mcpwm_capture_clock_source_t; + +/** + * @brief MCPWM timer count direction + */ typedef enum { MCPWM_TIMER_DIRECTION_UP, /*!< Counting direction: Increase */ MCPWM_TIMER_DIRECTION_DOWN, /*!< Counting direction: Decrease */ } mcpwm_timer_direction_t; +/** + * @brief MCPWM timer events + */ typedef enum { - MCPWM_TIMER_EVENT_ZERO, /*!< MCPWM timer counts to zero */ - MCPWM_TIMER_EVENT_PEAK, /*!< MCPWM timer counts to peak */ + MCPWM_TIMER_EVENT_EMPTY, /*!< MCPWM timer counts to zero (i.e. counter is empty) */ + MCPWM_TIMER_EVENT_FULL, /*!< MCPWM timer counts to peak (i.e. counter is full) */ + MCPWM_TIMER_EVENT_INVALID, /*!< MCPWM timer invalid event */ } mcpwm_timer_event_t; +/** + * @brief MCPWM timer count modes + */ typedef enum { MCPWM_TIMER_COUNT_MODE_PAUSE, /*!< MCPWM timer paused */ MCPWM_TIMER_COUNT_MODE_UP, /*!< MCPWM timer counting up */ @@ -31,14 +49,20 @@ typedef enum { MCPWM_TIMER_COUNT_MODE_UP_DOWN, /*!< MCPWM timer counting up and down */ } mcpwm_timer_count_mode_t; +/** + * @brief MCPWM timer commands, specify the way to start or stop the timer + */ typedef enum { - MCPWM_TIMER_STOP_AT_ZERO, /*!< MCPWM timer stops when couting to zero */ - MCPWM_TIMER_STOP_AT_PEAK, /*!< MCPWM timer stops when counting to peak */ - MCPWM_TIMER_START_NO_STOP, /*!< MCPWM timer starts couting */ - MCPWM_TIMER_START_STOP_AT_ZERO, /*!< MCPWM timer starts counting and stops when couting to zero */ - MCPWM_TIMER_START_STOP_AT_PEAK, /*!< MCPWM timer starts counting and stops when counting to peak */ -} mcpwm_timer_execute_cmd_t; + MCPWM_TIMER_STOP_EMPTY, /*!< MCPWM timer stops when next count reaches zero */ + MCPWM_TIMER_STOP_FULL, /*!< MCPWM timer stops when next count reaches peak */ + MCPWM_TIMER_START_NO_STOP, /*!< MCPWM timer starts couting, and don't stop until received stop command */ + MCPWM_TIMER_START_STOP_EMPTY, /*!< MCPWM timer starts counting and stops when next count reaches zero */ + MCPWM_TIMER_START_STOP_FULL, /*!< MCPWM timer starts counting and stops when next count reaches peak */ +} mcpwm_timer_start_stop_cmd_t; +/** + * @brief MCPWM generator actions + */ typedef enum { MCPWM_GEN_ACTION_KEEP, /*!< Generator action: Keep the same level */ MCPWM_GEN_ACTION_LOW, /*!< Generator action: Force to low level */ @@ -46,7 +70,23 @@ typedef enum { MCPWM_GEN_ACTION_TOGGLE, /*!< Generator action: Toggle level */ } mcpwm_generator_action_t; +/** + * @brief MCPWM operator brake mode + */ typedef enum { - MCPWM_TRIP_TYPE_CBC, /*!< CBC trip type, shut down the operator cycle by cycle*/ - MCPWM_TRIP_TYPE_OST, /*!< OST trip type, shut down the operator in one shot */ -} mcpwm_trip_type_t; + 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_INVALID, /*!< MCPWM operator invalid brake mode */ +} mcpwm_operator_brake_mode_t; + +/** + * @brief MCPWM capture edge + */ +typedef enum { + MCPWM_CAP_EDGE_POS, /*!< Capture on the positive edge */ + MCPWM_CAP_EDGE_NEG, /*!< Capture on the negative edge */ +} mcpwm_capture_edge_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/mcpwm_hal.c b/components/hal/mcpwm_hal.c index 37ab6b2a9a..e9108404ec 100644 --- a/components/hal/mcpwm_hal.c +++ b/components/hal/mcpwm_hal.c @@ -1,23 +1,56 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// The HAL layer for MCPWM (common part) +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "soc/soc_caps.h" #include "hal/mcpwm_hal.h" #include "hal/mcpwm_ll.h" void mcpwm_hal_init(mcpwm_hal_context_t *hal, const mcpwm_hal_init_config_t *init_config) { - hal->dev = MCPWM_LL_GET_HW(init_config->host_id); + hal->dev = MCPWM_LL_GET_HW(init_config->group_id); + mcpwm_ll_group_enable_shadow_mode(hal->dev); + mcpwm_ll_group_flush_shadow(hal->dev); +} + +void mcpwm_hal_deinit(mcpwm_hal_context_t *hal) +{ + hal->dev = NULL; +} + +void mcpwm_hal_timer_reset(mcpwm_hal_context_t *hal, int timer_id) +{ + mcpwm_ll_timer_set_count_mode(hal->dev, timer_id, MCPWM_TIMER_COUNT_MODE_PAUSE); + mcpwm_ll_timer_update_period_at_once(hal->dev, timer_id); + // disable sync input and output by default + mcpwm_ll_timer_disable_sync_out(hal->dev, timer_id); + mcpwm_ll_timer_enable_sync_input(hal->dev, timer_id, false); + mcpwm_ll_timer_clear_sync_input(hal->dev, timer_id); +} + +void mcpwm_hal_operator_reset(mcpwm_hal_context_t *hal, int oper_id) +{ + // allow to update action, compare, and dead time configuration + mcpwm_ll_operator_stop_update_action(hal->dev, oper_id, false); + mcpwm_ll_operator_update_action_at_once(hal->dev, oper_id); + mcpwm_ll_deadtime_stop_update_delay(hal->dev, oper_id, false); + mcpwm_ll_deadtime_update_delay_at_once(hal->dev, oper_id); + for (int i = 0; i < SOC_MCPWM_COMPARATORS_PER_OPERATOR; i++) { + mcpwm_ll_operator_stop_update_compare(hal->dev, oper_id, i, false); + mcpwm_ll_operator_update_compare_at_once(hal->dev, oper_id, i); + } + mcpwm_ll_brake_enable_cbc_refresh_on_tez(hal->dev, oper_id, false); + mcpwm_ll_fault_enable_cbc_refresh_on_tep(hal->dev, oper_id, false); + mcpwm_ll_brake_enable_soft_cbc(hal->dev, oper_id, false); + mcpwm_ll_brake_enable_soft_ost(hal->dev, oper_id, false); +} + +void mcpwm_hal_generator_reset(mcpwm_hal_context_t *hal, int oper_id, int gen_id) +{ + mcpwm_ll_generator_reset_actions(hal->dev, oper_id, gen_id); + mcpwm_ll_gen_disable_continue_force_action(hal->dev, oper_id, gen_id); + mcpwm_ll_gen_disable_noncontinue_force_action(hal->dev, oper_id, gen_id); } diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 33161ac474..530ea372d6 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -387,10 +387,6 @@ config SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP int default 3 -config SOC_MCPWM_BASE_CLK_HZ - int - default 160000000 - config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED bool default n diff --git a/components/soc/esp32/include/soc/clk_tree_defs.h b/components/soc/esp32/include/soc/clk_tree_defs.h index 7a218bc307..086b8549d7 100644 --- a/components/soc/esp32/include/soc/clk_tree_defs.h +++ b/components/soc/esp32/include/soc/clk_tree_defs.h @@ -210,6 +210,34 @@ typedef enum { UART_SCLK_DEFAULT = SOC_MOD_CLK_APB, /*!< UART source clock default choice is APB */ } soc_periph_uart_clk_src_legacy_t; +//////////////////////////////////////////////////MCPWM///////////////////////////////////////////////////////////////// + +/** + * @brief Array initializer for all supported clock sources of MCPWM Timer + */ +#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_D2} + +/** + * @brief Type of MCPWM timer clock source + */ +typedef enum { + MCPWM_TIMER_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_D2, /*!< Select PLL_D2 (160MHz) as the source clock */ + MCPWM_TIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_D2, /*!< Select PLL_D2 as the default clock choice */ +} soc_periph_mcpwm_timer_clk_src_t; + +/** + * @brief Array initializer for all supported clock sources of MCPWM Capture Timer + */ +#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_APB} + +/** + * @brief Type of MCPWM capture clock source + */ +typedef enum { + MCPWM_CAPTURE_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */ + MCPWM_CAPTURE_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< SElect APB as the default clock choice */ +} soc_periph_mcpwm_capture_clk_src_t; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32/include/soc/mcpwm_struct.h b/components/soc/esp32/include/soc/mcpwm_struct.h index 4e13290fe8..e2f4d32eba 100644 --- a/components/soc/esp32/include/soc/mcpwm_struct.h +++ b/components/soc/esp32/include/soc/mcpwm_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1435,7 +1435,7 @@ typedef struct { mcpwm_fh_status_reg_t fh_status; } mcpwm_operator_reg_t; -typedef struct { +typedef struct mcpwm_dev_t { volatile mcpwm_clk_cfg_reg_t clk_cfg; volatile mcpwm_timer_regs_t timer[3]; volatile mcpwm_timer_synci_cfg_reg_t timer_synci_cfg; diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 38cbe76484..05ced26846 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -223,7 +223,6 @@ #define SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP (1) ///< The number of capture timers that each group has #define SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER (3) ///< The number of capture channels that each capture timer has #define SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP (3) ///< The number of GPIO synchros that each group has -#define SOC_MCPWM_BASE_CLK_HZ (160000000ULL) ///< Base Clock frequency of 160MHz /*-------------------------- MPU CAPS ----------------------------------------*/ //TODO: correct the caller and remove unsupported lines diff --git a/components/soc/esp32/mcpwm_periph.c b/components/soc/esp32/mcpwm_periph.c index ae51d75c6a..61fcf07a1c 100644 --- a/components/soc/esp32/mcpwm_periph.c +++ b/components/soc/esp32/mcpwm_periph.c @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/soc.h" #include "soc/mcpwm_periph.h" diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 443c3da2f5..aa03171f07 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -451,10 +451,6 @@ config SOC_MCPWM_SWSYNC_CAN_PROPAGATE bool default y -config SOC_MCPWM_BASE_CLK_HZ - int - default 160000000 - config SOC_PCNT_GROUPS bool default y diff --git a/components/soc/esp32s3/include/soc/clk_tree_defs.h b/components/soc/esp32s3/include/soc/clk_tree_defs.h index b94deb5a81..8429c42971 100644 --- a/components/soc/esp32s3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s3/include/soc/clk_tree_defs.h @@ -217,6 +217,34 @@ typedef enum { UART_SCLK_DEFAULT = SOC_MOD_CLK_APB, /*!< UART source clock default choice is APB */ } soc_periph_uart_clk_src_legacy_t; +//////////////////////////////////////////////////MCPWM///////////////////////////////////////////////////////////////// + +/** + * @brief Array initializer for all supported clock sources of MCPWM Timer + */ +#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_D2} + +/** + * @brief Type of MCPWM timer clock source + */ +typedef enum { + MCPWM_TIMER_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + MCPWM_TIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ +} soc_periph_mcpwm_timer_clk_src_t; + +/** + * @brief Array initializer for all supported clock sources of MCPWM Capture Timer + */ +#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_APB} + +/** + * @brief Type of MCPWM capture clock source + */ +typedef enum { + MCPWM_CAPTURE_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */ + MCPWM_CAPTURE_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< SElect APB as the default clock choice */ +} soc_periph_mcpwm_capture_clk_src_t; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32s3/include/soc/mcpwm_struct.h b/components/soc/esp32s3/include/soc/mcpwm_struct.h index 4e13290fe8..e2f4d32eba 100644 --- a/components/soc/esp32s3/include/soc/mcpwm_struct.h +++ b/components/soc/esp32s3/include/soc/mcpwm_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1435,7 +1435,7 @@ typedef struct { mcpwm_fh_status_reg_t fh_status; } mcpwm_operator_reg_t; -typedef struct { +typedef struct mcpwm_dev_t { volatile mcpwm_clk_cfg_reg_t clk_cfg; volatile mcpwm_timer_regs_t timer[3]; volatile mcpwm_timer_synci_cfg_reg_t timer_synci_cfg; diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index bf0a452094..36f451662b 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -185,7 +185,6 @@ #define SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER (3) ///< The number of capture channels that each capture timer has #define SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP (3) ///< The number of GPIO synchros that each group has #define SOC_MCPWM_SWSYNC_CAN_PROPAGATE (1) ///< Software sync event can be routed to its output -#define SOC_MCPWM_BASE_CLK_HZ (160000000ULL) ///< Base Clock frequency of 160MHz /*-------------------------- MPU CAPS ----------------------------------------*/ #include "mpu_caps.h" diff --git a/components/soc/esp32s3/mcpwm_periph.c b/components/soc/esp32s3/mcpwm_periph.c index ae51d75c6a..61fcf07a1c 100644 --- a/components/soc/esp32s3/mcpwm_periph.c +++ b/components/soc/esp32s3/mcpwm_periph.c @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/soc.h" #include "soc/mcpwm_periph.h" diff --git a/components/soc/include/soc/mcpwm_periph.h b/components/soc/include/soc/mcpwm_periph.h index d807600c4a..a07bb49cb2 100644 --- a/components/soc/include/soc/mcpwm_periph.h +++ b/components/soc/include/soc/mcpwm_periph.h @@ -1,16 +1,8 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 01d5f74b45..2b505b6d23 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -867,8 +867,6 @@ components/hal/include/hal/ds_hal.h components/hal/include/hal/esp_flash_err.h components/hal/include/hal/interrupt_controller_hal.h components/hal/include/hal/interrupt_controller_types.h -components/hal/include/hal/mcpwm_hal.h -components/hal/include/hal/mcpwm_types.h components/hal/include/hal/mpu_hal.h components/hal/include/hal/mpu_types.h components/hal/include/hal/rtc_io_types.h @@ -889,7 +887,6 @@ components/hal/include/hal/wdt_hal.h components/hal/include/hal/wdt_types.h components/hal/interrupt_controller_hal.c components/hal/ledc_hal_iram.c -components/hal/mcpwm_hal.c components/hal/mpu_hal.c components/hal/platform_port/include/hal/assert.h components/hal/platform_port/include/hal/check.h @@ -1224,7 +1221,6 @@ components/soc/esp32/include/soc/uhci_struct.h components/soc/esp32/include/soc/wdev_reg.h components/soc/esp32/interrupts.c components/soc/esp32/ledc_periph.c -components/soc/esp32/mcpwm_periph.c components/soc/esp32/sdio_slave_periph.c components/soc/esp32/sdmmc_periph.c components/soc/esp32/sigmadelta_periph.c @@ -1502,7 +1498,6 @@ components/soc/esp32s3/include/soc/world_controller_reg.h components/soc/esp32s3/include/soc/world_controller_struct.h components/soc/esp32s3/interrupts.c components/soc/esp32s3/ledc_periph.c -components/soc/esp32s3/mcpwm_periph.c components/soc/esp32s3/rtc_io_periph.c components/soc/esp32s3/sdio_slave_periph.c components/soc/esp32s3/sdmmc_periph.c @@ -1519,7 +1514,6 @@ components/soc/include/soc/gpio_periph.h components/soc/include/soc/i2c_periph.h components/soc/include/soc/interrupts.h components/soc/include/soc/ledc_periph.h -components/soc/include/soc/mcpwm_periph.h components/soc/include/soc/rtc_cntl_periph.h components/soc/include/soc/rtc_periph.h components/soc/include/soc/sdio_slave_periph.h From a12936dca915ca48fb7cd1a0a0f41b2c844d54d4 Mon Sep 17 00:00:00 2001 From: morris Date: Sat, 28 May 2022 17:27:02 +0800 Subject: [PATCH 2/3] mcpwm: rename MCPWM_ISR_IN_IRAM to MCPWM_ISR_IRAM_SAFE --- components/driver/Kconfig | 37 +++++++------- components/driver/mcpwm.c | 79 +++++++++++++++++------------- components/driver/sdkconfig.rename | 1 + components/driver/test/test_pwm.c | 4 +- 4 files changed, 66 insertions(+), 55 deletions(-) diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 3a33772188..93c0c97c1d 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -1,6 +1,6 @@ -menu "Driver configurations" +menu "Driver Configurations" - menu "ADC configuration" + menu "ADC Configuration" config ADC_FORCE_XPD_FSM bool "Use the FSM to control ADC power" @@ -21,20 +21,7 @@ menu "Driver configurations" endmenu # ADC Configuration - menu "MCPWM configuration" - depends on SOC_MCPWM_SUPPORTED - config MCPWM_ISR_IN_IRAM - bool "Place MCPWM ISR function into IRAM" - default n - help - If this option is not selected, the MCPWM interrupt will be deferred when the Cache - is in a disabled state (e.g. Flash write/erase operation). - - Note that if this option is selected, all user registered ISR callbacks should never - try to use cache as well. (with IRAM_ATTR) - endmenu # MCPWM Configuration - - menu "SPI configuration" + menu "SPI Configuration" config SPI_MASTER_IN_IRAM bool "Place transmitting functions of SPI master into IRAM" @@ -84,7 +71,7 @@ menu "Driver configurations" endmenu # SPI Configuration - menu "TWAI configuration" + menu "TWAI Configuration" depends on SOC_TWAI_SUPPORTED config TWAI_ISR_IN_IRAM @@ -166,7 +153,7 @@ menu "Driver configurations" endmenu # TEMP_SENSOR Configuration - menu "UART configuration" + menu "UART Configuration" config UART_ISR_IN_IRAM bool "Place UART ISR function into IRAM" @@ -306,4 +293,16 @@ menu "Driver configurations" Note that, this option only controls the RMT driver log, won't affect other drivers. endmenu # RMT Configuration -endmenu # Driver configurations + menu "MCPWM Configuration" + depends on SOC_MCPWM_SUPPORTED + config MCPWM_ISR_IRAM_SAFE + bool "Place MCPWM ISR function into IRAM" + default n + help + This will ensure the MCPWM interrupt handle is IRAM-Safe, allow to avoid flash + cache misses, and also be able to run whilst the cache is disabled. + (e.g. SPI Flash write) + + endmenu # MCPWM Configuration + +endmenu # Driver Configurations diff --git a/components/driver/mcpwm.c b/components/driver/mcpwm.c index 4142db246d..292bb3524d 100644 --- a/components/driver/mcpwm.c +++ b/components/driver/mcpwm.c @@ -19,6 +19,7 @@ #include "hal/mcpwm_hal.h" #include "hal/gpio_hal.h" #include "hal/mcpwm_ll.h" +#include "driver/gpio.h" #include "driver/mcpwm.h" #include "esp_private/periph_ctrl.h" @@ -36,16 +37,17 @@ static const char *TAG = "mcpwm"; #define MCPWM_DT_ERROR "MCPWM DEADTIME TYPE ERROR" #define MCPWM_CAP_EXIST_ERROR "MCPWM USER CAP INT SERVICE ALREADY EXISTS" -#ifdef CONFIG_MCPWM_ISR_IN_IRAM +#ifdef CONFIG_MCPWM_ISR_IRAM_SAFE #define MCPWM_ISR_ATTR IRAM_ATTR -#define MCPWM_INTR_FLAG (ESP_INTR_FLAG_IRAM) +#define MCPWM_INTR_FLAG ESP_INTR_FLAG_IRAM #else #define MCPWM_ISR_ATTR #define MCPWM_INTR_FLAG 0 #endif +#define MCPWM_GROUP_CLK_SRC_HZ 160000000 #define MCPWM_GROUP_CLK_PRESCALE (16) -#define MCPWM_GROUP_CLK_HZ (SOC_MCPWM_BASE_CLK_HZ / MCPWM_GROUP_CLK_PRESCALE) +#define MCPWM_GROUP_CLK_HZ (MCPWM_GROUP_CLK_SRC_HZ / MCPWM_GROUP_CLK_PRESCALE) #define MCPWM_TIMER_CLK_HZ (MCPWM_GROUP_CLK_HZ / 10) _Static_assert(SOC_MCPWM_OPERATORS_PER_GROUP >= SOC_MCPWM_TIMERS_PER_GROUP, "This driver assumes the timer num equals to the operator num."); @@ -87,26 +89,30 @@ typedef struct { } mcpwm_context_t; static mcpwm_context_t context[SOC_MCPWM_GROUPS] = { - [0] = { - .hal = {MCPWM_LL_GET_HW(0)}, - .spinlock = portMUX_INITIALIZER_UNLOCKED, - .group_id = 0, - .group_pre_scale = SOC_MCPWM_BASE_CLK_HZ / MCPWM_GROUP_CLK_HZ, - .timer_pre_scale = {[0 ... SOC_MCPWM_TIMERS_PER_GROUP - 1] = - MCPWM_GROUP_CLK_HZ / MCPWM_TIMER_CLK_HZ}, - .mcpwm_intr_handle = NULL, - .cap_isr_func = {[0 ... SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER - 1] = {NULL, NULL}}, + [0] = { + .hal = {MCPWM_LL_GET_HW(0)}, + .spinlock = portMUX_INITIALIZER_UNLOCKED, + .group_id = 0, + .group_pre_scale = MCPWM_GROUP_CLK_SRC_HZ / MCPWM_GROUP_CLK_HZ, + .timer_pre_scale = { + [0 ... SOC_MCPWM_TIMERS_PER_GROUP - 1] = + MCPWM_GROUP_CLK_HZ / MCPWM_TIMER_CLK_HZ }, - [1] = { - .hal = {MCPWM_LL_GET_HW(1)}, - .spinlock = portMUX_INITIALIZER_UNLOCKED, - .group_id = 1, - .group_pre_scale = SOC_MCPWM_BASE_CLK_HZ / MCPWM_GROUP_CLK_HZ, - .timer_pre_scale = {[0 ... SOC_MCPWM_TIMERS_PER_GROUP - 1] = - MCPWM_GROUP_CLK_HZ / MCPWM_TIMER_CLK_HZ}, - .mcpwm_intr_handle = NULL, - .cap_isr_func = {[0 ... SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER - 1] = {NULL, NULL}}, - } + .mcpwm_intr_handle = NULL, + .cap_isr_func = {[0 ... SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER - 1] = {NULL, NULL}}, + }, + [1] = { + .hal = {MCPWM_LL_GET_HW(1)}, + .spinlock = portMUX_INITIALIZER_UNLOCKED, + .group_id = 1, + .group_pre_scale = MCPWM_GROUP_CLK_SRC_HZ / MCPWM_GROUP_CLK_HZ, + .timer_pre_scale = { + [0 ... SOC_MCPWM_TIMERS_PER_GROUP - 1] = + MCPWM_GROUP_CLK_HZ / MCPWM_TIMER_CLK_HZ + }, + .mcpwm_intr_handle = NULL, + .cap_isr_func = {[0 ... SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER - 1] = {NULL, NULL}}, + } }; typedef void (*mcpwm_ll_gen_set_event_action_t)(mcpwm_dev_t *mcpwm, int op, int gen, int action); @@ -121,11 +127,13 @@ static inline void mcpwm_critical_exit(mcpwm_unit_t mcpwm_num) portEXIT_CRITICAL(&context[mcpwm_num].spinlock); } -static inline void mcpwm_mutex_lock(mcpwm_unit_t mcpwm_num){ +static inline void mcpwm_mutex_lock(mcpwm_unit_t mcpwm_num) +{ _lock_acquire(&context[mcpwm_num].mutex_lock); } -static inline void mcpwm_mutex_unlock(mcpwm_unit_t mcpwm_num){ +static inline void mcpwm_mutex_unlock(mcpwm_unit_t mcpwm_num) +{ _lock_release(&context[mcpwm_num].mutex_lock); } @@ -202,9 +210,10 @@ esp_err_t mcpwm_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) return ESP_OK; } -esp_err_t mcpwm_group_set_resolution(mcpwm_unit_t mcpwm_num, unsigned long int resolution) { +esp_err_t mcpwm_group_set_resolution(mcpwm_unit_t mcpwm_num, unsigned long int resolution) +{ mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; - int pre_scale_temp = SOC_MCPWM_BASE_CLK_HZ / resolution; + int pre_scale_temp = MCPWM_GROUP_CLK_SRC_HZ / resolution; ESP_RETURN_ON_FALSE(pre_scale_temp >= 1, ESP_ERR_INVALID_ARG, TAG, "invalid resolution"); context[mcpwm_num].group_pre_scale = pre_scale_temp; mcpwm_critical_enter(mcpwm_num); @@ -213,11 +222,12 @@ esp_err_t mcpwm_group_set_resolution(mcpwm_unit_t mcpwm_num, unsigned long int r return ESP_OK; } -esp_err_t mcpwm_timer_set_resolution(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, unsigned long int resolution) { +esp_err_t mcpwm_timer_set_resolution(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, unsigned long int resolution) +{ MCPWM_TIMER_CHECK(mcpwm_num, timer_num); mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; - int pre_scale_temp = SOC_MCPWM_BASE_CLK_HZ / context[mcpwm_num].group_pre_scale / resolution; + int pre_scale_temp = MCPWM_GROUP_CLK_SRC_HZ / context[mcpwm_num].group_pre_scale / resolution; ESP_RETURN_ON_FALSE(pre_scale_temp >= 1, ESP_ERR_INVALID_ARG, TAG, "invalid resolution"); context[mcpwm_num].timer_pre_scale[timer_num] = pre_scale_temp; mcpwm_critical_enter(mcpwm_num); @@ -239,7 +249,7 @@ esp_err_t mcpwm_set_frequency(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, u uint32_t previous_peak = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false); int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev); unsigned long int real_timer_clk_hz = - SOC_MCPWM_BASE_CLK_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); + MCPWM_GROUP_CLK_SRC_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); uint32_t new_peak = real_timer_clk_hz / frequency; mcpwm_ll_timer_set_peak(hal->dev, timer_num, new_peak, false); // keep the duty cycle unchanged @@ -286,7 +296,7 @@ esp_err_t mcpwm_set_duty_in_us(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_critical_enter(mcpwm_num); int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev); unsigned long int real_timer_clk_hz = - SOC_MCPWM_BASE_CLK_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); + MCPWM_GROUP_CLK_SRC_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); mcpwm_ll_operator_set_compare_value(hal->dev, op, cmp, duty_in_us * real_timer_clk_hz / 1000000); mcpwm_ll_operator_enable_update_compare_on_tez(hal->dev, op, cmp, true); mcpwm_critical_exit(mcpwm_num); @@ -393,7 +403,7 @@ esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpw mcpwm_ll_timer_update_period_at_once(hal->dev, timer_num); int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev); unsigned long int real_timer_clk_hz = - SOC_MCPWM_BASE_CLK_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); + MCPWM_GROUP_CLK_SRC_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); mcpwm_ll_timer_set_peak(hal->dev, timer_num, real_timer_clk_hz / mcpwm_conf->frequency, false); mcpwm_ll_operator_connect_timer(hal->dev, timer_num, timer_num); //the driver currently always use the timer x for operator x mcpwm_critical_exit(mcpwm_num); @@ -414,7 +424,7 @@ uint32_t mcpwm_get_frequency(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) mcpwm_critical_enter(mcpwm_num); int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev); unsigned long int real_timer_clk_hz = - SOC_MCPWM_BASE_CLK_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); + MCPWM_GROUP_CLK_SRC_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); uint32_t peak = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false); uint32_t freq = real_timer_clk_hz / peak; mcpwm_critical_exit(mcpwm_num); @@ -433,7 +443,8 @@ float mcpwm_get_duty(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_gene return duty; } -uint32_t mcpwm_get_duty_in_us(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_operator_t gen){ +uint32_t mcpwm_get_duty_in_us(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_operator_t gen) +{ //the driver currently always use the timer x for operator x const int op = timer_num; MCPWM_GEN_CHECK(mcpwm_num, timer_num, gen); @@ -441,7 +452,7 @@ uint32_t mcpwm_get_duty_in_us(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, m mcpwm_critical_enter(mcpwm_num); int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev); unsigned long int real_timer_clk_hz = - SOC_MCPWM_BASE_CLK_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); + MCPWM_GROUP_CLK_SRC_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num); uint32_t duty = mcpwm_ll_operator_get_compare_value(hal->dev, op, gen) * (1000000.0 / real_timer_clk_hz); mcpwm_critical_exit(mcpwm_num); return duty; diff --git a/components/driver/sdkconfig.rename b/components/driver/sdkconfig.rename index 311467d012..ab2b09bf76 100644 --- a/components/driver/sdkconfig.rename +++ b/components/driver/sdkconfig.rename @@ -2,3 +2,4 @@ # CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC +CONFIG_MCPWM_ISR_IN_IRAM CONFIG_MCPWM_ISR_IRAM_SAFE diff --git a/components/driver/test/test_pwm.c b/components/driver/test/test_pwm.c index 3fffbe738d..0a3240b01c 100644 --- a/components/driver/test/test_pwm.c +++ b/components/driver/test/test_pwm.c @@ -6,7 +6,6 @@ #include #include #include "unity.h" -#include "test_utils.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "soc/soc_caps.h" @@ -27,7 +26,8 @@ #define TEST_SYNC_GPIO_2 (19) #define TEST_CAP_GPIO (21) -#define MCPWM_TEST_GROUP_CLK_HZ (SOC_MCPWM_BASE_CLK_HZ / 16) +#define MCPWM_GROUP_CLK_SRC_HZ 160000000 +#define MCPWM_TEST_GROUP_CLK_HZ (MCPWM_GROUP_CLK_SRC_HZ / 16) #define MCPWM_TEST_TIMER_CLK_HZ (MCPWM_TEST_GROUP_CLK_HZ / 10) const static mcpwm_io_signals_t pwma[] = {MCPWM0A, MCPWM1A, MCPWM2A}; From 3247335770ea6d1003a208c0d1dd8c221f3602e2 Mon Sep 17 00:00:00 2001 From: morris Date: Sat, 28 May 2022 17:02:07 +0800 Subject: [PATCH 3/3] mcpwm: don't support disable carrier first pulse The first pulse of MCPWM carrier can not be disabled, this commit will remove the feature. Closes https://github.com/espressif/esp-idf/issues/8984 --- components/driver/include/driver/mcpwm.h | 72 +++++++------------ components/driver/mcpwm.c | 11 +-- docs/en/migration-guides/peripherals.rst | 17 ++--- .../mcpwm_bldc_hall_control_example_main.c | 14 ++-- .../main/mcpwm_capture_hc_sr04.c | 15 +--- .../main/mcpwm_sync_example.c | 22 ++---- tools/ci/check_copyright_ignore.txt | 3 - 7 files changed, 46 insertions(+), 108 deletions(-) diff --git a/components/driver/include/driver/mcpwm.h b/components/driver/include/driver/mcpwm.h index 7f900f78d4..0779076996 100644 --- a/components/driver/include/driver/mcpwm.h +++ b/components/driver/include/driver/mcpwm.h @@ -6,11 +6,12 @@ #pragma once -#include "soc/soc_caps.h" -#if SOC_MCPWM_SUPPORTED +#include +#include #include "esp_err.h" -#include "driver/gpio.h" +#include "esp_bit_defs.h" #include "esp_intr_alloc.h" +#include "soc/soc_caps.h" #include "hal/mcpwm_types.h" #ifdef __cplusplus @@ -100,14 +101,6 @@ typedef enum { #define MCPWM_OPR_MAX MCPWM_GEN_MAX ///< @deprecated typedef mcpwm_generator_t mcpwm_operator_t; ///< @deprecated -/** - * @brief MCPWM carrier oneshot mode, in this mode the width of the first pulse of carrier can be programmed - */ -typedef enum { - MCPWM_ONESHOT_MODE_DIS, /*!carrier_period); mcpwm_carrier_set_duty_cycle(mcpwm_num, timer_num, carrier_conf->carrier_duty); - if (carrier_conf->carrier_os_mode == MCPWM_ONESHOT_MODE_EN) { - mcpwm_carrier_oneshot_mode_enable(mcpwm_num, timer_num, carrier_conf->pulse_width_in_os); - } else { - mcpwm_carrier_oneshot_mode_disable(mcpwm_num, timer_num); - } + mcpwm_carrier_oneshot_mode_enable(mcpwm_num, timer_num, carrier_conf->pulse_width_in_os); mcpwm_carrier_output_invert(mcpwm_num, timer_num, carrier_conf->carrier_ivt_mode); mcpwm_critical_enter(mcpwm_num); diff --git a/docs/en/migration-guides/peripherals.rst b/docs/en/migration-guides/peripherals.rst index 19230105db..4b3c9a88ea 100644 --- a/docs/en/migration-guides/peripherals.rst +++ b/docs/en/migration-guides/peripherals.rst @@ -243,15 +243,8 @@ LCD MCPWM ----- - +---------------------------+---------------------------------------------------+-----------------------------------------------------------+ - | Removed/Deprecated items | Replacement | Remarks | - +===========================+===================================================+===========================================================+ - | ``mcpwm_capture_enable`` | :cpp:func:`mcpwm_capture_enable_channel` | Enable capture channel. | - +---------------------------+---------------------------------------------------+-----------------------------------------------------------+ - | ``mcpwm_capture_disable`` | :cpp:func:`mcpwm_capture_capture_disable_channel` | Disable capture channel. | - +---------------------------+---------------------------------------------------+-----------------------------------------------------------+ - | ``mcpwm_sync_enable`` | :cpp:func:`mcpwm_sync_configure` | Configure synchronization. | - +---------------------------+---------------------------------------------------+-----------------------------------------------------------+ - | ``mcpwm_isr_register`` | By registering event callbacks, e.g. | MCPWM interrupt handling is implemented by driver itself. | - | | :cpp:member:`mcpwm_capture_config_t::capture_cb` | | - +---------------------------+---------------------------------------------------+-----------------------------------------------------------+ + - ``mcpwm_capture_enable`` is removed. To enable capture channel, please use :cpp:func:`mcpwm_capture_enable_channel`. + - ``mcpwm_capture_disable`` is remove. To disable capture channel, please use :cpp:func:`mcpwm_capture_capture_disable_channel`. + - ``mcpwm_sync_enable`` is removed. To configure synchronization, please use :cpp:func:`mcpwm_sync_configure`. + - ``mcpwm_isr_register`` is removed. You can register event callbacks, for capture channels. e.g. :cpp:member:`mcpwm_capture_config_t::capture_cb`. + - ``mcpwm_carrier_oneshot_mode_disable`` is removed. Disable the first pulse (a.k.a the one-shot pulse) in the carrier is not supported by hardware. diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c index 6acbbdbd17..6de0aee093 100644 --- a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c +++ b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c @@ -1,17 +1,15 @@ -/* MCPWM BLDC control with Hall sensor - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/mcpwm.h" +#include "driver/gpio.h" #include "esp_timer.h" #include "esp_attr.h" #include "esp_log.h" diff --git a/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c b/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c index d79f422d1c..e7fefeb6d2 100644 --- a/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c +++ b/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c @@ -1,25 +1,16 @@ -/* MCPWM capture example: HC-SR04 - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - /* - * This example will show you how to use capture function to read HC-SR04 sonar sensor. + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * - * HC_SR04_SAMPLE_PERIOD_MS should be at least 50ms + * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "esp_log.h" -#include "esp_check.h" #include "esp_private/esp_clk.h" #include "driver/mcpwm.h" +#include "driver/gpio.h" const static char *TAG = "hc-sr04"; diff --git a/examples/peripherals/mcpwm/mcpwm_sync_example/main/mcpwm_sync_example.c b/examples/peripherals/mcpwm/mcpwm_sync_example/main/mcpwm_sync_example.c index b1f17de8a2..bc7b6c30a1 100644 --- a/examples/peripherals/mcpwm/mcpwm_sync_example/main/mcpwm_sync_example.c +++ b/examples/peripherals/mcpwm/mcpwm_sync_example/main/mcpwm_sync_example.c @@ -1,28 +1,16 @@ -/* MCPWM sync example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - /* - * This example will show you how to use capture function to read HC-SR04 sonar sensor. + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/queue.h" -#include "esp_rom_gpio.h" -#include "soc/mcpwm_periph.h" -#include "hal/gpio_hal.h" #include "esp_log.h" -#include "esp_check.h" -#include "soc/rtc.h" #include "driver/mcpwm.h" +#include "driver/gpio.h" -const static char *TAG = "sync_example"; +const static char *TAG = "example"; #define TARGET_MCPWM_UNIT MCPWM_UNIT_0 #define TIMER0_OUTPUT_GPIO GPIO_NUM_16 diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 2b505b6d23..ee840f9ed4 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1994,13 +1994,10 @@ examples/peripherals/i2s/i2s_audio_recorder_sdcard/main/i2s_recorder_main.c examples/peripherals/i2s/i2s_basic/main/i2s_example_main.c examples/peripherals/ledc/ledc_basic/main/ledc_basic_example_main.c examples/peripherals/ledc/ledc_fade/main/ledc_fade_example_main.c -examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/cmd_mcpwm_motor.c examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_control_example.c examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_control_example.h -examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c -examples/peripherals/mcpwm/mcpwm_sync_example/main/mcpwm_sync_example.c examples/peripherals/sdio/host/main/app_main.c examples/peripherals/sdio/sdio_test.py examples/peripherals/sdio/slave/main/app_main.c