mcpwm: support esp32h2

This commit is contained in:
morris 2023-01-06 14:17:04 +08:00
parent b37980d26e
commit 15b9352f60
31 changed files with 1877 additions and 153 deletions

View File

@ -51,10 +51,10 @@ esp_err_t mcpwm_set_pin(mcpwm_unit_t mcpwm_num, const mcpwm_pin_config_t *mcpwm_
/**
* @brief Initialize MCPWM parameters
* @note
* The default resolution configured for MCPWM group and timer are 160M / 16 = 10M and 10M / 10 = 1M
* The default resolution can be changed by calling mcpwm_group_set_resolution() and mcpwm_timer_set_resolution(),
* before calling this function.
* @note The default resolution configured for MCPWM timer is 1M, it can be changed by `mcpwm_timer_set_resolution`.
* @note The default resolution configured for MCPWM group can be different on different esp targets (because of different clock source).
* You can change the group resolution by mcpwm_group_set_resolution()
* @note If you want to change the preset resolution of MCPWM group and timer, please call them before this function.
*
* @param mcpwm_num set MCPWM unit
* @param timer_num set timer number(0-2) of MCPWM, each MCPWM unit has 3 timers.
@ -68,11 +68,9 @@ esp_err_t mcpwm_init( mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcp
/**
* @brief Set resolution of the MCPWM group
* @note
* This will override default resolution of group(=10,000,000).
* This WILL NOT automatically update frequency and duty. Call mcpwm_set_frequency() and mcpwm_set_duty() manually
* to set them back.
* The group resolution must be an integral multiple of timer resolution.
* @note This will override default resolution of MCPWM group.
* @note This WILL NOT automatically update PWM frequency and duty. Please call `mcpwm_set_frequency` and `mcpwm_set_duty` manually to reflect the change.
* @note The group resolution must be an integral multiple of timer resolution.
*
* @param mcpwm_num set MCPWM unit
* @param resolution set expected frequency resolution
@ -85,11 +83,9 @@ esp_err_t mcpwm_group_set_resolution(mcpwm_unit_t mcpwm_num, unsigned long int r
/**
* @brief Set resolution of each timer
* @note
* This WILL override default resolution of timer(=1,000,000).
* This WILL NOT automatically update frequency and duty. Call mcpwm_set_frequency() and mcpwm_set_duty() manually
* to set them back.
* The group resolution must be an integral multiple of timer resolution.
* @note This will override default resolution of timer(=1,000,000).
* @note This WILL NOT automatically update PWM frequency and duty. Please call `mcpwm_set_frequency` and `mcpwm_set_duty` manually to reflect the change.
* @note The group resolution must be an integral multiple of timer resolution.
*
* @param mcpwm_num set MCPWM unit
* @param timer_num set timer number(0-2) of MCPWM, each MCPWM unit has 3 timers

View File

@ -1,20 +1,17 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_check.h"
#include "esp_rom_gpio.h"
#include "esp_intr_alloc.h"
#include "soc/gpio_periph.h"
#include "soc/mcpwm_periph.h"
#include "hal/mcpwm_hal.h"
#include "hal/gpio_hal.h"
@ -22,6 +19,7 @@
#include "driver/mcpwm_types_legacy.h"
#include "driver/gpio.h"
#include "esp_private/periph_ctrl.h"
#include "clk_tree.h"
#include "esp_private/esp_clk.h"
static const char *TAG = "mcpwm(legacy)";
@ -48,14 +46,20 @@ _Static_assert(MCPWM_UNIT_MAX == SOC_MCPWM_GROUPS, "MCPWM unit number not equal
#define MCPWM_INTR_FLAG 0
#endif
#define MCPWM_GROUP_CLK_SRC_HZ 160000000 // MCPWM clock source is fixed to `MCPWM_CAPTURE_CLK_SRC_PLL160M`
#define MCPWM_GROUP_CLK_PRESCALE (16)
#define MCPWM_GROUP_CLK_HZ (MCPWM_GROUP_CLK_SRC_HZ / MCPWM_GROUP_CLK_PRESCALE)
#define MCPWM_TIMER_CLK_HZ (MCPWM_GROUP_CLK_HZ / 10)
// Note: we can't modify the default MCPWM group resolution once it's determined
// otherwise we may break user's existing code which configures the dead-time based on this resolution, see `mcpwm_deadtime_enable`
#if CONFIG_IDF_TARGET_ESP32H2
#define MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ (12 * 1000 * 1000)
#else
#define MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ (10 * 1000 * 1000)
#endif
_Static_assert(SOC_MCPWM_OPERATORS_PER_GROUP >= SOC_MCPWM_TIMERS_PER_GROUP, "This driver assumes the timer num equals to the operator num.");
_Static_assert(SOC_MCPWM_COMPARATORS_PER_OPERATOR >= SOC_MCPWM_GENERATORS_PER_OPERATOR, "This driver assumes the generator num equals to the generator num.");
_Static_assert(SOC_MCPWM_GENERATORS_PER_OPERATOR == 2, "This driver assumes the generator num equals to 2.");
// Preset MCPWM Timer clock resolution (1MHz)
#define MCPWM_DEFAULT_TIMER_CLK_RESOLUTION_HZ (1 * 1000 * 1000)
ESP_STATIC_ASSERT(SOC_MCPWM_OPERATORS_PER_GROUP >= SOC_MCPWM_TIMERS_PER_GROUP, "This driver assumes the timer num equals to the operator num.");
ESP_STATIC_ASSERT(SOC_MCPWM_COMPARATORS_PER_OPERATOR >= SOC_MCPWM_GENERATORS_PER_OPERATOR, "This driver assumes the generator num equals to the generator num.");
ESP_STATIC_ASSERT(SOC_MCPWM_GENERATORS_PER_OPERATOR == 2, "This driver assumes the generator num equals to 2.");
#define MCPWM_TIMER_ID_CHECK(mcpwm_num, timer_num) \
do { \
@ -85,8 +89,8 @@ typedef struct {
portMUX_TYPE spinlock;
_lock_t mutex_lock;
const int group_id;
int group_pre_scale; // starts from 1, not 0. will be subtracted by 1 in ll driver
int timer_pre_scale[SOC_MCPWM_TIMERS_PER_GROUP]; // same as above
int group_resolution_hz;
int timer_resolution_hz[SOC_MCPWM_TIMERS_PER_GROUP];
intr_handle_t mcpwm_intr_handle; // handler for ISR register, one per MCPWM group
cap_isr_func_t cap_isr_func[SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER]; // handler for ISR callback, one for each cap ch
} mcpwm_context_t;
@ -96,27 +100,13 @@ static mcpwm_context_t context[SOC_MCPWM_GROUPS] = {
.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
},
.mcpwm_intr_handle = NULL,
.cap_isr_func = {[0 ... SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER - 1] = {NULL, NULL}},
},
#if SOC_MCPWM_GROUPS > 1
[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}},
}
},
#endif
};
@ -215,28 +205,51 @@ 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)
static inline uint32_t mcpwm_group_get_resolution(mcpwm_unit_t mcpwm_num)
{
if (context[mcpwm_num].group_resolution_hz == 0) {
context[mcpwm_num].group_resolution_hz = MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ;
}
return context[mcpwm_num].group_resolution_hz;
}
static inline uint32_t mcpwm_timer_get_resolution(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
{
if (context[mcpwm_num].timer_resolution_hz[timer_num] == 0) {
context[mcpwm_num].timer_resolution_hz[timer_num] = MCPWM_DEFAULT_TIMER_CLK_RESOLUTION_HZ;
}
return context[mcpwm_num].timer_resolution_hz[timer_num];
}
esp_err_t mcpwm_group_set_resolution(mcpwm_unit_t mcpwm_num, uint32_t resolution)
{
mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
int pre_scale_temp = MCPWM_GROUP_CLK_SRC_HZ / resolution;
uint32_t clk_src_hz = 0;
clk_tree_src_get_freq_hz(MCPWM_TIMER_CLK_SRC_DEFAULT, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_hz);
int pre_scale_temp = 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;
context[mcpwm_num].group_resolution_hz = clk_src_hz / pre_scale_temp;
mcpwm_critical_enter(mcpwm_num);
mcpwm_ll_group_set_clock_prescale(hal->dev, context[mcpwm_num].group_pre_scale);
mcpwm_ll_group_set_clock_prescale(hal->dev, pre_scale_temp);
mcpwm_critical_exit(mcpwm_num);
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, uint32_t resolution)
{
MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
int pre_scale_temp = MCPWM_GROUP_CLK_SRC_HZ / context[mcpwm_num].group_pre_scale / resolution;
uint32_t group_resolution = mcpwm_group_get_resolution(mcpwm_num);
int pre_scale_temp = group_resolution / 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;
context[mcpwm_num].timer_resolution_hz[timer_num] = context[mcpwm_num].group_resolution_hz / pre_scale_temp;
mcpwm_critical_enter(mcpwm_num);
mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_num, context[mcpwm_num].timer_pre_scale[timer_num]);
mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_num, pre_scale_temp);
mcpwm_critical_exit(mcpwm_num);
return ESP_OK;
}
@ -252,10 +265,8 @@ esp_err_t mcpwm_set_frequency(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, u
mcpwm_ll_timer_update_period_at_once(hal->dev, timer_num);
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 =
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;
uint32_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
uint32_t new_peak = timer_resolution / frequency;
mcpwm_ll_timer_set_peak(hal->dev, timer_num, new_peak, false);
// keep the duty cycle unchanged
float scale = ((float)new_peak) / previous_peak;
@ -300,11 +311,9 @@ esp_err_t mcpwm_set_duty_in_us(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num,
mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
mcpwm_critical_enter(mcpwm_num);
int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev);
// to avid multiplication overflow, use uint64_t here
uint64_t real_timer_clk_hz =
MCPWM_GROUP_CLK_SRC_HZ / real_group_prescale / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num);
uint64_t compare_val = real_timer_clk_hz * duty_in_us / 1000000;
uint64_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
uint64_t compare_val = timer_resolution * duty_in_us / 1000000;
mcpwm_ll_operator_set_compare_value(hal->dev, op, cmp, (uint32_t)compare_val);
mcpwm_ll_operator_enable_update_compare_on_tez(hal->dev, op, cmp, true);
mcpwm_ll_operator_enable_update_compare_on_tep(hal->dev, op, cmp, true);
@ -405,17 +414,21 @@ esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpw
};
mcpwm_hal_init(hal, &config);
uint32_t clk_src_hz = 0;
clk_tree_src_get_freq_hz(MCPWM_TIMER_CLK_SRC_DEFAULT, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_hz);
uint32_t group_resolution = mcpwm_group_get_resolution(mcpwm_num);
uint32_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
uint32_t group_pre_scale = clk_src_hz / group_resolution;
uint32_t timer_pre_scale = group_resolution / timer_resolution;
mcpwm_critical_enter(mcpwm_num);
mcpwm_ll_group_enable_clock(hal->dev, true);
mcpwm_ll_group_set_clock_source(hal->dev, (soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT);
mcpwm_ll_group_set_clock_prescale(hal->dev, context[mcpwm_num].group_pre_scale);
mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_num, context[mcpwm_num].timer_pre_scale[timer_num]);
mcpwm_ll_group_set_clock_prescale(hal->dev, group_pre_scale);
mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_num, timer_pre_scale);
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);
int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev);
unsigned long int real_timer_clk_hz =
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_timer_set_peak(hal->dev, timer_num, timer_resolution / 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);
@ -434,13 +447,13 @@ uint32_t mcpwm_get_frequency(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
ESP_LOGE(TAG, "Invalid MCPWM timer instance");
return 0;
}
uint32_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
mcpwm_critical_enter(mcpwm_num);
int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev);
unsigned long int real_timer_clk_hz =
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;
uint32_t freq = timer_resolution / peak;
mcpwm_critical_exit(mcpwm_num);
return freq;
}
@ -466,14 +479,14 @@ uint32_t mcpwm_get_duty_in_us(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, m
ESP_LOGE(TAG, "Invalid MCPWM generator instance");
return 0;
}
uint32_t timer_resolution = mcpwm_timer_get_resolution(mcpwm_num, timer_num);
//the driver currently always use the timer x for operator x
const int op = timer_num;
mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
mcpwm_critical_enter(mcpwm_num);
int real_group_prescale = mcpwm_ll_group_get_clock_prescale(hal->dev);
unsigned long int real_timer_clk_hz =
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);
uint32_t duty = mcpwm_ll_operator_get_compare_value(hal->dev, op, gen) * (1000000.0 / timer_resolution);
mcpwm_critical_exit(mcpwm_num);
return duty;
}
@ -797,10 +810,16 @@ esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_cha
.group_id = mcpwm_num
};
mcpwm_hal_init(hal, &init_config);
uint32_t clk_src_hz = 0;
clk_tree_src_get_freq_hz(MCPWM_TIMER_CLK_SRC_DEFAULT, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_hz);
uint32_t group_resolution = mcpwm_group_get_resolution(mcpwm_num);
uint32_t group_pre_scale = clk_src_hz / group_resolution;
mcpwm_critical_enter(mcpwm_num);
mcpwm_ll_group_enable_clock(hal->dev, true);
mcpwm_ll_group_set_clock_source(hal->dev, (soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT);
mcpwm_ll_group_set_clock_prescale(hal->dev, context[mcpwm_num].group_pre_scale);
mcpwm_ll_group_set_clock_prescale(hal->dev, group_pre_scale);
mcpwm_ll_capture_enable_timer(hal->dev, true);
mcpwm_ll_capture_enable_channel(hal->dev, cap_channel, true);
mcpwm_ll_capture_enable_negedge(hal->dev, cap_channel, cap_conf->cap_edge & MCPWM_NEG_EDGE);
@ -879,7 +898,7 @@ uint32_t mcpwm_capture_get_resolution(mcpwm_unit_t mcpwm_num)
return 0;
}
#if SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
return MCPWM_GROUP_CLK_SRC_HZ / context[mcpwm_num].group_pre_scale;
return mcpwm_group_get_resolution(mcpwm_num);
#else
return esp_clk_apb_freq();
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -14,8 +14,8 @@
#endif
#include "esp_log.h"
#include "esp_check.h"
#include "clk_tree.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk.h"
#include "soc/mcpwm_periph.h"
#include "hal/mcpwm_ll.h"
#include "mcpwm_private.h"
@ -115,29 +115,14 @@ esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_s
"group clock conflict, already is %d but attempt to %d", group->clk_src, clk_src);
if (do_clock_init) {
// [clk_tree] ToDo: replace the following switch-case table by clock_tree APIs
switch (clk_src) {
#if SOC_MCPWM_CLK_SUPPORT_PLL160M
case SOC_MOD_CLK_PLL_F160M:
periph_src_clk_hz = 160000000;
#if CONFIG_PM_ENABLE
sprintf(group->pm_lock_name, "mcpwm_%d", group->group_id); // e.g. mcpwm_0
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, group->pm_lock_name, &group->pm_lock);
ESP_RETURN_ON_ERROR(ret, TAG, "create ESP_PM_APB_FREQ_MAX lock failed");
ESP_LOGD(TAG, "install ESP_PM_APB_FREQ_MAX lock for MCPWM group(%d)", group->group_id);
#endif // CONFIG_PM_ENABLE
break;
#endif // SOC_MCPWM_CLK_SUPPORT_PLL160M
ESP_RETURN_ON_ERROR(clk_tree_src_get_freq_hz(clk_src, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), TAG, "get clock source freq failed");
#if SOC_MCPWM_CLK_SUPPORT_XTAL
case SOC_MOD_CLK_XTAL:
periph_src_clk_hz = esp_clk_xtal_freq();
break;
#endif // SOC_MCPWM_CLK_SUPPORT_XTAL
default:
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "clock source %d is not supported", clk_src);
break;
}
#if CONFIG_PM_ENABLE
sprintf(group->pm_lock_name, "mcpwm_%d", group->group_id); // e.g. mcpwm_0
ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, group->pm_lock_name, &group->pm_lock);
ESP_RETURN_ON_ERROR(ret, TAG, "create pm lock failed");
ESP_LOGD(TAG, "install NO_LIGHT_SLEEP lock for MCPWM group(%d)", group->group_id);
#endif // CONFIG_PM_ENABLE
mcpwm_ll_group_set_clock_source(group->hal.dev, clk_src);
mcpwm_ll_group_set_clock_prescale(group->hal.dev, MCPWM_PERIPH_CLOCK_PRE_SCALE);

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C6 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |

View File

@ -25,9 +25,13 @@
#define TEST_SYNC_GPIO_2 (19)
#define TEST_CAP_GPIO (21)
#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)
// MCPWM default resolution
#if CONFIG_IDF_TARGET_ESP32H2
#define MCPWM_TEST_GROUP_CLK_HZ (12 * 1000 * 1000)
#else
#define MCPWM_TEST_GROUP_CLK_HZ (10 * 1000 * 1000)
#endif
#define MCPWM_TEST_TIMER_CLK_HZ (1 * 1000 * 1000)
const static mcpwm_io_signals_t pwma[] = {MCPWM0A, MCPWM1A, MCPWM2A};
const static mcpwm_io_signals_t pwmb[] = {MCPWM0B, MCPWM1B, MCPWM2B};

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
@ -8,6 +8,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s3
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
@pytest.mark.parametrize(
'config',

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C6 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
@ -8,6 +8,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s3
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
@pytest.mark.parametrize(
'config',

View File

@ -53,6 +53,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
return PCR_TWAI0_CLK_EN;
case PERIPH_GDMA_MODULE:
return PCR_GDMA_CLK_EN;
case PERIPH_MCPWM0_MODULE:
return PCR_PWM_CLK_EN;
case PERIPH_AES_MODULE:
return PCR_AES_CLK_EN;
case PERIPH_SHA_MODULE:
@ -120,6 +122,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
return PCR_TWAI0_RST_EN;
case PERIPH_GDMA_MODULE:
return PCR_GDMA_RST_EN;
case PERIPH_MCPWM0_MODULE:
return PCR_PWM_RST_EN;
case PERIPH_AES_MODULE:
if (enable == true) {
// Clear reset on digital signature, otherwise AES unit is held in reset also.
@ -210,6 +214,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
return PCR_TWAI0_CONF_REG;
case PERIPH_GDMA_MODULE:
return PCR_GDMA_CONF_REG;
case PERIPH_MCPWM0_MODULE:
return PCR_PWM_CONF_REG;
case PERIPH_AES_MODULE:
return PCR_AES_CONF_REG;
case PERIPH_SHA_MODULE:
@ -263,6 +269,8 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
return PCR_TWAI0_CONF_REG;
case PERIPH_GDMA_MODULE:
return PCR_GDMA_CONF_REG;
case PERIPH_MCPWM0_MODULE:
return PCR_PWM_CONF_REG;
case PERIPH_AES_MODULE:
return PCR_AES_CONF_REG;
case PERIPH_SHA_MODULE:

File diff suppressed because it is too large Load Diff

View File

@ -439,10 +439,6 @@ config SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP
int
default 3
config SOC_MCPWM_CLK_SUPPORT_PLL160M
bool
default y
config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
bool
default n

View File

@ -229,7 +229,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_CLK_SUPPORT_PLL160M (1) ///< Support PLL160M as clock source
/*-------------------------- MPU CAPS ----------------------------------------*/
//TODO: correct the caller and remove unsupported lines

View File

@ -659,14 +659,6 @@ config SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
bool
default y
config SOC_MCPWM_CLK_SUPPORT_PLL160M
bool
default y
config SOC_MCPWM_CLK_SUPPORT_XTAL
bool
default y
config SOC_RSA_MAX_BIT_LEN
int
default 3072

View File

@ -280,8 +280,6 @@
#define SOC_MCPWM_SWSYNC_CAN_PROPAGATE (1) ///< Software sync event can be routed to its output
#define SOC_MCPWM_SUPPORT_ETM (1) ///< Support ETM (Event Task Matrix)
#define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP (1) ///< Capture timer shares clock with other PWM timers
#define SOC_MCPWM_CLK_SUPPORT_PLL160M (1) ///< Support PLL160M as clock source
#define SOC_MCPWM_CLK_SUPPORT_XTAL (1) ///< Support XTAL as clock source
// TODO: IDF-5359 (Copy from esp32c3, need check)
/*--------------------------- RSA CAPS ---------------------------------------*/

View File

@ -15,6 +15,10 @@ config SOC_PCNT_SUPPORTED
bool
default y
config SOC_MCPWM_SUPPORTED
bool
default y
config SOC_GPTIMER_SUPPORTED
bool
default y
@ -507,14 +511,6 @@ config SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
bool
default y
config SOC_MCPWM_CLK_SUPPORT_PLL160M
bool
default y
config SOC_MCPWM_CLK_SUPPORT_XTAL
bool
default y
config SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH
int
default 128

View File

@ -38,6 +38,7 @@ typedef enum {
PERIPH_HMAC_MODULE,
PERIPH_DS_MODULE,
PERIPH_GDMA_MODULE,
PERIPH_MCPWM0_MODULE,
PERIPH_SYSTIMER_MODULE,
PERIPH_SARADC_MODULE,
PERIPH_MODULE_MAX
@ -93,7 +94,7 @@ typedef enum {
ETS_SYSTIMER_TARGET1_EDGE_INTR_SOURCE, /**< interrupt of system timer 1, EDGE*/
ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE, /**< interrupt of system timer 2, EDGE*/
ETS_APB_ADC_INTR_SOURCE, /**< interrupt of APB ADC, LEVEL*/
ETS_PWM_INTR_SOURCE,
ETS_MCPWM0_INTR_SOURCE,
ETS_PCNT_INTR_SOURCE,
ETS_PARL_IO_TX_INTR_SOURCE,
ETS_PARL_IO_RX_INTR_SOURCE,

View File

@ -30,7 +30,7 @@
#define SOC_GDMA_SUPPORTED 1
#define SOC_ASYNC_MEMCPY_SUPPORTED 1
#define SOC_PCNT_SUPPORTED 1
// #define SOC_MCPWM_SUPPORTED 1 // TODO: IDF-6237
#define SOC_MCPWM_SUPPORTED 1
// #define SOC_TWAI_SUPPORTED 1 // TODO: IDF-6217
// #define SOC_BT_SUPPORTED 1 // TODO: IDF-6416
// #define SOC_IEEE802154_SUPPORTED 1 // TODO: IDF-6577
@ -235,7 +235,6 @@
#define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */
// #define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST as the RMT clock source */
// TODO: IDF-6237
/*-------------------------- MCPWM CAPS --------------------------------------*/
#define SOC_MCPWM_GROUPS (1U) ///< 1 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals)
#define SOC_MCPWM_TIMERS_PER_GROUP (3) ///< The number of timers that each group has
@ -249,9 +248,7 @@
#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_SUPPORT_ETM (1) ///< Support ETM (Event Task Matrix)
#define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP (1) ///< Capture timer shares clock with other PWM timers
#define SOC_MCPWM_CLK_SUPPORT_PLL160M (1) ///< Support PLL160M as clock source
#define SOC_MCPWM_CLK_SUPPORT_XTAL (1) ///< Support XTAL as clock source
#define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP (1) ///< Capture timer shares clock with other PWM timers
// TODO: IDF-6267 (Copy from esp32c6, need check)
/*-------------------------- RTC CAPS --------------------------------------*/

View File

@ -27,7 +27,7 @@ PROVIDE ( INTMTX = 0x60010000 );
PROVIDE ( ATOMIC_LOCKER = 0x60011000 );
PROVIDE ( PCNT = 0x60012000 );
PROVIDE ( SOC_ETM = 0x60013000 );
PROVIDE ( MCPWM = 0x60014000 );
PROVIDE ( MCPWM0 = 0x60014000 );
PROVIDE ( PARL_IO = 0x60015000 );
PROVIDE ( PVT_MONITOR = 0x60019000 );

View File

@ -0,0 +1,83 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/mcpwm_periph.h"
#include "soc/gpio_sig_map.h"
const mcpwm_signal_conn_t mcpwm_periph_signals = {
.groups = {
[0] = {
.module = PERIPH_MCPWM0_MODULE,
.irq_id = ETS_MCPWM0_INTR_SOURCE,
.operators = {
[0] = {
.generators = {
[0] = {
.pwm_sig = PWM0_OUT0A_IDX
},
[1] = {
.pwm_sig = PWM0_OUT0B_IDX
}
}
},
[1] = {
.generators = {
[0] = {
.pwm_sig = PWM0_OUT1A_IDX
},
[1] = {
.pwm_sig = PWM0_OUT1B_IDX
}
}
},
[2] = {
.generators = {
[0] = {
.pwm_sig = PWM0_OUT2A_IDX
},
[1] = {
.pwm_sig = PWM0_OUT2B_IDX
}
}
}
},
.gpio_faults = {
[0] = {
.fault_sig = PWM0_F0_IN_IDX
},
[1] = {
.fault_sig = PWM0_F1_IN_IDX
},
[2] = {
.fault_sig = PWM0_F2_IN_IDX
}
},
.captures = {
[0] = {
.cap_sig = PWM0_CAP0_IN_IDX
},
[1] = {
.cap_sig = PWM0_CAP1_IN_IDX
},
[2] = {
.cap_sig = PWM0_CAP2_IN_IDX
}
},
.gpio_synchros = {
[0] = {
.sync_sig = PWM0_SYNC0_IN_IDX
},
[1] = {
.sync_sig = PWM0_SYNC1_IN_IDX
},
[2] = {
.sync_sig = PWM0_SYNC2_IN_IDX
}
}
},
}
};

View File

@ -535,10 +535,6 @@ config SOC_MCPWM_SWSYNC_CAN_PROPAGATE
bool
default y
config SOC_MCPWM_CLK_SUPPORT_PLL160M
bool
default y
config SOC_PCNT_GROUPS
int
default 1

View File

@ -219,7 +219,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_CLK_SUPPORT_PLL160M (1) ///< Support PLL160M as clock source
/*-------------------------- MPU CAPS ----------------------------------------*/
#include "mpu_caps.h"

View File

@ -81,7 +81,6 @@ api-reference/peripherals/etm
api-reference/peripherals/i2s
api-reference/peripherals/touch_element
api-reference/peripherals/lcd
api-reference/peripherals/mcpwm
api-reference/peripherals/secure_element
api-reference/peripherals/temp_sensor
api-reference/peripherals/spi_features

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C6 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
# MCPWM Brushed DC Motor Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C6 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
# MCPWM BLDC Motor Control with HALL Sensor Example

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C6 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
# HC-SR04 Example based on MCPWM Capture

View File

@ -8,6 +8,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s3
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
def test_hc_sr04_example(dut: Dut) -> None:
dut.expect_exact('example: Install capture timer')

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C6 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
# MCPWM RC Servo Control Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)

View File

@ -8,6 +8,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s3
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
def test_servo_mg996r_example(dut: Dut) -> None:
dut.expect_exact('example: Create timer and operator')

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C6 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
# MCPWM Sync Example

View File

@ -8,6 +8,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s3
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
@pytest.mark.parametrize('config', [
pytest.param('gpio', marks=[pytest.mark.esp32, pytest.mark.esp32s3]),

View File

@ -10,7 +10,11 @@
#include "driver/rmt_tx.h"
#include "dshot_esc_encoder.h"
#if CONFIG_IDF_TARGET_ESP32H2
#define DSHOT_ESC_RESOLUTION_HZ 32000000 // 32MHz resolution, DSHot protocol needs a relative high resolution
#else
#define DSHOT_ESC_RESOLUTION_HZ 40000000 // 40MHz resolution, DSHot protocol needs a relative high resolution
#endif
#define DSHOT_ESC_GPIO_NUM 0
static const char *TAG = "example";