Skip to content

Commit 9b5944b

Browse files
committed
feat(esp_hw_support): support switch to VBAT power supply in deepsleep on esp32p4
1 parent 190eca3 commit 9b5944b

File tree

21 files changed

+317
-41
lines changed

21 files changed

+317
-41
lines changed

components/esp_hw_support/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ if(NOT non_os_build)
157157
list(APPEND srcs "power_supply/brownout.c")
158158
endif()
159159

160-
if(CONFIG_ESP_VBAT_INIT_AUTO)
160+
if(CONFIG_SOC_VBAT_SUPPORTED)
161161
list(APPEND srcs "power_supply/vbat.c")
162162
endif()
163163

components/esp_hw_support/include/esp_private/esp_pmu.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ typedef enum {
4747
#define RTC_SLEEP_PD_MODEM PMU_SLEEP_PD_MODEM //!< Power down modem(include wifi, ble and 15.4)
4848

4949
//These flags are not power domains, but will affect some sleep parameters
50+
#define RTC_SLEEP_POWER_BY_VBAT BIT(26)
5051
#define RTC_SLEEP_DIG_USE_8M BIT(27)
5152
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(28)
5253
#define RTC_SLEEP_NO_ULTRA_LOW BIT(29) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
@@ -123,6 +124,12 @@ typedef enum {
123124
#define RTC_LP_VAD_TRIG_EN 0
124125
#endif //SOC_LP_VAD_SUPPORTED
125126

127+
#if SOC_VBAT_SUPPORTED
128+
#define RTC_VBAT_UNDER_VOLT_TRIG_EN PMU_VBAT_UNDERVOLT_WAKEUP_EN //!< VBAT under voltage wakeup
129+
#else
130+
#define RTC_VBAT_UNDER_VOLT_TRIG_EN 0
131+
#endif //SOC_VBAT_SUPPORTED
132+
126133
#define RTC_XTAL32K_DEAD_TRIG_EN 0 // TODO
127134
#define RTC_BROWNOUT_DET_TRIG_EN 0 // TODO
128135

@@ -143,6 +150,7 @@ typedef enum {
143150
RTC_XTAL32K_DEAD_TRIG_EN | \
144151
RTC_USB_TRIG_EN | \
145152
RTC_LP_VAD_TRIG_EN | \
153+
RTC_VBAT_UNDER_VOLT_TRIG_EN | \
146154
RTC_BROWNOUT_DET_TRIG_EN)
147155

148156

components/esp_hw_support/include/esp_private/esp_sleep_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ typedef enum {
3939
ESP_SLEEP_RTC_FAST_USE_XTAL_MODE, //!< The mode in which the crystal is used as the RTC_FAST clock source, need keep XTAL on in HP_SLEEP mode when ULP is working.
4040
ESP_SLEEP_DIG_USE_XTAL_MODE, //!< The mode requested by digital peripherals to keep XTAL clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the XTAL domain config by esp_sleep_pd_config)
4141
ESP_SLEEP_LP_USE_XTAL_MODE, //!< The mode requested by lp peripherals to keep XTAL clock on during sleep. Only valid for lightsleep.
42+
ESP_SLEEP_VBAT_POWER_DEEPSLEEP_MODE, //!< The mode to switch power supply to VBAT during deep sleep.
4243
ESP_SLEEP_MODE_MAX,
4344
} esp_sleep_sub_mode_t;
4445

components/esp_hw_support/include/esp_sleep.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ typedef enum {
119119
ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG, //!< Wakeup caused by COCPU crash
120120
ESP_SLEEP_WAKEUP_BT, //!< Wakeup caused by BT (light sleep only)
121121
ESP_SLEEP_WAKEUP_VAD, //!< Wakeup caused by VAD
122+
ESP_SLEEP_WAKEUP_VBAT_UNDER_VOLT, //!< Wakeup caused by VDD_BAT under voltage.
122123
} esp_sleep_source_t;
123124

124125
/**
@@ -194,6 +195,16 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us);
194195
esp_err_t esp_sleep_enable_vad_wakeup(void);
195196
#endif
196197

198+
#if SOC_VBAT_SUPPORTED
199+
/**
200+
* Wakeup chip is VBAT power voltage is lower than the configured brownout_threshold value.
201+
*
202+
* @return
203+
* - ESP_OK on success
204+
*/
205+
esp_err_t esp_sleep_enable_vbat_under_volt_wakeup(void);
206+
#endif
207+
197208
#if SOC_TOUCH_SENSOR_SUPPORTED
198209
/**
199210
* @brief Enable wakeup by touch sensor
@@ -591,6 +602,7 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain,
591602
*
592603
* @return
593604
* - No return - If the sleep is not rejected.
605+
* - ESP_ERR_INVALID_STATE VBAT power does not meet the requirements for entering deepsleep
594606
* - ESP_ERR_SLEEP_REJECT sleep request is rejected(wakeup source set before the sleep request)
595607
*/
596608
esp_err_t esp_deep_sleep_try_to_start(void);

components/esp_hw_support/linker.lf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ entries:
6868
sar_periph_ctrl (noflash)
6969
elif PM_SLP_IRAM_OPT = y:
7070
sar_periph_ctrl: sar_periph_ctrl_power_enable (noflash)
71+
if ESP_VBAT_ISR_CACHE_SAFE = y:
72+
sleep_modes: esp_sleep_disable_wakeup_source (noflash)
73+
sleep_modes: esp_sleep_enable_vbat_under_volt_wakeup (noflash)
74+
sleep_modes: esp_sleep_sub_mode_config (noflash)
75+
sleep_modes: esp_sleep_sub_mode_force_disable (noflash)
7176

7277
[mapping:soc_pm]
7378
archive: libsoc.a

components/esp_hw_support/port/esp32h2/pmu_sleep.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,18 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
140140
)
141141
{
142142
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
143-
config->power = power_default;
144-
145-
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
146-
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
147-
148143
if (dslp) {
149144
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
150145
config->digital = digital_default;
151146

152147
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
153148
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
154149
config->analog = analog_default;
150+
151+
if (sleep_flags & RTC_SLEEP_POWER_BY_VBAT) {
152+
power_default.lp_sys[PMU_MODE_LP_SLEEP].dig_power.vddbat_mode = 1;
153+
power_default.lp_sys[PMU_MODE_LP_SLEEP].dig_power.bod_source_sel = 1;
154+
}
155155
} else {
156156
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
157157
config->digital = digital_default;
@@ -174,6 +174,9 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
174174
}
175175
config->analog = analog_default;
176176
}
177+
config->power = power_default;
178+
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
179+
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
177180
return config;
178181
}
179182

components/esp_hw_support/port/esp32h2/private_include/pmu_bit_defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ extern "C" {
1818
#define PMU_UART1_WAKEUP_EN BIT(7)
1919
#define PMU_BLE_SOC_WAKEUP_EN BIT(10)
2020
#define PMU_USB_WAKEUP_EN BIT(14)
21+
#define PMU_VBAT_UNDERVOLT_WAKEUP_EN BIT(15)
2122

2223
#ifdef __cplusplus
2324
}

components/esp_hw_support/port/esp32h2/private_include/pmu_param.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ typedef union {
139139

140140
typedef union {
141141
struct {
142-
uint32_t reserved0 : 30;
142+
uint32_t reserved0 : 27;
143+
uint32_t bod_source_sel : 1;
144+
uint32_t vddbat_mode : 2;
143145
uint32_t mem_dslp : 1;
144146
uint32_t peri_pd_en: 1;
145147
};

components/esp_hw_support/port/esp32p4/pmu_sleep.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
169169
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
170170
analog_default.hp_sys.analog.xpd_0p1a = 0;
171171
config->analog = analog_default;
172+
173+
if (sleep_flags & RTC_SLEEP_POWER_BY_VBAT) {
174+
power_default.lp_sys[PMU_MODE_LP_SLEEP].dig_power.vddbat_mode = 1;
175+
power_default.lp_sys[PMU_MODE_LP_SLEEP].dig_power.bod_source_sel = 1;
176+
}
172177
} else {
173178
// Get light sleep digital_default
174179
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);

components/esp_hw_support/port/esp32p4/private_include/pmu_bit_defs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extern "C" {
2525
#define PMU_EXT1_WAKEUP_EN BIT(12)
2626
#define PMU_LP_TIMER_WAKEUP_EN BIT(13)
2727
#define PMU_BOD_WAKEUP_EN BIT(14)
28-
#define PMU_VDDBAT_UNDERVOLT_WAKEUP_EN BIT(15)
28+
#define PMU_VBAT_UNDERVOLT_WAKEUP_EN BIT(15)
2929
#define PMU_LP_CORE_TRAP_WAKEUP_EN BIT(16)
3030
#define PMU_ETM_WAKEUP_EN BIT(17)
3131
#define PMU_LP_TIMER1_WAKEUP_EN BIT(18)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include "sdkconfig.h"
10+
#include "freertos/FreeRTOS.h"
11+
#include "esp_err.h"
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
typedef enum {
18+
ESP_VBAT_STATE_NORMAL, /*!< Normal working state, not charging */
19+
ESP_VBAT_STATE_CHARGING, /*!< Battery is charging by VDDA, only for chargeable battery. */
20+
ESP_VBAT_STATE_LOWBATTERY, /*!< Battery is under voltage, battery replacement required */
21+
} esp_vbat_state_t;
22+
23+
#if CONFIG_ESP_VBAT_USE_RECHARGEABLE_BATTERY
24+
/**
25+
* @brief Wait until battery charging done.
26+
*
27+
* @note This function is not allowed to be called in ISR context.
28+
*
29+
* @param checking_period Time in ticks to wait until timeout or succeed
30+
* @return
31+
* - ESP_OK: Battery charging completed
32+
* - ESP_FAIL: Called in ISR context
33+
* - ESP_ERR_TIMEOUT: Timeout waiting for battery charging to complete
34+
*/
35+
esp_err_t esp_vbat_wait_battery_charge_done(TickType_t checking_period);
36+
#endif
37+
38+
/**
39+
* @brief Get battery status.
40+
* @return
41+
* - DISCHARGING Battery is discharging.
42+
* - CHARGING Battery is charing (ESP_VBAT_USE_RECHARGEABLE_BATTERY only).
43+
* - LOWBATTERY Battery is under voltage.
44+
*/
45+
esp_vbat_state_t esp_vbat_get_battery_state(void);
46+
47+
#ifdef __cplusplus
48+
}
49+
#endif

components/esp_hw_support/power_supply/port/esp32h2/Kconfig.power

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ menu "Power Supplier"
7878
during deep sleep.
7979
- When this option is disabled, the RTC battery input (VBAT) must not be left floating.
8080

81+
config ESP_VBAT_ISR_CACHE_SAFE
82+
bool "VBAT ISR IRAM-Safe"
83+
default y
84+
depends on SOC_VBAT_SUPPORTED && ESP_VBAT_INIT_AUTO
85+
help
86+
Ensure the VBAT interrupt is IRAM-Safe by allowing the interrupt handler to be
87+
executable when the cache is disabled (e.g. SPI Flash write).
88+
8189
config ESP_VBAT_USE_RECHARGEABLE_BATTERY
8290
bool "The battery for RTC battery is a rechargeable battery"
8391
default n
@@ -167,6 +175,13 @@ menu "Power Supplier"
167175
bool "2.57V"
168176
endchoice
169177

178+
config ESP_VBAT_WAKEUP_CHIP_ON_VBAT_BROWNOUT
179+
bool "Wake up chip in deepsleep if VBAT brownout"
180+
depends on !ESP_VBAT_USE_RECHARGEABLE_BATTERY
181+
default n
182+
help
183+
Wake up the chip if the vbat voltage drops below the brownout voltage during deepsleep.
184+
170185
config ESP_VBAT_DET_LVL_LOW
171186
int
172187
depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY

components/esp_hw_support/power_supply/port/esp32p4/Kconfig.power

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ menu "Power Supplier"
6767
during deep sleep.
6868
- When this option is disabled, the RTC battery input (VBAT) must not be left floating.
6969

70+
config ESP_VBAT_ISR_CACHE_SAFE
71+
bool "VBAT ISR IRAM-Safe"
72+
default y
73+
depends on SOC_VBAT_SUPPORTED && ESP_VBAT_INIT_AUTO
74+
help
75+
Ensure the VBAT interrupt is IRAM-Safe by allowing the interrupt handler to be
76+
executable when the cache is disabled (e.g. SPI Flash write).
77+
7078
config ESP_VBAT_USE_RECHARGEABLE_BATTERY
7179
bool "The battery for RTC battery is a rechargeable battery"
7280
default n
@@ -126,6 +134,13 @@ menu "Power Supplier"
126134
bool "2.42V"
127135
endchoice
128136

137+
config ESP_VBAT_WAKEUP_CHIP_ON_VBAT_BROWNOUT
138+
bool "Wake up chip in deepsleep if VBAT brownout"
139+
depends on !ESP_VBAT_USE_RECHARGEABLE_BATTERY
140+
default n
141+
help
142+
Wake up the chip if the vbat voltage drops below the brownout voltage during deepsleep.
143+
129144
config ESP_VBAT_DET_LVL_LOW
130145
int
131146
depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY

0 commit comments

Comments
 (0)