Merge branch 'feat/bod_bringup_h4' into 'master'

feat(bod): Add bod support on esp32h4

Closes IDF-12295

See merge request espressif/esp-idf!47657
This commit is contained in:
C.S.M
2026-04-17 18:30:35 +08:00
9 changed files with 277 additions and 51 deletions
@@ -130,15 +130,13 @@ __attribute__((weak)) void bootloader_clock_configure(void)
#elif CONFIG_IDF_TARGET_ESP32H4
// CLR ENA
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */
// TODO [ESP32H4] IDF-12295
// 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 [ESP32H4] IDF-12295
// 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);
@@ -41,6 +41,7 @@
#include "hal/efuse_hal.h"
#include "hal/lpwdt_ll.h"
#include "hal/assist_debug_ll.h"
#include "hal/brownout_ll.h"
ESP_LOG_ATTR_TAG(TAG, "boot.esp32h4");
@@ -101,7 +102,7 @@ static inline void bootloader_ana_reset_config(void)
//Enable super WDT reset.
bootloader_ana_super_wdt_reset_config(true);
//Enable BOD reset
//TODO: [ESP32H4] IDF-12295 need check
brownout_ll_ana_reset_enable(true);
}
static inline void bootloader_config_dcache(void)
@@ -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 <stdbool.h>
#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
@@ -0,0 +1,85 @@
menu "Power Supplier"
menu "Brownout Detector"
config ESP_BROWNOUT_DET
bool "Hardware brownout detect & reset"
depends on !IDF_ENV_FPGA
default y
help
The ESP32-H4 has a built-in brownout detector which can detect if the voltage is lower than
a specific value. If this happens, it will reset the chip in order to prevent unintended
behaviour.
choice ESP_BROWNOUT_DET_LVL_SEL
prompt "Brownout voltage level"
depends on ESP_BROWNOUT_DET
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
between each chip.
#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.96V"
config ESP_BROWNOUT_DET_LVL_SEL_6
bool "2.86V"
config ESP_BROWNOUT_DET_LVL_SEL_5
bool "2.75V"
config ESP_BROWNOUT_DET_LVL_SEL_4
bool "2.66V"
config ESP_BROWNOUT_DET_LVL_SEL_3
bool "2.55V"
config ESP_BROWNOUT_DET_LVL_SEL_2
bool "2.45V"
endchoice
config ESP_BROWNOUT_DET_LVL
int
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
default n
help
This config allows to trigger an interrupt when brownout detected. Software restart will be done
at the end of the default callback.
This is because for some special workflow, the chip needs do more things when brownout happens
before restart instead of restarting directly. This part needs to be done in callback function
of interrupt.
endmenu
endmenu
@@ -1,45 +0,0 @@
menu "Brownout Detector"
config ESP_BROWNOUT_DET
bool "Hardware brownout detect & reset"
depends on !IDF_ENV_FPGA
default y
help
The ESP32-H4 has a built-in brownout detector which can detect if the voltage is lower than
a specific value. If this happens, it will reset the chip in order to prevent unintended
behaviour.
choice ESP_BROWNOUT_DET_LVL_SEL
prompt "Brownout voltage level"
depends on ESP_BROWNOUT_DET
default ESP_BROWNOUT_DET_LVL_SEL_7
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
between each chip.
#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_7
bool "2.51V"
config ESP_BROWNOUT_DET_LVL_SEL_6
bool "2.64V"
config ESP_BROWNOUT_DET_LVL_SEL_5
bool "2.76V"
config ESP_BROWNOUT_DET_LVL_SEL_4
bool "2.92V"
config ESP_BROWNOUT_DET_LVL_SEL_3
bool "3.10V"
config ESP_BROWNOUT_DET_LVL_SEL_2
bool "3.27V"
endchoice
config ESP_BROWNOUT_DET_LVL
int
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
endmenu
@@ -147,6 +147,10 @@ config SOC_FLASH_ENC_SUPPORTED
bool
default n
config SOC_BOD_SUPPORTED
bool
default y
config SOC_PMU_SUPPORTED
bool
default y
@@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
#pragma once
#include "regi2c_dcdc.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_DCDC
#define I2C_BOD_HOSTID I2C_DCDC_HOSTID
#define I2C_BOD_THRESHOLD 0xD
#define I2C_BOD_THRESHOLD_MSB 6
#define I2C_BOD_THRESHOLD_LSB 3
@@ -74,7 +74,7 @@
#define SOC_FLASH_ENC_SUPPORTED 0 // TODO: [ESP32H4] IDF-12261
// #define SOC_SECURE_BOOT_SUPPORTED 1 // TODO: [ESP32H4] IDF-12262
// #define SOC_BOD_SUPPORTED 1 // TODO: [ESP32H4] IDF-12295
#define SOC_BOD_SUPPORTED 1
// #define SOC_APM_SUPPORTED 1 // TODO: [ESP32H4] IDF-12256
#define SOC_PMU_SUPPORTED 1 // TODO: [ESP32H4] IDF-12286
#define SOC_PAU_SUPPORTED 1
@@ -0,0 +1,11 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
#include "soc/power_supply_periph.h"
const power_supply_signal_conn_t power_supply_periph_signal = {
.irq = ETS_LP_RTC_TIMER_INTR_SOURCE,
};