Merge branch 'bugfix/fix_x32k_startup_slow_bug' into 'master'

bugfix: Fix xtal 32k not oscillate or oscillate too slowly issue for esp32

See merge request espressif/esp-idf!10519
This commit is contained in:
Michael (XIAO Xufeng) 2020-11-24 17:37:29 +08:00
commit af992c26bc
10 changed files with 101 additions and 34 deletions

View File

@ -287,6 +287,10 @@ esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold)
esp_err_t touch_pad_init(void)
{
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
ESP_LOGE(TOUCH_TAG, "Touch Pad can't work because it provides current to external XTAL");
return ESP_ERR_NOT_SUPPORTED;
#endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
if (rtc_touch_mux == NULL) {
rtc_touch_mux = xSemaphoreCreateMutex();
}

View File

@ -28,6 +28,7 @@ extern "C" {
* @return
* - ESP_OK Success
* - ESP_ERR_NO_MEM Touch pad init error
* - ESP_ERR_NOT_SUPPORTED Touch pad is providing current to external XTAL
*/
esp_err_t touch_pad_init(void);

View File

@ -570,18 +570,35 @@ menu "ESP32-specific"
bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)"
endchoice
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
bool "Additional current for external 32kHz crystal"
choice ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_METHOD
prompt "Additional current for external 32kHz crystal"
depends on ESP32_RTC_CLK_SRC_EXT_CRYS
default "n"
depends on ESP32_REV_MIN <= 1
default ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_NONE
help
Choose which additional current is used for rtc external crystal.
With some 32kHz crystal configurations, the X32N and X32P pins may not have enough
drive strength to keep the crystal oscillating. Choose the method to provide
additional current from touchpad 9 to the external 32kHz crystal. Note that
the deep sleep current is slightly high (4-5uA) and the touchpad and the
wakeup sources of both touchpad and ULP are not available in method 1 and method 2.
- With some 32kHz crystal configurations, the X32N and X32P pins may not
have enough drive strength to keep the crystal oscillating during deep sleep.
If this option is enabled, additional current from touchpad 9 is provided
internally to drive the 32kHz crystal. If this option is enabled, deep sleep current
is slightly higher (4-5uA) and the touchpad and ULP wakeup sources are not available.
This problem is fixed in ESP32 ECO 3, so this workaround is not needed. Setting the
project configuration to minimum revision ECO3 will disable this option, , allow
all wakeup sources, and save some code size.
- "None" option will not provide additional current to external crystal
- "Method 1" option can't ensure 100% to solve the external 32k crystal start failed
issue, but the touchpad can work in this method.
- "Method 2" option can solve the external 32k issue, but the touchpad can't work
in this method.
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_NONE
bool "None"
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
bool "Method 1"
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
bool "Method 2"
endchoice
config ESP32_RTC_CLK_CAL_CYCLES
int "Number of cycles for RTC_SLOW_CLK calibration"

View File

@ -1,7 +1,14 @@
idf_build_get_property(target IDF_TARGET)
set(requires soc)
if(${target} STREQUAL "esp32")
list(APPEND requires efuse)
endif()
idf_component_register(SRCS "compare_set.c"
"cpu_util.c"
INCLUDE_DIRS include
REQUIRES soc
REQUIRES ${requires}
LDFRAGMENTS linker.lf)
idf_build_get_property(target IDF_TARGET)

View File

@ -19,6 +19,7 @@
#include "esp32/rom/ets_sys.h" // for ets_update_cpu_frequency
#include "esp32/rom/rtc.h"
#include "esp_rom_gpio.h"
#include "esp_efuse.h"
#include "soc/rtc.h"
#include "soc/rtc_periph.h"
#include "soc/sens_periph.h"
@ -58,7 +59,7 @@
#define APLL_CAL_DELAY_2 0x3f
#define APLL_CAL_DELAY_3 0x1f
#define XTAL_32K_DAC_VAL 3
#define XTAL_32K_DAC_VAL 1
#define XTAL_32K_DRES_VAL 3
#define XTAL_32K_DBIAS_VAL 0
@ -127,20 +128,42 @@ static void rtc_clk_32k_enable_common(int dac, int dres, int dbias)
REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DBIAS_XTAL_32K, dbias);
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
uint8_t chip_ver = esp_efuse_get_chip_ver();
// version0 and version1 need provide additional current to external XTAL.
if(chip_ver == 0 || chip_ver == 1) {
/* TOUCH sensor can provide additional current to external XTAL.
In some case, X32N and X32P PAD don't have enough drive capability to start XTAL */
SET_PERI_REG_MASK(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS_M);
/* Tie PAD Touch8 to VDD
NOTE: TOUCH8 and TOUCH9 register settings are reversed except for DAC, so we set RTC_IO_TOUCH_PAD9_REG here instead*/
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_TIE_OPT_M);
/* Set the current used to compensate TOUCH PAD8 */
SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD8_REG, RTC_IO_TOUCH_PAD8_DAC, 4, RTC_IO_TOUCH_PAD8_DAC_S);
/* Power up TOUCH8
So the Touch DAC start to drive some current from VDD to TOUCH8(which is also XTAL-N)*/
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
}
#elif defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
uint8_t chip_ver = esp_efuse_get_chip_ver();
if(chip_ver == 0 || chip_ver == 1) {
/* TOUCH sensor can provide additional current to external XTAL.
In some case, X32N and X32P PAD don't have enough drive capability to start XTAL */
SET_PERI_REG_MASK(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS_M);
SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_DCUR, 3, RTC_IO_TOUCH_DCUR_S);
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FSM_EN_M);
/* Tie PAD Touch8 to VDD
NOTE: TOUCH8 and TOUCH9 register settings are reversed except for DAC, so we set RTC_IO_TOUCH_PAD9_REG here instead
*/
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_TIE_OPT_M);
/* Set the current used to compensate TOUCH PAD8 */
SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD8_REG, RTC_IO_TOUCH_PAD8_DAC, 4, RTC_IO_TOUCH_PAD8_DAC_S);
SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD8_REG, RTC_IO_TOUCH_PAD8_DAC, 1, RTC_IO_TOUCH_PAD8_DAC_S);
/* Power up TOUCH8
So the Touch DAC start to drive some current from VDD to TOUCH8(which is also XTAL-N)
*/
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
#endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_START_M);
}
#endif
/* Power up external xtal */
SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M);
}
@ -155,9 +178,21 @@ void rtc_clk_32k_enable(bool enable)
CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
uint8_t chip_ver = esp_efuse_get_chip_ver();
if(chip_ver == 0 || chip_ver == 1) {
/* Power down TOUCH */
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
#endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
}
#elif defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
uint8_t chip_ver = esp_efuse_get_chip_ver();
if(chip_ver == 0 || chip_ver == 1) {
/* Power down TOUCH */
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS_M);
SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_DCUR, 0, RTC_IO_TOUCH_DCUR_S);
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FSM_EN_M);
}
#endif
}
}

View File

@ -542,9 +542,10 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
esp_err_t esp_sleep_enable_ulp_wakeup(void)
{
#if CONFIG_IDF_TARGET_ESP32
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
return ESP_ERR_NOT_SUPPORTED;
#endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
#endif
#ifdef CONFIG_ESP32_ULP_COPROC_ENABLED
if(s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
@ -596,7 +597,8 @@ static void touch_wakeup_prepare(void)
esp_err_t esp_sleep_enable_touchpad_wakeup(void)
{
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
return ESP_ERR_NOT_SUPPORTED;
#endif
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) {

View File

@ -233,6 +233,7 @@ static inline void touch_ll_get_tie_option(touch_pad_t touch_num, touch_tie_opt_
*/
static inline void touch_ll_set_fsm_mode(touch_fsm_mode_t mode)
{
SENS.sar_touch_ctrl2.touch_start_fsm_en = 1;
SENS.sar_touch_ctrl2.touch_start_en = 0;
SENS.sar_touch_ctrl2.touch_start_force = mode;
}

View File

@ -151,7 +151,7 @@ void app_main(void)
{
// Initialize touch pad peripheral, it will start a timer to run a filter
ESP_LOGI(TAG, "Initializing touch pad");
touch_pad_init();
ESP_ERROR_CHECK(touch_pad_init());
// If use interrupt trigger mode, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'.
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
// Set reference voltage for charging/discharging

View File

@ -57,7 +57,7 @@ void app_main(void)
{
// Initialize touch pad peripheral.
// The default fsm mode is software trigger mode.
touch_pad_init();
ESP_ERROR_CHECK(touch_pad_init());
// Set reference voltage for charging/discharging
// In this case, the high reference valtage will be 2.7V - 1V = 1.7V
// The low reference voltage will be 0.5

View File

@ -159,7 +159,7 @@ void app_main(void)
#if CONFIG_IDF_TARGET_ESP32
// Initialize touch pad peripheral.
// The default fsm mode is software trigger mode.
touch_pad_init();
ESP_ERROR_CHECK(touch_pad_init());
// If use touch pad wake up, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'.
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
// Set reference voltage for charging/discharging