From 35115885c5e239e407e4552f94ecdb588018e44e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 14 Dec 2016 14:20:01 +0800 Subject: [PATCH] deep sleep: add API to control power down --- components/driver/include/driver/rtc_io.h | 13 +++ components/driver/rtc_module.c | 91 +++++++++++-------- components/esp32/cpu_start.c | 3 + .../esp32/{deepsleep.c => deep_sleep.c} | 85 ++++++++++++++++- components/esp32/include/esp_deep_sleep.h | 76 +++++++++++----- .../{test_deepsleep.c => test_deep_sleep.c} | 4 +- 6 files changed, 202 insertions(+), 70 deletions(-) rename components/esp32/{deepsleep.c => deep_sleep.c} (66%) rename components/esp32/test/{test_deepsleep.c => test_deep_sleep.c} (96%) diff --git a/components/driver/include/driver/rtc_io.h b/components/driver/include/driver/rtc_io.h index 04f699e50..3f06b6850 100644 --- a/components/driver/include/driver/rtc_io.h +++ b/components/driver/include/driver/rtc_io.h @@ -35,6 +35,7 @@ typedef struct { uint32_t pulldown; /*!< Mask of pulldown enable */ uint32_t slpsel; /*!< Mask of the bit to select pin as wakeup pin */ uint32_t slpie; /*!< Mask of input enable in sleep mode */ + uint32_t hold; /*!< Mask of hold_force bit for RTC IO in RTC_CNTL_HOLD_FORCE_REG */ int rtc_num; /*!< RTC IO number, or -1 if not an RTC GPIO */ } rtc_gpio_desc_t; @@ -168,6 +169,18 @@ esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num); */ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num); +/** + * @brief Disable "hold" signal for all RTC IOs + * + * Each RTC pad has a "hold" input signal from the RTC controller. + * If hold signal is set, pad latches current values of input enable, + * function, output enable, and other signals which come from the RTC mux. + * Hold signal is enabled before going into deep sleep for pins which + * are used for EXT1 wakeup. + */ +void rtc_gpio_unhold_all(); + + #ifdef __cplusplus } #endif diff --git a/components/driver/rtc_module.c b/components/driver/rtc_module.c index 804ad6c0d..19fd3123a 100644 --- a/components/driver/rtc_module.c +++ b/components/driver/rtc_module.c @@ -40,46 +40,46 @@ portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED; //Reg,Mux,Fun,IE,Up,Down,Rtc_number const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = { - {RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, 11}, //0 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //1 - {RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, RTC_IO_TOUCH_PAD2_FUN_SEL_S, RTC_IO_TOUCH_PAD2_FUN_IE_M, RTC_IO_TOUCH_PAD2_RUE_M, RTC_IO_TOUCH_PAD2_RDE_M, RTC_IO_TOUCH_PAD2_SLP_SEL_M, RTC_IO_TOUCH_PAD2_SLP_IE_M, 12}, //2 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //3 - {RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_MUX_SEL_M, RTC_IO_TOUCH_PAD0_FUN_SEL_S, RTC_IO_TOUCH_PAD0_FUN_IE_M, RTC_IO_TOUCH_PAD0_RUE_M, RTC_IO_TOUCH_PAD0_RDE_M, RTC_IO_TOUCH_PAD0_SLP_SEL_M, RTC_IO_TOUCH_PAD0_SLP_IE_M, 10}, //4 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //5 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //6 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //7 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //8 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //9 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //10 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //11 - {RTC_IO_TOUCH_PAD5_REG, RTC_IO_TOUCH_PAD5_MUX_SEL_M, RTC_IO_TOUCH_PAD5_FUN_SEL_S, RTC_IO_TOUCH_PAD5_FUN_IE_M, RTC_IO_TOUCH_PAD5_RUE_M, RTC_IO_TOUCH_PAD5_RDE_M, RTC_IO_TOUCH_PAD5_SLP_SEL_M, RTC_IO_TOUCH_PAD5_SLP_IE_M, 15}, //12 - {RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_MUX_SEL_M, RTC_IO_TOUCH_PAD4_FUN_SEL_S, RTC_IO_TOUCH_PAD4_FUN_IE_M, RTC_IO_TOUCH_PAD4_RUE_M, RTC_IO_TOUCH_PAD4_RDE_M, RTC_IO_TOUCH_PAD4_SLP_SEL_M, RTC_IO_TOUCH_PAD4_SLP_IE_M, 14}, //13 - {RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_MUX_SEL_M, RTC_IO_TOUCH_PAD6_FUN_SEL_S, RTC_IO_TOUCH_PAD6_FUN_IE_M, RTC_IO_TOUCH_PAD6_RUE_M, RTC_IO_TOUCH_PAD6_RDE_M, RTC_IO_TOUCH_PAD6_SLP_SEL_M, RTC_IO_TOUCH_PAD6_SLP_IE_M, 16}, //14 - {RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_MUX_SEL_M, RTC_IO_TOUCH_PAD3_FUN_SEL_S, RTC_IO_TOUCH_PAD3_FUN_IE_M, RTC_IO_TOUCH_PAD3_RUE_M, RTC_IO_TOUCH_PAD3_RDE_M, RTC_IO_TOUCH_PAD3_SLP_SEL_M, RTC_IO_TOUCH_PAD3_SLP_IE_M, 13}, //15 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //16 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //17 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //18 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //19 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //20 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //21 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //22 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //23 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //24 - {RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M, RTC_IO_PDAC1_FUN_SEL_S, RTC_IO_PDAC1_FUN_IE_M, RTC_IO_PDAC1_RUE_M, RTC_IO_PDAC1_RDE_M, RTC_IO_PDAC1_SLP_SEL_M, RTC_IO_PDAC1_SLP_IE_M, 6}, //25 - {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, 7}, //26 - {RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_MUX_SEL_M, RTC_IO_TOUCH_PAD7_FUN_SEL_S, RTC_IO_TOUCH_PAD7_FUN_IE_M, RTC_IO_TOUCH_PAD7_RUE_M, RTC_IO_TOUCH_PAD7_RDE_M, RTC_IO_TOUCH_PAD7_SLP_SEL_M, RTC_IO_TOUCH_PAD7_SLP_IE_M, 17}, //27 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //28 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //29 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //30 - {0, 0, 0, 0, 0, 0, 0, 0, -1}, //31 - {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, RTC_IO_X32P_FUN_SEL_S, RTC_IO_X32P_FUN_IE_M, RTC_IO_X32P_RUE_M, RTC_IO_X32P_RDE_M, RTC_IO_X32P_SLP_SEL_M, RTC_IO_X32P_SLP_IE_M, 9}, //32 - {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, RTC_IO_X32N_FUN_SEL_S, RTC_IO_X32N_FUN_IE_M, RTC_IO_X32N_RUE_M, RTC_IO_X32N_RDE_M, RTC_IO_X32N_SLP_SEL_M, RTC_IO_X32N_SLP_IE_M, 8}, //33 - {RTC_IO_ADC_PAD_REG, RTC_IO_ADC1_MUX_SEL_M, RTC_IO_ADC1_FUN_SEL_S, RTC_IO_ADC1_FUN_IE_M, 0, 0, RTC_IO_ADC1_SLP_SEL_M, RTC_IO_ADC1_SLP_IE_M, 4}, //34 - {RTC_IO_ADC_PAD_REG, RTC_IO_ADC2_MUX_SEL_M, RTC_IO_ADC2_FUN_SEL_S, RTC_IO_ADC2_FUN_IE_M, 0, 0, RTC_IO_ADC2_SLP_SEL_M, RTC_IO_ADC2_SLP_IE_M, 5}, //35 - {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE1_MUX_SEL_M, RTC_IO_SENSE1_FUN_SEL_S, RTC_IO_SENSE1_FUN_IE_M, 0, 0, RTC_IO_SENSE1_SLP_SEL_M, RTC_IO_SENSE1_SLP_IE_M, 0}, //36 - {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE2_MUX_SEL_M, RTC_IO_SENSE2_FUN_SEL_S, RTC_IO_SENSE2_FUN_IE_M, 0, 0, RTC_IO_SENSE2_SLP_SEL_M, RTC_IO_SENSE2_SLP_IE_M, 1}, //37 - {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE3_MUX_SEL_M, RTC_IO_SENSE3_FUN_SEL_S, RTC_IO_SENSE3_FUN_IE_M, 0, 0, RTC_IO_SENSE3_SLP_SEL_M, RTC_IO_SENSE3_SLP_IE_M, 2}, //38 - {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE4_MUX_SEL_M, RTC_IO_SENSE4_FUN_SEL_S, RTC_IO_SENSE4_FUN_IE_M, 0, 0, RTC_IO_SENSE4_SLP_SEL_M, RTC_IO_SENSE4_SLP_IE_M, 3}, //39 + {RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_M, 11}, //0 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //1 + {RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, RTC_IO_TOUCH_PAD2_FUN_SEL_S, RTC_IO_TOUCH_PAD2_FUN_IE_M, RTC_IO_TOUCH_PAD2_RUE_M, RTC_IO_TOUCH_PAD2_RDE_M, RTC_IO_TOUCH_PAD2_SLP_SEL_M, RTC_IO_TOUCH_PAD2_SLP_IE_M, RTC_CNTL_TOUCH_PAD2_HOLD_FORCE_M, 12}, //2 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //3 + {RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_MUX_SEL_M, RTC_IO_TOUCH_PAD0_FUN_SEL_S, RTC_IO_TOUCH_PAD0_FUN_IE_M, RTC_IO_TOUCH_PAD0_RUE_M, RTC_IO_TOUCH_PAD0_RDE_M, RTC_IO_TOUCH_PAD0_SLP_SEL_M, RTC_IO_TOUCH_PAD0_SLP_IE_M, RTC_CNTL_TOUCH_PAD0_HOLD_FORCE_M, 10}, //4 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //5 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //6 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //7 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //8 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //9 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //10 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //11 + {RTC_IO_TOUCH_PAD5_REG, RTC_IO_TOUCH_PAD5_MUX_SEL_M, RTC_IO_TOUCH_PAD5_FUN_SEL_S, RTC_IO_TOUCH_PAD5_FUN_IE_M, RTC_IO_TOUCH_PAD5_RUE_M, RTC_IO_TOUCH_PAD5_RDE_M, RTC_IO_TOUCH_PAD5_SLP_SEL_M, RTC_IO_TOUCH_PAD5_SLP_IE_M, RTC_CNTL_TOUCH_PAD5_HOLD_FORCE_M, 15}, //12 + {RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_MUX_SEL_M, RTC_IO_TOUCH_PAD4_FUN_SEL_S, RTC_IO_TOUCH_PAD4_FUN_IE_M, RTC_IO_TOUCH_PAD4_RUE_M, RTC_IO_TOUCH_PAD4_RDE_M, RTC_IO_TOUCH_PAD4_SLP_SEL_M, RTC_IO_TOUCH_PAD4_SLP_IE_M, RTC_CNTL_TOUCH_PAD4_HOLD_FORCE_M, 14}, //13 + {RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_MUX_SEL_M, RTC_IO_TOUCH_PAD6_FUN_SEL_S, RTC_IO_TOUCH_PAD6_FUN_IE_M, RTC_IO_TOUCH_PAD6_RUE_M, RTC_IO_TOUCH_PAD6_RDE_M, RTC_IO_TOUCH_PAD6_SLP_SEL_M, RTC_IO_TOUCH_PAD6_SLP_IE_M, RTC_CNTL_TOUCH_PAD6_HOLD_FORCE_M, 16}, //14 + {RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_MUX_SEL_M, RTC_IO_TOUCH_PAD3_FUN_SEL_S, RTC_IO_TOUCH_PAD3_FUN_IE_M, RTC_IO_TOUCH_PAD3_RUE_M, RTC_IO_TOUCH_PAD3_RDE_M, RTC_IO_TOUCH_PAD3_SLP_SEL_M, RTC_IO_TOUCH_PAD3_SLP_IE_M, RTC_CNTL_TOUCH_PAD3_HOLD_FORCE_M, 13}, //15 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //16 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //17 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //18 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //19 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //20 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //21 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //22 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //23 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //24 + {RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M, RTC_IO_PDAC1_FUN_SEL_S, RTC_IO_PDAC1_FUN_IE_M, RTC_IO_PDAC1_RUE_M, RTC_IO_PDAC1_RDE_M, RTC_IO_PDAC1_SLP_SEL_M, RTC_IO_PDAC1_SLP_IE_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, 6}, //25 + {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, 7}, //26 + {RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_MUX_SEL_M, RTC_IO_TOUCH_PAD7_FUN_SEL_S, RTC_IO_TOUCH_PAD7_FUN_IE_M, RTC_IO_TOUCH_PAD7_RUE_M, RTC_IO_TOUCH_PAD7_RDE_M, RTC_IO_TOUCH_PAD7_SLP_SEL_M, RTC_IO_TOUCH_PAD7_SLP_IE_M, RTC_CNTL_TOUCH_PAD7_HOLD_FORCE_M, 17}, //27 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //28 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //29 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //30 + {0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //31 + {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, RTC_IO_X32P_FUN_SEL_S, RTC_IO_X32P_FUN_IE_M, RTC_IO_X32P_RUE_M, RTC_IO_X32P_RDE_M, RTC_IO_X32P_SLP_SEL_M, RTC_IO_X32P_SLP_IE_M, RTC_CNTL_X32P_HOLD_FORCE_M, 9}, //32 + {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, RTC_IO_X32N_FUN_SEL_S, RTC_IO_X32N_FUN_IE_M, RTC_IO_X32N_RUE_M, RTC_IO_X32N_RDE_M, RTC_IO_X32N_SLP_SEL_M, RTC_IO_X32N_SLP_IE_M, RTC_CNTL_X32N_HOLD_FORCE_M, 8}, //33 + {RTC_IO_ADC_PAD_REG, RTC_IO_ADC1_MUX_SEL_M, RTC_IO_ADC1_FUN_SEL_S, RTC_IO_ADC1_FUN_IE_M, 0, 0, RTC_IO_ADC1_SLP_SEL_M, RTC_IO_ADC1_SLP_IE_M, RTC_CNTL_ADC1_HOLD_FORCE_M, 4}, //34 + {RTC_IO_ADC_PAD_REG, RTC_IO_ADC2_MUX_SEL_M, RTC_IO_ADC2_FUN_SEL_S, RTC_IO_ADC2_FUN_IE_M, 0, 0, RTC_IO_ADC2_SLP_SEL_M, RTC_IO_ADC2_SLP_IE_M, RTC_CNTL_ADC2_HOLD_FORCE_M, 5}, //35 + {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE1_MUX_SEL_M, RTC_IO_SENSE1_FUN_SEL_S, RTC_IO_SENSE1_FUN_IE_M, 0, 0, RTC_IO_SENSE1_SLP_SEL_M, RTC_IO_SENSE1_SLP_IE_M, RTC_CNTL_SENSE1_HOLD_FORCE_M, 0}, //36 + {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE2_MUX_SEL_M, RTC_IO_SENSE2_FUN_SEL_S, RTC_IO_SENSE2_FUN_IE_M, 0, 0, RTC_IO_SENSE2_SLP_SEL_M, RTC_IO_SENSE2_SLP_IE_M, RTC_CNTL_SENSE2_HOLD_FORCE_M, 1}, //37 + {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE3_MUX_SEL_M, RTC_IO_SENSE3_FUN_SEL_S, RTC_IO_SENSE3_FUN_IE_M, 0, 0, RTC_IO_SENSE3_SLP_SEL_M, RTC_IO_SENSE3_SLP_IE_M, RTC_CNTL_SENSE3_HOLD_FORCE_M, 2}, //38 + {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE4_MUX_SEL_M, RTC_IO_SENSE4_FUN_SEL_S, RTC_IO_SENSE4_FUN_IE_M, 0, 0, RTC_IO_SENSE4_SLP_SEL_M, RTC_IO_SENSE4_SLP_IE_M, RTC_CNTL_SENSE4_HOLD_FORCE_M, 3}, //39 }; /*--------------------------------------------------------------- @@ -261,6 +261,17 @@ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num) return ESP_OK; } +void rtc_gpio_unhold_all() +{ + for (int gpio = 0; gpio < GPIO_PIN_COUNT; ++gpio) { + const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio]; + if (desc->hold != 0) { + REG_CLR_BIT(RTC_CNTL_HOLD_FORCE_REG, desc->hold); + } + } +} + + /*--------------------------------------------------------------- Touch Pad ---------------------------------------------------------------*/ diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index c7667fec6..864a17a1b 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -28,6 +28,8 @@ #include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" +#include "driver/rtc_io.h" + #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" @@ -174,6 +176,7 @@ void start_cpu0_default(void) #if CONFIG_BROWNOUT_DET esp_brownout_init(); #endif + rtc_gpio_unhold_all(); esp_setup_time_syscalls(); esp_vfs_dev_uart_register(); esp_reent_init(_GLOBAL_REENT); diff --git a/components/esp32/deepsleep.c b/components/esp32/deep_sleep.c similarity index 66% rename from components/esp32/deepsleep.c rename to components/esp32/deep_sleep.c index ae6745c82..c6a43c6f1 100644 --- a/components/esp32/deepsleep.c +++ b/components/esp32/deep_sleep.c @@ -19,6 +19,7 @@ #include "esp_log.h" #include "rom/cache.h" #include "rom/rtc.h" +#include "rom/uart.h" #include "soc/cpu.h" #include "soc/rtc_cntl_reg.h" #include "soc/dport_reg.h" @@ -35,6 +36,14 @@ static uint32_t s_wakeup_options = 0; static uint64_t s_sleep_duration = 0; static const char* TAG = "deepsleep"; +static esp_deep_sleep_pd_option_t s_pd_options[ESP_PD_DOMAIN_MAX] = { + ESP_PD_OPTION_AUTO, + ESP_PD_OPTION_AUTO, + ESP_PD_OPTION_AUTO, +}; + +static uint32_t get_power_down_flags(); + /* Wake from deep sleep stub See esp_deepsleep.h esp_wake_deep_sleep() comments for details. @@ -85,6 +94,12 @@ void esp_deep_sleep(uint64_t time_in_us) void IRAM_ATTR esp_deep_sleep_start() { + uint32_t pd_flags = get_power_down_flags(); + + uart_tx_wait_idle(0); + uart_tx_wait_idle(1); + uart_tx_wait_idle(2); + if (esp_get_deep_sleep_wake_stub() == NULL) { esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); } @@ -96,7 +111,7 @@ void IRAM_ATTR esp_deep_sleep_start() uint32_t period = rtc_slowck_cali(CALI_RTC_MUX, 128); rtc_usec2rtc(s_sleep_duration >> 32, s_sleep_duration & 0xffffffff, period, &cycle_h, &cycle_l); } - rtc_slp_prep_lite(DEEP_SLEEP_PD_NORMAL, 0); + rtc_slp_prep_lite(pd_flags, 0); rtc_sleep(cycle_h, cycle_l, s_wakeup_options, 0); while (1) { ; @@ -108,7 +123,7 @@ void system_deep_sleep(uint64_t) __attribute__((alias("esp_deep_sleep"))); esp_err_t esp_deep_sleep_enable_ulp_wakeup() { #ifdef CONFIG_ULP_COPROC_ENABLED - s_wakeup_options |= SAR_TRIG_EN; + s_wakeup_options |= RTC_SAR_TRIG_EN; return ESP_OK; #else return ESP_ERR_INVALID_STATE; @@ -117,7 +132,7 @@ esp_err_t esp_deep_sleep_enable_ulp_wakeup() esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us) { - s_wakeup_options |= TIMER_EXPIRE_EN; + s_wakeup_options |= RTC_TIMER_EXPIRE_EN; s_sleep_duration = time_in_us; return ESP_OK; } @@ -141,7 +156,7 @@ esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level) esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_t mode) { - if (mode > EXT1_WAKEUP_ANY_HIGH) { + if (mode > ESP_EXT1_WAKEUP_ANY_HIGH) { return ESP_ERR_INVALID_ARG; } // Translate bit map of GPIO numbers into the bit map of RTC IO numbers @@ -188,3 +203,65 @@ uint64_t esp_deep_sleep_get_ext1_wakeup_status() } return gpio_mask; } + +esp_err_t esp_deep_sleep_pd_config(esp_deep_sleep_pd_domain_t domain, + esp_deep_sleep_pd_option_t option) +{ + if (domain >= ESP_PD_DOMAIN_MAX || option > ESP_PD_OPTION_AUTO) { + return ESP_ERR_INVALID_ARG; + } + s_pd_options[domain] = option; + return ESP_OK; +} + +static uint32_t get_power_down_flags() +{ + // Where needed, convert AUTO options to ON. Later interpret AUTO as OFF. + + // RTC_SLOW_MEM is needed only for the ULP. + // If RTC_SLOW_MEM is Auto, and ULP wakeup isn't enabled, power down RTC_SLOW_MEM. + if (s_pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) { + if (s_wakeup_options & RTC_SAR_TRIG_EN) { + s_pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON; + } + } + + // RTC_FAST_MEM is needed for deep sleep stub. + // If RTC_FAST_MEM is Auto, keep it powered on, so that deep sleep stub + // can run. + // In the new chip revision, deep sleep stub will be optional, + // and this can be changed. + if (s_pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] == ESP_PD_OPTION_AUTO) { + s_pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON; + } + + // RTC_PERIPH is needed for EXT0 wakeup and for ULP. + // If RTC_PERIPH is auto, and both EXT0 and ULP aren't enabled, + // power down RTC_PERIPH. + if (s_pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) { + if (s_wakeup_options & + (RTC_SAR_TRIG_EN | RTC_EXT_EVENT0_TRIG_EN | RTC_EXT_EVENT1_TRIG_EN)) { + s_pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON; + } + } + + const char* option_str[] = {"OFF", "ON", "OFF" /* Auto works as OFF */}; + ESP_LOGD(TAG, "RTC_PERIPH: %s, RTC_SLOW_MEM: %s, RTC_FAST_MEM: %s", + option_str[s_pd_options[ESP_PD_DOMAIN_RTC_PERIPH]], + option_str[s_pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]], + option_str[s_pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]); + + // Prepare flags based on the selected options + uint32_t pd_flags = DEEP_SLEEP_PD_NORMAL; + if (s_pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] != ESP_PD_OPTION_ON) { + pd_flags |= DEEP_SLEEP_PD_RTC_FAST_MEM; + } + if (s_pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] != ESP_PD_OPTION_ON) { + pd_flags |= DEEP_SLEEP_PD_RTC_SLOW_MEM; + } + if (s_pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) { + pd_flags |= DEEP_SLEEP_PD_RTC_PERIPH; + } + ESP_LOGD(TAG, "power down flags: %02x", pd_flags); + return pd_flags; +} diff --git a/components/esp32/include/esp_deep_sleep.h b/components/esp32/include/esp_deep_sleep.h index dffbd09a2..72bdf48c5 100644 --- a/components/esp32/include/esp_deep_sleep.h +++ b/components/esp32/include/esp_deep_sleep.h @@ -34,34 +34,29 @@ extern "C" { * @brief Logic function used for EXT1 wakeup mode. */ typedef enum { - EXT1_WAKEUP_ALL_LOW = 0, //!< Wake the chip when all selected GPIOs go low - EXT1_WAKEUP_ANY_HIGH = 1 //!< Wake the chip when any of the selected GPIOs go high + ESP_EXT1_WAKEUP_ALL_LOW = 0, //!< Wake the chip when all selected GPIOs go low + ESP_EXT1_WAKEUP_ANY_HIGH = 1 //!< Wake the chip when any of the selected GPIOs go high } esp_ext1_wakeup_mode_t; /** - * @brief Parts of RTC power domain which can be powered down in deep sleep + * @brief Power domains which can be powered down in deep sleep */ typedef enum { - RTC_POWER_DOMAIN_PERIPH, //!< RTC IO, sensors and ULP co-processor - RTC_POWER_DOMAIN_SLOW_MEM, //!< RTC slow memory - RTC_POWER_DOMAIN_FAST_MEM, //!< RTC fast memory -} esp_rtc_power_domain_t; + ESP_PD_DOMAIN_RTC_PERIPH, //!< RTC IO, sensors and ULP co-processor + ESP_PD_DOMAIN_RTC_SLOW_MEM, //!< RTC slow memory + ESP_PD_DOMAIN_RTC_FAST_MEM, //!< RTC fast memory + ESP_PD_DOMAIN_MAX //!< Number of domains +} esp_deep_sleep_pd_domain_t; /** - * @brief Enter deep-sleep mode - * - * The device will automatically wake up after the deep-sleep time - * Upon waking up, the device calls deep sleep wake stub, and then proceeds - * to load application. - * - * Call to this function is equivalent to a call to esp_deep_sleep_enable_timer_wakeup - * followed by a call to esp_deep_sleep_start. - * - * This function does not return. - * - * @param time_in_us deep-sleep time, unit: microsecond + * @brief Power down options */ -void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn)); +typedef enum { + ESP_PD_OPTION_OFF, //!< Power down the power domain in deep sleep + ESP_PD_OPTION_ON, //!< Keep power domain enabled during deep sleep + ESP_PD_OPTION_AUTO //!< Keep power domain enabled in deep sleep, if it is needed by one of the wakeup options. Otherwise power it down. +} esp_deep_sleep_pd_option_t; + /** * @brief Enable wakeup by ULP coprocessor @@ -104,6 +99,12 @@ esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); * This function uses external wakeup feature of RTC controller. * It will work even if RTC peripherals are shut down during deep sleep. * + * @note Currently this doesn't actually work if RTC_PERIPH domain is + * powered down. This is a known issue which will be resolved soon. + * For now, unless esp_deep_sleep_pd_config function is used to + * power down RTC_PERIPH domain, it will be kept on during deep sleep, + * slightly increasing power consumption. + * * This feature can monitor any number of pins which are in RTC IOs. * Once any of the selected pins goes into the state given by level argument, * the chip will be woken up. @@ -112,8 +113,8 @@ esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); * which are have RTC functionality can be used in this bit map: * 0,2,4,12-15,25-27,32-39. * @param mode select logic function used to determine wakeup condition: - * - EXT1_WAKEUP_ALL_LOW: wake up when all selected GPIOs are low - * - EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high + * - ESP_EXT1_WAKEUP_ALL_LOW: wake up when all selected GPIOs are low + * - ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high * @return * - ESP_OK on success * - ESP_ERR_INVALID_ARG if either of the arguments is out of range @@ -130,8 +131,19 @@ esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_ */ uint64_t esp_deep_sleep_get_ext1_wakeup_status(); - -void esp_deep_sleep_set_powerdown(esp_rtc_powerdown_t ) +/** + * @brief Set if specific power domain has to be powered down in deep sleep + * + * If not set set using this API, all power domains default to ESP_PD_OPTION_AUTO. + * + * @param domain power domain to configure + * @param option power down option (ESP_PD_OPTION_OFF, ESP_PD_OPTION_ON, or ESP_PD_OPTION_AUTO) + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if either of the arguments is out of range + */ +esp_err_t esp_deep_sleep_pd_config(esp_deep_sleep_pd_domain_t domain, + esp_deep_sleep_pd_option_t option); /** * @brief Enter deep sleep with the configured wakeup options @@ -140,6 +152,22 @@ void esp_deep_sleep_set_powerdown(esp_rtc_powerdown_t ) */ void esp_deep_sleep_start() __attribute__((noreturn)); +/** + * @brief Enter deep-sleep mode + * + * The device will automatically wake up after the deep-sleep time + * Upon waking up, the device calls deep sleep wake stub, and then proceeds + * to load application. + * + * Call to this function is equivalent to a call to esp_deep_sleep_enable_timer_wakeup + * followed by a call to esp_deep_sleep_start. + * + * This function does not return. + * + * @param time_in_us deep-sleep time, unit: microsecond + */ +void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn)); + /** * @brief Enter deep-sleep mode * diff --git a/components/esp32/test/test_deepsleep.c b/components/esp32/test/test_deep_sleep.c similarity index 96% rename from components/esp32/test/test_deepsleep.c rename to components/esp32/test/test_deep_sleep.c index 03068092b..17636235f 100644 --- a/components/esp32/test/test_deepsleep.c +++ b/components/esp32/test/test_deep_sleep.c @@ -61,7 +61,7 @@ TEST_CASE("can wake up from deep sleep using ext1 (13 high)", "[deepsleep]") ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pulldown_en(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_deep_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), EXT1_WAKEUP_ANY_HIGH)); + ESP_ERROR_CHECK(esp_deep_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_HIGH)); esp_deep_sleep_start(); } @@ -70,6 +70,6 @@ TEST_CASE("can wake up from deep sleep using ext1 (13 low)", "[deepsleep]") ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_deep_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), EXT1_WAKEUP_ALL_LOW)); + ESP_ERROR_CHECK(esp_deep_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW)); esp_deep_sleep_start(); }