mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/modify_mcpwm_clock_pre_scale_v5.1' into 'release/v5.1'
feat(mcpwm): Make the MCPWM capture timer's resolution configurable (v5.1) See merge request espressif/esp-idf!25904
This commit is contained in:
commit
5baf0197f0
@ -21,6 +21,7 @@ extern "C" {
|
||||
typedef struct {
|
||||
int group_id; /*!< Specify from which group to allocate the capture timer */
|
||||
mcpwm_capture_clock_source_t clk_src; /*!< MCPWM capture timer clock source */
|
||||
uint32_t resolution_hz; /*!< Resolution of capture timer */
|
||||
} mcpwm_capture_timer_config_t;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
int group_id; /*!< Specify from which group to allocate the MCPWM timer */
|
||||
mcpwm_timer_clock_source_t clk_src; /*!< MCPWM timer clock source */
|
||||
uint32_t resolution_hz; /*!< Counter resolution in Hz, ranges from around 300KHz to 80MHz.
|
||||
uint32_t resolution_hz; /*!< Counter resolution in Hz
|
||||
The step size of each count tick equals to (1 / resolution_hz) seconds */
|
||||
mcpwm_timer_count_mode_t count_mode; /*!< Count mode */
|
||||
uint32_t period_ticks; /*!< Number of count ticks within a period */
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_memory_utils.h"
|
||||
@ -100,12 +101,25 @@ esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mc
|
||||
#if SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
|
||||
// capture timer clock source is same as the MCPWM group
|
||||
ESP_GOTO_ON_ERROR(mcpwm_select_periph_clock(group, (soc_module_clk_t)clk_src), err, TAG, "set group clock failed");
|
||||
uint32_t periph_src_clk_hz = 0;
|
||||
ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), err, TAG, "get clock source freq failed");
|
||||
ESP_LOGD(TAG, "periph_src_clk_hz %"PRIu32"", periph_src_clk_hz);
|
||||
// when resolution_hz set to zero, use default resolution_hz
|
||||
uint32_t resolution_hz = config->resolution_hz ? config->resolution_hz : periph_src_clk_hz / MCPWM_GROUP_CLOCK_DEFAULT_PRESCALE;
|
||||
|
||||
ESP_GOTO_ON_ERROR(mcpwm_set_prescale(group, resolution_hz, MCPWM_LL_MAX_CAPTURE_TIMER_PRESCALE, NULL), err, TAG, "set prescale failed");
|
||||
cap_timer->resolution_hz = group->resolution_hz;
|
||||
if (cap_timer->resolution_hz != resolution_hz) {
|
||||
ESP_LOGW(TAG, "adjust cap_timer resolution to %"PRIu32"Hz", cap_timer->resolution_hz);
|
||||
}
|
||||
#else
|
||||
// capture timer has independent clock source selection
|
||||
switch (clk_src) {
|
||||
case MCPWM_CAPTURE_CLK_SRC_APB:
|
||||
cap_timer->resolution_hz = esp_clk_apb_freq();
|
||||
if (config->resolution_hz) {
|
||||
ESP_LOGW(TAG, "cap_timer resolution is not adjustable in current target, still %"PRIu32"Hz", cap_timer->resolution_hz);
|
||||
}
|
||||
#if CONFIG_PM_ENABLE
|
||||
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "mcpwm_cap_timer", &cap_timer->pm_lock);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "create ESP_PM_APB_FREQ_MAX lock failed");
|
||||
|
@ -126,10 +126,9 @@ int mcpwm_get_intr_priority_flag(mcpwm_group_t *group)
|
||||
esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_src)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint32_t periph_src_clk_hz = 0;
|
||||
bool clock_selection_conflict = false;
|
||||
bool do_clock_init = false;
|
||||
// check if we need to update the group clock source, group clock source is shared by all mcpwm objects
|
||||
// check if we need to update the group clock source, group clock source is shared by all mcpwm modules
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
if (group->clk_src == 0) {
|
||||
group->clk_src = clk_src;
|
||||
@ -142,7 +141,6 @@ 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) {
|
||||
ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), TAG, "get clock source freq failed");
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
sprintf(group->pm_lock_name, "mcpwm_%d", group->group_id); // e.g. mcpwm_0
|
||||
@ -152,9 +150,77 @@ esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_s
|
||||
#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);
|
||||
group->resolution_hz = periph_src_clk_hz / MCPWM_PERIPH_CLOCK_PRE_SCALE;
|
||||
ESP_LOGD(TAG, "group (%d) clock resolution:%"PRIu32"Hz", group->group_id, group->resolution_hz);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t mcpwm_set_prescale(mcpwm_group_t *group, uint32_t expect_module_resolution_hz, uint32_t module_prescale_max, uint32_t* ret_module_prescale)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group && expect_module_resolution_hz && module_prescale_max, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
uint32_t periph_src_clk_hz = 0;
|
||||
int group_id = group->group_id;
|
||||
uint32_t group_resolution_hz = 0;
|
||||
uint32_t group_prescale = group->prescale > 0 ? group->prescale : MCPWM_GROUP_CLOCK_DEFAULT_PRESCALE; // range: 1~256, 0 means not calculated
|
||||
uint32_t module_prescale = 0; // range: 1~256 (for timer) or 1~16 (for carrier) or 1 (for capture)
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(group->clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), TAG, "get clock source freq failed");
|
||||
|
||||
// calc the group prescale
|
||||
|
||||
group_resolution_hz = periph_src_clk_hz / group_prescale;
|
||||
module_prescale = group_resolution_hz / expect_module_resolution_hz;
|
||||
|
||||
// default prescale cannot match
|
||||
// try to ensure accurate division. If none of the division factors can be guaranteed to be integers, then allocate the clock frequency to the highest divisor
|
||||
uint32_t fit_module_prescale = 0;
|
||||
uint32_t fit_group_prescale = 0;
|
||||
if (!(module_prescale >= 1 && module_prescale <= module_prescale_max)) {
|
||||
group_prescale = 0;
|
||||
while (++group_prescale <= MCPWM_LL_MAX_GROUP_PRESCALE) {
|
||||
group_resolution_hz = periph_src_clk_hz / group_prescale;
|
||||
module_prescale = group_resolution_hz / expect_module_resolution_hz;
|
||||
if (module_prescale >= 1 && module_prescale <= module_prescale_max) {
|
||||
// maintain the first value found during the search that satisfies the division requirement (highest frequency), applicable for cases where integer division is not possible."
|
||||
fit_module_prescale = fit_module_prescale ? fit_module_prescale : module_prescale;
|
||||
fit_group_prescale = fit_group_prescale ? fit_group_prescale : group_prescale;
|
||||
// find accurate division
|
||||
if (group_resolution_hz == expect_module_resolution_hz * module_prescale) {
|
||||
fit_module_prescale = module_prescale;
|
||||
fit_group_prescale = group_prescale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
module_prescale = fit_module_prescale;
|
||||
group_prescale = fit_group_prescale;
|
||||
group_resolution_hz = periph_src_clk_hz / group_prescale;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "group (%d) calc prescale:%"PRIu32", module calc prescale:%"PRIu32"", group_id, group_prescale, module_prescale);
|
||||
ESP_RETURN_ON_FALSE(group_prescale > 0 && group_prescale <= MCPWM_LL_MAX_GROUP_PRESCALE, ESP_ERR_INVALID_STATE, TAG,
|
||||
"set group prescale failed, group clock cannot match the resolution");
|
||||
|
||||
// check if we need to update the group prescale, group prescale is shared by all mcpwm modules
|
||||
bool prescale_conflict = false;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
if (group->prescale == 0) {
|
||||
group->prescale = group_prescale;
|
||||
group->resolution_hz = group_resolution_hz;
|
||||
mcpwm_ll_group_set_clock_prescale(group->hal.dev, group_prescale);
|
||||
} else {
|
||||
prescale_conflict = (group->prescale != group_prescale);
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
ESP_RETURN_ON_FALSE(!prescale_conflict, ESP_ERR_INVALID_STATE, TAG,
|
||||
"group prescale conflict, already is %"PRIu32" but attempt to %"PRIu32"", group->prescale, group_prescale);
|
||||
|
||||
ESP_LOGD(TAG, "group (%d) clock resolution:%"PRIu32"Hz", group_id, group->resolution_hz);
|
||||
|
||||
// set module resolution
|
||||
if (ret_module_prescale) {
|
||||
*ret_module_prescale = module_prescale;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -194,7 +194,10 @@ esp_err_t mcpwm_operator_apply_carrier(mcpwm_oper_handle_t oper, const mcpwm_car
|
||||
mcpwm_carrier_clock_source_t clk_src = config->clk_src ? config->clk_src : MCPWM_CARRIER_CLK_SRC_DEFAULT;
|
||||
ESP_RETURN_ON_ERROR(mcpwm_select_periph_clock(group, (soc_module_clk_t)clk_src), TAG, "set group clock failed");
|
||||
|
||||
uint8_t prescale = group->resolution_hz / 8 / config->frequency_hz;
|
||||
uint32_t prescale = 0;
|
||||
ESP_RETURN_ON_ERROR(mcpwm_set_prescale(group, config->frequency_hz, MCPWM_LL_MAX_CARRIER_PRESCALE * 8, &prescale), TAG, "set prescale failed");
|
||||
// here div 8 because the duty has 3 register bits
|
||||
prescale /= 8;
|
||||
ESP_RETURN_ON_FALSE(prescale > 0 && prescale <= MCPWM_LL_MAX_CARRIER_PRESCALE, ESP_ERR_INVALID_STATE, TAG, "group clock cannot match the frequency");
|
||||
mcpwm_ll_carrier_set_prescale(hal->dev, oper_id, prescale);
|
||||
real_frequency = group->resolution_hz / 8 / prescale;
|
||||
|
@ -36,7 +36,7 @@ extern "C" {
|
||||
|
||||
#define MCPWM_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED
|
||||
|
||||
#define MCPWM_PERIPH_CLOCK_PRE_SCALE (2)
|
||||
#define MCPWM_GROUP_CLOCK_DEFAULT_PRESCALE 2
|
||||
#define MCPWM_PM_LOCK_NAME_LEN_MAX 16
|
||||
|
||||
typedef struct mcpwm_group_t mcpwm_group_t;
|
||||
@ -59,7 +59,8 @@ struct mcpwm_group_t {
|
||||
int intr_priority; // MCPWM interrupt priority
|
||||
mcpwm_hal_context_t hal; // HAL instance is at group level
|
||||
portMUX_TYPE spinlock; // group level spinlock
|
||||
uint32_t resolution_hz; // MCPWM group clock resolution
|
||||
uint32_t prescale; // group prescale
|
||||
uint32_t resolution_hz; // MCPWM group clock resolution: clock_src_hz / clock_prescale = resolution_hz
|
||||
esp_pm_lock_handle_t pm_lock; // power management lock
|
||||
soc_module_clk_t clk_src; // peripheral source clock
|
||||
mcpwm_cap_timer_t *cap_timer; // mcpwm capture timers
|
||||
@ -231,6 +232,7 @@ void mcpwm_release_group_handle(mcpwm_group_t *group);
|
||||
esp_err_t mcpwm_check_intr_priority(mcpwm_group_t *group, int intr_priority);
|
||||
int mcpwm_get_intr_priority_flag(mcpwm_group_t *group);
|
||||
esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_src);
|
||||
esp_err_t mcpwm_set_prescale(mcpwm_group_t *group, uint32_t expect_module_resolution_hz, uint32_t module_prescale_max, uint32_t* ret_module_prescale);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -115,8 +115,8 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
|
||||
// reset the timer to a determined state
|
||||
mcpwm_hal_timer_reset(hal, timer_id);
|
||||
// set timer resolution
|
||||
uint32_t prescale = group->resolution_hz / config->resolution_hz;
|
||||
ESP_RETURN_ON_FALSE(prescale > 0 && prescale <= MCPWM_LL_MAX_TIMER_PRESCALE, ESP_ERR_INVALID_STATE, TAG, "group clock cannot match the resolution");
|
||||
uint32_t prescale = 0;
|
||||
ESP_GOTO_ON_ERROR(mcpwm_set_prescale(group, config->resolution_hz, MCPWM_LL_MAX_TIMER_PRESCALE, &prescale), err, TAG, "set prescale failed");
|
||||
mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_id, prescale);
|
||||
timer->resolution_hz = group->resolution_hz / prescale;
|
||||
if (timer->resolution_hz != config->resolution_hz) {
|
||||
|
@ -76,6 +76,7 @@ TEST_CASE("mcpwm_capture_ext_gpio", "[mcpwm]")
|
||||
mcpwm_capture_timer_config_t cap_timer_config = {
|
||||
.clk_src = MCPWM_CAPTURE_CLK_SRC_DEFAULT,
|
||||
.group_id = 0,
|
||||
.resolution_hz = 8 * 1000 * 1000,
|
||||
};
|
||||
TEST_ESP_OK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer));
|
||||
|
||||
@ -118,6 +119,7 @@ TEST_CASE("mcpwm_capture_ext_gpio", "[mcpwm]")
|
||||
uint32_t clk_src_res;
|
||||
TEST_ESP_OK(mcpwm_capture_timer_get_resolution(cap_timer, &clk_src_res));
|
||||
clk_src_res /= 1000; // convert to kHz
|
||||
printf("timer resolution:%"PRIu32"KHz\r\n", clk_src_res);
|
||||
TEST_ASSERT_UINT_WITHIN(1000, 10000, (cap_value[1] - cap_value[0]) * 1000 / clk_src_res);
|
||||
|
||||
printf("uninstall capture channel and timer\r\n");
|
||||
|
@ -123,3 +123,48 @@ TEST_CASE("mcpwm_set_interrupt_priority", "[mcpwm]")
|
||||
TEST_ESP_OK(mcpwm_del_timer(timer));
|
||||
TEST_ESP_OK(mcpwm_del_fault(fault));
|
||||
}
|
||||
|
||||
TEST_CASE("mcpwm_group_set_prescale_dynamically", "[mcpwm]")
|
||||
{
|
||||
mcpwm_timer_config_t timer_config = {
|
||||
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
|
||||
.resolution_hz = 100 * 1000, // 100kHz
|
||||
.period_ticks = 400,
|
||||
.count_mode = MCPWM_TIMER_COUNT_MODE_UP_DOWN,
|
||||
.group_id = 0,
|
||||
};
|
||||
|
||||
mcpwm_timer_handle_t timer = NULL;
|
||||
printf("create mcpwm timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
|
||||
|
||||
mcpwm_operator_config_t operator_config = {
|
||||
.group_id = 0,
|
||||
};
|
||||
mcpwm_oper_handle_t oper = NULL;
|
||||
TEST_ESP_OK(mcpwm_new_operator(&operator_config, &oper));
|
||||
|
||||
mcpwm_generator_config_t generator_config = {
|
||||
.gen_gpio_num = 0,
|
||||
};
|
||||
mcpwm_gen_handle_t generator = NULL;
|
||||
TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &generator));
|
||||
|
||||
printf("add carrier to PWM wave\r\n");
|
||||
mcpwm_carrier_config_t carrier_config = {
|
||||
.clk_src = MCPWM_CARRIER_CLK_SRC_DEFAULT,
|
||||
.frequency_hz = 100000, // 100KHz carrier need higher group prescale
|
||||
.duty_cycle = 0.5,
|
||||
.first_pulse_duration_us = 10,
|
||||
};
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_operator_apply_carrier(oper, &carrier_config));
|
||||
carrier_config.frequency_hz = 2000000; // 2MHz carrier
|
||||
carrier_config.first_pulse_duration_us = 5;
|
||||
TEST_ESP_OK(mcpwm_operator_apply_carrier(oper, &carrier_config));
|
||||
|
||||
|
||||
TEST_ESP_OK(mcpwm_del_generator(generator));
|
||||
TEST_ESP_OK(mcpwm_del_operator(oper));
|
||||
TEST_ESP_OK(mcpwm_del_timer(timer));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -43,10 +43,12 @@ extern "C" {
|
||||
#define MCPWM_LL_EVENT_CAPTURE(cap) (1 << ((cap) + 27))
|
||||
|
||||
// Maximum values due to limited register bit width
|
||||
#define MCPWM_LL_MAX_GROUP_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_TIMER_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_CARRIER_PRESCALE 16
|
||||
#define MCPWM_LL_MAX_CARRIER_ONESHOT 16
|
||||
#define MCPWM_LL_MAX_CAPTURE_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_CAPTURE_TIMER_PRESCALE 1
|
||||
#define MCPWM_LL_MAX_DEAD_DELAY 65536
|
||||
#define MCPWM_LL_MAX_COUNT_VALUE 65536
|
||||
|
||||
@ -97,10 +99,11 @@ static inline void mcpwm_ll_group_enable_clock(mcpwm_dev_t *mcpwm, bool en)
|
||||
* @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)
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int prescale)
|
||||
{
|
||||
// group clock: PWM_clk = CLK_160M / (prescale + 1)
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale, pre_scale - 1);
|
||||
// group clock: PWM_clk = CLK_160M / (prescale)
|
||||
HAL_ASSERT(prescale <= 256 && prescale > 0);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale, prescale - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,10 +45,12 @@ extern "C" {
|
||||
#define MCPWM_LL_EVENT_CAPTURE(cap) (1 << ((cap) + 27))
|
||||
|
||||
// Maximum values due to limited register bit width
|
||||
#define MCPWM_LL_MAX_GROUP_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_TIMER_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_CARRIER_PRESCALE 16
|
||||
#define MCPWM_LL_MAX_CARRIER_ONESHOT 16
|
||||
#define MCPWM_LL_MAX_CAPTURE_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_CAPTURE_TIMER_PRESCALE 1
|
||||
#define MCPWM_LL_MAX_DEAD_DELAY 65536
|
||||
#define MCPWM_LL_MAX_COUNT_VALUE 65536
|
||||
|
||||
@ -105,13 +107,14 @@ static inline void mcpwm_ll_group_enable_clock(mcpwm_dev_t *mcpwm, bool en)
|
||||
* @brief Set the MCPWM group clock prescale
|
||||
*
|
||||
* @param mcpwm Peripheral instance address
|
||||
* @param pre_scale Prescale value
|
||||
* @param prescale Prescale value
|
||||
*/
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale)
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int prescale)
|
||||
{
|
||||
(void)mcpwm; // only one MCPWM instance
|
||||
// group clock: PWM_clk = source_clock / (prescale + 1)
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.pwm_clk_conf, pwm_div_num, pre_scale - 1);
|
||||
// group clock: PWM_clk = source_clock / (prescale)
|
||||
HAL_ASSERT(prescale <= 256 && prescale > 0);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.pwm_clk_conf, pwm_div_num, prescale - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,10 +43,12 @@ extern "C" {
|
||||
#define MCPWM_LL_EVENT_CAPTURE(cap) (1 << ((cap) + 27))
|
||||
|
||||
// Maximum values due to limited register bit width
|
||||
#define MCPWM_LL_MAX_GROUP_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_TIMER_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_CARRIER_PRESCALE 16
|
||||
#define MCPWM_LL_MAX_CARRIER_ONESHOT 16
|
||||
#define MCPWM_LL_MAX_CAPTURE_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_CAPTURE_TIMER_PRESCALE 1
|
||||
#define MCPWM_LL_MAX_DEAD_DELAY 65536
|
||||
#define MCPWM_LL_MAX_COUNT_VALUE 65536
|
||||
|
||||
@ -103,13 +105,14 @@ static inline void mcpwm_ll_group_enable_clock(mcpwm_dev_t *mcpwm, bool en)
|
||||
* @brief Set the MCPWM group clock prescale
|
||||
*
|
||||
* @param mcpwm Peripheral instance address
|
||||
* @param pre_scale Prescale value
|
||||
* @param prescale Prescale value
|
||||
*/
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale)
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int prescale)
|
||||
{
|
||||
(void)mcpwm; // only one MCPWM instance
|
||||
// group clock: PWM_clk = source_clock / (prescale + 1)
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.pwm_clk_conf, pwm_div_num, pre_scale - 1);
|
||||
// group clock: PWM_clk = source_clock / (prescale)
|
||||
HAL_ASSERT(prescale <= 256 && prescale > 0);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.pwm_clk_conf, pwm_div_num, prescale - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -43,10 +43,12 @@ extern "C" {
|
||||
#define MCPWM_LL_EVENT_CAPTURE(cap) (1 << ((cap) + 27))
|
||||
|
||||
// Maximum values due to limited register bit width
|
||||
#define MCPWM_LL_MAX_GROUP_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_TIMER_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_CARRIER_PRESCALE 16
|
||||
#define MCPWM_LL_MAX_CARRIER_ONESHOT 16
|
||||
#define MCPWM_LL_MAX_CAPTURE_PRESCALE 256
|
||||
#define MCPWM_LL_MAX_CAPTURE_TIMER_PRESCALE 1
|
||||
#define MCPWM_LL_MAX_DEAD_DELAY 65536
|
||||
#define MCPWM_LL_MAX_COUNT_VALUE 65536
|
||||
|
||||
@ -95,12 +97,13 @@ static inline void mcpwm_ll_group_enable_clock(mcpwm_dev_t *mcpwm, bool en)
|
||||
* @brief Set the MCPWM group clock prescale
|
||||
*
|
||||
* @param mcpwm Peripheral instance address
|
||||
* @param pre_scale Prescale value
|
||||
* @param prescale Prescale value
|
||||
*/
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale)
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int prescale)
|
||||
{
|
||||
// group clock: PWM_clk = CLK_160M / (prescale + 1)
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale, pre_scale - 1);
|
||||
// group clock: PWM_clk = CLK_160M / (prescale)
|
||||
HAL_ASSERT(prescale <= 256 && prescale > 0);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale, prescale - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,6 +173,13 @@ To allocate a capture timer, you can call :cpp:func:`mcpwm_new_capture_timer` fu
|
||||
|
||||
- :cpp:member:`mcpwm_capture_timer_config_t::group_id` sets the MCPWM group ID. The ID should belong to [0, :c:macro:`SOC_MCPWM_GROUPS` - 1] range.
|
||||
- :cpp:member:`mcpwm_capture_timer_config_t::clk_src` sets the clock source of the capture timer.
|
||||
- :cpp:member:`mcpwm_capture_timer_config_t::resolution_hz` The driver internally will set a proper divider based on the clock source and the resolution. If it is set to ``0``, the driver will pick an appropriate resolution on its own, and you can subsequently view the current timer resolution via :cpp:func:`mcpwm_capture_timer_get_resolution`.
|
||||
|
||||
.. only:: not SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
|
||||
|
||||
.. note::
|
||||
|
||||
In {IDF_TARGET_NAME}, :cpp:member:`mcpwm_capture_timer_config_t::resolution_hz` parameter is invalid, the capture timer resolution is always equal to the :cpp:enumerator:`MCPWM_CAPTURE_CLK_SRC_APB`.
|
||||
|
||||
The :cpp:func:`mcpwm_new_capture_timer` will return a pointer to the allocated capture timer object if the allocation succeeds. Otherwise, it will return error code. Specifically, when there are no free capture timer left in the MCPWM group, this function will return :c:macro:`ESP_ERR_NOT_FOUND` error. [1]_
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user