feat(brownout): Add brownout detector support on esp32p4

This commit is contained in:
C.S.M 2024-05-16 18:29:39 +08:00 committed by Cao Sen Miao
parent 3f632df143
commit 91cedfe89d
8 changed files with 214 additions and 4 deletions

View File

@ -76,7 +76,9 @@ void esp_brownout_init(void)
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 // TODO: [ESP32C5] IDF-8647, [ESP32C61] IDF-9254 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 // TODO: [ESP32C5] IDF-8647, [ESP32C61] IDF-9254
// TODO IDF-6606: LP_RTC_TIMER interrupt source is shared by lp_timer and brownout detector, but lp_timer interrupt // TODO IDF-6606: LP_RTC_TIMER interrupt source is shared by lp_timer and brownout detector, but lp_timer interrupt
// is not used now. An interrupt allocator is needed when lp_timer intr gets supported. // is not used now. An interrupt allocator is needed when lp_timer intr gets supported.
esp_intr_alloc(ETS_LP_RTC_TIMER_INTR_SOURCE, ESP_INTR_FLAG_IRAM, &rtc_brownout_isr_handler, NULL, NULL); esp_intr_alloc_intrstatus(ETS_LP_RTC_TIMER_INTR_SOURCE, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_SHARED, (uint32_t)brownout_ll_intr_get_status_reg(), BROWNOUT_DETECTOR_LL_INTERRUPT_MASK, &rtc_brownout_isr_handler, NULL, NULL);
#elif CONFIG_IDF_TARGET_ESP32P4
esp_intr_alloc(ETS_LP_ANAPERI_INTR_SOURCE, ESP_INTR_FLAG_IRAM, &rtc_brownout_isr_handler, NULL, NULL);
#else #else
rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M, RTC_INTR_FLAG_IRAM); rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M, RTC_INTR_FLAG_IRAM);
#endif #endif

View File

@ -0,0 +1,45 @@
menu "Brownout Detector"
config ESP_BROWNOUT_DET
bool "Hardware brownout detect & reset"
depends on !IDF_ENV_FPGA
default y
help
The ESP32-P4 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

View File

@ -20,6 +20,8 @@
extern "C" { extern "C" {
#endif #endif
#define BROWNOUT_DETECTOR_LL_INTERRUPT_MASK (BIT(31))
/** /**
* @brief power down the flash when a brown out happens. * @brief power down the flash when a brown out happens.
* *
@ -123,6 +125,16 @@ static inline void brownout_ll_clear_count(void)
LP_ANA_PERI.bod_mode0_cntl.bod_mode0_cnt_clr = 0; LP_ANA_PERI.bod_mode0_cntl.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.int_st;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -20,6 +20,8 @@
extern "C" { extern "C" {
#endif #endif
#define BROWNOUT_DETECTOR_LL_INTERRUPT_MASK (BIT(31))
/** /**
* @brief power down the flash when a brown out happens. * @brief power down the flash when a brown out happens.
* *
@ -124,6 +126,16 @@ static inline void brownout_ll_clear_count(void)
LP_ANA_PERI.bod_mode0_cntl.bod_mode0_cnt_clr = 0; LP_ANA_PERI.bod_mode0_cntl.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.int_st;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -0,0 +1,128 @@
/*
* SPDX-FileCopyrightText: 2023-2024 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 "soc/lp_analog_peri_struct.h"
#include "hal/regi2c_ctrl.h"
#include "soc/regi2c_brownout.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief power down the flash when a brown out happens.
*
* @param enable true: power down flash. false: not power down
*/
static inline void brownout_ll_enable_flash_power_down(bool enable)
{
LP_ANA_PERI.bod_mode0_cntl.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 done.
*/
static inline void brownout_ll_enable_rf_power_down(bool enable)
{
LP_ANA_PERI.bod_mode0_cntl.bod_mode0_pd_rf_ena = enable;
}
/**
* @brief Enable this to reset brown out
*
* @note: If brown out interrupt is used, this should be disabled.
*
* @param reset_ena true: enable reset. false: disable reset.
* @param reset_wait brown out reset wait cycles
* @param select 1: chip reset, 0: system reset
*/
static inline void brownout_ll_reset_config(bool reset_ena, uint32_t reset_wait, uint8_t select)
{
LP_ANA_PERI.bod_mode0_cntl.bod_mode0_reset_wait = reset_wait;
LP_ANA_PERI.bod_mode0_cntl.bod_mode0_reset_ena = reset_ena;
LP_ANA_PERI.bod_mode0_cntl.bod_mode0_reset_sel = select;
}
/**
* @brief Set brown out threshold
*
* @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.bod_mode0_cntl.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.bod_mode0_cntl.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.int_ena.bod_mode0_int_ena = enable;
}
/**
* @brief Enable brownout hardware reset
*
* @param enable
*/
static inline void brownout_ll_ana_reset_enable(bool enable)
{
LP_ANA_PERI.bod_mode1_cntl.bod_mode1_reset_ena = enable;
}
/**
* @brief Clear interrupt bits.
*/
__attribute__((always_inline))
static inline void brownout_ll_intr_clear(void)
{
LP_ANA_PERI.int_clr.bod_mode0_int_clr = 1;
}
/**
* @brief Clear BOD internal count.
*/
static inline void brownout_ll_clear_count(void)
{
LP_ANA_PERI.bod_mode0_cntl.bod_mode0_cnt_clr = 1;
LP_ANA_PERI.bod_mode0_cntl.bod_mode0_cnt_clr = 0;
}
#ifdef __cplusplus
}
#endif

View File

@ -191,6 +191,10 @@ config SOC_SECURE_BOOT_SUPPORTED
bool bool
default y default y
config SOC_BOD_SUPPORTED
bool
default y
config SOC_PMU_SUPPORTED config SOC_PMU_SUPPORTED
bool bool
default y default y

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -13,3 +13,10 @@
* This file lists register fields of the brownout detector, located on an internal configuration * 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. * bus. These definitions are used via macros defined in regi2c_ctrl.h.
*/ */
#define I2C_BOD 0x61
#define I2C_BOD_HOSTID 0
#define I2C_BOD_THRESHOLD 0x5
#define I2C_BOD_THRESHOLD_MSB 2
#define I2C_BOD_THRESHOLD_LSB 0

View File

@ -67,7 +67,7 @@
#define SOC_KEY_MANAGER_SUPPORTED 1 #define SOC_KEY_MANAGER_SUPPORTED 1
#define SOC_FLASH_ENC_SUPPORTED 1 #define SOC_FLASH_ENC_SUPPORTED 1
#define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_SECURE_BOOT_SUPPORTED 1
// #define SOC_BOD_SUPPORTED 1 //TODO: IDF-7519 #define SOC_BOD_SUPPORTED 1
// #define SOC_APM_SUPPORTED 1 //TODO: IDF-7542 // #define SOC_APM_SUPPORTED 1 //TODO: IDF-7542
#define SOC_PMU_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1
#define SOC_DCDC_SUPPORTED 1 #define SOC_DCDC_SUPPORTED 1