mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(esp_hw_support): support main power control during VBAT powered deep sleep
This commit is contained in:
@@ -634,12 +634,36 @@ FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_down_wait_cycle(pmu_dev_t
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
|
||||
{
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
HAL_ASSERT(slow_clk_cycle <= 1020);
|
||||
uint32_t target = 0, expand = 0;
|
||||
if (slow_clk_cycle <= 255) {
|
||||
target = slow_clk_cycle;
|
||||
expand = 0;
|
||||
} else if (slow_clk_cycle <= 510) {
|
||||
expand = 1;
|
||||
target = (slow_clk_cycle + 1) >> 1;
|
||||
} else if (slow_clk_cycle <= 1020) {
|
||||
expand = 2;
|
||||
target = (slow_clk_cycle + 3) >> 2;
|
||||
}
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target, target);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target_expand, expand);
|
||||
#else
|
||||
HAL_ASSERT(slow_clk_cycle <= 255);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target, slow_clk_cycle);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_analog_wait_target_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
uint32_t target = HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target);
|
||||
uint32_t expand = HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target_expand);
|
||||
return target << expand;
|
||||
#else
|
||||
return HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
|
||||
@@ -28,6 +28,8 @@ typedef enum {
|
||||
#define VBAT_LL_CHARGER_MASK (BIT(27)|BIT(28))
|
||||
#define VBAT_LL_DETECT_MASK (BIT(30))
|
||||
|
||||
#define VBAT_LL_LP_SLEEP_PROBE_ID (9)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -237,7 +237,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint16_t digital_power_supply_wait_cycle;
|
||||
uint8_t min_slp_slow_clk_cycle;
|
||||
uint8_t analog_wait_target_cycle;
|
||||
uint16_t analog_wait_target_cycle;
|
||||
uint8_t digital_power_down_wait_cycle;
|
||||
uint8_t digital_power_up_wait_cycle;
|
||||
} pmu_lp_param_t;
|
||||
@@ -526,11 +526,21 @@ typedef struct pmu_sleep_machine_constant {
|
||||
// DCDC startup, which saves more power compared to waiting in the Active state.
|
||||
#define PMU_HP_ANA_WAIT_TIME_PU_TOP_US (PMU_HP_ANA_WAIT_TIME_PD_TOP_US + PMU_REGDMA_S2A_WORK_TIME_US) // 945
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||
#define PMU_LP_ANA_WAIT_TIME_US MAX(154, CONFIG_ESP_VBAT_MAIN_POWER_WAKEUP_ADVANCE_US)
|
||||
#else
|
||||
#define PMU_LP_ANA_WAIT_TIME_US 154
|
||||
#endif
|
||||
|
||||
#define PMU_SLEEP_MC_DEFAULT() { \
|
||||
.lp = { \
|
||||
.min_slp_time_us = 450, \
|
||||
.wakeup_wait_cycle = 4, \
|
||||
.analog_wait_time_us = 154, \
|
||||
.analog_wait_time_us = PMU_LP_ANA_WAIT_TIME_US, \
|
||||
.xtal_wait_stable_time_us = 250, \
|
||||
.clk_switch_cycle = 1, \
|
||||
.clk_power_on_wait_cycle = 1, \
|
||||
|
||||
@@ -200,6 +200,48 @@ menu "Power Supplier"
|
||||
help
|
||||
The resistor value of charger circuit.
|
||||
|
||||
config ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||
bool "Control main power (ESP_3V3) enable via GPIO when VBAT powers deep sleep"
|
||||
default n
|
||||
depends on ESP_VBAT_INIT_AUTO && SOC_MAIN_POWER_CONTROL_SUPPORTED
|
||||
help
|
||||
When enabled, after the chip enters deep sleep and switches to VDD_BAT (VBAT)
|
||||
power, ESP_VBAT_MAIN_POWER_CTRL_PIN is used to disable the main power (ESP_3V3)
|
||||
enable. The main power is re-enabled in advance before wakeup.
|
||||
|
||||
config ESP_VBAT_MAIN_POWER_CTRL_PIN
|
||||
int "GPIO for main power (ESP_3V3) enable"
|
||||
default 2
|
||||
range 0 3 if !RTC_CLK_SRC_EXT_CRYS
|
||||
range 2 3 if RTC_CLK_SRC_EXT_CRYS
|
||||
depends on ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||
help
|
||||
RTC GPIO used to enable/disable the main power rail (ESP_3V3) when VBAT is active.
|
||||
|
||||
config ESP_VBAT_MAIN_POWER_CTRL_PIN_INV
|
||||
bool "Invert main power control pin output (Output high to enable power by default)"
|
||||
default n
|
||||
depends on ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||
help
|
||||
When enabled, the ESP_VBAT_MAIN_POWER_CTRL_PIN logic for the main power control
|
||||
pin is inverted. (n: output high to enable power; y = output low to enable power).
|
||||
|
||||
config ESP_VBAT_MAIN_POWER_WAKEUP_ADVANCE_US
|
||||
int "Main power enable advance time before wakeup (us)"
|
||||
default 1000
|
||||
range 0 1500 if !RTC_CLK_SRC_EXT_CRYS && ESP32P4_SELECTS_REV_LESS_V3
|
||||
range 0 7500 if RTC_CLK_SRC_EXT_CRYS && ESP32P4_SELECTS_REV_LESS_V3
|
||||
range 0 6000 if !RTC_CLK_SRC_EXT_CRYS && !ESP32P4_SELECTS_REV_LESS_V3
|
||||
range 0 30000 if RTC_CLK_SRC_EXT_CRYS && !ESP32P4_SELECTS_REV_LESS_V3
|
||||
depends on ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||
help
|
||||
Advance time in microseconds to assert main power (ESP_3V3) enable before the
|
||||
chip starts the wakeup sequence and switches to main voltage supply. The delay
|
||||
allows the external main power rail to reach target voltage before chip exits
|
||||
deep sleep. Set this value to be greater than or equal to your main power
|
||||
supply's startup/settling time (from enable assertion to stable output voltage).
|
||||
If too small, the main rail may not be ready when the chip wakes, which can
|
||||
cause brownout or unstable boot.
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "hal/vbat_hal.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_private/debug_probe.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "esp_private/rtc_ctrl.h"
|
||||
@@ -46,6 +47,10 @@
|
||||
#define VBAT_CHARGER_HYSTERESIS_THRESHOLD_HIGH (VBAT_CHARGER_HYSTERESIS_THRESHOLD_LOW + (VBAT_CHARGER_FILTER_TIME_US * SOC_CLK_RC_FAST_FREQ_APPROX) / MHZ)
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||
#define ESP_3V3_CTRL_PIN CONFIG_ESP_VBAT_MAIN_POWER_CTRL_PIN
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_VBAT_USE_RECHARGEABLE_BATTERY
|
||||
#if (VBAT_CHARGER_RESISTOR_VALUE < 1000 || VBAT_CHARGER_RESISTOR_VALUE > 4500 || VBAT_CHARGER_RESISTOR_VALUE % 500 != 0)
|
||||
#error "vbat charger resistor (ESP_VBAT_CHARGER_CIRCUIT_RESISTOR_VAL) must be between 1000 and 4500 ohms and must be a multiple of 500."
|
||||
@@ -54,7 +59,7 @@
|
||||
#if (VBAT_BROWNOUT_DET_LVL >= VBAT_CHARGE_DET_LVL_LOW)
|
||||
#error "vbat charger low threshold is equal or lower than vbat brownout threshold, please put vbat brownout threshold lower than vbat charger low threshold"
|
||||
#endif
|
||||
#endif
|
||||
#endif // CONFIG_ESP_VBAT_INIT_AUTO
|
||||
|
||||
ESP_LOG_ATTR_TAG(TAG, "VBAT");
|
||||
#endif
|
||||
@@ -171,6 +176,29 @@ esp_err_t esp_vbat_init(void)
|
||||
esp_sleep_sub_mode_force_disable(ESP_SLEEP_VBAT_POWER_DEEPSLEEP_MODE);
|
||||
esp_sleep_sub_mode_config(ESP_SLEEP_VBAT_POWER_DEEPSLEEP_MODE, true);
|
||||
esp_sleep_enable_vbat_under_volt_wakeup();
|
||||
|
||||
#if CONFIG_ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||
if (esp_reset_reason() != ESP_RST_DEEPSLEEP) {
|
||||
debug_probe_unit_handle_t lp_probe_hdl;
|
||||
debug_probe_unit_config_t unit_config = {
|
||||
.unit_id = DEBUG_PROBE_UNIT_LP,
|
||||
.probe_out_gpio_nums = DEBUG_PROBE_GPIO_NUMS_NONE,
|
||||
};
|
||||
debug_probe_channel_config_t chan_config = {0};
|
||||
debug_probe_channel_handle_t lp_probe_channel_hdl;
|
||||
chan_config.target_module.lp_target = DEBUG_PROBE_TARGET_LP_PMU;
|
||||
unit_config.probe_out_gpio_nums[VBAT_LL_LP_SLEEP_PROBE_ID] = ESP_3V3_CTRL_PIN;
|
||||
#if !CONFIG_ESP_VBAT_MAIN_POWER_CTRL_PIN_INV
|
||||
unit_config.probe_out_inv_mask |= BIT(VBAT_LL_LP_SLEEP_PROBE_ID);
|
||||
#endif
|
||||
ESP_ERROR_CHECK(debug_probe_new_unit(&unit_config, &lp_probe_hdl));
|
||||
ESP_ERROR_CHECK(debug_probe_new_channel(lp_probe_hdl, &chan_config, &lp_probe_channel_hdl));
|
||||
ESP_ERROR_CHECK(debug_probe_chan_add_signal_by_byte(lp_probe_channel_hdl, 1, DEBUG_PROBE_TARGET_LP_PMU));
|
||||
ESP_ERROR_CHECK(debug_probe_unit_merge16(lp_probe_hdl, lp_probe_channel_hdl, DEBUG_PROBE_SPLIT_UPPER16, NULL, 0));
|
||||
}
|
||||
// The LP Probe & LP IOMUX pathways depend on the LP_PERIPH power domain.
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1811,6 +1811,10 @@ config SOC_PM_RETENTION_MODULE_NUM
|
||||
int
|
||||
default 64
|
||||
|
||||
config SOC_MAIN_POWER_CONTROL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -686,6 +686,8 @@
|
||||
|
||||
#define SOC_PM_RETENTION_MODULE_NUM (64)
|
||||
|
||||
#define SOC_MAIN_POWER_CONTROL_SUPPORTED (1) /*!<Supports outputting an enable signal to control the power-on and power-off of the main power supply when powered by VBAT.*/
|
||||
|
||||
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
|
||||
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user