diff --git a/components/bootloader_support/src/bootloader_clock_init.c b/components/bootloader_support/src/bootloader_clock_init.c index a86daa6d0c..74288afa95 100644 --- a/components/bootloader_support/src/bootloader_clock_init.c +++ b/components/bootloader_support/src/bootloader_clock_init.c @@ -117,15 +117,13 @@ __attribute__((weak)) void bootloader_clock_configure(void) #elif CONFIG_IDF_TARGET_ESP32H21 // CLR ENA CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */ - // TODO [ESP32H21] IDF-11530 - // CLEAR_PERI_REG_MASK(LP_ANA_LP_INT_ENA_REG, LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */ + CLEAR_PERI_REG_MASK(LP_ANA_LP_INT_ENA_REG, LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */ CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */ CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */ CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */ // SET CLR SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */ - // TODO [ESP32H21] IDF-11530 - // SET_PERI_REG_MASK(LP_ANA_LP_INT_CLR_REG, LP_ANA_BOD_MODE0_LP_INT_CLR); /* BROWN_OUT */ + SET_PERI_REG_MASK(LP_ANA_LP_INT_CLR_REG, LP_ANA_BOD_MODE0_LP_INT_CLR); /* BROWN_OUT */ SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */ SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */ SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_SLEEP_REJECT_INT_CLR); diff --git a/components/bootloader_support/src/esp32h21/bootloader_esp32h21.c b/components/bootloader_support/src/esp32h21/bootloader_esp32h21.c index 483001bae1..9b985f8bc5 100644 --- a/components/bootloader_support/src/esp32h21/bootloader_esp32h21.c +++ b/components/bootloader_support/src/esp32h21/bootloader_esp32h21.c @@ -37,6 +37,7 @@ #include "hal/mmu_hal.h" #include "hal/cache_hal.h" #include "hal/lpwdt_ll.h" +#include "hal/brownout_ll.h" #include "soc/lp_wdt_reg.h" #include "soc/pmu_reg.h" #include "hal/efuse_hal.h" @@ -96,8 +97,7 @@ static inline void bootloader_ana_reset_config(void) //Enable super WDT reset. bootloader_ana_super_wdt_reset_config(true); //Enable BOD reset (mode1) - //TODO: [ESP32H21] IDF-11530 - // brownout_ll_ana_reset_enable(true); + brownout_ll_ana_reset_enable(true); } esp_err_t bootloader_init(void) diff --git a/components/bootloader_support/src/esp32h21/bootloader_soc.c b/components/bootloader_support/src/esp32h21/bootloader_soc.c index 88284aa50a..c52181f542 100644 --- a/components/bootloader_support/src/esp32h21/bootloader_soc.c +++ b/components/bootloader_support/src/esp32h21/bootloader_soc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,18 +13,6 @@ void bootloader_ana_super_wdt_reset_config(bool enable) REG_CLR_BIT(LP_ANA_FIB_ENABLE_REG, LP_ANALOG_PERI_LP_ANA_FIB_SUPER_WDT_RST); } -//TODO: [ESP32H21] IDF-11531, there is a `bootloader_ana_bod_reset_config` in verify code, please check -void bootloader_ana_bod_reset_config(bool enable) -{ - REG_CLR_BIT(LP_ANA_FIB_ENABLE_REG, LP_ANALOG_PERI_LP_ANA_FIB_BOD_RST); - - if (enable) { - REG_SET_BIT(LP_ANA_BOD_MODE1_CNTL_REG, LP_ANA_BOD_MODE1_RESET_ENA); - } else { - REG_CLR_BIT(LP_ANA_BOD_MODE1_CNTL_REG, LP_ANA_BOD_MODE1_RESET_ENA); - } -} - //Not supported but common bootloader calls the function. Do nothing void bootloader_ana_clock_glitch_reset_config(bool enable) { diff --git a/components/esp_hal_pmu/esp32h21/include/hal/brownout_ll.h b/components/esp_hal_pmu/esp32h21/include/hal/brownout_ll.h new file mode 100644 index 0000000000..ca37ffd9ae --- /dev/null +++ b/components/esp_hal_pmu/esp32h21/include/hal/brownout_ll.h @@ -0,0 +1,148 @@ +/* + * SPDX-FileCopyrightText: 2026 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 "hal/psdet_types.h" +#include "soc/regi2c_brownout.h" + +#define BROWNOUT_DETECTOR_LL_INTERRUPT_MASK (BIT(31)) +#define BROWNOUT_DETECTOR_LL_FIB_ENABLE (BIT(1)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief suspend the flash when a brown out happens. + * + * @param enable true: suspend flash. false: not suspend + */ +static inline void brownout_ll_enable_flash_suspend(bool enable) +{ + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_close_flash_ena = enable; +} + +/** + * @brief power down the RF circuits when a brown out happens + * + * @param enable true: power down. false: not power down. + */ +static inline void brownout_ll_enable_rf_power_down(bool enable) +{ + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_pd_rf_ena = enable; +} + +/** + * @brief Configure the brown out detector to do a hardware reset + * + * @note: If brown out interrupt is also used, the hardware reset can be disabled, + * because we can call software reset in the interrupt handler. + * + * @param reset_ena true: enable reset. false: disable reset. + * @param reset_wait brown out reset wait cycles + * @param reset_level reset level + */ +static inline void brownout_ll_reset_config(bool reset_ena, uint32_t reset_wait, brownout_reset_level_t reset_level) +{ + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_reset_wait = reset_wait; + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_reset_ena = reset_ena; + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_reset_sel = reset_level; +} + +/** + * @brief Set brown out threshold voltage + * + * @param threshold brownout threshold + */ +static inline void brownout_ll_set_threshold(uint8_t threshold) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD, threshold); +} + +/** + * @brief Set this bit to enable the brown out detection + * + * @param bod_enable true: enable, false: disable + */ +static inline void brownout_ll_bod_enable(bool bod_enable) +{ + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_intr_ena = bod_enable; +} + +/** + * @brief configure the waiting cycles before sending an interrupt + * + * @param cycle waiting cycles. + */ +static inline void brownout_ll_set_intr_wait_cycles(uint8_t cycle) +{ + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_intr_wait = cycle; +} + +/** + * @brief Enable brown out interrupt + * + * @param enable true: enable, false: disable + */ +static inline void brownout_ll_intr_enable(bool enable) +{ + LP_ANA_PERI.ana_int_ena.ana_bod_mode0_int_ena = enable; +} + +/** + * @brief Enable brownout hardware reset (mode1) + * + * @param enable true: enable, false: disable + */ +static inline void brownout_ll_ana_reset_enable(bool enable) +{ + // give BOD mode1 control permission to the software + LP_ANA_PERI.ana_fib_enable.val &= ~BROWNOUT_DETECTOR_LL_FIB_ENABLE; + // then we can enable or disable if we want the BOD mode1 to reset the system + LP_ANA_PERI.ana_bod_mode1_cntl.ana_bod_mode1_reset_ena = enable; +} + +/** + * @brief Clear interrupt bits. + */ +__attribute__((always_inline)) +static inline void brownout_ll_intr_clear(void) +{ + LP_ANA_PERI.ana_int_clr.val = BROWNOUT_DETECTOR_LL_INTERRUPT_MASK; +} + +/** + * @brief Clear BOD internal count. + */ +static inline void brownout_ll_clear_count(void) +{ + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_cnt_clr = 1; + LP_ANA_PERI.ana_bod_mode0_cntl.ana_bod_mode0_cnt_clr = 0; +} + +/** + * @brief Get interrupt status register address + * + * @return Register address + */ +static inline volatile void *brownout_ll_intr_get_status_reg(void) +{ + return &LP_ANA_PERI.ana_int_st; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.power index d01bbdfe72..9a4e9f73b6 100644 --- a/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.power +++ b/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.power @@ -13,7 +13,7 @@ menu "Power Supplier" choice ESP_BROWNOUT_DET_LVL_SEL prompt "Brownout voltage level" depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_0 + default ESP_BROWNOUT_DET_LVL_SEL_4 help The brownout detector will reset the chip when the supply voltage is approximately below this level. Note that there may be some variation of brownout voltage level @@ -21,34 +21,54 @@ menu "Power Supplier" #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_15 + bool "3.77V" + config ESP_BROWNOUT_DET_LVL_SEL_14 + bool "3.68V" + config ESP_BROWNOUT_DET_LVL_SEL_13 + bool "3.58V" + config ESP_BROWNOUT_DET_LVL_SEL_12 + bool "3.47V" + config ESP_BROWNOUT_DET_LVL_SEL_11 + bool "3.37V" + config ESP_BROWNOUT_DET_LVL_SEL_10 + bool "3.26V" + config ESP_BROWNOUT_DET_LVL_SEL_9 + bool "3.16V" + config ESP_BROWNOUT_DET_LVL_SEL_8 + bool "3.06V" config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.94V" + bool "2.96V" config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.88V" + bool "2.86V" config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.83V" + bool "2.75V" config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.78V" + bool "2.66V" config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "2.73V" + bool "2.55V" config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "2.67V" - config ESP_BROWNOUT_DET_LVL_SEL_1 - bool "2.62V" - config ESP_BROWNOUT_DET_LVL_SEL_0 - bool "2.57V" + bool "2.45V" + endchoice config ESP_BROWNOUT_DET_LVL int - default 0 if ESP_BROWNOUT_DET_LVL_SEL_0 - default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + default 8 if ESP_BROWNOUT_DET_LVL_SEL_8 + default 9 if ESP_BROWNOUT_DET_LVL_SEL_9 + default 10 if ESP_BROWNOUT_DET_LVL_SEL_10 + default 11 if ESP_BROWNOUT_DET_LVL_SEL_11 + default 12 if ESP_BROWNOUT_DET_LVL_SEL_12 + default 13 if ESP_BROWNOUT_DET_LVL_SEL_13 + default 14 if ESP_BROWNOUT_DET_LVL_SEL_14 + default 15 if ESP_BROWNOUT_DET_LVL_SEL_15 + config ESP_BROWNOUT_USE_INTR bool diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 1e57246b0d..47666caffa 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -111,6 +111,10 @@ config SOC_SECURE_BOOT_SUPPORTED bool default y +config SOC_BOD_SUPPORTED + bool + default y + config SOC_PMU_SUPPORTED bool default y diff --git a/components/soc/esp32h21/include/soc/regi2c_brownout.h b/components/soc/esp32h21/include/soc/regi2c_brownout.h new file mode 100644 index 0000000000..dc2390d804 --- /dev/null +++ b/components/soc/esp32h21/include/soc/regi2c_brownout.h @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + */ + +#pragma once + +#include "regi2c_pmu.h" + +/** + * @file regi2c_brownout.h + * @brief Register definitions for brownout detector + * + * This file lists register fields of the brownout detector, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h. + */ + +#define I2C_BOD I2C_PMU +#define I2C_BOD_HOSTID I2C_PMU_HOSTID + +#define I2C_BOD_THRESHOLD 0xD +#define I2C_BOD_THRESHOLD_MSB 6 +#define I2C_BOD_THRESHOLD_LSB 3 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index a251947d5a..dd57b8bcd4 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -58,7 +58,7 @@ #define SOC_ECDSA_SUPPORTED 1 #define SOC_FLASH_ENC_SUPPORTED 1 #define SOC_SECURE_BOOT_SUPPORTED 1 -// #define SOC_BOD_SUPPORTED 1 //TODO: [ESP32H21] IDF-11530 +#define SOC_BOD_SUPPORTED 1 // #define SOC_APM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11494 #define SOC_PMU_SUPPORTED 1 #define SOC_RTC_TIMER_SUPPORTED 1