mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
feat(ledc): support ledc sleep mode selection
Support LEDC sleep retention on C6/H2/P4
This commit is contained in:
parent
b949e9e729
commit
4a90deb227
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -33,6 +33,18 @@ extern "C" {
|
||||
#define LEDC_ERR_DUTY (0xFFFFFFFF)
|
||||
#define LEDC_ERR_VAL (-1)
|
||||
|
||||
/**
|
||||
* @brief Strategies to be applied to the LEDC channel during system Light-sleep period
|
||||
*/
|
||||
typedef enum {
|
||||
LEDC_SLEEP_MODE_NO_ALIVE_NO_PD = 0, /*!< The default mode: no LEDC output, and no power off the LEDC power domain. */
|
||||
LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD, /*!< The low-power-consumption mode: no LEDC output, and allow to power off the LEDC power domain.
|
||||
This can save power, but at the expense of more RAM being consumed to save register context.
|
||||
This option is only available on targets that support TOP domain to be powered down. */
|
||||
LEDC_SLEEP_MODE_KEEP_ALIVE, /*!< The high-power-consumption mode: keep LEDC output when the system enters Light-sleep. */
|
||||
LEDC_SLEEP_MODE_INVALID, /*!< Invalid LEDC sleep mode strategy */
|
||||
} ledc_sleep_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration parameters of LEDC channel for ledc_channel_config function
|
||||
*/
|
||||
@ -44,6 +56,7 @@ typedef struct {
|
||||
ledc_timer_t timer_sel; /*!< Select the timer source of channel (0 - LEDC_TIMER_MAX-1) */
|
||||
uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */
|
||||
int hpoint; /*!< LEDC channel hpoint value, the range is [0, (2**duty_resolution)-1] */
|
||||
ledc_sleep_mode_t sleep_mode; /*!< choose the desired behavior for the LEDC channel in Light-sleep */
|
||||
struct {
|
||||
unsigned int output_invert: 1;/*!< Enable (1) or disable (0) gpio output invert */
|
||||
} flags; /*!< LEDC flags */
|
||||
|
@ -25,6 +25,12 @@
|
||||
#include "esp_private/esp_clk_tree_common.h"
|
||||
#include "esp_private/esp_gpio_reserve.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#if SOC_PMU_SUPPORTED // TODO: replace when icg API available IDF-7595
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_types.h"
|
||||
#include "soc/pmu_icg_mapping.h"
|
||||
#endif
|
||||
|
||||
static __attribute__((unused)) const char *LEDC_TAG = "ledc";
|
||||
|
||||
@ -58,6 +64,8 @@ static __attribute__((unused)) const char *LEDC_TAG = "ledc";
|
||||
#define LEDC_FUNC_CLOCK_ATOMIC()
|
||||
#endif
|
||||
|
||||
#define LEDC_USE_RETENTION_LINK (SOC_LEDC_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
|
||||
typedef enum {
|
||||
LEDC_FSM_IDLE,
|
||||
LEDC_FSM_HW_FADE,
|
||||
@ -87,6 +95,10 @@ typedef struct {
|
||||
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
|
||||
ledc_clk_src_t timer_specific_clk[LEDC_TIMER_MAX]; /*!< Tracks the timer-specific clock selection for each timer */
|
||||
#endif
|
||||
ledc_sleep_mode_t sleep_mode; /*!< Records the sleep strategy to be applied to the LEDC module */
|
||||
bool channel_keep_alive[LEDC_CHANNEL_MAX]; /*!< Records whether each channel needs to keep output during sleep */
|
||||
uint8_t timer_xpd_ref_cnt[LEDC_TIMER_MAX]; /*!< Records the timer (glb_clk) not power down during sleep requirement */
|
||||
bool glb_clk_xpd; /*!< Records the power strategy applied to the global clock */
|
||||
} ledc_obj_t;
|
||||
|
||||
static ledc_obj_t *p_ledc_obj[LEDC_SPEED_MODE_MAX] = {
|
||||
@ -118,6 +130,37 @@ static const ledc_slow_clk_sel_t s_glb_clks[] = LEDC_LL_GLOBAL_CLOCKS;
|
||||
static const ledc_clk_src_t s_timer_specific_clks[] = LEDC_LL_TIMER_SPECIFIC_CLOCKS;
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
static esp_err_t ledc_create_sleep_retention_link_cb(void *arg)
|
||||
{
|
||||
#if SOC_LEDC_SUPPORT_SLEEP_RETENTION
|
||||
sleep_retention_module_t module = ledc_reg_retention_info.module_id;
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(ledc_reg_retention_info.common.regdma_entry_array,
|
||||
ledc_reg_retention_info.common.array_size,
|
||||
REGDMA_LINK_PRI_LEDC, module);
|
||||
bool slp_retention_create_failed = (err != ESP_OK);
|
||||
|
||||
for (int i = 0; i < SOC_LEDC_TIMER_NUM && !slp_retention_create_failed; i++) {
|
||||
err = sleep_retention_entries_create(ledc_reg_retention_info.timer[i].regdma_entry_array,
|
||||
ledc_reg_retention_info.timer[i].array_size,
|
||||
REGDMA_LINK_PRI_LEDC, module);
|
||||
slp_retention_create_failed |= (err != ESP_OK);
|
||||
}
|
||||
|
||||
for (int j = 0; j < SOC_LEDC_CHANNEL_NUM && !slp_retention_create_failed; j++) {
|
||||
err = sleep_retention_entries_create(ledc_reg_retention_info.channel[j].regdma_entry_array,
|
||||
ledc_reg_retention_info.channel[j].array_size,
|
||||
REGDMA_LINK_PRI_LEDC, module);
|
||||
slp_retention_create_failed |= (err != ESP_OK);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_FALSE(!slp_retention_create_failed, err, LEDC_TAG, "create retention link failed");
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ledc_ls_timer_update(ledc_mode_t speed_mode, ledc_timer_t timer_sel)
|
||||
{
|
||||
if (speed_mode == LEDC_LOW_SPEED_MODE) {
|
||||
@ -240,15 +283,78 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* return 1 if the global clock cannot keep alive in sleep, as an error raised
|
||||
*/
|
||||
static bool ledc_glb_clk_set_sleep_mode(ledc_mode_t speed_mode, bool xpd)
|
||||
{
|
||||
bool glb_clk_xpd_err = false;
|
||||
if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_RC_FAST) {
|
||||
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, xpd);
|
||||
p_ledc_obj[speed_mode]->glb_clk_xpd = xpd;
|
||||
}
|
||||
#if SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
else if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_XTAL) {
|
||||
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_XTAL_MODE, xpd);
|
||||
p_ledc_obj[speed_mode]->glb_clk_xpd = xpd;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if (xpd) {
|
||||
glb_clk_xpd_err = true;
|
||||
}
|
||||
}
|
||||
return glb_clk_xpd_err;
|
||||
}
|
||||
|
||||
/**
|
||||
* spinlock should wrap outside
|
||||
* return 1 if the timer cannot keep alive in sleep, as an error raised
|
||||
*/
|
||||
static bool ledc_timer_clk_src_set_xpd_in_sleep(ledc_mode_t speed_mode, ledc_timer_t timer_sel)
|
||||
{
|
||||
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_sel]++;
|
||||
bool timer_clock_xpd_err = false;
|
||||
// if the timer has not been configured yet, leave the xpd configuration to ledc_timer_config
|
||||
if (p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] && p_ledc_obj[speed_mode]->glb_clk != LEDC_SLOW_CLK_UNINIT && !p_ledc_obj[speed_mode]->glb_clk_xpd) {
|
||||
timer_clock_xpd_err = ledc_glb_clk_set_sleep_mode(speed_mode, true);
|
||||
}
|
||||
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
|
||||
else if (p_ledc_obj[speed_mode]->timer_specific_clk[timer_sel] != LEDC_TIMER_SPECIFIC_CLK_UNINIT) {
|
||||
timer_clock_xpd_err = true;
|
||||
}
|
||||
#endif
|
||||
if (timer_clock_xpd_err) {
|
||||
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_sel]--;
|
||||
}
|
||||
return timer_clock_xpd_err;
|
||||
}
|
||||
|
||||
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_timer_t timer_sel)
|
||||
{
|
||||
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
|
||||
LEDC_ARG_CHECK(timer_sel < LEDC_TIMER_MAX, "timer_select");
|
||||
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
|
||||
|
||||
bool timer_xpd_err = false;
|
||||
ledc_timer_t old_timer_sel;
|
||||
ledc_hal_get_channel_timer(&(p_ledc_obj[speed_mode]->ledc_hal), channel, &old_timer_sel);
|
||||
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
ledc_hal_bind_channel_timer(&(p_ledc_obj[speed_mode]->ledc_hal), channel, timer_sel);
|
||||
ledc_ls_channel_update(speed_mode, channel);
|
||||
|
||||
if (p_ledc_obj[speed_mode]->channel_keep_alive[channel] && old_timer_sel != timer_sel) {
|
||||
if (p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[old_timer_sel] > 0) {
|
||||
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[old_timer_sel]--;
|
||||
}
|
||||
// timer clock source should not be powered down during sleep
|
||||
timer_xpd_err = ledc_timer_clk_src_set_xpd_in_sleep(speed_mode, timer_sel);
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
if (timer_xpd_err) {
|
||||
ESP_LOGW(LEDC_TAG, "the binded timer can't keep alive in sleep");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -316,6 +422,24 @@ static bool ledc_speed_mode_ctx_create(ledc_mode_t speed_mode)
|
||||
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
|
||||
memset(ledc_new_mode_obj->timer_specific_clk, LEDC_TIMER_SPECIFIC_CLK_UNINIT, sizeof(ledc_clk_src_t) * LEDC_TIMER_MAX);
|
||||
#endif
|
||||
|
||||
ledc_new_mode_obj->sleep_mode = LEDC_SLEEP_MODE_INVALID;
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // for targets that is !SOC_LEDC_SUPPORT_SLEEP_RETENTION, retention module should still be inited to avoid TOP PD
|
||||
// Initialize sleep retention module for LEDC
|
||||
sleep_retention_module_t module = ledc_reg_retention_info.module_id;
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = {
|
||||
.create = {
|
||||
.handle = ledc_create_sleep_retention_link_cb,
|
||||
.arg = NULL,
|
||||
},
|
||||
},
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM),
|
||||
};
|
||||
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
|
||||
ESP_LOGW(LEDC_TAG, "init sleep retention failed for ledc, power domain may be turned off during sleep");
|
||||
}
|
||||
#endif
|
||||
p_ledc_obj[speed_mode] = ledc_new_mode_obj;
|
||||
}
|
||||
}
|
||||
@ -530,6 +654,8 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
ESP_LOGD(LEDC_TAG, "Using clock source %d (in %s mode), divisor: 0x%"PRIx32,
|
||||
timer_clk_src, (speed_mode == LEDC_LOW_SPEED_MODE ? "slow" : "fast"), div_param);
|
||||
|
||||
bool timer_clk_xpd_err = false;
|
||||
|
||||
/* The following block configures the global clock.
|
||||
* Thus, in theory, this only makes sense when configuring the LOW_SPEED timer and the source clock is LEDC_SCLK (as
|
||||
* HIGH_SPEED timers won't be clocked by the global clock). However, there are some limitations due to HW design.
|
||||
@ -563,16 +689,6 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
}
|
||||
p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_num] = true;
|
||||
if (p_ledc_obj[speed_mode]->glb_clk != glb_clk) {
|
||||
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||
/* keep ESP_PD_DOMAIN_RC_FAST on during light sleep */
|
||||
if (glb_clk == LEDC_SLOW_CLK_RC_FAST) {
|
||||
/* Keep ESP_PD_DOMAIN_RC_FAST on during light sleep */
|
||||
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, true);
|
||||
} else if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_RC_FAST) {
|
||||
/* No need to keep ESP_PD_DOMAIN_RC_FAST on during light sleep anymore */
|
||||
esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, false);
|
||||
}
|
||||
#endif
|
||||
// TODO: release old glb_clk (if not UNINIT), and acquire new glb_clk [clk_tree]
|
||||
p_ledc_obj[speed_mode]->glb_clk = glb_clk;
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)glb_clk, true);
|
||||
@ -581,6 +697,13 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
ledc_hal_set_slow_clk_sel(&(p_ledc_obj[speed_mode]->ledc_hal), glb_clk);
|
||||
}
|
||||
}
|
||||
// acquire power domain for the timer clock source if desired and possible
|
||||
if (p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_num] > 0 && !p_ledc_obj[speed_mode]->glb_clk_xpd) {
|
||||
timer_clk_xpd_err = ledc_glb_clk_set_sleep_mode(speed_mode, true);
|
||||
if (timer_clk_xpd_err) {
|
||||
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_num] = 0;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
|
||||
ESP_LOGD(LEDC_TAG, "In slow speed mode, global clk set: %d", glb_clk);
|
||||
@ -588,6 +711,19 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
|
||||
/* The divisor is correct, we can write in the hardware. */
|
||||
ledc_timer_set(speed_mode, timer_num, div_param, duty_resolution, timer_clk_src);
|
||||
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
if (p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_num] > 0 && !p_ledc_obj[speed_mode]->glb_clk_xpd) {
|
||||
// if still get into here, it means the speed mode is high speed mode
|
||||
assert(speed_mode != LEDC_LOW_SPEED_MODE);
|
||||
timer_clk_xpd_err = true;
|
||||
p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[timer_num] = 0;
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
if (timer_clk_xpd_err) {
|
||||
ESP_LOGW(LEDC_TAG, "the timer can't keep alive in sleep");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
error:
|
||||
@ -612,6 +748,20 @@ static esp_err_t ledc_timer_del(ledc_mode_t speed_mode, ledc_timer_t timer_sel)
|
||||
is_deleted = true;
|
||||
p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] = false;
|
||||
// TODO: release timer specific clk and global clk if possible [clk_tree]
|
||||
|
||||
// check if the acquired power domain for the timer clock source can be released
|
||||
if (p_ledc_obj[speed_mode]->glb_clk_xpd) {
|
||||
bool timer_clk_allow_pd = true;
|
||||
for (int i = 0; i < LEDC_TIMER_MAX; i++) {
|
||||
if (p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] && p_ledc_obj[speed_mode]->timer_xpd_ref_cnt[i] > 0) {
|
||||
timer_clk_allow_pd = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (timer_clk_allow_pd) {
|
||||
ledc_glb_clk_set_sleep_mode(speed_mode, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
ESP_RETURN_ON_FALSE(is_configured && is_deleted, ESP_ERR_INVALID_STATE, LEDC_TAG, "timer hasn't been configured, or it is still running, please stop it with ledc_timer_pause first");
|
||||
@ -687,6 +837,10 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
|
||||
LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num");
|
||||
LEDC_ARG_CHECK(timer_select < LEDC_TIMER_MAX, "timer_select");
|
||||
LEDC_ARG_CHECK(intr_type < LEDC_INTR_MAX, "intr_type");
|
||||
LEDC_ARG_CHECK(ledc_conf->sleep_mode < LEDC_SLEEP_MODE_INVALID, "sleep_mode");
|
||||
#if !SOC_LEDC_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(ledc_conf->sleep_mode != LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD, ESP_ERR_NOT_SUPPORTED, LEDC_TAG, "register back up is not supported");
|
||||
#endif
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
@ -732,6 +886,86 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
|
||||
/*set LEDC signal in gpio matrix*/
|
||||
_ledc_set_pin(gpio_num, output_invert, speed_mode, ledc_channel);
|
||||
|
||||
// apply desired sleep strategy
|
||||
bool slp_mode_conflict = false;
|
||||
bool slp_retention_alloc __attribute__((unused)) = false;
|
||||
bool slp_retention_free __attribute__((unused)) = false;
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
if (ledc_conf->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD) {
|
||||
#if LEDC_USE_RETENTION_LINK
|
||||
if (p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_NO_PD || p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_KEEP_ALIVE) {
|
||||
// conflict sleep strategy with other LEDC channels, power domain cannot be turned off
|
||||
slp_mode_conflict = true;
|
||||
} else {
|
||||
p_ledc_obj[speed_mode]->sleep_mode = LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD;
|
||||
slp_retention_alloc = true;
|
||||
}
|
||||
#endif
|
||||
} else if (ledc_conf->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_NO_PD) {
|
||||
if (p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_INVALID) {
|
||||
p_ledc_obj[speed_mode]->sleep_mode = LEDC_SLEEP_MODE_NO_ALIVE_NO_PD;
|
||||
}
|
||||
#if LEDC_USE_RETENTION_LINK
|
||||
else if (p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD) {
|
||||
// conflict sleep strategy with other LEDC channels, power domain might still be turned off
|
||||
slp_mode_conflict = true;
|
||||
}
|
||||
#endif
|
||||
} else if (ledc_conf->sleep_mode == LEDC_SLEEP_MODE_KEEP_ALIVE) {
|
||||
p_ledc_obj[speed_mode]->channel_keep_alive[ledc_channel] = true;
|
||||
#if LEDC_USE_RETENTION_LINK
|
||||
if (p_ledc_obj[speed_mode]->sleep_mode == LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD) {
|
||||
// conflict sleep strategy with other LEDC channels, power domain won't be turned off
|
||||
slp_mode_conflict = true;
|
||||
slp_retention_free = true;
|
||||
}
|
||||
#endif
|
||||
p_ledc_obj[speed_mode]->sleep_mode = LEDC_SLEEP_MODE_KEEP_ALIVE;
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
if (slp_mode_conflict) {
|
||||
ESP_LOGW(LEDC_TAG, "conflict sleep strategy with other LEDC channels, power domain may not be on/off as desired in sleep");
|
||||
}
|
||||
#if LEDC_USE_RETENTION_LINK
|
||||
if (slp_retention_alloc) {
|
||||
if (sleep_retention_module_allocate(ledc_reg_retention_info.module_id) != ESP_OK) {
|
||||
ESP_LOGW(LEDC_TAG, "create retention module failed, power domain can't turn off");
|
||||
}
|
||||
}
|
||||
if (slp_retention_free) {
|
||||
sleep_retention_module_free(ledc_reg_retention_info.module_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ledc_conf->sleep_mode == LEDC_SLEEP_MODE_KEEP_ALIVE) {
|
||||
// 1. timer clock source should not be powered down during sleep
|
||||
bool timer_xpd_err = false;
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
timer_xpd_err = ledc_timer_clk_src_set_xpd_in_sleep(speed_mode, timer_select);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
if (timer_xpd_err) {
|
||||
ESP_LOGW(LEDC_TAG, "the binded timer can't keep alive in sleep");
|
||||
}
|
||||
|
||||
// 2. keep IO output during sleep
|
||||
gpio_sleep_sel_dis(gpio_num);
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// To workaround DIG-399, all LP IOs are held when LP_PERIPH is powered off to ensure EXT wakeup functionality
|
||||
// But holding LP IOs will cause LEDC signal cannot output on the pad during sleep
|
||||
// Therefore, we will force LP periph xpd in such case
|
||||
if ((1ULL << gpio_num) & SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK) {
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 3. keep related module integrated clock gating on during sleep
|
||||
// TODO: use proper icg API IDF-7595
|
||||
#if SOC_PMU_SUPPORTED && !CONFIG_IDF_TARGET_ESP32P4 // P4 does not have peripheral icg
|
||||
uint32_t val = PMU.hp_sys[PMU_MODE_HP_SLEEP].icg_func;
|
||||
PMU.hp_sys[PMU_MODE_HP_SLEEP].icg_func = (val | BIT(PMU_ICG_FUNC_ENA_LEDC) | BIT(PMU_ICG_FUNC_ENA_IOMUX));
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
set(srcs "test_app_main.c"
|
||||
"test_ledc.c")
|
||||
"test_ledc.c"
|
||||
"test_ledc_sleep.c"
|
||||
"test_ledc_utils.c")
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
|
@ -22,54 +22,7 @@
|
||||
#include "driver/ledc.h"
|
||||
#include "soc/ledc_struct.h"
|
||||
#include "esp_clk_tree.h"
|
||||
|
||||
#define PULSE_IO 5
|
||||
|
||||
#define TEST_PWM_FREQ 2000
|
||||
|
||||
#if SOC_LEDC_SUPPORT_HS_MODE
|
||||
#define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE
|
||||
#define SPEED_MODE_LIST {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}
|
||||
#else
|
||||
#define TEST_SPEED_MODE LEDC_LOW_SPEED_MODE
|
||||
#define SPEED_MODE_LIST {LEDC_LOW_SPEED_MODE}
|
||||
#endif
|
||||
|
||||
#if SOC_LEDC_SUPPORT_APB_CLOCK
|
||||
#define TEST_DEFAULT_CLK_CFG LEDC_USE_APB_CLK
|
||||
#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
|
||||
#if SOC_CLK_TREE_SUPPORTED
|
||||
#define TEST_DEFAULT_CLK_CFG LEDC_USE_PLL_DIV_CLK
|
||||
#else
|
||||
#define TEST_DEFAULT_CLK_CFG LEDC_USE_XTAL_CLK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static ledc_channel_config_t initialize_channel_config(void)
|
||||
{
|
||||
ledc_channel_config_t config;
|
||||
memset(&config, 0, sizeof(ledc_channel_config_t));
|
||||
config.gpio_num = PULSE_IO;
|
||||
config.speed_mode = TEST_SPEED_MODE;
|
||||
config.channel = LEDC_CHANNEL_0;
|
||||
config.intr_type = LEDC_INTR_DISABLE;
|
||||
config.timer_sel = LEDC_TIMER_0;
|
||||
config.duty = 4000;
|
||||
config.hpoint = 0;
|
||||
return config;
|
||||
}
|
||||
|
||||
static ledc_timer_config_t create_default_timer_config(void)
|
||||
{
|
||||
ledc_timer_config_t ledc_time_config;
|
||||
memset(&ledc_time_config, 0, sizeof(ledc_timer_config_t));
|
||||
ledc_time_config.speed_mode = TEST_SPEED_MODE;
|
||||
ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT;
|
||||
ledc_time_config.timer_num = LEDC_TIMER_0;
|
||||
ledc_time_config.freq_hz = TEST_PWM_FREQ;
|
||||
ledc_time_config.clk_cfg = TEST_DEFAULT_CLK_CFG;
|
||||
return ledc_time_config;
|
||||
}
|
||||
#include "test_ledc_utils.h"
|
||||
|
||||
static void fade_setup(void)
|
||||
{
|
||||
@ -474,52 +427,6 @@ TEST_CASE("LEDC multi fade test", "[ledc]")
|
||||
|
||||
#if SOC_PCNT_SUPPORTED // Note. C61, C3, C2 do not have PCNT peripheral, the following test cases cannot be tested
|
||||
|
||||
#include "driver/pulse_cnt.h"
|
||||
|
||||
#define HIGHEST_LIMIT 10000
|
||||
#define LOWEST_LIMIT -10000
|
||||
|
||||
static pcnt_unit_handle_t pcnt_unit;
|
||||
static pcnt_channel_handle_t pcnt_chan;
|
||||
|
||||
static void setup_testbench(void)
|
||||
{
|
||||
pcnt_unit_config_t unit_config = {
|
||||
.high_limit = HIGHEST_LIMIT,
|
||||
.low_limit = LOWEST_LIMIT,
|
||||
};
|
||||
TEST_ESP_OK(pcnt_new_unit(&unit_config, &pcnt_unit));
|
||||
pcnt_chan_config_t chan_config = {
|
||||
.edge_gpio_num = PULSE_IO,
|
||||
.level_gpio_num = -1,
|
||||
};
|
||||
TEST_ESP_OK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit));
|
||||
}
|
||||
|
||||
static void tear_testbench(void)
|
||||
{
|
||||
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit));
|
||||
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
|
||||
TEST_ESP_OK(pcnt_del_unit(pcnt_unit));
|
||||
}
|
||||
|
||||
// use PCNT to test the waveform of LEDC
|
||||
static int wave_count(int last_time)
|
||||
{
|
||||
// The input ability of PULSE_IO is disabled after ledc driver install, so we need to re-enable it again
|
||||
gpio_ll_input_enable(&GPIO, PULSE_IO);
|
||||
int test_counter = 0;
|
||||
TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit));
|
||||
TEST_ESP_OK(pcnt_unit_start(pcnt_unit));
|
||||
vTaskDelay(pdMS_TO_TICKS(last_time));
|
||||
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
|
||||
TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &test_counter));
|
||||
return test_counter;
|
||||
}
|
||||
|
||||
// the PCNT will count the frequency of it
|
||||
static void frequency_set_get(ledc_mode_t speed_mode, ledc_timer_t timer, uint32_t desired_freq, int16_t theoretical_freq, int16_t error)
|
||||
{
|
||||
@ -731,8 +638,6 @@ static void ledc_cpu_reset_test_second_stage(void)
|
||||
int count;
|
||||
TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason());
|
||||
setup_testbench();
|
||||
// reconfigure the GPIO again, as the GPIO output ability has been disabled during initialize pcnt peripheral
|
||||
ledc_set_pin(PULSE_IO, TEST_SPEED_MODE, LEDC_CHANNEL_0);
|
||||
count = wave_count(1000);
|
||||
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, count);
|
||||
tear_testbench();
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "test_ledc_utils.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_private/sleep_cpu.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "soc/ledc_periph.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
|
||||
// Note. Test cases in this file cannot run one after another without reset
|
||||
|
||||
/**
|
||||
* @brief Test LEDC can still output PWM signal after light sleep
|
||||
*
|
||||
* @param allow_pd Whether to allow powering down the peripheral in light sleep
|
||||
*/
|
||||
static void test_ledc_sleep_retention(bool allow_pd)
|
||||
{
|
||||
int pulse_count __attribute__((unused)) = 0;
|
||||
|
||||
ledc_timer_config_t ledc_time_config = create_default_timer_config();
|
||||
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
|
||||
|
||||
ledc_channel_config_t ledc_ch_config = initialize_channel_config();
|
||||
ledc_ch_config.sleep_mode = (allow_pd ? LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD : LEDC_SLEEP_MODE_NO_ALIVE_NO_PD);
|
||||
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
|
||||
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
|
||||
#if SOC_PCNT_SUPPORTED
|
||||
setup_testbench();
|
||||
pulse_count = wave_count(1000);
|
||||
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, pulse_count);
|
||||
tear_testbench(); // tear down so that PCNT won't affect TOP PD
|
||||
#endif
|
||||
|
||||
esp_sleep_context_t sleep_ctx;
|
||||
esp_sleep_set_sleep_context(&sleep_ctx);
|
||||
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
TEST_ESP_OK(sleep_cpu_configure(true));
|
||||
#endif
|
||||
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000));
|
||||
|
||||
printf("go to light sleep for 2 seconds\n");
|
||||
TEST_ESP_OK(esp_light_sleep_start());
|
||||
printf("Waked up! Let's see if LEDC peripheral can still work...\n");
|
||||
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
TEST_ESP_OK(sleep_cpu_configure(false));
|
||||
#endif
|
||||
|
||||
printf("check if the sleep happened as expected\r\n");
|
||||
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
|
||||
#if SOC_PMU_SUPPORTED
|
||||
// check if the TOP power domain on/off as desired
|
||||
TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
|
||||
#endif
|
||||
esp_sleep_set_sleep_context(NULL);
|
||||
|
||||
if (allow_pd) {
|
||||
// check if the RO duty_r register field get synced back
|
||||
TEST_ASSERT_EQUAL(4000, ledc_get_duty(TEST_SPEED_MODE, LEDC_CHANNEL_0));
|
||||
}
|
||||
|
||||
#if SOC_PCNT_SUPPORTED
|
||||
setup_testbench();
|
||||
pulse_count = wave_count(1000);
|
||||
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, pulse_count);
|
||||
tear_testbench();
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("ledc can output after light sleep (LEDC power domain xpd)", "[ledc]")
|
||||
{
|
||||
test_ledc_sleep_retention(false);
|
||||
}
|
||||
|
||||
#if SOC_LEDC_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
TEST_CASE("ledc can output after light sleep (LEDC power domain pd)", "[ledc]")
|
||||
{
|
||||
// test retention feature
|
||||
test_ledc_sleep_retention(true);
|
||||
|
||||
// ledc driver does not have channel release, we will do retention release here to avoid memory leak
|
||||
sleep_retention_module_t module = ledc_reg_retention_info.module_id;
|
||||
sleep_retention_module_free(module);
|
||||
sleep_retention_module_deinit(module);
|
||||
}
|
||||
#endif
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "test_ledc_utils.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
ledc_channel_config_t initialize_channel_config(void)
|
||||
{
|
||||
ledc_channel_config_t config;
|
||||
memset(&config, 0, sizeof(ledc_channel_config_t));
|
||||
config.gpio_num = PULSE_IO;
|
||||
config.speed_mode = TEST_SPEED_MODE;
|
||||
config.channel = LEDC_CHANNEL_0;
|
||||
config.intr_type = LEDC_INTR_DISABLE;
|
||||
config.timer_sel = LEDC_TIMER_0;
|
||||
config.duty = 4000;
|
||||
config.hpoint = 0;
|
||||
return config;
|
||||
}
|
||||
|
||||
ledc_timer_config_t create_default_timer_config(void)
|
||||
{
|
||||
ledc_timer_config_t ledc_time_config;
|
||||
memset(&ledc_time_config, 0, sizeof(ledc_timer_config_t));
|
||||
ledc_time_config.speed_mode = TEST_SPEED_MODE;
|
||||
ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT;
|
||||
ledc_time_config.timer_num = LEDC_TIMER_0;
|
||||
ledc_time_config.freq_hz = TEST_PWM_FREQ;
|
||||
ledc_time_config.clk_cfg = TEST_DEFAULT_CLK_CFG;
|
||||
return ledc_time_config;
|
||||
}
|
||||
|
||||
// use PCNT to test the waveform of LEDC
|
||||
#if SOC_PCNT_SUPPORTED
|
||||
#include "driver/pulse_cnt.h"
|
||||
|
||||
#define HIGHEST_LIMIT 10000
|
||||
#define LOWEST_LIMIT -10000
|
||||
|
||||
static pcnt_unit_handle_t pcnt_unit;
|
||||
static pcnt_channel_handle_t pcnt_chan;
|
||||
|
||||
void setup_testbench(void)
|
||||
{
|
||||
pcnt_unit_config_t unit_config = {
|
||||
.high_limit = HIGHEST_LIMIT,
|
||||
.low_limit = LOWEST_LIMIT,
|
||||
};
|
||||
TEST_ESP_OK(pcnt_new_unit(&unit_config, &pcnt_unit));
|
||||
pcnt_chan_config_t chan_config = {
|
||||
.edge_gpio_num = PULSE_IO,
|
||||
.level_gpio_num = -1,
|
||||
};
|
||||
TEST_ESP_OK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit));
|
||||
}
|
||||
|
||||
void tear_testbench(void)
|
||||
{
|
||||
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit));
|
||||
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
|
||||
TEST_ESP_OK(pcnt_del_unit(pcnt_unit));
|
||||
}
|
||||
|
||||
int wave_count(int last_time)
|
||||
{
|
||||
int test_counter = 0;
|
||||
TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit));
|
||||
TEST_ESP_OK(pcnt_unit_start(pcnt_unit));
|
||||
vTaskDelay(pdMS_TO_TICKS(last_time));
|
||||
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
|
||||
TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &test_counter));
|
||||
return test_counter;
|
||||
}
|
||||
#endif
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "driver/ledc.h"
|
||||
|
||||
#define PULSE_IO 5
|
||||
|
||||
#define TEST_PWM_FREQ 2000
|
||||
|
||||
#if SOC_LEDC_SUPPORT_HS_MODE
|
||||
#define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE
|
||||
#define SPEED_MODE_LIST {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}
|
||||
#else
|
||||
#define TEST_SPEED_MODE LEDC_LOW_SPEED_MODE
|
||||
#define SPEED_MODE_LIST {LEDC_LOW_SPEED_MODE}
|
||||
#endif
|
||||
|
||||
#if SOC_LEDC_SUPPORT_APB_CLOCK
|
||||
#define TEST_DEFAULT_CLK_CFG LEDC_USE_APB_CLK
|
||||
#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
|
||||
#if SOC_CLK_TREE_SUPPORTED
|
||||
#define TEST_DEFAULT_CLK_CFG LEDC_USE_PLL_DIV_CLK
|
||||
#else
|
||||
#define TEST_DEFAULT_CLK_CFG LEDC_USE_XTAL_CLK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize a LEDC channel config structure
|
||||
*/
|
||||
ledc_channel_config_t initialize_channel_config(void);
|
||||
|
||||
/**
|
||||
* Initialize a LEDC timer config structure
|
||||
*/
|
||||
ledc_timer_config_t create_default_timer_config(void);
|
||||
|
||||
#if SOC_PCNT_SUPPORTED
|
||||
/**
|
||||
* Setup PCNT test bench
|
||||
*/
|
||||
void setup_testbench(void);
|
||||
|
||||
/**
|
||||
* Tear down PCNT test bench
|
||||
*/
|
||||
void tear_testbench(void);
|
||||
|
||||
/**
|
||||
* Use PCNT to count pulse
|
||||
*
|
||||
* @param last_time Duration time in ms
|
||||
* @return Pulse count
|
||||
*/
|
||||
int wave_count(int last_time);
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
CONFIG_PM_ENABLE=y
|
||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
|
@ -2,3 +2,5 @@ CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP_TASK_WDT_INIT=n
|
||||
# Disable memory protection, because "LEDC continue work after software reset" test case requires a cpu reset
|
||||
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
|
||||
# primitives for checking sleep internal state
|
||||
CONFIG_ESP_SLEEP_DEBUG=y
|
||||
|
@ -483,6 +483,10 @@ config SOC_LEDC_SUPPORT_HS_MODE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 8
|
||||
|
@ -241,6 +241,7 @@
|
||||
#define SOC_LEDC_SUPPORT_APB_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_REF_TICK (1)
|
||||
#define SOC_LEDC_SUPPORT_HS_MODE (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (8)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (20)
|
||||
|
||||
|
@ -383,6 +383,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 6
|
||||
|
@ -170,6 +170,7 @@
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (6)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (14)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
|
@ -527,6 +527,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 6
|
||||
|
@ -223,6 +223,7 @@
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_APB_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (6)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (14)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
|
@ -695,6 +695,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 6
|
||||
|
@ -40,6 +40,8 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_ETM0 = 17,
|
||||
SLEEP_RETENTION_MODULE_TEMP_SENSOR = 18,
|
||||
SLEEP_RETENTION_MODULE_PARLIO0 = 19,
|
||||
SLEEP_RETENTION_MODULE_GPSPI2 = 20,
|
||||
SLEEP_RETENTION_MODULE_LEDC = 21,
|
||||
|
||||
/* modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
|
||||
@ -82,6 +84,8 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
|
||||
SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR),
|
||||
SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2),
|
||||
SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC),
|
||||
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0),
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1),
|
||||
@ -106,6 +110,8 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_ETM0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \
|
||||
| SLEEP_RETENTION_MODULE_BM_PARLIO0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_LEDC \
|
||||
)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -294,6 +294,7 @@
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (6)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (20)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
|
@ -15,3 +15,7 @@ const ledc_signal_conn_t ledc_periph_signal[1] = {
|
||||
.sig_out0_idx = LEDC_LS_SIG_OUT0_IDX,
|
||||
}
|
||||
};
|
||||
|
||||
const ledc_reg_retention_info_t ledc_reg_retention_info = {
|
||||
.module_id = SLEEP_RETENTION_MODULE_LEDC,
|
||||
};
|
||||
|
@ -687,6 +687,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 6
|
||||
@ -711,6 +715,10 @@ config SOC_LEDC_FADE_PARAMS_BIT_WIDTH
|
||||
int
|
||||
default 10
|
||||
|
||||
config SOC_LEDC_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MMU_PAGE_SIZE_CONFIGURABLE
|
||||
bool
|
||||
default y
|
||||
|
@ -42,6 +42,8 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_TWAI0 = 19,
|
||||
SLEEP_RETENTION_MODULE_TWAI1 = 20,
|
||||
SLEEP_RETENTION_MODULE_PARLIO0 = 21,
|
||||
SLEEP_RETENTION_MODULE_GPSPI2 = 22,
|
||||
SLEEP_RETENTION_MODULE_LEDC = 23,
|
||||
|
||||
/* Modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
|
||||
@ -80,6 +82,8 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0),
|
||||
SLEEP_RETENTION_MODULE_BM_TWAI1 = BIT(SLEEP_RETENTION_MODULE_TWAI1),
|
||||
SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2),
|
||||
SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC),
|
||||
/* modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC),
|
||||
SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB),
|
||||
@ -108,6 +112,8 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_TWAI0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_TWAI1 \
|
||||
| SLEEP_RETENTION_MODULE_BM_PARLIO0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_LEDC \
|
||||
)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -279,12 +279,14 @@
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (6)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (20)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
#define SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED (1)
|
||||
#define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16)
|
||||
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
|
||||
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
|
||||
|
||||
/*-------------------------- MMU CAPS ----------------------------------------*/
|
||||
#define SOC_MMU_PAGE_SIZE_CONFIGURABLE (1)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -15,3 +15,139 @@ const ledc_signal_conn_t ledc_periph_signal[1] = {
|
||||
.sig_out0_idx = LEDC_LS_SIG_OUT0_IDX,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* LEDC registers to be saved for sleep retention
|
||||
*
|
||||
* channel:
|
||||
* LEDC_CHx_CONF0_REG, LEDC_CHx_HPOINT_REG, LEDC_CHx_DUTY_R_REG -> LEDC_CHx_DUTY_REG,
|
||||
*
|
||||
* timer:
|
||||
* LEDC_TIMERn_CONF_REG, LEDC_TIMERn_CMP_REG,
|
||||
*
|
||||
* common:
|
||||
* LEDC_INT_ENA_REG,
|
||||
* LEDC_EVT_TASK_EN0_REG, LEDC_EVT_TASK_EN1_REG, LEDC_EVT_TASK_EN2_REG,
|
||||
* LEDC_CONF_REG,
|
||||
*
|
||||
* Note 1: Gamma feature is hard to do hardware retention, will consider to use software to do the backup and restore.
|
||||
* We won't start a fade automatically after wake-up.
|
||||
* Instead, we will only start a PWM with a constant duty cycle, the same value as before entering the sleep.
|
||||
*
|
||||
* Note 2: For timer/channel registers to get synced, update bits need to be set
|
||||
*/
|
||||
#define LEDC_COMMON_RETENTION_REGS_CNT 5
|
||||
#define LEDC_COMMON_RETENTION_REGS_BASE (DR_REG_LEDC_BASE + 0xc8)
|
||||
static const uint32_t ledc_common_regs_map[4] = {0x1, 0x1c00000, 0x400, 0x0};
|
||||
static const regdma_entries_config_t ledc_common_regdma_entries[] = {
|
||||
// If a fade is in process, the DUTY_CHNG_END_CHx intr bit is enabled, however, we don't want it to be restored after wake-up (no fade after wake-up).
|
||||
// Therefore, we can set it to 0 before backup the LEDC_INT_ENA_REG.
|
||||
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x00),
|
||||
LEDC_INT_ENA_REG, 0,
|
||||
(LEDC_DUTY_CHNG_END_CH0_INT_ENA_M | LEDC_DUTY_CHNG_END_CH1_INT_ENA_M | LEDC_DUTY_CHNG_END_CH2_INT_ENA_M | LEDC_DUTY_CHNG_END_CH3_INT_ENA_M | LEDC_DUTY_CHNG_END_CH4_INT_ENA_M | LEDC_DUTY_CHNG_END_CH5_INT_ENA_M), 0, 1),
|
||||
.owner = LEDC_RETENTION_ENTRY },
|
||||
[1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x01),
|
||||
LEDC_COMMON_RETENTION_REGS_BASE, LEDC_COMMON_RETENTION_REGS_BASE,
|
||||
LEDC_COMMON_RETENTION_REGS_CNT, 0, 0,
|
||||
ledc_common_regs_map[0], ledc_common_regs_map[1],
|
||||
ledc_common_regs_map[2], ledc_common_regs_map[3]),
|
||||
.owner = LEDC_RETENTION_ENTRY },
|
||||
};
|
||||
|
||||
#define LEDC_TIMER_RETENTION_ENTRIES(timer) { \
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x00), \
|
||||
LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_CONF_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \
|
||||
LEDC_TIMER##timer##_CMP_REG, LEDC_TIMER##timer##_CMP_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \
|
||||
LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_PARA_UP, \
|
||||
LEDC_TIMER##timer##_PARA_UP_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
}
|
||||
|
||||
#define LEDC_CHANNEL_RETENTION_REGS_CNT 2
|
||||
static const uint32_t ledc_channel_regs_map[4] = {0x3, 0x0, 0x0, 0x0};
|
||||
#define LEDC_CHANNEL_RETENTION_ENTRIES(chan) { \
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x00), \
|
||||
LEDC_CH##chan##_CONF0_REG, LEDC_CH##chan##_CONF0_REG, \
|
||||
LEDC_CHANNEL_RETENTION_REGS_CNT, 0, 0, \
|
||||
ledc_channel_regs_map[0], ledc_channel_regs_map[1], \
|
||||
ledc_channel_regs_map[2], ledc_channel_regs_map[3]), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \
|
||||
LEDC_CH##chan##_DUTY_R_REG, LEDC_CH##chan##_DUTY_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \
|
||||
LEDC_CH##chan##_CONF1_REG, LEDC_DUTY_START_CH##chan, \
|
||||
LEDC_DUTY_START_CH##chan##_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x03), \
|
||||
LEDC_CH##chan##_CONF0_REG, LEDC_PARA_UP_CH##chan, \
|
||||
LEDC_PARA_UP_CH##chan##_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
}
|
||||
|
||||
static const regdma_entries_config_t ledc_timer0_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(0);
|
||||
static const regdma_entries_config_t ledc_timer1_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(1);
|
||||
static const regdma_entries_config_t ledc_timer2_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(2);
|
||||
static const regdma_entries_config_t ledc_timer3_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(3);
|
||||
|
||||
static const regdma_entries_config_t ledc_channel0_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(0);
|
||||
static const regdma_entries_config_t ledc_channel1_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(1);
|
||||
static const regdma_entries_config_t ledc_channel2_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(2);
|
||||
static const regdma_entries_config_t ledc_channel3_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(3);
|
||||
static const regdma_entries_config_t ledc_channel4_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(4);
|
||||
static const regdma_entries_config_t ledc_channel5_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(5);
|
||||
|
||||
const ledc_reg_retention_info_t ledc_reg_retention_info = {
|
||||
.common = {
|
||||
.regdma_entry_array = ledc_common_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_common_regdma_entries),
|
||||
},
|
||||
.timer[0] = {
|
||||
.regdma_entry_array = ledc_timer0_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer0_regdma_entries),
|
||||
},
|
||||
.timer[1] = {
|
||||
.regdma_entry_array = ledc_timer1_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer1_regdma_entries),
|
||||
},
|
||||
.timer[2] = {
|
||||
.regdma_entry_array = ledc_timer2_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer2_regdma_entries),
|
||||
},
|
||||
.timer[3] = {
|
||||
.regdma_entry_array = ledc_timer3_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer3_regdma_entries),
|
||||
},
|
||||
.channel[0] = {
|
||||
.regdma_entry_array = ledc_channel0_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel0_regdma_entries),
|
||||
},
|
||||
.channel[1] = {
|
||||
.regdma_entry_array = ledc_channel1_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel1_regdma_entries),
|
||||
},
|
||||
.channel[2] = {
|
||||
.regdma_entry_array = ledc_channel2_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel2_regdma_entries),
|
||||
},
|
||||
.channel[3] = {
|
||||
.regdma_entry_array = ledc_channel3_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel3_regdma_entries),
|
||||
},
|
||||
.channel[4] = {
|
||||
.regdma_entry_array = ledc_channel4_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel4_regdma_entries),
|
||||
},
|
||||
.channel[5] = {
|
||||
.regdma_entry_array = ledc_channel5_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel5_regdma_entries),
|
||||
},
|
||||
.module_id = SLEEP_RETENTION_MODULE_LEDC,
|
||||
};
|
||||
|
@ -451,6 +451,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 6
|
||||
|
@ -34,6 +34,8 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_UART0 = 14,
|
||||
SLEEP_RETENTION_MODULE_UART1 = 15,
|
||||
SLEEP_RETENTION_MODULE_ETM0 = 16,
|
||||
SLEEP_RETENTION_MODULE_GPSPI2 = 17,
|
||||
SLEEP_RETENTION_MODULE_LEDC = 18,
|
||||
|
||||
/* Modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
|
||||
@ -64,6 +66,8 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
|
||||
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
|
||||
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2),
|
||||
SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC),
|
||||
/* modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC),
|
||||
SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB),
|
||||
@ -84,6 +88,8 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_UART0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_UART1 \
|
||||
| SLEEP_RETENTION_MODULE_BM_ETM0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_LEDC \
|
||||
)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -245,6 +245,7 @@
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (6)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (20)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
|
@ -15,3 +15,7 @@ const ledc_signal_conn_t ledc_periph_signal[1] = {
|
||||
.sig_out0_idx = LEDC_LS_SIG_OUT0_IDX,
|
||||
}
|
||||
};
|
||||
|
||||
const ledc_reg_retention_info_t ledc_reg_retention_info = {
|
||||
.module_id = SLEEP_RETENTION_MODULE_LEDC,
|
||||
};
|
||||
|
@ -691,6 +691,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 6
|
||||
@ -715,6 +719,10 @@ config SOC_LEDC_FADE_PARAMS_BIT_WIDTH
|
||||
int
|
||||
default 10
|
||||
|
||||
config SOC_LEDC_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
|
||||
bool
|
||||
default n
|
||||
|
@ -42,6 +42,8 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_TEMP_SENSOR = 19,
|
||||
SLEEP_RETENTION_MODULE_TWAI0 = 20,
|
||||
SLEEP_RETENTION_MODULE_PARLIO0 = 21,
|
||||
SLEEP_RETENTION_MODULE_GPSPI2 = 22,
|
||||
SLEEP_RETENTION_MODULE_LEDC = 23,
|
||||
|
||||
/* Modem module, which includes BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BLE_MAC = 28,
|
||||
@ -78,6 +80,8 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR),
|
||||
SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0),
|
||||
SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2),
|
||||
SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC),
|
||||
/* modem module, which includes BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC),
|
||||
SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB),
|
||||
@ -104,6 +108,8 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \
|
||||
| SLEEP_RETENTION_MODULE_BM_TWAI0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_PARLIO0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_LEDC \
|
||||
)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -280,12 +280,14 @@
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (6)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (20)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
#define SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED (1)
|
||||
#define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16)
|
||||
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
|
||||
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
|
||||
|
||||
/*-------------------------- MPU CAPS ----------------------------------------*/
|
||||
#define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED 0
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -15,3 +15,139 @@ const ledc_signal_conn_t ledc_periph_signal[1] = {
|
||||
.sig_out0_idx = LEDC_LS_SIG_OUT0_IDX,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* LEDC registers to be saved for sleep retention
|
||||
*
|
||||
* channel:
|
||||
* LEDC_CHx_CONF0_REG, LEDC_CHx_HPOINT_REG, LEDC_CHx_DUTY_R_REG -> LEDC_CHx_DUTY_REG,
|
||||
*
|
||||
* timer:
|
||||
* LEDC_TIMERn_CONF_REG, LEDC_TIMERn_CMP_REG,
|
||||
*
|
||||
* common:
|
||||
* LEDC_INT_ENA_REG,
|
||||
* LEDC_EVT_TASK_EN0_REG, LEDC_EVT_TASK_EN1_REG, LEDC_EVT_TASK_EN2_REG,
|
||||
* LEDC_CONF_REG,
|
||||
*
|
||||
* Note 1: Gamma feature is hard to do hardware retention, will consider to use software to do the backup and restore.
|
||||
* We won't start a fade automatically after wake-up.
|
||||
* Instead, we will only start a PWM with a constant duty cycle, the same value as before entering the sleep.
|
||||
*
|
||||
* Note 2: For timer/channel registers to get synced, update bits need to be set
|
||||
*/
|
||||
#define LEDC_COMMON_RETENTION_REGS_CNT 5
|
||||
#define LEDC_COMMON_RETENTION_REGS_BASE (DR_REG_LEDC_BASE + 0xc8)
|
||||
static const uint32_t ledc_common_regs_map[4] = {0x1, 0x1c00000, 0x400, 0x0};
|
||||
static const regdma_entries_config_t ledc_common_regdma_entries[] = {
|
||||
// If a fade is in process, the DUTY_CHNG_END_CHx intr bit is enabled, however, we don't want it to be restored after wake-up (no fade after wake-up).
|
||||
// Therefore, we can set it to 0 before backup the LEDC_INT_ENA_REG.
|
||||
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x00),
|
||||
LEDC_INT_ENA_REG, 0,
|
||||
(LEDC_DUTY_CHNG_END_CH0_INT_ENA_M | LEDC_DUTY_CHNG_END_CH1_INT_ENA_M | LEDC_DUTY_CHNG_END_CH2_INT_ENA_M | LEDC_DUTY_CHNG_END_CH3_INT_ENA_M | LEDC_DUTY_CHNG_END_CH4_INT_ENA_M | LEDC_DUTY_CHNG_END_CH5_INT_ENA_M), 0, 1),
|
||||
.owner = LEDC_RETENTION_ENTRY },
|
||||
[1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x01),
|
||||
LEDC_COMMON_RETENTION_REGS_BASE, LEDC_COMMON_RETENTION_REGS_BASE,
|
||||
LEDC_COMMON_RETENTION_REGS_CNT, 0, 0,
|
||||
ledc_common_regs_map[0], ledc_common_regs_map[1],
|
||||
ledc_common_regs_map[2], ledc_common_regs_map[3]),
|
||||
.owner = LEDC_RETENTION_ENTRY },
|
||||
};
|
||||
|
||||
#define LEDC_TIMER_RETENTION_ENTRIES(timer) { \
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x00), \
|
||||
LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_CONF_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \
|
||||
LEDC_TIMER##timer##_CMP_REG, LEDC_TIMER##timer##_CMP_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \
|
||||
LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_PARA_UP, \
|
||||
LEDC_TIMER##timer##_PARA_UP_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
}
|
||||
|
||||
#define LEDC_CHANNEL_RETENTION_REGS_CNT 2
|
||||
static const uint32_t ledc_channel_regs_map[4] = {0x3, 0x0, 0x0, 0x0};
|
||||
#define LEDC_CHANNEL_RETENTION_ENTRIES(chan) { \
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x00), \
|
||||
LEDC_CH##chan##_CONF0_REG, LEDC_CH##chan##_CONF0_REG, \
|
||||
LEDC_CHANNEL_RETENTION_REGS_CNT, 0, 0, \
|
||||
ledc_channel_regs_map[0], ledc_channel_regs_map[1], \
|
||||
ledc_channel_regs_map[2], ledc_channel_regs_map[3]), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \
|
||||
LEDC_CH##chan##_DUTY_R_REG, LEDC_CH##chan##_DUTY_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \
|
||||
LEDC_CH##chan##_CONF1_REG, LEDC_DUTY_START_CH##chan, \
|
||||
LEDC_DUTY_START_CH##chan##_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x03), \
|
||||
LEDC_CH##chan##_CONF0_REG, LEDC_PARA_UP_CH##chan, \
|
||||
LEDC_PARA_UP_CH##chan##_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
}
|
||||
|
||||
static const regdma_entries_config_t ledc_timer0_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(0);
|
||||
static const regdma_entries_config_t ledc_timer1_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(1);
|
||||
static const regdma_entries_config_t ledc_timer2_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(2);
|
||||
static const regdma_entries_config_t ledc_timer3_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(3);
|
||||
|
||||
static const regdma_entries_config_t ledc_channel0_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(0);
|
||||
static const regdma_entries_config_t ledc_channel1_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(1);
|
||||
static const regdma_entries_config_t ledc_channel2_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(2);
|
||||
static const regdma_entries_config_t ledc_channel3_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(3);
|
||||
static const regdma_entries_config_t ledc_channel4_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(4);
|
||||
static const regdma_entries_config_t ledc_channel5_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(5);
|
||||
|
||||
const ledc_reg_retention_info_t ledc_reg_retention_info = {
|
||||
.common = {
|
||||
.regdma_entry_array = ledc_common_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_common_regdma_entries),
|
||||
},
|
||||
.timer[0] = {
|
||||
.regdma_entry_array = ledc_timer0_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer0_regdma_entries),
|
||||
},
|
||||
.timer[1] = {
|
||||
.regdma_entry_array = ledc_timer1_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer1_regdma_entries),
|
||||
},
|
||||
.timer[2] = {
|
||||
.regdma_entry_array = ledc_timer2_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer2_regdma_entries),
|
||||
},
|
||||
.timer[3] = {
|
||||
.regdma_entry_array = ledc_timer3_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer3_regdma_entries),
|
||||
},
|
||||
.channel[0] = {
|
||||
.regdma_entry_array = ledc_channel0_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel0_regdma_entries),
|
||||
},
|
||||
.channel[1] = {
|
||||
.regdma_entry_array = ledc_channel1_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel1_regdma_entries),
|
||||
},
|
||||
.channel[2] = {
|
||||
.regdma_entry_array = ledc_channel2_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel2_regdma_entries),
|
||||
},
|
||||
.channel[3] = {
|
||||
.regdma_entry_array = ledc_channel3_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel3_regdma_entries),
|
||||
},
|
||||
.channel[4] = {
|
||||
.regdma_entry_array = ledc_channel4_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel4_regdma_entries),
|
||||
},
|
||||
.channel[5] = {
|
||||
.regdma_entry_array = ledc_channel5_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel5_regdma_entries),
|
||||
},
|
||||
.module_id = SLEEP_RETENTION_MODULE_LEDC,
|
||||
};
|
||||
|
@ -1023,6 +1023,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 8
|
||||
@ -1047,6 +1051,10 @@ config SOC_LEDC_FADE_PARAMS_BIT_WIDTH
|
||||
int
|
||||
default 10
|
||||
|
||||
config SOC_LEDC_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MMU_PERIPH_NUM
|
||||
int
|
||||
default 2
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// TODO: IDF-5731
|
||||
|
||||
#define PMU_ICG_APB_ENA_CORE0_CPU 0
|
||||
#define PMU_ICG_APB_ENA_CORE1_CPU 1
|
||||
#define PMU_ICG_APB_ENA_CORE0_CLIC 2
|
||||
|
@ -50,6 +50,9 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_TWAI1 = 26,
|
||||
SLEEP_RETENTION_MODULE_TWAI2 = 27,
|
||||
SLEEP_RETENTION_MODULE_PARLIO0 = 28,
|
||||
SLEEP_RETENTION_MODULE_GPSPI2 = 29,
|
||||
SLEEP_RETENTION_MODULE_GPSPI3 = 30,
|
||||
SLEEP_RETENTION_MODULE_LEDC = 31,
|
||||
|
||||
SLEEP_RETENTION_MODULE_MAX = 31
|
||||
} periph_retention_module_t;
|
||||
@ -90,6 +93,9 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_TWAI1 = BIT(SLEEP_RETENTION_MODULE_TWAI1),
|
||||
SLEEP_RETENTION_MODULE_BM_TWAI2 = BIT(SLEEP_RETENTION_MODULE_TWAI2),
|
||||
SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI3 = BIT(SLEEP_RETENTION_MODULE_GPSPI3),
|
||||
SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC),
|
||||
|
||||
SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1
|
||||
} periph_retention_module_bitmap_t;
|
||||
@ -121,6 +127,9 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_TWAI1 \
|
||||
| SLEEP_RETENTION_MODULE_BM_TWAI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_PARLIO0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI3 \
|
||||
| SLEEP_RETENTION_MODULE_BM_LEDC \
|
||||
)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -379,12 +379,14 @@
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (8)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (20)
|
||||
#define SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED (1)
|
||||
#define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
|
||||
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
|
||||
|
||||
/*-------------------------- MMU CAPS ----------------------------------------*/
|
||||
#define SOC_MMU_PERIPH_NUM (2U)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -15,3 +15,160 @@ const ledc_signal_conn_t ledc_periph_signal[1] = {
|
||||
.sig_out0_idx = LEDC_LS_SIG_OUT_PAD_OUT0_IDX,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* LEDC registers to be saved for sleep retention
|
||||
*
|
||||
* channel:
|
||||
* LEDC_CHx_CONF0_REG, LEDC_CHx_HPOINT_REG, LEDC_CHx_DUTY_R_REG -> LEDC_CHx_DUTY_REG,
|
||||
* LEDC_CHx_GAMMA_CONF_REG, LEDC_CHx_GAMMA_RANGEi_REG
|
||||
*
|
||||
* timer:
|
||||
* LEDC_TIMERn_CONF_REG, LEDC_TIMERn_CMP_REG,
|
||||
*
|
||||
* common:
|
||||
* LEDC_INT_ENA_REG,
|
||||
* LEDC_EVT_TASK_EN0_REG, LEDC_EVT_TASK_EN1_REG, LEDC_EVT_TASK_EN2_REG,
|
||||
* LEDC_CONF_REG,
|
||||
*
|
||||
* Note 1: Gamma parameter registers are backuped and restored. But we won't start a fade automatically after wake-up.
|
||||
* Instead, we will only start a PWM with a constant duty cycle, the same value as before entering the sleep.
|
||||
*
|
||||
* Note 2: For timer/channel registers to get synced, update bits need to be set
|
||||
*/
|
||||
#define LEDC_COMMON_RETENTION_REGS_CNT 5
|
||||
#define LEDC_COMMON_RETENTION_REGS_BASE (DR_REG_LEDC_BASE + 0xc8)
|
||||
static const uint32_t ledc_common_regs_map[4] = {0x1c00001, 0x400, 0x0, 0x0};
|
||||
static const regdma_entries_config_t ledc_common_regdma_entries[] = {
|
||||
// If a fade is in process, the DUTY_CHNG_END_CHx intr bit is enabled, however, we don't want it to be restored after wake-up (no fade after wake-up).
|
||||
// Therefore, we can set it to 0 before backup the LEDC_INT_ENA_REG.
|
||||
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x00),
|
||||
LEDC_INT_ENA_REG, 0,
|
||||
(LEDC_DUTY_CHNG_END_CH0_INT_ENA_M | LEDC_DUTY_CHNG_END_CH1_INT_ENA_M | LEDC_DUTY_CHNG_END_CH2_INT_ENA_M | LEDC_DUTY_CHNG_END_CH3_INT_ENA_M | LEDC_DUTY_CHNG_END_CH4_INT_ENA_M | LEDC_DUTY_CHNG_END_CH5_INT_ENA_M | LEDC_DUTY_CHNG_END_CH6_INT_ENA_M | LEDC_DUTY_CHNG_END_CH7_INT_ENA_M), 0, 1),
|
||||
.owner = LEDC_RETENTION_ENTRY },
|
||||
[1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x01),
|
||||
LEDC_COMMON_RETENTION_REGS_BASE, LEDC_COMMON_RETENTION_REGS_BASE,
|
||||
LEDC_COMMON_RETENTION_REGS_CNT, 0, 0,
|
||||
ledc_common_regs_map[0], ledc_common_regs_map[1],
|
||||
ledc_common_regs_map[2], ledc_common_regs_map[3]),
|
||||
.owner = LEDC_RETENTION_ENTRY },
|
||||
};
|
||||
|
||||
#define LEDC_TIMER_RETENTION_ENTRIES(timer) { \
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x00), \
|
||||
LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_CONF_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \
|
||||
LEDC_TIMER##timer##_CMP_REG, LEDC_TIMER##timer##_CMP_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \
|
||||
LEDC_TIMER##timer##_CONF_REG, LEDC_TIMER##timer##_PARA_UP, \
|
||||
LEDC_TIMER##timer##_PARA_UP_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
}
|
||||
|
||||
#define LEDC_CHANNEL_RETENTION_REGS_CNT 2
|
||||
static const uint32_t ledc_channel_regs_map[4] = {0x3, 0x0, 0x0, 0x0};
|
||||
static const uint32_t ledc_channel_gamma_regs_map[4] = {0xffff, 0x0, 0x0, 0x0};
|
||||
#define LEDC_CHANNEL_RETENTION_ENTRIES(chan) { \
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x00), \
|
||||
LEDC_CH##chan##_CONF0_REG, LEDC_CH##chan##_CONF0_REG, \
|
||||
LEDC_CHANNEL_RETENTION_REGS_CNT, 0, 0, \
|
||||
ledc_channel_regs_map[0], ledc_channel_regs_map[1], \
|
||||
ledc_channel_regs_map[2], ledc_channel_regs_map[3]), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x01), \
|
||||
LEDC_CH##chan##_DUTY_R_REG, LEDC_CH##chan##_DUTY_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x02), \
|
||||
LEDC_CH##chan##_CONF1_REG, LEDC_DUTY_START_CH##chan, \
|
||||
LEDC_DUTY_START_CH##chan##_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_LEDC_LINK(0x03), \
|
||||
LEDC_CH##chan##_CONF0_REG, LEDC_PARA_UP_CH##chan, \
|
||||
LEDC_PARA_UP_CH##chan##_M, 1, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_LEDC_LINK(0x04), \
|
||||
LEDC_CH##chan##_GAMMA_CONF_REG, LEDC_CH##chan##_GAMMA_CONF_REG, \
|
||||
1, 0, 0), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
[5] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LEDC_LINK(0x05), \
|
||||
LEDC_CH##chan##_GAMMA_RANGE0_REG, LEDC_CH##chan##_GAMMA_RANGE0_REG, \
|
||||
SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX, 0, 0, \
|
||||
ledc_channel_gamma_regs_map[0], ledc_channel_gamma_regs_map[1], \
|
||||
ledc_channel_gamma_regs_map[2], ledc_channel_gamma_regs_map[3]), \
|
||||
.owner = LEDC_RETENTION_ENTRY }, \
|
||||
}
|
||||
|
||||
static const regdma_entries_config_t ledc_timer0_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(0);
|
||||
static const regdma_entries_config_t ledc_timer1_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(1);
|
||||
static const regdma_entries_config_t ledc_timer2_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(2);
|
||||
static const regdma_entries_config_t ledc_timer3_regdma_entries[] = LEDC_TIMER_RETENTION_ENTRIES(3);
|
||||
|
||||
static const regdma_entries_config_t ledc_channel0_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(0);
|
||||
static const regdma_entries_config_t ledc_channel1_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(1);
|
||||
static const regdma_entries_config_t ledc_channel2_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(2);
|
||||
static const regdma_entries_config_t ledc_channel3_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(3);
|
||||
static const regdma_entries_config_t ledc_channel4_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(4);
|
||||
static const regdma_entries_config_t ledc_channel5_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(5);
|
||||
static const regdma_entries_config_t ledc_channel6_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(6);
|
||||
static const regdma_entries_config_t ledc_channel7_regdma_entries[] = LEDC_CHANNEL_RETENTION_ENTRIES(7);
|
||||
|
||||
const ledc_reg_retention_info_t ledc_reg_retention_info = {
|
||||
.common = {
|
||||
.regdma_entry_array = ledc_common_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_common_regdma_entries),
|
||||
},
|
||||
.timer[0] = {
|
||||
.regdma_entry_array = ledc_timer0_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer0_regdma_entries),
|
||||
},
|
||||
.timer[1] = {
|
||||
.regdma_entry_array = ledc_timer1_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer1_regdma_entries),
|
||||
},
|
||||
.timer[2] = {
|
||||
.regdma_entry_array = ledc_timer2_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer2_regdma_entries),
|
||||
},
|
||||
.timer[3] = {
|
||||
.regdma_entry_array = ledc_timer3_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_timer3_regdma_entries),
|
||||
},
|
||||
.channel[0] = {
|
||||
.regdma_entry_array = ledc_channel0_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel0_regdma_entries),
|
||||
},
|
||||
.channel[1] = {
|
||||
.regdma_entry_array = ledc_channel1_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel1_regdma_entries),
|
||||
},
|
||||
.channel[2] = {
|
||||
.regdma_entry_array = ledc_channel2_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel2_regdma_entries),
|
||||
},
|
||||
.channel[3] = {
|
||||
.regdma_entry_array = ledc_channel3_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel3_regdma_entries),
|
||||
},
|
||||
.channel[4] = {
|
||||
.regdma_entry_array = ledc_channel4_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel4_regdma_entries),
|
||||
},
|
||||
.channel[5] = {
|
||||
.regdma_entry_array = ledc_channel5_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel5_regdma_entries),
|
||||
},
|
||||
.channel[6] = {
|
||||
.regdma_entry_array = ledc_channel6_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel6_regdma_entries),
|
||||
},
|
||||
.channel[7] = {
|
||||
.regdma_entry_array = ledc_channel7_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(ledc_channel7_regdma_entries),
|
||||
},
|
||||
.module_id = SLEEP_RETENTION_MODULE_LEDC,
|
||||
};
|
||||
|
@ -535,6 +535,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 8
|
||||
|
@ -233,6 +233,7 @@
|
||||
#define SOC_LEDC_SUPPORT_APB_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_REF_TICK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (8)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (14)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
|
@ -603,6 +603,10 @@ config SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_TIMER_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_LEDC_CHANNEL_NUM
|
||||
int
|
||||
default 8
|
||||
|
@ -236,6 +236,7 @@
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_APB_CLOCK (1)
|
||||
#define SOC_LEDC_SUPPORT_XTAL_CLOCK (1)
|
||||
#define SOC_LEDC_TIMER_NUM (4)
|
||||
#define SOC_LEDC_CHANNEL_NUM (8)
|
||||
#define SOC_LEDC_TIMER_BIT_WIDTH (14)
|
||||
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
|
||||
|
@ -1,21 +1,18 @@
|
||||
// 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-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/ledc_reg.h"
|
||||
#include "soc/ledc_struct.h"
|
||||
#if SOC_PAU_SUPPORTED
|
||||
#include "soc/regdma.h"
|
||||
#include "soc/retention_periph_defs.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -34,6 +31,33 @@ extern const ledc_signal_conn_t ledc_periph_signal[2];
|
||||
extern const ledc_signal_conn_t ledc_periph_signal[1];
|
||||
#endif
|
||||
|
||||
#if SOC_PAU_SUPPORTED
|
||||
|
||||
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||
#if SOC_PHY_SUPPORTED
|
||||
#define LEDC_RETENTION_ENTRY (ENTRY(0) | ENTRY(2))
|
||||
#else
|
||||
#define LEDC_RETENTION_ENTRY (ENTRY(0))
|
||||
#endif
|
||||
#else // !SOC_LIGHT_SLEEP_SUPPORTED
|
||||
#define LEDC_RETENTION_ENTRY REGDMA_SW_TRIGGER_ENTRY
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const regdma_entries_config_t *regdma_entry_array;
|
||||
uint32_t array_size;
|
||||
} ledc_sub_reg_retention_info_t;
|
||||
|
||||
typedef struct {
|
||||
ledc_sub_reg_retention_info_t common;
|
||||
ledc_sub_reg_retention_info_t timer[SOC_LEDC_TIMER_NUM];
|
||||
ledc_sub_reg_retention_info_t channel[SOC_LEDC_CHANNEL_NUM];
|
||||
const periph_retention_module_t module_id;
|
||||
} ledc_reg_retention_info_t;
|
||||
|
||||
extern const ledc_reg_retention_info_t ledc_reg_retention_info;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -58,6 +58,8 @@ extern "C" {
|
||||
#define REGDMA_TSENS_LINK(_pri) ((0x20 << 8) | _pri)
|
||||
#define REGDMA_TWAI_LINK(_pri) ((0x21 << 8) | _pri)
|
||||
#define REGDMA_PARLIO_LINK(_pri) ((0x22 << 8) | _pri)
|
||||
#define REGDMA_GPSPI_LINK(_pri) ((0x23 << 8) | _pri)
|
||||
#define REGDMA_LEDC_LINK(_pri) ((0x24 << 8) | _pri)
|
||||
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
|
||||
|
||||
#define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0
|
||||
@ -80,6 +82,8 @@ extern "C" {
|
||||
#define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_TEMPERATURE_SENSOR REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_TWAI REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_GPSPI REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_LEDC REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
|
||||
typedef enum {
|
||||
REGDMA_LINK_PRI_0 = 0,
|
||||
|
@ -88,7 +88,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f
|
||||
* - RC_FAST_CLK
|
||||
- ~ 8 MHz
|
||||
- Low
|
||||
- Dynamic Frequency Scaling compatible, Light sleep compatible
|
||||
- Dynamic Frequency Scaling compatible, Light-sleep compatible
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
@ -107,7 +107,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f
|
||||
- Dynamic Frequency Scaling compatible
|
||||
* - RC_FAST_CLK
|
||||
- ~ 8 MHz
|
||||
- Dynamic Frequency Scaling compatible, Light sleep compatible
|
||||
- Dynamic Frequency Scaling compatible, Light-sleep compatible
|
||||
* - XTAL_CLK
|
||||
- 40 MHz
|
||||
- Dynamic Frequency Scaling compatible
|
||||
@ -126,7 +126,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f
|
||||
- /
|
||||
* - RC_FAST_CLK
|
||||
- ~ 20 MHz
|
||||
- Dynamic Frequency Scaling compatible, Light sleep compatible
|
||||
- Dynamic Frequency Scaling compatible, Light-sleep compatible
|
||||
* - XTAL_CLK
|
||||
- 40 MHz
|
||||
- Dynamic Frequency Scaling compatible
|
||||
@ -145,7 +145,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f
|
||||
- /
|
||||
* - RC_FAST_CLK
|
||||
- ~ 20 MHz
|
||||
- Dynamic Frequency Scaling compatible, Light sleep compatible
|
||||
- Dynamic Frequency Scaling compatible, Light-sleep compatible
|
||||
* - XTAL_CLK
|
||||
- 40/26 MHz
|
||||
- Dynamic Frequency Scaling compatible
|
||||
@ -164,7 +164,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f
|
||||
- /
|
||||
* - RC_FAST_CLK
|
||||
- ~ 17.5 MHz
|
||||
- Dynamic Frequency Scaling compatible, Light sleep compatible
|
||||
- Dynamic Frequency Scaling compatible, Light-sleep compatible
|
||||
* - XTAL_CLK
|
||||
- 48 MHz
|
||||
- Dynamic Frequency Scaling compatible
|
||||
@ -183,7 +183,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f
|
||||
- /
|
||||
* - RC_FAST_CLK
|
||||
- ~ 17.5 MHz
|
||||
- Dynamic Frequency Scaling compatible, Light sleep compatible
|
||||
- Dynamic Frequency Scaling compatible, Light-sleep compatible
|
||||
* - XTAL_CLK
|
||||
- 40 MHz
|
||||
- Dynamic Frequency Scaling compatible
|
||||
@ -202,7 +202,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f
|
||||
- /
|
||||
* - RC_FAST_CLK
|
||||
- ~ 8 MHz
|
||||
- Dynamic Frequency Scaling compatible, Light sleep compatible
|
||||
- Dynamic Frequency Scaling compatible, Light-sleep compatible
|
||||
* - XTAL_CLK
|
||||
- 32 MHz
|
||||
- Dynamic Frequency Scaling compatible
|
||||
@ -337,6 +337,18 @@ When configuring an LEDC channel, one of the parameters selected within :cpp:typ
|
||||
For registration of a handler to address this interrupt, call :cpp:func:`ledc_isr_register`.
|
||||
|
||||
|
||||
Power Management
|
||||
----------------
|
||||
|
||||
LEDC driver does not utilize power management lock to prevent the system from going into Light-sleep. Instead, the LEDC peripheral power domain state and the PWM signal output behavior during sleep can be chosen by configuring :cpp:member:`ledc_channel_config_t::sleep_mode`. The default mode is :cpp:enumerator:`LEDC_SLEEP_MODE_NO_ALIVE_NO_PD`, which stands for no signal output and LEDC power domain will not be powered down during sleep.
|
||||
|
||||
If signal output needs to be maintained in Light-sleep, then select :cpp:enumerator:`LEDC_SLEEP_MODE_KEEP_ALIVE`. As long as the binded LEDC timer clock source is Light-sleep compatible, the PWM signal can continue its output even the system enters Light-sleep. The cost is a higher power consumption in sleep, since the clock source and the power domain where LEDC belongs to cannot be powered down. Note that, if there is an unfinished fade before entering sleep, the fade can also continue during sleep, but the target duty might not be reached exactly. It will adjust to the target duty after wake-up.
|
||||
|
||||
.. only:: SOC_LEDC_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
There is another sleep mode, :cpp:enumerator:`LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD`, can save some power consumption in sleep, but at the expense of more memory being consumed. The system retains LEDC register context before entering Light-sleep and restores them after waking up, so that the LEDC power domain can be powered down during sleep. Any unfinished fade will not resume upon waking up from sleep, instead, it will output a PWM signal with a fixed duty cycle that matches the duty cycle just before entering sleep.
|
||||
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
.. _ledc-api-high_low_speed_mode:
|
||||
|
@ -153,6 +153,7 @@ The following peripheral drivers are not aware of DFS yet. Applications need to
|
||||
:SOC_TIMER_SUPPORT_SLEEP_RETENTION: - GPTimer
|
||||
:SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT
|
||||
:SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM
|
||||
:SOC_LEDC_SUPPORT_SLEEP_RETENTION: - LEDC
|
||||
:SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C
|
||||
:SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S
|
||||
:SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs
|
||||
@ -170,7 +171,6 @@ The following peripheral drivers are not aware of DFS yet. Applications need to
|
||||
- SPI2
|
||||
- PCNT
|
||||
- USB-Serial-JTAG
|
||||
- LEDC
|
||||
- MCPWM
|
||||
- SARADC
|
||||
- SDIO
|
||||
|
@ -337,6 +337,18 @@ LED PWM 控制器 API 有多种方式即时改变 PWM 频率:
|
||||
要注册处理程序来处理中断,可调用函数 :cpp:func:`ledc_isr_register`。
|
||||
|
||||
|
||||
电源管理
|
||||
--------
|
||||
|
||||
LEDC 驱动不使用电源管理锁来防止系统进入 Light-sleep 。相反,可以通过配置 :cpp:member:`ledc_channel_config_t::sleep_mode` 来选择 LEDC 外设电源域状态和 PWM 信号在睡眠期间的输出行为。默认模式是 :cpp:enumerator:`LEDC_SLEEP_MODE_NO_ALIVE_NO_PD`,它表示没有信号输出,并且 LEDC 电源域在睡眠期间不会下电。
|
||||
|
||||
如果需要在 Light-sleep 中保持信号输出,则可以选择 :cpp:enumerator:`LEDC_SLEEP_MODE_KEEP_ALIVE` 模式。只要绑定的 LEDC 定时器时钟源兼容 Light-sleep , PWM 信号就可以在系统进入 Light-sleep 期间继续输出。其代价是睡眠期间的功耗会更高,这是由于时钟源和 LEDC 所属的电源域无法被下电。值得注意的是,在入睡前未完成的渐变也可以在睡眠期间继续,只是有可能没法准确停在目标占空比上。系统被唤醒后,驱动会调整 PWM 占空比到原来设定的目标占空比上。
|
||||
|
||||
.. only:: SOC_LEDC_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
此外还有另一种睡眠模式,:cpp:enumerator:`LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD` 。选择此模式可以在睡眠中节省一些功耗,但会消耗更多内存。在进入 Light-sleep 之前,系统会保存 LEDC 寄存器上下文,并在唤醒后恢复它们,从而使 LEDC 电源域可以在睡眠期间被下电。任何未完成的渐变在从睡眠状态唤醒后都不会继续进行,而是输出一个固定占空比的 PWM 信号,该占空比与进入睡眠前的当下占空比相匹配。
|
||||
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
.. _ledc-api-high_low_speed_mode:
|
||||
|
@ -152,6 +152,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
|
||||
- SYSTIMER
|
||||
:SOC_TIMER_SUPPORT_SLEEP_RETENTION: - GPTimer
|
||||
:SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT
|
||||
:SOC_LEDC_SUPPORT_SLEEP_RETENTION: - LEDC
|
||||
:SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C
|
||||
:SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S
|
||||
:SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM
|
||||
@ -170,7 +171,6 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
|
||||
- SPI2
|
||||
- PCNT
|
||||
- USB-Serial-JTAG
|
||||
- LEDC
|
||||
- MCPWM
|
||||
- SARADC
|
||||
- SDIO
|
||||
|
@ -542,7 +542,6 @@ components/soc/esp32s2/ledc_periph.c
|
||||
components/soc/esp32s3/include/soc/mpu_caps.h
|
||||
components/soc/esp32s3/ledc_periph.c
|
||||
components/soc/include/soc/gpio_periph.h
|
||||
components/soc/include/soc/ledc_periph.h
|
||||
components/soc/lldesc.c
|
||||
components/spi_flash/include/spi_flash_chip_boya.h
|
||||
components/spi_flash/include/spi_flash_chip_gd.h
|
||||
|
Loading…
x
Reference in New Issue
Block a user