diff --git a/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.power index 441d6d5683..579ae69d19 100644 --- a/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.power +++ b/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.power @@ -62,4 +62,154 @@ menu "Power Supplier" endmenu + + menu "RTC Backup Battery" + + config ESP_VBAT_INIT_AUTO + bool "Enable VBAT power supply for RTC battery" + default n + depends on SOC_VBAT_SUPPORTED + help + Enable this option to allow the use of a button cell battery to power the RTC (Real-Time Clock) domain. + When this option is enabled, the hardware will configure VBAT as the power supply source for the RTC. + + - Ensure a compatible battery (2.5V ~ 3.6V) is connected to the VBAT pin. + - The VBAT battery provides power to retain RTC state and keep low-power peripherals active + during deep sleep. + - When this option is disabled, the RTC battery input (VBAT) must not be left floating. + + config ESP_VBAT_USE_RECHARGEABLE_BATTERY + bool "The battery for RTC battery is a rechargeable battery" + default n + depends on ESP_VBAT_INIT_AUTO + help + Select this option if the RTC backup battery used in your design is a rechargeable battery. + + When enabled, the system will configure the RTC battery management circuitry to operate + in a mode suitable for charging a rechargeable battery. This includes enabling + charging current regulation via resistor and voltage monitoring to ensure safe and efficient charging. + + Use this option carefully to avoid damage to non-rechargeable batteries. + + choice ESP_VBAT_DET_LVL_LOW_SEL + prompt "VBAT start charging voltage level" + default ESP_VBAT_DET_LVL_LOW_SEL_2 + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + help + The brownout detector will start charging when the supply voltage drops below the selected threshold. + This ensures that the power supply is maintained at a stable level. + + config ESP_VBAT_DET_LVL_LOW_SEL_7 + bool "2.94V" + config ESP_VBAT_DET_LVL_LOW_SEL_6 + bool "2.88V" + config ESP_VBAT_DET_LVL_LOW_SEL_5 + bool "2.83V" + config ESP_VBAT_DET_LVL_LOW_SEL_4 + bool "2.78V" + config ESP_VBAT_DET_LVL_LOW_SEL_3 + bool "2.73V" + config ESP_VBAT_DET_LVL_LOW_SEL_2 + bool "2.67V" + config ESP_VBAT_DET_LVL_LOW_SEL_1 + bool "2.62V" + config ESP_VBAT_DET_LVL_LOW_SEL_0 + bool "2.57V" + endchoice + + choice ESP_VBAT_DET_LVL_HIGH_SEL + prompt "VBAT stop charging voltage level" + default ESP_VBAT_DET_LVL_HIGH_SEL_7 + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + help + The brownout detector will stop charging when the supply voltage arrives the selected threshold. + + config ESP_VBAT_DET_LVL_HIGH_SEL_7 + bool "2.94V" + config ESP_VBAT_DET_LVL_HIGH_SEL_6 + bool "2.88V" + config ESP_VBAT_DET_LVL_HIGH_SEL_5 + bool "2.83V" + config ESP_VBAT_DET_LVL_HIGH_SEL_4 + bool "2.78V" + config ESP_VBAT_DET_LVL_HIGH_SEL_3 + bool "2.73V" + config ESP_VBAT_DET_LVL_HIGH_SEL_2 + bool "2.67V" + config ESP_VBAT_DET_LVL_HIGH_SEL_1 + bool "2.62V" + config ESP_VBAT_DET_LVL_HIGH_SEL_0 + bool "2.57V" + endchoice + + choice ESP_VBAT_BROWNOUT_DET_LVL_SEL + prompt "VBAT brownout voltage level" + default ESP_VBAT_BROWNOUT_DET_LVL_SEL_0 + depends on ESP_VBAT_INIT_AUTO + help + The brownout detector will git a brownout signal when vbat brownout detected. + + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_7 + bool "2.94V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_6 + bool "2.88V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_5 + bool "2.83V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_4 + bool "2.78V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_3 + bool "2.73V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_2 + bool "2.67V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_1 + bool "2.62V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_0 + bool "2.57V" + endchoice + + config ESP_VBAT_DET_LVL_LOW + int + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + default 0 if ESP_VBAT_DET_LVL_LOW_SEL_0 + default 1 if ESP_VBAT_DET_LVL_LOW_SEL_1 + default 2 if ESP_VBAT_DET_LVL_LOW_SEL_2 + default 3 if ESP_VBAT_DET_LVL_LOW_SEL_3 + default 4 if ESP_VBAT_DET_LVL_LOW_SEL_4 + default 5 if ESP_VBAT_DET_LVL_LOW_SEL_5 + default 6 if ESP_VBAT_DET_LVL_LOW_SEL_6 + default 7 if ESP_VBAT_DET_LVL_LOW_SEL_7 + + config ESP_VBAT_DET_LVL_HIGH + int + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + default 0 if ESP_VBAT_DET_LVL_HIGH_SEL_0 + default 1 if ESP_VBAT_DET_LVL_HIGH_SEL_1 + default 2 if ESP_VBAT_DET_LVL_HIGH_SEL_2 + default 3 if ESP_VBAT_DET_LVL_HIGH_SEL_3 + default 4 if ESP_VBAT_DET_LVL_HIGH_SEL_4 + default 5 if ESP_VBAT_DET_LVL_HIGH_SEL_5 + default 6 if ESP_VBAT_DET_LVL_HIGH_SEL_6 + default 7 if ESP_VBAT_DET_LVL_HIGH_SEL_7 + + config ESP_VBAT_BROWNOUT_DET_LVL + int + default 0 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_0 + default 1 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_1 + default 2 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_7 + + config ESP_VBAT_CHARGER_CIRCUIT_RESISTOR_VAL + int "vbat charger circuit resistor value (ohms), should be multiple of 500" + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + range 1000 8500 + default 1000 + help + The resistor value of charger circuit. + + endmenu + endmenu diff --git a/components/hal/esp32h2/include/hal/vbat_ll.h b/components/hal/esp32h2/include/hal/vbat_ll.h new file mode 100644 index 0000000000..f637ee4db0 --- /dev/null +++ b/components/hal/esp32h2/include/hal/vbat_ll.h @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The ll is not public api, don't use in application code. + * See readme.md in hal/readme.md + ******************************************************************************/ + +#pragma once + +#include +#include "esp_bit_defs.h" +#include "soc/lp_analog_peri_struct.h" +#include "hal/regi2c_ctrl.h" +#include "soc/regi2c_brownout.h" + + +typedef enum { + VBAT_LL_CHARGER_UPVOLTAGE_INTR = BIT(27), + VBAT_LL_CHARGER_UNDERVOLTAGE_INTR = BIT(28), + VBAT_LL_BROWNOUT_INTR = BIT(30), +} vbat_ll_intr_t; + +#define VBAT_LL_CHARGER_MASK (BIT(27)|BIT(28)) +#define VBAT_LL_DETECT_MASK (BIT(30)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set vbat brownout threshold voltage + * + * @param threshold vbat brownout threshold + */ +static inline void vbat_ll_set_brownout_threshold(uint8_t threshold) +{ + // Give same value + REGI2C_WRITE_MASK(I2C_BOD, I2C_PMU_OR_DREF_VBAT_L, threshold); + REGI2C_WRITE_MASK(I2C_BOD, I2C_PMU_OR_DREF_VBAT_H, threshold); +} + +/** + * @brief Set vbat charge threshold voltage + * + * @param threshold vbat charge threshold + */ +static inline void vbat_ll_set_charger_threshold(uint8_t threshold_l, uint8_t threshold_h) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DREF_VBAT_CHARGER_L, threshold_l); + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DREF_VBAT_CHARGER_H, threshold_h); +} + +/** + * @brief Enable or disable the VBAT charger comparator + * + * @param enable Set to `true` to enable the comparator, or `false` to disable it. + */ +static inline void vbat_ll_enable_charger_comparator(bool enable) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER, enable); +} + +/** + * @brief Set the under voltage filter time for the charger detector + * + * @param time_tick The filter time in ticks (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_undervoltage_filter_time(uint32_t time_tick) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_undervoltage_target = time_tick; +} + +/** + * @brief Set the upvoltage filter time for the charger detector + * + * @param time_tick The filter time in ticks (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_upvoltage_filter_time(uint32_t time_tick) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_upvoltage_target = time_tick; +} + +/** + * @brief Set the charger resistor value for VBAT charging + * + * @param resistor Resistor value to be set (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_charger_resistor(uint32_t resistor) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DRES_CHARGER, resistor); +} + +/* + * @brief Start or stop the VBAT battery charging process + * + * @param start Set to true to start charging, or false to stop charging. + */ +static inline void vbat_ll_start_battery_charge(bool start) +{ + LP_ANA_PERI.vddbat_bod_cntl.vddbat_charger = start; +} + +/** + * @brief Enable the interrupt mask for vbat usage + * + * @param mask A bitmask representing the interrupts to enable. + * Each bit corresponds to a specific interrupt source. + * @param enable true for enabling the interrupt, otherwise false. + * + * @note Avoid concurrency risky with brownout_ll_intr_enable + */ +static inline void vbat_ll_enable_intr_mask(uint32_t mask, bool enable) +{ + if (enable) { + LP_ANA_PERI.int_ena.val |= mask; + } else { + LP_ANA_PERI.int_ena.val &= ~mask; + } +} + +/** + * @brief Clear the interrupt mask for vbat usage + * + * @param mask A bitmask representing the interrupts to clear. + * Each bit corresponds to a specific interrupt source. + */ +static inline void vbat_ll_clear_intr_mask(uint32_t mask) +{ + LP_ANA_PERI.int_clr.val = mask; +} + +/** + * @brief Get the current interrupt mask for vbat usage + * + * @param intr_status Pointer to a variable where the interrupt status mask will be stored. + * The function will write the current interrupt status to this variable. + */ +static inline void vbat_ll_get_interrupt_status(uint32_t *intr_status) +{ + *intr_status = LP_ANA_PERI.int_st.val; +} + +/** + * @brief Clear the VBAT count for charge detection + * + * This function clears the internal counter that tracks the number of charge events detected + * related to the VBAT power supply. It is typically used to reset the count for monitoring purposes. + */ +static inline void vbat_ll_clear_count(void) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_cnt_clr = 1; + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_cnt_clr = 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 7b30cf6742..d3aa4adaa4 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -179,6 +179,10 @@ config SOC_BOD_SUPPORTED bool default y +config SOC_VBAT_SUPPORTED + bool + default y + config SOC_APM_SUPPORTED bool default y diff --git a/components/soc/esp32h2/include/soc/regi2c_brownout.h b/components/soc/esp32h2/include/soc/regi2c_brownout.h index 0d2caf531c..200894c86a 100644 --- a/components/soc/esp32h2/include/soc/regi2c_brownout.h +++ b/components/soc/esp32h2/include/soc/regi2c_brownout.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,12 +19,12 @@ #define I2C_BOD I2C_PMU #define I2C_BOD_HOSTID I2C_PMU_HOSTID -#define I2C_PMU_OR_DREFL_VBAT 17 -#define I2C_PMU_OR_DREFL_VBAT_MSB 4 -#define I2C_PMU_OR_DREFL_VBAT_LSB 2 -#define I2C_PMU_OR_DREFH_VBAT 17 -#define I2C_PMU_OR_DREFH_VBAT_MSB 7 -#define I2C_PMU_OR_DREFH_VBAT_LSB 5 +#define I2C_PMU_OR_DREF_VBAT_L 17 +#define I2C_PMU_OR_DREF_VBAT_L_MSB 4 +#define I2C_PMU_OR_DREF_VBAT_L_LSB 2 +#define I2C_PMU_OR_DREF_VBAT_H 17 +#define I2C_PMU_OR_DREF_VBAT_H_MSB 7 +#define I2C_PMU_OR_DREF_VBAT_H_LSB 5 #define I2C_PMU_OR_XPD_DIGDET 18 #define I2C_PMU_OR_XPD_DIGDET_MSB 0 @@ -44,6 +44,22 @@ #define I2C_PMU_OR_DREFH_VDDA_MSB 7 #define I2C_PMU_OR_DREFH_VDDA_LSB 5 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L 20 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L_MSB 4 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L_LSB 2 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H 20 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H_MSB 7 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H_LSB 5 + +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER 20 +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER_MSB 0 +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER_LSB 0 + +/** Change the charging current by adjusting the value of the series resistor. 1kΩ + N * 0.5kΩ */ +#define I2C_BIAS_OR_DRES_CHARGER 15 +#define I2C_BIAS_OR_DRES_CHARGER_MSB 7 +#define I2C_BIAS_OR_DRES_CHARGER_LSB 4 + #define I2C_BOD_THRESHOLD_L I2C_PMU_OR_DREFL_VDDA #define I2C_BOD_THRESHOLD_L_MSB I2C_PMU_OR_DREFL_VDDA_MSB #define I2C_BOD_THRESHOLD_L_LSB I2C_PMU_OR_DREFL_VDDA_LSB diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 238264020a..9127a6a1b2 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -77,6 +77,7 @@ #define SOC_FLASH_ENC_SUPPORTED 1 #define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1 +#define SOC_VBAT_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 /*!< Support for APM peripheral */ #define SOC_PMU_SUPPORTED 1 #define SOC_LP_TIMER_SUPPORTED 1