Merge branch 'bugfix/external_rtc_start_fail' into 'master'

Bugfix/external rtc start fail

See merge request idf/esp-idf!4374
This commit is contained in:
Angus Gratton 2019-04-02 09:42:27 +08:00
commit ae585b6615
4 changed files with 64 additions and 7 deletions

View file

@ -775,6 +775,19 @@ menu "ESP32-specific"
bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)" bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)"
endchoice endchoice
config ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT
bool "Additional current for external 32kHz crystal"
depends on ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
default "n"
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 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.
config ESP32_RTC_CLK_CAL_CYCLES config ESP32_RTC_CLK_CAL_CYCLES
int "Number of cycles for RTC_SLOW_CLK calibration" int "Number of cycles for RTC_SLOW_CLK calibration"
default 3000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL default 3000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL

View file

@ -95,6 +95,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source);
* source is used. * source is used.
* @return * @return
* - ESP_OK on success * - ESP_OK on success
* - ESP_ERR_NOT_SUPPORTED if additional current by touch (CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT) is enabled.
* - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled or if wakeup triggers conflict * - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled or if wakeup triggers conflict
*/ */
esp_err_t esp_sleep_enable_ulp_wakeup(); esp_err_t esp_sleep_enable_ulp_wakeup();
@ -121,6 +122,7 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us);
* *
* @return * @return
* - ESP_OK on success * - ESP_OK on success
* - ESP_ERR_NOT_SUPPORTED if additional current by touch (CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT) is enabled.
* - ESP_ERR_INVALID_STATE if wakeup triggers conflict * - ESP_ERR_INVALID_STATE if wakeup triggers conflict
*/ */
esp_err_t esp_sleep_enable_touchpad_wakeup(); esp_err_t esp_sleep_enable_touchpad_wakeup();

View file

@ -403,6 +403,9 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
esp_err_t esp_sleep_enable_ulp_wakeup() esp_err_t esp_sleep_enable_ulp_wakeup()
{ {
#ifdef CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT
return ESP_ERR_NOT_SUPPORTED;
#endif
#ifdef CONFIG_ULP_COPROC_ENABLED #ifdef CONFIG_ULP_COPROC_ENABLED
if(s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { if(s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0"); ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
@ -436,6 +439,9 @@ static void timer_wakeup_prepare()
esp_err_t esp_sleep_enable_touchpad_wakeup() esp_err_t esp_sleep_enable_touchpad_wakeup()
{ {
#ifdef CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT
return ESP_ERR_NOT_SUPPORTED;
#endif
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) { if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) {
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0"); ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
@ -695,6 +701,13 @@ static uint32_t get_power_down_flags()
if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) { if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) {
pd_flags |= RTC_SLEEP_PD_XTAL; pd_flags |= RTC_SLEEP_PD_XTAL;
} }
if ((s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) == 0) {
// If enabled EXT1 only and enable the additional current by touch, should be keep RTC_PERIPH power on.
#if ((defined CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL) && (defined CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT))
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
#endif
}
return pd_flags; return pd_flags;
} }

View file

@ -58,7 +58,7 @@
#define APLL_CAL_DELAY_2 0x3f #define APLL_CAL_DELAY_2 0x3f
#define APLL_CAL_DELAY_3 0x1f #define APLL_CAL_DELAY_3 0x1f
#define XTAL_32K_DAC_VAL 1 #define XTAL_32K_DAC_VAL 3
#define XTAL_32K_DRES_VAL 3 #define XTAL_32K_DRES_VAL 3
#define XTAL_32K_DBIAS_VAL 0 #define XTAL_32K_DBIAS_VAL 0
@ -114,14 +114,36 @@ static const char* TAG = "rtc_clk";
static void rtc_clk_32k_enable_common(int dac, int dres, int dbias) static void rtc_clk_32k_enable_common(int dac, int dres, int dbias)
{ {
SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG,
RTC_IO_X32P_RDE | RTC_IO_X32P_RUE | RTC_IO_X32N_RUE | RTC_IO_X32P_RDE | RTC_IO_X32P_RUE | RTC_IO_X32N_RUE |
RTC_IO_X32N_RDE | RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL); RTC_IO_X32N_RDE | RTC_IO_X32N_FUN_IE | RTC_IO_X32P_FUN_IE);
SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
/* Set the parameters of xtal
dac --> current
dres --> resistance
dbias --> bais voltage
*/
REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DAC_XTAL_32K, dac); REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DAC_XTAL_32K, dac);
REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DRES_XTAL_32K, dres); REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DRES_XTAL_32K, dres);
REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DBIAS_XTAL_32K, dbias); REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DBIAS_XTAL_32K, dbias);
SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K);
#ifdef CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT
/* 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);
#endif // CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT
/* Power up external xtal */
SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M);
} }
void rtc_clk_32k_enable(bool enable) void rtc_clk_32k_enable(bool enable)
@ -129,7 +151,14 @@ void rtc_clk_32k_enable(bool enable)
if (enable) { if (enable) {
rtc_clk_32k_enable_common(XTAL_32K_DAC_VAL, XTAL_32K_DRES_VAL, XTAL_32K_DBIAS_VAL); rtc_clk_32k_enable_common(XTAL_32K_DAC_VAL, XTAL_32K_DRES_VAL, XTAL_32K_DBIAS_VAL);
} else { } else {
CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K); /* Disable X32N and X32P pad drive external xtal */
CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M);
CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
#ifdef CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT
/* Power down TOUCH */
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
#endif // CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT
} }
} }