esp32s2: add brownout detector support

1. add brownout detector HAL for esp32 and esp32s2
2. enable brownout reset for esp32 rev. 1 and above
3. add approximate brownout detector levels for esp32s2
This commit is contained in:
Ivan Grokhotkov 2020-01-21 16:32:28 +01:00
parent 46035032cf
commit 70752baba4
11 changed files with 259 additions and 30 deletions

View File

@ -20,6 +20,7 @@
#include "soc/soc.h"
#include "soc/cpu.h"
#include "soc/rtc_periph.h"
#include "hal/brownout_hal.h"
#include "esp32/rom/ets_sys.h"
#include "esp_private/system_internal.h"
#include "driver/rtc_cntl.h"
@ -49,14 +50,17 @@ static void rtc_brownout_isr_handler(void *arg)
void esp_brownout_init(void)
{
REG_WRITE(RTC_CNTL_BROWN_OUT_REG,
RTC_CNTL_BROWN_OUT_ENA /* Enable BOD */
| RTC_CNTL_BROWN_OUT_PD_RF_ENA /* Automatically power down RF */
/* Reset timeout must be set to >1 even if BOR feature is not used */
| (2 << RTC_CNTL_BROWN_OUT_RST_WAIT_S)
| (BROWNOUT_DET_LVL << RTC_CNTL_DBROWN_OUT_THRES_S));
brownout_hal_config_t cfg = {
.threshold = BROWNOUT_DET_LVL,
.enabled = true,
.reset_enabled = false,
.flash_power_down = true,
.rf_power_down = true,
};
brownout_hal_config(&cfg);
ESP_ERROR_CHECK( rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M) );
REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_BROWN_OUT_INT_ENA_M);
brownout_hal_intr_enable(true);
}

View File

@ -364,42 +364,39 @@ menu "ESP32S2-specific"
bool "Hardware brownout detect & reset"
default y
help
The ESP32S2 has a built-in brownout detector which can detect if the voltage is lower than
The ESP32-S2 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 ESP32S2_BROWNOUT_DET_LVL_SEL
prompt "Brownout voltage level"
depends on ESP32S2_BROWNOUT_DET
default ESP32S2_BROWNOUT_DET_LVL_SEL_0
default ESP32S2_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 ESP32 chip.
between each ESP3-S2 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 ESP32S2_BROWNOUT_DET_LVL_SEL_0
bool "2.43V +/- 0.05"
config ESP32S2_BROWNOUT_DET_LVL_SEL_1
bool "2.48V +/- 0.05"
config ESP32S2_BROWNOUT_DET_LVL_SEL_2
bool "2.58V +/- 0.05"
config ESP32S2_BROWNOUT_DET_LVL_SEL_3
bool "2.62V +/- 0.05"
config ESP32S2_BROWNOUT_DET_LVL_SEL_4
bool "2.67V +/- 0.05"
config ESP32S2_BROWNOUT_DET_LVL_SEL_5
bool "2.70V +/- 0.05"
config ESP32S2_BROWNOUT_DET_LVL_SEL_6
bool "2.77V +/- 0.05"
config ESP32S2_BROWNOUT_DET_LVL_SEL_7
bool "2.80V +/- 0.05"
bool "2.44V"
config ESP32S2_BROWNOUT_DET_LVL_SEL_6
bool "2.56V"
config ESP32S2_BROWNOUT_DET_LVL_SEL_5
bool "2.67V"
config ESP32S2_BROWNOUT_DET_LVL_SEL_4
bool "2.84V"
config ESP32S2_BROWNOUT_DET_LVL_SEL_3
bool "2.98V"
config ESP32S2_BROWNOUT_DET_LVL_SEL_2
bool "3.19V"
config ESP32S2_BROWNOUT_DET_LVL_SEL_1
bool "3.30V"
endchoice
config ESP32S2_BROWNOUT_DET_LVL
int
default 0 if ESP32S2_BROWNOUT_DET_LVL_SEL_0
default 1 if ESP32S2_BROWNOUT_DET_LVL_SEL_1
default 2 if ESP32S2_BROWNOUT_DET_LVL_SEL_2
default 3 if ESP32S2_BROWNOUT_DET_LVL_SEL_3

View File

@ -17,10 +17,11 @@
#include <stdlib.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "soc/soc.h"
#include "soc/cpu.h"
#include "soc/rtc_cntl_reg.h"
#include "esp32s2/rom/ets_sys.h"
#include "soc/rtc_periph.h"
#include "hal/brownout_hal.h"
#include "esp_private/system_internal.h"
#include "driver/rtc_cntl.h"
#include "freertos/FreeRTOS.h"
@ -42,15 +43,24 @@ static void rtc_brownout_isr_handler(void *arg)
* at the same time as the following ets_printf.
*/
esp_cpu_stall(!xPortGetCoreID());
esp_reset_reason_set_hint(ESP_RST_BROWNOUT);
ets_printf("\r\nBrownout detector was triggered\r\n\r\n");
esp_restart_noos();
}
void esp_brownout_init(void)
{
// TODO: implement brownout threshold configuration for esp32s2 - IDF-751
brownout_hal_config_t cfg = {
.threshold = BROWNOUT_DET_LVL,
.enabled = true,
.reset_enabled = false,
.flash_power_down = true,
.rf_power_down = true,
};
brownout_hal_config(&cfg);
ESP_ERROR_CHECK( rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M) );
REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_BROWN_OUT_INT_ENA_M);
brownout_hal_intr_enable(true);
}

View File

@ -0,0 +1,41 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "hal/brownout_hal.h"
#include "soc/rtc_cntl_struct.h"
void brownout_hal_config(const brownout_hal_config_t *cfg)
{
typeof(RTCCNTL.brown_out) brown_out_reg = {
.close_flash_ena = cfg->flash_power_down,
.pd_rf_ena = cfg->rf_power_down,
.rst_wait = 0x3ff,
.rst_ena = cfg->reset_enabled,
.thres = cfg->threshold,
.ena = cfg->enabled,
};
RTCCNTL.brown_out = brown_out_reg;
}
void brownout_hal_intr_enable(bool enable)
{
RTCCNTL.int_ena.rtc_brown_out = enable;
}
void brownout_hal_intr_clear(void)
{
RTCCNTL.int_clr.rtc_brown_out = 1;
}

View File

@ -0,0 +1,27 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#if (CONFIG_ESP32_REV_MIN >= 1)
#define SOC_BROWNOUT_RESET_SUPPORTED 1
#endif
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,5 @@
set(SOC_SRCS "adc_periph.c"
"brownout_hal.c"
"dac_periph.c"
"cpu_util.c"
"gpio_periph.c"

View File

@ -0,0 +1,46 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "hal/brownout_hal.h"
#include "soc/rtc_cntl_struct.h"
#include "soc/rtc_cntl_reg.h"
#include "i2c_rtc_clk.h"
#include "i2c_brownout.h"
void brownout_hal_config(const brownout_hal_config_t *cfg)
{
I2C_WRITEREG_MASK_RTC(I2C_BOD, I2C_BOD_THRESHOLD, cfg->threshold);
typeof(RTCCNTL.brown_out) brown_out_reg = {
.out2_ena = 1,
.int_wait = 0x002,
.close_flash_ena = cfg->flash_power_down,
.pd_rf_ena = cfg->rf_power_down,
.rst_wait = 0x3ff,
.rst_ena = cfg->reset_enabled,
.ena = cfg->enabled,
};
RTCCNTL.brown_out = brown_out_reg;
}
void brownout_hal_intr_enable(bool enable)
{
RTCCNTL.int_ena.rtc_brown_out = enable;
}
void brownout_hal_intr_clear(void)
{
RTCCNTL.int_clr.rtc_brown_out = 1;
}

View File

@ -0,0 +1,30 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
/**
* @file i2c_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 i2c_rtc_clk.h.
*/
#define I2C_BOD 0x61
#define I2C_BOD_HOSTID 1
#define I2C_BOD_THRESHOLD 0x5
#define I2C_BOD_THRESHOLD_MSB 2
#define I2C_BOD_THRESHOLD_LSB 0

View File

@ -0,0 +1,25 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define SOC_BROWNOUT_RESET_SUPPORTED 1
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,5 @@
set(SOC_SRCS "adc_periph.c"
"brownout_hal.c"
"dac_periph.c"
"cpu_util.c"
"gpio_periph.c"

View File

@ -0,0 +1,47 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct {
uint8_t threshold;
bool enabled;
bool reset_enabled;
bool flash_power_down;
bool rf_power_down;
} brownout_hal_config_t;
void brownout_hal_config(const brownout_hal_config_t *cfg);
void brownout_hal_intr_enable(bool enable);
void brownout_hal_intr_clear(void);
#ifdef __cplusplus
}
#endif