From 71daf49e397c6a1e72131523bda66aea30aeee73 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 8 Dec 2016 18:37:22 +0800 Subject: [PATCH 01/11] driver/rtc_io: improve header comments Fix descriptions of return values, fix typos, use upper case for abbreviations. --- components/driver/include/driver/rtc_io.h | 108 ++++++++++++---------- 1 file changed, 57 insertions(+), 51 deletions(-) diff --git a/components/driver/include/driver/rtc_io.h b/components/driver/include/driver/rtc_io.h index 5196b058a..2e351cf13 100644 --- a/components/driver/include/driver/rtc_io.h +++ b/components/driver/include/driver/rtc_io.h @@ -27,136 +27,142 @@ extern "C" { * @brief Pullup/pulldown information for a single GPIO pad */ typedef struct { - uint32_t reg; /*!< Register of Rtc Pad */ - uint32_t mux; /*!< Mux seletct the Rtc pad is Digital Pad or Rtc pad */ - uint32_t func; /*!< Select Rtc Pad Func */ - uint32_t ie; /*!< Input Enable */ - uint32_t pullup; /*!< Pullup Enable */ - uint32_t pulldown; /*!< PullDown Enable */ - int rtc_num; /*!< The Rtc number */ + uint32_t reg; /*!< Register of RTC pad, or 0 if not an RTC GPIO */ + uint32_t mux; /*!< Bit mask for selecting digital pad or RTC pad */ + uint32_t func; /*!< Mask of RTC pad function */ + uint32_t ie; /*!< Mask of input enable */ + uint32_t pullup; /*!< Mask of pullup enable */ + uint32_t pulldown; /*!< Mask of pulldown enable */ + int rtc_num; /*!< RTC IO number, or -1 if not an RTC GPIO */ } rtc_gpio_desc_t; typedef enum { - RTC_GPIO_MODE_INPUT_ONLY , /*!< Pad output */ - RTC_GPIO_MODE_OUTPUT_ONLY, /*!< Pad input */ - RTC_GPIO_MODE_INPUT_OUTUT, /*!< Pad pull output + input */ - RTC_GPIO_MODE_DISABLED, /*!< Pad (output + input) disable */ + RTC_GPIO_MODE_INPUT_ONLY , /*!< Pad output */ + RTC_GPIO_MODE_OUTPUT_ONLY, /*!< Pad input */ + RTC_GPIO_MODE_INPUT_OUTUT, /*!< Pad pull output + input */ + RTC_GPIO_MODE_DISABLED, /*!< Pad (output + input) disable */ } rtc_gpio_mode_t; #define RTC_GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && rtc_gpio_desc[gpio_num].reg != 0)) //to decide whether it is a valid GPIO number -extern const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] ; +extern const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT]; -/* - * @brief Init a gpio as rtc gpio +/** + * @brief Init a GPIO as RTC GPIO * - * when init a pad as analog function,need to call this funciton + * This function must be called when initializing a pad for an analog function. * - * @param gpio_num gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_12 (12); + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) * * @return * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ esp_err_t rtc_gpio_init(gpio_num_t gpio_num); /** - * @brief Init a gpio as digital gpio + * @brief Init a GPIO as digital GPIO * - * @param gpio_num gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_12 (12); + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) * * @return * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num); /** - * @brief Get the rtc io input level + * @brief Get the RTC IO input level * - * @param gpio_num gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_12 (12); + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) * * @return * - 1 High level * - 0 Low level + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ uint32_t rtc_gpio_get_level(gpio_num_t gpio_num); /** - * @brief Set the rtc io output level + * @brief Set the RTC IO output level * - * @param gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_12 (12); - * @param level output level; + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) + * @param level output level * * @return - * - 1 High level - * - 0 Low level + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level); /** - * @brief Rtc gpio set direction + * @brief RTC GPIO set direction * - * Configure Rtc gpio direction,such as output_only,input_only,output_and_input + * Configure RTC GPIO direction, such as output only, input only, + * output and input. * - * @param gpio_num Configure GPIO pins number, it should be GPIO number. If you want to set direction of e.g. GPIO12, gpio_num should be GPIO_NUM_12 (12); + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) * @param mode GPIO direction * * @return * - ESP_OK Success - * - ESP_ERR_INVALID_ARG GPIO error + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode); /** - * @brief Rtc gpio pullup enable + * @brief RTC GPIO pullup enable * - * If the user needs to configure the GPIO pull ,Please call gpio_set_pull_mode.This function will be called in gpio_set_pull + * This function only works for RTC IOs. In general, call gpio_pullup_en, + * which will work both for normal GPIOs and RTC IOs. * - * @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO12, gpio_num should be GPIO_NUM_12 (12); + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) * * @return - * - True the gpio number is Rts pad - * - False the gpio number is Digital pad + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ esp_err_t rtc_gpio_pullup_en(gpio_num_t gpio_num); /** - * @brief Rtc gpio pulldown enable + * @brief RTC GPIO pulldown enable * - * If the user needs to configure the GPIO pull ,Please call gpio_set_pull_mode.This function will be called in gpio_set_pull + * This function only works for RTC IOs. In general, call gpio_pulldown_en, + * which will work both for normal GPIOs and RTC IOs. * - * @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO12, gpio_num should be GPIO_NUM_12 (12); + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) * * @return - * - True the gpio number is Rts pad - * - False the gpio number is Digital pad + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num); /** - * @brief Rtc gpio pullup clear + * @brief RTC GPIO pullup disable * - * If the user needs to configure the GPIO pull ,Please call gpio_set_pull_mode.This function will be called in gpio_set_pull + * This function only works for RTC IOs. In general, call gpio_pullup_dis, + * which will work both for normal GPIOs and RTC IOs. * - * @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO12, gpio_num should be GPIO_NUM_12 (12); + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) * * @return - * - True the gpio number is Rts pad - * - False the gpio number is Digital pad + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num); /** - * @brief Rtc gpio pulldown clear + * @brief RTC GPIO pulldown disable * - * If the user needs to configure the GPIO pull ,Please call gpio_set_pull_mode.This function will be called in gpio_set_pull + * This function only works for RTC IOs. In general, call gpio_pulldown_dis, + * which will work both for normal GPIOs and RTC IOs. * - * @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO12, gpio_num should be GPIO_NUM_12 (12); + * @param gpio_num GPIO number (e.g. GPIO_NUM_12) * * @return - * - True the gpio number is Rts pad - * - False the gpio number is Digital pad + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO is not an RTC IO */ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num); From 3b854fe46a0216d7fbc7e6f5248bfb837fb85f95 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 8 Dec 2016 22:22:10 +0800 Subject: [PATCH 02/11] deep sleep: implement wake up using ULP, EXT0, EXT1 sources This adds the following APIs to enable various wakeup sources: - esp_deep_sleep_enable_timer_wakeup - esp_deep_sleep_enable_ulp_wakeup - esp_deep_sleep_enable_ext0_wakeup - esp_deep_sleep_enable_ext1_wakeup And an API to start deep sleep: - esp_deep_sleep_start --- components/driver/gpio.c | 2 +- components/driver/include/driver/rtc_io.h | 2 + components/driver/rtc_module.c | 80 ++++++------- components/esp32/deepsleep.c | 134 ++++++++++++++++++++-- components/esp32/include/esp_deepsleep.h | 107 +++++++++++++++-- components/esp32/test/test_deepsleep.c | 75 ++++++++++++ 6 files changed, 339 insertions(+), 61 deletions(-) create mode 100644 components/esp32/test/test_deepsleep.c diff --git a/components/driver/gpio.c b/components/driver/gpio.c index 1f916921b..4bdd716f3 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -77,7 +77,7 @@ esp_err_t gpio_pullup_en(gpio_num_t gpio_num) { if(RTC_GPIO_IS_VALID_GPIO(gpio_num)){ rtc_gpio_pullup_en(gpio_num); }else{ - REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU); + REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU); } return ESP_OK; } diff --git a/components/driver/include/driver/rtc_io.h b/components/driver/include/driver/rtc_io.h index 2e351cf13..04f699e50 100644 --- a/components/driver/include/driver/rtc_io.h +++ b/components/driver/include/driver/rtc_io.h @@ -33,6 +33,8 @@ typedef struct { uint32_t ie; /*!< Mask of input enable */ uint32_t pullup; /*!< Mask of pullup enable */ 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 */ int rtc_num; /*!< RTC IO number, or -1 if not an RTC GPIO */ } rtc_gpio_desc_t; diff --git a/components/driver/rtc_module.c b/components/driver/rtc_module.c index ecb7e434d..804ad6c0d 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, 11}, //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, 12}, //2 - {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, 10}, //4 - {0, 0, 0, 0, 0, 0, -1}, //5 - {0, 0, 0, 0, 0, 0, -1}, //6 - {0, 0, 0, 0, 0, 0, -1}, //7 - {0, 0, 0, 0, 0, 0, -1}, //8 - {0, 0, 0, 0, 0, 0, -1}, //9 - {0, 0, 0, 0, 0, 0, -1}, //10 - {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, 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, 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, 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, 13}, //15 - {0, 0, 0, 0, 0, 0, -1}, //16 - {0, 0, 0, 0, 0, 0, -1}, //17 - {0, 0, 0, 0, 0, 0, -1}, //18 - {0, 0, 0, 0, 0, 0, -1}, //19 - {0, 0, 0, 0, 0, 0, -1}, //20 - {0, 0, 0, 0, 0, 0, -1}, //21 - {0, 0, 0, 0, 0, 0, -1}, //22 - {0, 0, 0, 0, 0, 0, -1}, //23 - {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, 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, 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, 17}, //27 - {0, 0, 0, 0, 0, 0, -1}, //28 - {0, 0, 0, 0, 0, 0, -1}, //29 - {0, 0, 0, 0, 0, 0, -1}, //30 - {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, 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, 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, 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, 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, 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, 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, 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, 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, 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 }; /*--------------------------------------------------------------- diff --git a/components/esp32/deepsleep.c b/components/esp32/deepsleep.c index b8b73a3b1..cf9ee852e 100644 --- a/components/esp32/deepsleep.c +++ b/components/esp32/deepsleep.c @@ -1,7 +1,17 @@ -/* Wake from deep sleep stub +// Copyright 2015-2016 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. - See esp_deepsleep.h esp_wake_deep_sleep() comments for details. -*/ #include #include #include "rom/cache.h" @@ -10,12 +20,24 @@ #include "soc/dport_reg.h" #include "esp_attr.h" #include "esp_deepsleep.h" +#include "esp_log.h" +#include "soc/cpu.h" #include "rtc.h" +#include "driver/rtc_io.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" /* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc() is not thread-safe. */ static _lock_t lock_rtc_memory_crc; +static uint32_t s_wakeup_options = 0; +static uint64_t s_sleep_duration = 0; +static const char* TAG = "deepsleep"; + +/* Wake from deep sleep stub + See esp_deepsleep.h esp_wake_deep_sleep() comments for details. +*/ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void) { _lock_acquire(&lock_rtc_memory_crc); @@ -50,18 +72,112 @@ void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_s void esp_deep_sleep(uint64_t time_in_us) { - rtc_set_cpu_freq(CPU_XTAL); + esp_deep_sleep_enable_timer_wakeup(time_in_us); + esp_deep_sleep_start(); +} + +void IRAM_ATTR esp_deep_sleep_start() +{ if (esp_get_deep_sleep_wake_stub() == NULL) { esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); } - uint32_t period = rtc_slowck_cali(CALI_RTC_MUX, 128); - uint32_t cycle_l, cycle_h; - rtc_usec2rtc(time_in_us >> 32, time_in_us, period, &cycle_h, &cycle_l); - rtc_slp_prep_lite(1, 0); - rtc_sleep(cycle_h, cycle_l, TIMER_EXPIRE_EN, 0); + + rtc_set_cpu_freq(CPU_XTAL); + uint32_t cycle_h = 0; + uint32_t cycle_l = 0; + if (s_sleep_duration > 0) { + 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_sleep(cycle_h, cycle_l, s_wakeup_options, 0); while (1) { ; } } 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; + return ESP_OK; +#else + return ESP_ERR_INVALID_STATE; +#endif +} + +esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us) +{ + s_wakeup_options |= TIMER_EXPIRE_EN; + s_sleep_duration = time_in_us; + return ESP_OK; +} + +esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level) +{ + if (level < 0 || level > 1) { + return ESP_ERR_INVALID_ARG; + } + if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_ERR_INVALID_ARG; + } + const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio_num]; + REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, desc->rtc_num); + SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, level, RTC_CNTL_EXT_WAKEUP0_LV_S); + REG_SET_BIT(desc->reg, desc->slpsel); + REG_SET_BIT(desc->reg, desc->slpie); + s_wakeup_options |= RTC_EXT_EVENT0_TRIG_EN; + return ESP_OK; +} + +esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_t mode) +{ + if (mode > EXT1_WAKEUP_ANY_HIGH) { + return ESP_ERR_INVALID_ARG; + } + // Translate bit map of GPIO numbers into the bit map of RTC IO numbers + uint32_t rtc_gpio_mask = 0; + for (int gpio = 0; mask; ++gpio, mask >>= 1) { + if ((mask & 1) == 0) { + continue; + } + if (!RTC_GPIO_IS_VALID_GPIO(gpio)) { + ESP_LOGE(TAG, "Not an RTC IO: GPIO%d", gpio); + return ESP_ERR_INVALID_ARG; + } + const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio]; + int rtc_pin = desc->rtc_num; + rtc_gpio_mask |= BIT(rtc_pin); + REG_SET_BIT(desc->reg, desc->slpsel); + REG_SET_BIT(desc->reg, desc->slpie); + } + REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR); + REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, rtc_gpio_mask); + SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, mode, RTC_CNTL_EXT_WAKEUP1_LV_S); + s_wakeup_options |= RTC_EXT_EVENT1_TRIG_EN; + return ESP_OK; +} + +uint64_t esp_deep_sleep_get_ext1_wakeup_status() +{ + int wakeup_reason = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE); + if (wakeup_reason != RTC_EXT_EVENT1_TRIG) { + return 0; + } + uint32_t status = REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS); + // Translate bit map of RTC IO numbers into the bit map of GPIO numbers + uint64_t gpio_mask = 0; + for (int gpio = 0; gpio < 40; ++gpio) { + if (!RTC_GPIO_IS_VALID_GPIO(gpio)) { + continue; + } + int rtc_pin = rtc_gpio_desc[gpio].rtc_num; + if ((status & BIT(rtc_pin)) == 0) { + continue; + } + gpio_mask |= BIT(gpio); + } + return gpio_mask; +} diff --git a/components/esp32/include/esp_deepsleep.h b/components/esp32/include/esp_deepsleep.h index 051ad14c3..ab2e2cbc5 100644 --- a/components/esp32/include/esp_deepsleep.h +++ b/components/esp32/include/esp_deepsleep.h @@ -3,7 +3,7 @@ // 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 @@ -12,10 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef __ESP_DEEPSLEEP_H__ -#define __ESP_DEEPSLEEP_H_ +#pragma once #include +#include "esp_err.h" +#include "driver/gpio.h" #ifdef __cplusplus extern "C" { @@ -29,6 +30,14 @@ 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_mode_t; + /** * @brief Enter deep-sleep mode * @@ -36,12 +45,88 @@ extern "C" { * 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 Enable wakeup by ULP coprocessor + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled. + */ +esp_err_t esp_deep_sleep_enable_ulp_wakeup(); + +/** + * @brief Enable wakeup by timer + * @param time_in_us time before wakeup, in microseconds + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if value is out of range (TBD) + */ +esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us); + +/** + * @brief Enable wakeup using a pin + * + * This function uses external wakeup feature of RTC_IO peripheral. + * It will work only if RTC peripherals are kept on during deep sleep. + * + * This feature can monitor any pin which is an RTC IO. Once the pin transitions + * into the state given by level argument, the chip will be woken up. + * + * @param gpio_num GPIO number used as wakeup source. Only GPIOs which are have RTC + * functionality can be used: 0,2,4,12-15,25-27,32-39. + * @param level input level which will trigger wakeup (0=low, 1=high) + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if either of the arguments is out of range + */ +esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); + +/** + * @brief Enable wakeup using multiple pins + * + * This function uses external wakeup feature of RTC controller. + * It will work even if RTC peripherals are shut down during deep sleep. + * + * 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. + * + * @param mask bit mask of GPIO numbers which will cause wakeup. Only GPIOs + * 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 + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if either of the arguments is out of range + */ +esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_t mode); + + +/** + * @brief Get the bit mask of GPIOs which caused wakeup (ext1) + * + * If wakeup was caused by another source, this function will return 0. + * + * @return bit mask, if GPIOn caused wakeup, BIT(n) will be set + */ +uint64_t esp_deep_sleep_get_ext1_wakeup_status(); + +/** + * @brief Enter deep sleep with the configured wakeup options + * + * This function does not return. + */ +void esp_deep_sleep_start() __attribute__((noreturn)); /** * @brief Enter deep-sleep mode @@ -87,15 +172,17 @@ typedef void (*esp_deep_sleep_wake_stub_fn_t)(void); void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub); /** - * @brief Return current wake from deep sleep stub, or NULL if - * no stub is installed. + * @brief Get current wake from deep sleep stub + * @return Return current wake from deep sleep stub, or NULL if + * no stub is installed. */ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void); -/* The default esp-idf-provided esp_wake_deep_sleep() stub. - - See docs/deep-sleep-stub.rst for details. -*/ +/** + * @brief The default esp-idf-provided esp_wake_deep_sleep() stub. + * + * See docs/deep-sleep-stub.rst for details. + */ void esp_default_wake_deep_sleep(void); /** @@ -110,5 +197,3 @@ void esp_default_wake_deep_sleep(void); #ifdef __cplusplus } #endif - -#endif /* __ESP_SYSTEM_H__ */ diff --git a/components/esp32/test/test_deepsleep.c b/components/esp32/test/test_deepsleep.c new file mode 100644 index 000000000..fb05f01f1 --- /dev/null +++ b/components/esp32/test/test_deepsleep.c @@ -0,0 +1,75 @@ +#include "unity.h" +#include "esp_deepsleep.h" +#include "driver/rtc_io.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +TEST_CASE("esp_deepsleep works", "[deepsleep]") +{ + esp_deep_sleep(2000000); +} + +static void deep_sleep_task(void* arg) +{ + esp_deep_sleep_start(); +} + +static void do_deep_sleep_from_app_cpu() +{ + xTaskCreatePinnedToCore(&deep_sleep_task, "ds", 2048, NULL, 5, NULL, 1); + + // keep running some non-IRAM code + vTaskSuspendAll(); + while(true) { + ; + } +} + +TEST_CASE("can wake up from deep sleep using timer", "[deepsleep]") +{ + esp_deep_sleep_enable_timer_wakeup(2000000); + esp_deep_sleep_start(); +} + +TEST_CASE("go into deep sleep from APP CPU and wake up using timer", "[deepsleep]") +{ + esp_deep_sleep_enable_timer_wakeup(2000000); + do_deep_sleep_from_app_cpu(); +} + + +TEST_CASE("can wake up from deep sleep using ext0 (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_ext0_wakeup(GPIO_NUM_13, 1)); + esp_deep_sleep_start(); +} + +TEST_CASE("can wake up from deep sleep using ext0 (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_ext0_wakeup(GPIO_NUM_13, 0)); + esp_deep_sleep_start(); +} + +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_deep_sleep_start(); +} + +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_deep_sleep_start(); +} From eac80b0651fbc4d8843a1410a3e06760fd350e68 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 12 Dec 2016 23:20:15 +0800 Subject: [PATCH 03/11] deep sleep: add option to delay CPU startup When ESP32 wakes up from deep sleep, flash is accessed an approximately 900us after power on. Some flash chips need more time to become ready. This change adds a menuconfig option to add some delay to the default deep sleep wake stub. Fixes https://github.com/espressif/esp-idf/issues/117 --- components/esp32/Kconfig | 19 +++++++++++++++++++ components/esp32/deepsleep.c | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 4112b3372..6ee5313b9 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -452,6 +452,25 @@ config ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL endchoice +config ESP32_DEEP_SLEEP_WAKEUP_DELAY + int "Extra delay in deep sleep wake stub (in us)" + default 0 + range 0 5000 + help + When ESP32 exits deep sleep, the CPU and the flash chip are powered on + at the same time. CPU will run deep sleep stub first, and then + proceed to load code from flash. Some flash chips need sufficient + time to pass between power on and first read operation. By default, + without any extra delay, this time is approximately 900us. + + If you are using a flash chip which needs more than 900us to become + ready after power on, set this parameter to add extra delay + to the default deep sleep stub. + + If you are seeing "flash read err, 1000" message printed to the + console after deep sleep reset, try increasing this value. + + config ESP32_PHY_AUTO_INIT bool "Initialize PHY in startup code" default y diff --git a/components/esp32/deepsleep.c b/components/esp32/deepsleep.c index cf9ee852e..0b13ce99a 100644 --- a/components/esp32/deepsleep.c +++ b/components/esp32/deepsleep.c @@ -26,6 +26,7 @@ #include "driver/rtc_io.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "sdkconfig.h" /* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc() is not thread-safe. */ @@ -66,6 +67,12 @@ void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) { /* Clear MMU for CPU 0 */ REG_SET_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MMU_IA_CLR); REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MMU_IA_CLR); +#if CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY > 0 + // ROM code has not started yet, so we need to set delay factor + // used by ets_delay_us first. + ets_update_cpu_frequency(ets_get_detected_xtal_freq() / 1000000); + ets_delay_us(CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY); +#endif } void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void); From 88ddf5aefa5bad08383de18523b813059889f9cf Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 13 Dec 2016 13:23:04 +0800 Subject: [PATCH 04/11] deep sleep: rename header file --- components/esp32/deepsleep.c | 10 +- components/esp32/include/esp_deep_sleep.h | 211 ++++++++++++++++++++++ components/esp32/include/esp_deepsleep.h | 201 +-------------------- components/esp32/include/esp_system.h | 2 +- components/esp32/test/test_deepsleep.c | 2 +- examples/06_sntp/main/sntp_main.c | 2 +- 6 files changed, 221 insertions(+), 207 deletions(-) create mode 100644 components/esp32/include/esp_deep_sleep.h diff --git a/components/esp32/deepsleep.c b/components/esp32/deepsleep.c index 0b13ce99a..ae6745c82 100644 --- a/components/esp32/deepsleep.c +++ b/components/esp32/deepsleep.c @@ -14,18 +14,18 @@ #include #include +#include "esp_attr.h" +#include "esp_deep_sleep.h" +#include "esp_log.h" #include "rom/cache.h" #include "rom/rtc.h" +#include "soc/cpu.h" #include "soc/rtc_cntl_reg.h" #include "soc/dport_reg.h" -#include "esp_attr.h" -#include "esp_deepsleep.h" -#include "esp_log.h" -#include "soc/cpu.h" -#include "rtc.h" #include "driver/rtc_io.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "rtc.h" #include "sdkconfig.h" /* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc() diff --git a/components/esp32/include/esp_deep_sleep.h b/components/esp32/include/esp_deep_sleep.h new file mode 100644 index 000000000..dffbd09a2 --- /dev/null +++ b/components/esp32/include/esp_deep_sleep.h @@ -0,0 +1,211 @@ +// Copyright 2015-2016 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 + +#include +#include "esp_err.h" +#include "driver/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup Deep_Sleep_API Deep Sleep API + * @brief API for putting device into deep sleep + */ + +/** @addtogroup Deep_Sleep_API + * @{ + */ + +/** + * @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_mode_t; + +/** + * @brief Parts of RTC power domain 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; + +/** + * @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 Enable wakeup by ULP coprocessor + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled. + */ +esp_err_t esp_deep_sleep_enable_ulp_wakeup(); + +/** + * @brief Enable wakeup by timer + * @param time_in_us time before wakeup, in microseconds + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if value is out of range (TBD) + */ +esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us); + +/** + * @brief Enable wakeup using a pin + * + * This function uses external wakeup feature of RTC_IO peripheral. + * It will work only if RTC peripherals are kept on during deep sleep. + * + * This feature can monitor any pin which is an RTC IO. Once the pin transitions + * into the state given by level argument, the chip will be woken up. + * + * @param gpio_num GPIO number used as wakeup source. Only GPIOs which are have RTC + * functionality can be used: 0,2,4,12-15,25-27,32-39. + * @param level input level which will trigger wakeup (0=low, 1=high) + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if either of the arguments is out of range + */ +esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); + +/** + * @brief Enable wakeup using multiple pins + * + * This function uses external wakeup feature of RTC controller. + * It will work even if RTC peripherals are shut down during deep sleep. + * + * 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. + * + * @param mask bit mask of GPIO numbers which will cause wakeup. Only GPIOs + * 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 + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if either of the arguments is out of range + */ +esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_t mode); + + +/** + * @brief Get the bit mask of GPIOs which caused wakeup (ext1) + * + * If wakeup was caused by another source, this function will return 0. + * + * @return bit mask, if GPIOn caused wakeup, BIT(n) will be set + */ +uint64_t esp_deep_sleep_get_ext1_wakeup_status(); + + +void esp_deep_sleep_set_powerdown(esp_rtc_powerdown_t ) + +/** + * @brief Enter deep sleep with the configured wakeup options + * + * This function does not return. + */ +void esp_deep_sleep_start() __attribute__((noreturn)); + +/** + * @brief Enter deep-sleep mode + * + * Function has been renamed to esp_deep_sleep. + * This name is deprecated and will be removed in a future version. + * + * @param time_in_us deep-sleep time, unit: microsecond + */ +void system_deep_sleep(uint64_t time_in_us) __attribute__((noreturn, deprecated)); + +/** + * @brief Default stub to run on wake from deep sleep. + * + * Allows for executing code immediately on wake from sleep, before + * the software bootloader or ESP-IDF app has started up. + * + * This function is weak-linked, so you can implement your own version + * to run code immediately when the chip wakes from + * sleep. + * + * See docs/deep-sleep-stub.rst for details. + */ +void esp_wake_deep_sleep(void); + +/** + * @brief Function type for stub to run on wake from sleep. + * + */ +typedef void (*esp_deep_sleep_wake_stub_fn_t)(void); + +/** + * @brief Install a new stub at runtime to run on wake from deep sleep + * + * If implementing esp_wake_deep_sleep() then it is not necessary to + * call this function. + * + * However, it is possible to call this function to substitute a + * different deep sleep stub. Any function used as a deep sleep stub + * must be marked RTC_IRAM_ATTR, and must obey the same rules given + * for esp_wake_deep_sleep(). + */ +void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub); + +/** + * @brief Get current wake from deep sleep stub + * @return Return current wake from deep sleep stub, or NULL if + * no stub is installed. + */ +esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void); + +/** + * @brief The default esp-idf-provided esp_wake_deep_sleep() stub. + * + * See docs/deep-sleep-stub.rst for details. + */ +void esp_default_wake_deep_sleep(void); + +/** + * @} + */ + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif diff --git a/components/esp32/include/esp_deepsleep.h b/components/esp32/include/esp_deepsleep.h index ab2e2cbc5..fe5364996 100644 --- a/components/esp32/include/esp_deepsleep.h +++ b/components/esp32/include/esp_deepsleep.h @@ -1,199 +1,2 @@ -// Copyright 2015-2016 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 - -#include -#include "esp_err.h" -#include "driver/gpio.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \defgroup Deep_Sleep_API Deep Sleep API - * @brief API for putting device into deep sleep - */ - -/** @addtogroup Deep_Sleep_API - * @{ - */ - -/** - * @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_mode_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 - */ -void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn)); - -/** - * @brief Enable wakeup by ULP coprocessor - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled. - */ -esp_err_t esp_deep_sleep_enable_ulp_wakeup(); - -/** - * @brief Enable wakeup by timer - * @param time_in_us time before wakeup, in microseconds - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if value is out of range (TBD) - */ -esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us); - -/** - * @brief Enable wakeup using a pin - * - * This function uses external wakeup feature of RTC_IO peripheral. - * It will work only if RTC peripherals are kept on during deep sleep. - * - * This feature can monitor any pin which is an RTC IO. Once the pin transitions - * into the state given by level argument, the chip will be woken up. - * - * @param gpio_num GPIO number used as wakeup source. Only GPIOs which are have RTC - * functionality can be used: 0,2,4,12-15,25-27,32-39. - * @param level input level which will trigger wakeup (0=low, 1=high) - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if either of the arguments is out of range - */ -esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); - -/** - * @brief Enable wakeup using multiple pins - * - * This function uses external wakeup feature of RTC controller. - * It will work even if RTC peripherals are shut down during deep sleep. - * - * 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. - * - * @param mask bit mask of GPIO numbers which will cause wakeup. Only GPIOs - * 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 - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if either of the arguments is out of range - */ -esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_t mode); - - -/** - * @brief Get the bit mask of GPIOs which caused wakeup (ext1) - * - * If wakeup was caused by another source, this function will return 0. - * - * @return bit mask, if GPIOn caused wakeup, BIT(n) will be set - */ -uint64_t esp_deep_sleep_get_ext1_wakeup_status(); - -/** - * @brief Enter deep sleep with the configured wakeup options - * - * This function does not return. - */ -void esp_deep_sleep_start() __attribute__((noreturn)); - -/** - * @brief Enter deep-sleep mode - * - * Function has been renamed to esp_deep_sleep. - * This name is deprecated and will be removed in a future version. - * - * @param time_in_us deep-sleep time, unit: microsecond - */ -void system_deep_sleep(uint64_t time_in_us) __attribute__((noreturn, deprecated)); - -/** - * @brief Default stub to run on wake from deep sleep. - * - * Allows for executing code immediately on wake from sleep, before - * the software bootloader or ESP-IDF app has started up. - * - * This function is weak-linked, so you can implement your own version - * to run code immediately when the chip wakes from - * sleep. - * - * See docs/deep-sleep-stub.rst for details. - */ -void esp_wake_deep_sleep(void); - -/** - * @brief Function type for stub to run on wake from sleep. - * - */ -typedef void (*esp_deep_sleep_wake_stub_fn_t)(void); - -/** - * @brief Install a new stub at runtime to run on wake from deep sleep - * - * If implementing esp_wake_deep_sleep() then it is not necessary to - * call this function. - * - * However, it is possible to call this function to substitute a - * different deep sleep stub. Any function used as a deep sleep stub - * must be marked RTC_IRAM_ATTR, and must obey the same rules given - * for esp_wake_deep_sleep(). - */ -void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub); - -/** - * @brief Get current wake from deep sleep stub - * @return Return current wake from deep sleep stub, or NULL if - * no stub is installed. - */ -esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void); - -/** - * @brief The default esp-idf-provided esp_wake_deep_sleep() stub. - * - * See docs/deep-sleep-stub.rst for details. - */ -void esp_default_wake_deep_sleep(void); - -/** - * @} - */ - - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif +#warning esp_deepsleep.h has been renamed to esp_deep_sleep.h, please update include directives +#include "esp_deep_sleep.h" diff --git a/components/esp32/include/esp_system.h b/components/esp32/include/esp_system.h index 40ebd8403..e1f46de80 100644 --- a/components/esp32/include/esp_system.h +++ b/components/esp32/include/esp_system.h @@ -18,7 +18,7 @@ #include #include #include "esp_err.h" -#include "esp_deepsleep.h" +#include "esp_deep_sleep.h" #ifdef __cplusplus extern "C" { diff --git a/components/esp32/test/test_deepsleep.c b/components/esp32/test/test_deepsleep.c index fb05f01f1..03068092b 100644 --- a/components/esp32/test/test_deepsleep.c +++ b/components/esp32/test/test_deepsleep.c @@ -1,5 +1,5 @@ #include "unity.h" -#include "esp_deepsleep.h" +#include "esp_deep_sleep.h" #include "driver/rtc_io.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" diff --git a/examples/06_sntp/main/sntp_main.c b/examples/06_sntp/main/sntp_main.c index c3edb9e2b..f128323dc 100644 --- a/examples/06_sntp/main/sntp_main.c +++ b/examples/06_sntp/main/sntp_main.c @@ -17,7 +17,7 @@ #include "esp_event_loop.h" #include "esp_log.h" #include "esp_attr.h" -#include "esp_deepsleep.h" +#include "esp_deep_sleep.h" #include "nvs_flash.h" #include "lwip/err.h" From 35115885c5e239e407e4552f94ecdb588018e44e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 14 Dec 2016 14:20:01 +0800 Subject: [PATCH 05/11] 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(); } From 83184bd52b14e78d3b639c53dafd7888af1edc23 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 14 Dec 2016 14:23:40 +0800 Subject: [PATCH 06/11] deep sleep: RTC fast memory may be disconnected after deep sleep wakeup This adds a workaround for a bug that following deep sleep wakeup, ISO (bus isolation) signal may be set for RTC fast memory. We set FORCE_NOISO bit in RTC_CNTL_PWC_REG until we find out what is causing ISO signal to be set. --- components/esp32/cpu_freq.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/esp32/cpu_freq.c b/components/esp32/cpu_freq.c index 0e9dc2304..257639cf9 100644 --- a/components/esp32/cpu_freq.c +++ b/components/esp32/cpu_freq.c @@ -18,6 +18,8 @@ #include "sdkconfig.h" #include "phy.h" #include "rtc.h" +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" /* * This function is not exposed as an API at this point, @@ -36,6 +38,10 @@ void esp_set_cpu_freq(void) uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM); rtc_init_lite(XTAL_AUTO); + // work around a bug that RTC fast memory may be isolated + // from the system after rtc_init_lite + SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO_M); + cpu_freq_t freq = CPU_80M; switch(freq_mhz) { case 240: From 616d1d32f1af3c3641cbfcb399b67a147207eb3b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 14 Dec 2016 14:25:42 +0800 Subject: [PATCH 07/11] ulp: add missing component.mk for tests --- components/ulp/test/component.mk | 1 + components/ulp/test/test_ulp.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 components/ulp/test/component.mk diff --git a/components/ulp/test/component.mk b/components/ulp/test/component.mk new file mode 100644 index 000000000..ce464a212 --- /dev/null +++ b/components/ulp/test/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/ulp/test/test_ulp.c b/components/ulp/test/test_ulp.c index f8dc174dc..f0000e1aa 100644 --- a/components/ulp/test/test_ulp.c +++ b/components/ulp/test/test_ulp.c @@ -27,7 +27,7 @@ #include "soc/soc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/saradc_reg.h" +#include "soc/sens_reg.h" #include "sdkconfig.h" From 609d852834653ac458848697d9038159ebd8f8d9 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 16 Dec 2016 14:10:07 +0800 Subject: [PATCH 08/11] deep sleep: power down RTC peripherals in EXT1 sleep --- components/driver/include/driver/rtc_io.h | 4 +-- components/esp32/deep_sleep.c | 7 ++++- components/esp32/include/esp_deep_sleep.h | 6 ---- components/esp32/test/test_deep_sleep.c | 34 +++++++++++++++++------ 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/components/driver/include/driver/rtc_io.h b/components/driver/include/driver/rtc_io.h index 3f06b6850..3fc328764 100644 --- a/components/driver/include/driver/rtc_io.h +++ b/components/driver/include/driver/rtc_io.h @@ -29,11 +29,11 @@ extern "C" { typedef struct { uint32_t reg; /*!< Register of RTC pad, or 0 if not an RTC GPIO */ uint32_t mux; /*!< Bit mask for selecting digital pad or RTC pad */ - uint32_t func; /*!< Mask of RTC pad function */ + uint32_t func; /*!< Shift of pad function (FUN_SEL) field */ uint32_t ie; /*!< Mask of input enable */ uint32_t pullup; /*!< Mask of pullup enable */ uint32_t pulldown; /*!< Mask of pulldown enable */ - uint32_t slpsel; /*!< Mask of the bit to select pin as wakeup pin */ + uint32_t slpsel; /*!< If slpsel bit is set, slpie will be used as pad input enabled signal in sleep mode */ 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 */ diff --git a/components/esp32/deep_sleep.c b/components/esp32/deep_sleep.c index c6a43c6f1..28ab27270 100644 --- a/components/esp32/deep_sleep.c +++ b/components/esp32/deep_sleep.c @@ -172,8 +172,13 @@ esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_ const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio]; int rtc_pin = desc->rtc_num; rtc_gpio_mask |= BIT(rtc_pin); + REG_SET_BIT(desc->reg, desc->ie); REG_SET_BIT(desc->reg, desc->slpsel); REG_SET_BIT(desc->reg, desc->slpie); + REG_CLR_BIT(desc->reg, desc->pulldown); + REG_CLR_BIT(desc->reg, desc->pullup); + REG_SET_BIT(desc->reg, desc->mux); + REG_SET_BIT(RTC_CNTL_HOLD_FORCE_REG, desc->hold); } REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR); REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, rtc_gpio_mask); @@ -240,7 +245,7 @@ static uint32_t get_power_down_flags() // 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)) { + (RTC_SAR_TRIG_EN | RTC_EXT_EVENT0_TRIG_EN)) { s_pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON; } } diff --git a/components/esp32/include/esp_deep_sleep.h b/components/esp32/include/esp_deep_sleep.h index 72bdf48c5..8b28f5ffe 100644 --- a/components/esp32/include/esp_deep_sleep.h +++ b/components/esp32/include/esp_deep_sleep.h @@ -99,12 +99,6 @@ 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. diff --git a/components/esp32/test/test_deep_sleep.c b/components/esp32/test/test_deep_sleep.c index 17636235f..a47b6daf3 100644 --- a/components/esp32/test/test_deep_sleep.c +++ b/components/esp32/test/test_deep_sleep.c @@ -25,20 +25,20 @@ static void do_deep_sleep_from_app_cpu() } } -TEST_CASE("can wake up from deep sleep using timer", "[deepsleep]") +TEST_CASE("wake up using timer", "[deepsleep]") { esp_deep_sleep_enable_timer_wakeup(2000000); esp_deep_sleep_start(); } -TEST_CASE("go into deep sleep from APP CPU and wake up using timer", "[deepsleep]") +TEST_CASE("enter deep sleep on APP CPU and wake up using timer", "[deepsleep]") { esp_deep_sleep_enable_timer_wakeup(2000000); do_deep_sleep_from_app_cpu(); } -TEST_CASE("can wake up from deep sleep using ext0 (13 high)", "[deepsleep]") +TEST_CASE("wake up using ext0 (13 high)", "[deepsleep]") { ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13)); @@ -47,7 +47,7 @@ TEST_CASE("can wake up from deep sleep using ext0 (13 high)", "[deepsleep]") esp_deep_sleep_start(); } -TEST_CASE("can wake up from deep sleep using ext0 (13 low)", "[deepsleep]") +TEST_CASE("wake up using ext0 (13 low)", "[deepsleep]") { ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13)); @@ -56,20 +56,38 @@ TEST_CASE("can wake up from deep sleep using ext0 (13 low)", "[deepsleep]") esp_deep_sleep_start(); } -TEST_CASE("can wake up from deep sleep using ext1 (13 high)", "[deepsleep]") +TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 high)", "[deepsleep]") { + // This test needs external pulldown 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), ESP_EXT1_WAKEUP_ANY_HIGH)); esp_deep_sleep_start(); } -TEST_CASE("can wake up from deep sleep using ext1 (13 low)", "[deepsleep]") +TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 low)", "[deepsleep]") +{ + // This test needs external pullup + ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); + ESP_ERROR_CHECK(esp_deep_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW)); + esp_deep_sleep_start(); +} + +TEST_CASE("wake up using ext1 when RTC_PERIPH is on (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_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)); + ESP_ERROR_CHECK(esp_deep_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_HIGH)); + esp_deep_sleep_start(); +} + +TEST_CASE("wake up using ext1 when RTC_PERIPH is on (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_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)); ESP_ERROR_CHECK(esp_deep_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW)); esp_deep_sleep_start(); } From 370f4b8556ce310b30dc1d23cc49087076a11716 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 16 Dec 2016 14:26:05 +0800 Subject: [PATCH 09/11] deep sleep: set pin configuration right before entering deep sleep This change allows setting pin configuration for EXT1 wakeup depending on the state of RTC_PERIPH power domain: - if peripherals are enabled (due to another wakeup mode, or due to esp_deep_sleep_pd_config call), we can keep internal pullups/pulldowns enabled - if peripherals are disabled, pullups and pulldowns need to be disabled as well Also add comments about the purpose of registers being configured. --- components/esp32/deep_sleep.c | 182 +++++++++++++++------- components/esp32/include/esp_deep_sleep.h | 23 ++- 2 files changed, 149 insertions(+), 56 deletions(-) diff --git a/components/esp32/deep_sleep.c b/components/esp32/deep_sleep.c index 28ab27270..7f59c2163 100644 --- a/components/esp32/deep_sleep.c +++ b/components/esp32/deep_sleep.c @@ -29,21 +29,33 @@ #include "rtc.h" #include "sdkconfig.h" +/** + * Internal structure which holds all requested deep sleep parameters + */ +typedef struct { + esp_deep_sleep_pd_option_t pd_options[ESP_PD_DOMAIN_MAX]; + uint64_t sleep_duration; + uint32_t wakeup_triggers : 11; + uint32_t ext1_trigger_mode : 1; + uint32_t ext1_rtc_gpio_mask : 18; + uint32_t ext0_trigger_level : 1; + uint32_t ext0_rtc_gpio_num : 5; +} deep_sleep_config_t; + +static deep_sleep_config_t s_config = { + .pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO }, + .wakeup_triggers = 0 +}; + /* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc() is not thread-safe. */ static _lock_t lock_rtc_memory_crc; -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(); - +static void ext0_wakeup_prepare(); +static void ext1_wakeup_prepare(); /* Wake from deep sleep stub See esp_deepsleep.h esp_wake_deep_sleep() comments for details. @@ -80,6 +92,8 @@ void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) { // ROM code has not started yet, so we need to set delay factor // used by ets_delay_us first. ets_update_cpu_frequency(ets_get_detected_xtal_freq() / 1000000); + // This delay is configured in menuconfig, it can be used to give + // the flash chip some time to become ready. ets_delay_us(CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY); #endif } @@ -94,8 +108,20 @@ void esp_deep_sleep(uint64_t time_in_us) void IRAM_ATTR esp_deep_sleep_start() { + // Decide which power domains can be powered down uint32_t pd_flags = get_power_down_flags(); + // Configure pins for external wakeup + if (s_config.wakeup_triggers & EXT_EVENT0_TRIG_EN) { + ext0_wakeup_prepare(); + } + if (s_config.wakeup_triggers & EXT_EVENT1_TRIG_EN) { + ext1_wakeup_prepare(); + } + // TODO: move timer wakeup configuration into a similar function + // once rtc_sleep is opensourced. + + // Flush UARTs so that output is not lost due to APB frequency change uart_tx_wait_idle(0); uart_tx_wait_idle(1); uart_tx_wait_idle(2); @@ -107,12 +133,18 @@ void IRAM_ATTR esp_deep_sleep_start() rtc_set_cpu_freq(CPU_XTAL); uint32_t cycle_h = 0; uint32_t cycle_l = 0; - if (s_sleep_duration > 0) { + // For timer wakeup, calibrate clock source against main XTAL + // This is hardcoded to use 150kHz internal oscillator for now + if (s_config.sleep_duration > 0) { 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_usec2rtc(s_config.sleep_duration >> 32, s_config.sleep_duration & UINT32_MAX, + period, &cycle_h, &cycle_l); } + // Enter deep sleep rtc_slp_prep_lite(pd_flags, 0); - rtc_sleep(cycle_h, cycle_l, s_wakeup_options, 0); + rtc_sleep(cycle_h, cycle_l, s_config.wakeup_triggers, 0); + // Because RTC is in a slower clock domain than the CPU, it + // can take several CPU cycles for the sleep mode to start. while (1) { ; } @@ -123,7 +155,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 |= RTC_SAR_TRIG_EN; + s_config.wakeup_triggers |= RTC_SAR_TRIG_EN; return ESP_OK; #else return ESP_ERR_INVALID_STATE; @@ -132,8 +164,8 @@ 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 |= RTC_TIMER_EXPIRE_EN; - s_sleep_duration = time_in_us; + s_config.wakeup_triggers |= RTC_TIMER_EXPIRE_EN; + s_config.sleep_duration = time_in_us; return ESP_OK; } @@ -145,15 +177,33 @@ esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level) if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) { return ESP_ERR_INVALID_ARG; } - const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio_num]; - REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, desc->rtc_num); - SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, level, RTC_CNTL_EXT_WAKEUP0_LV_S); - REG_SET_BIT(desc->reg, desc->slpsel); - REG_SET_BIT(desc->reg, desc->slpie); - s_wakeup_options |= RTC_EXT_EVENT0_TRIG_EN; + s_config.ext0_rtc_gpio_num = rtc_gpio_desc[gpio_num].rtc_num; + s_config.ext0_trigger_level = level; + s_config.wakeup_triggers |= RTC_EXT_EVENT0_TRIG_EN; return ESP_OK; } +static void ext0_wakeup_prepare() +{ + int rtc_gpio_num = s_config.ext0_rtc_gpio_num; + // Set GPIO to be used for wakeup + REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, rtc_gpio_num); + // Set level which will trigger wakeup + SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, + s_config.ext0_trigger_level, RTC_CNTL_EXT_WAKEUP0_LV_S); + // Find GPIO descriptor in the rtc_gpio_desc table and configure the pad + for (size_t gpio_num = 0; gpio_num < GPIO_PIN_COUNT; ++gpio_num) { + const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio_num]; + if (desc->rtc_num == rtc_gpio_num) { + REG_SET_BIT(desc->reg, desc->mux); + SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func); + REG_SET_BIT(desc->reg, desc->slpsel); + REG_SET_BIT(desc->reg, desc->slpie); + break; + } + } +} + esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_t mode) { if (mode > ESP_EXT1_WAKEUP_ANY_HIGH) { @@ -169,24 +219,53 @@ esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_ ESP_LOGE(TAG, "Not an RTC IO: GPIO%d", gpio); return ESP_ERR_INVALID_ARG; } - const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio]; - int rtc_pin = desc->rtc_num; - rtc_gpio_mask |= BIT(rtc_pin); - REG_SET_BIT(desc->reg, desc->ie); - REG_SET_BIT(desc->reg, desc->slpsel); - REG_SET_BIT(desc->reg, desc->slpie); - REG_CLR_BIT(desc->reg, desc->pulldown); - REG_CLR_BIT(desc->reg, desc->pullup); - REG_SET_BIT(desc->reg, desc->mux); - REG_SET_BIT(RTC_CNTL_HOLD_FORCE_REG, desc->hold); + rtc_gpio_mask |= BIT(rtc_gpio_desc[gpio].rtc_num); } - REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR); - REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, rtc_gpio_mask); - SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, mode, RTC_CNTL_EXT_WAKEUP1_LV_S); - s_wakeup_options |= RTC_EXT_EVENT1_TRIG_EN; + s_config.ext1_rtc_gpio_mask = rtc_gpio_mask; + s_config.ext1_trigger_mode = mode; + s_config.wakeup_triggers |= RTC_EXT_EVENT1_TRIG_EN; return ESP_OK; } +static void ext1_wakeup_prepare() +{ + // Configure all RTC IOs selected as ext1 wakeup inputs + uint32_t rtc_gpio_mask = s_config.ext1_rtc_gpio_mask; + for (int gpio = 0; gpio < GPIO_PIN_COUNT && rtc_gpio_mask != 0; ++gpio) { + int rtc_pin = rtc_gpio_desc[gpio].rtc_num; + if ((rtc_gpio_mask & BIT(rtc_pin)) == 0) { + continue; + } + const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio]; + // Route pad to RTC + REG_SET_BIT(desc->reg, desc->mux); + SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func); + // Pad configuration depends on RTC_PERIPH state in sleep mode + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_ON) { + // set input enable in sleep mode + REG_SET_BIT(desc->reg, desc->slpie); + // allow sleep status signal to control IE/SLPIE mux + REG_SET_BIT(desc->reg, desc->slpsel); + } else { + // RTC_PERIPH will be disabled, so need to enable input and + // lock pad configuration. Pullups/pulldowns also need to be disabled. + REG_SET_BIT(desc->reg, desc->ie); + REG_CLR_BIT(desc->reg, desc->pulldown); + REG_CLR_BIT(desc->reg, desc->pullup); + REG_SET_BIT(RTC_CNTL_HOLD_FORCE_REG, desc->hold); + } + // Keep track of pins which are processed to bail out early + rtc_gpio_mask &= ~BIT(rtc_pin); + } + // Clear state from previous wakeup + REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR); + // Set pins to be used for wakeup + REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, s_config.ext1_rtc_gpio_mask); + // Set logic function (any low, all high) + SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, + s_config.ext1_trigger_mode, RTC_CNTL_EXT_WAKEUP1_LV_S); +} + uint64_t esp_deep_sleep_get_ext1_wakeup_status() { int wakeup_reason = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE); @@ -196,7 +275,7 @@ uint64_t esp_deep_sleep_get_ext1_wakeup_status() uint32_t status = REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS); // Translate bit map of RTC IO numbers into the bit map of GPIO numbers uint64_t gpio_mask = 0; - for (int gpio = 0; gpio < 40; ++gpio) { + for (int gpio = 0; gpio < GPIO_PIN_COUNT; ++gpio) { if (!RTC_GPIO_IS_VALID_GPIO(gpio)) { continue; } @@ -215,7 +294,7 @@ esp_err_t esp_deep_sleep_pd_config(esp_deep_sleep_pd_domain_t domain, if (domain >= ESP_PD_DOMAIN_MAX || option > ESP_PD_OPTION_AUTO) { return ESP_ERR_INVALID_ARG; } - s_pd_options[domain] = option; + s_config.pd_options[domain] = option; return ESP_OK; } @@ -225,9 +304,9 @@ static uint32_t get_power_down_flags() // 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; + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) { + if (s_config.wakeup_triggers & RTC_SAR_TRIG_EN) { + s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON; } } @@ -236,37 +315,36 @@ static uint32_t get_power_down_flags() // 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; + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] == ESP_PD_OPTION_AUTO) { + s_config.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 & + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) { + if (s_config.wakeup_triggers & (RTC_SAR_TRIG_EN | RTC_EXT_EVENT0_TRIG_EN)) { - s_pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON; + s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON; } } - const char* option_str[] = {"OFF", "ON", "OFF" /* Auto works as OFF */}; + const char* option_str[] = {"OFF", "ON", "AUTO(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]]); + option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]], + option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]], + option_str[s_config.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) { + if (s_config.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) { + if (s_config.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) { + if (s_config.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 8b28f5ffe..63343526b 100644 --- a/components/esp32/include/esp_deep_sleep.h +++ b/components/esp32/include/esp_deep_sleep.h @@ -84,12 +84,17 @@ esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us); * This feature can monitor any pin which is an RTC IO. Once the pin transitions * into the state given by level argument, the chip will be woken up. * + * @note This function does not modify pin configuration. The pin is + * configured in esp_deep_sleep_start, immediately before + * entering deep sleep. + * * @param gpio_num GPIO number used as wakeup source. Only GPIOs which are have RTC * functionality can be used: 0,2,4,12-15,25-27,32-39. * @param level input level which will trigger wakeup (0=low, 1=high) * @return * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if either of the arguments is out of range + * - ESP_ERR_INVALID_ARG if the selected GPIO is not an RTC GPIO, + * or the mode is invalid */ esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); @@ -100,9 +105,18 @@ esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); * It will work even if RTC peripherals are shut down during deep sleep. * * 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, + * Once any of the selected pins goes into the state given by mode argument, * the chip will be woken up. * + * @note This function does not modify pin configuration. The pins are + * configured in esp_deep_sleep_start, immediately before + * entering deep sleep. + * + * @note internal pullups and pulldowns don't work when RTC peripherals are + * shut down. In this case, external resistors need to be added. + * Alternatively, RTC peripherals (and pullups/pulldowns) may be + * kept enabled using esp_deep_sleep_pd_config function. + * * @param mask bit mask of GPIO numbers which will cause wakeup. Only GPIOs * which are have RTC functionality can be used in this bit map: * 0,2,4,12-15,25-27,32-39. @@ -111,7 +125,8 @@ esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level); * - 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 + * - ESP_ERR_INVALID_ARG if any of the selected GPIOs is not an RTC GPIO, + * or mode is invalid */ esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_t mode); @@ -126,7 +141,7 @@ 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(); /** - * @brief Set if specific power domain has to be powered down in deep sleep + * @brief Set power down mode for an RTC power domain in deep sleep * * If not set set using this API, all power domains default to ESP_PD_OPTION_AUTO. * From 628bad1dbfb0cd038f5d0ee7280164e38fea0039 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 16 Dec 2016 14:26:52 +0800 Subject: [PATCH 10/11] deep sleep: add documentation --- components/esp32/include/esp_deep_sleep.h | 15 ---- docs/Doxyfile | 3 +- docs/api/deep_sleep.rst | 87 +++++++++++++++++++++++ docs/index.rst | 1 + 4 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 docs/api/deep_sleep.rst diff --git a/components/esp32/include/esp_deep_sleep.h b/components/esp32/include/esp_deep_sleep.h index 63343526b..a6251e2de 100644 --- a/components/esp32/include/esp_deep_sleep.h +++ b/components/esp32/include/esp_deep_sleep.h @@ -22,13 +22,6 @@ extern "C" { #endif -/** \defgroup Deep_Sleep_API Deep Sleep API - * @brief API for putting device into deep sleep - */ - -/** @addtogroup Deep_Sleep_API - * @{ - */ /** * @brief Logic function used for EXT1 wakeup mode. @@ -234,14 +227,6 @@ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void); */ void esp_default_wake_deep_sleep(void); -/** - * @} - */ - - -/** - * @} - */ #ifdef __cplusplus } diff --git a/docs/Doxyfile b/docs/Doxyfile index e2c85f0de..668ebaba0 100755 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -31,7 +31,8 @@ INPUT = ../components/esp32/include/esp_wifi.h \ ../components/esp32/include/esp_intr_alloc.h \ ../components/esp32/include/esp_heap_alloc_caps.h \ ../components/freertos/include/freertos/heap_regions.h \ - ../components/esp32/include/esp_smartconfig.h + ../components/esp32/include/esp_smartconfig.h \ + ../components/esp32/include/esp_deep_sleep.h ## Get warnings for functions that have no documentation for their parameters or return value ## diff --git a/docs/api/deep_sleep.rst b/docs/api/deep_sleep.rst new file mode 100644 index 000000000..3a458fb4a --- /dev/null +++ b/docs/api/deep_sleep.rst @@ -0,0 +1,87 @@ +Deep Sleep +========== + +Overview +-------- + +ESP32 is capable of deep sleep power saving mode. In this mode CPUs, most of the RAM, and all the digital peripherals which are clocked from APB_CLK are powered off. The only parts of the chip which can still be powered on are: RTC controller, RTC peripherals (including ULP coprocessor), and RTC memories (slow and fast). + +Wakeup from deep sleep mode can be done using several sources. These sources can be combined, in this case the chip will wake up when any one of the sources is triggered. Wakeup sources can be enabled using ``esp_deep_sleep_enable_X_wakeup`` APIs. Next section describes these APIs in detail. Wakeup sources can be configured at any moment before entering deep sleep mode. + +Additionally, the application can force specific powerdown modes for the RTC peripherals and RTC memories using ``esp_deep_sleep_pd_config`` API. + +Once wakeup sources are configured, application can start deep sleep using ``esp_deep_sleep_start`` API. At this point the hardware will be configured according to the requested wakeup sources, and RTC controller will power down the CPUs and digital peripherals. + +Wakeup sources +-------------- + +Timer +^^^^^ + +RTC controller has a built in timer which can be used to wake up the chip after a predefined amount of time. Time is specified at microsecond precision, but the actual resolution depends on the clock source selected for RTC SLOW_CLK. See chapter "Reset and Clock" of the ESP32 Technical Reference Manual for details about RTC clock options. + +This wakeup mode doesn't require RTC peripherals or RTC memories to be powered on during deep sleep. + +The following function can be used to enable deep sleep wakeup using a timer. + +.. doxygenfunction:: esp_deep_sleep_enable_timer_wakeup + + +External wakeup (ext0) +^^^^^^^^^^^^^^^^^^^^^^ + +RTC IO module contains logic to trigger wakeup when one of RTC GPIOs is set to a predefined logic level. RTC IO is part of RTC peripherals power domain, so RTC peripherals will be kept powered on during deep sleep if this wakeup source is requested. + +Because RTC IO module is enabled in this mode, internal pullup or pulldown resistors can also be used. They need to be configured by the application using ``rtc_gpio_pullup_en`` and ``rtc_gpio_pulldown_en`` functions, before calling ``esp_deep_sleep_start``. + +.. doxygenfunction:: esp_deep_sleep_enable_ext0_wakeup + +External wakeup (ext1) +^^^^^^^^^^^^^^^^^^^^^^ + +RTC controller contains logic to trigger wakeup using multiple RTC GPIOs. One of the two logic functions can be used to trigger wakeup: + + - wake up if any of the selected pins is low + - wake up if all the selected pins are high + +This wakeup source is implemented by the RTC controller. As such, RTC peripherals and RTC memories can be powered off in this mode. However, if RTC peripherals are powered down, internal pullup and pulldown resistors will be disabled. To use internal pullup or pulldown resistors, request RTC peripherals power domain to be kept on during deep sleep, and configure pullup/pulldown resistors using ``rtc_gpio_`` functions, before entering deep sleep:: + + esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + gpio_pullup_dis(gpio_num); + gpio_pulldown_en(gpio_num); + +The following function can be used to enable this wakeup mode: + +.. doxygenfunction:: esp_deep_sleep_enable_ext1_wakeup + +.. doxygenenum:: esp_ext1_wakeup_mode_t + + +ULP coprocessor wakeup +^^^^^^^^^^^^^^^^^^^^^^ + +ULP coprocessor can run while the chip is in deep sleep, and may be used to poll sensors, monitor ADC or touch sensor values, and wake up the chip when a specific event is detected. ULP coprocessor is part of RTC peripherals power domain, and it runs the program stored in RTC slow memeory. Therefore RTC peripherals and RTC slow memory will be powered on during deep sleep if this wakeup mode is requested. + +The following function can be used to enable this wakeup mode: + +.. doxygenfunction:: esp_deep_sleep_enable_ulp_wakeup + +Power-down of RTC peripherals and memories +------------------------------------------ + +By default, ``esp_deep_sleep_start`` function will power down all RTC power domains which are not needed by the enabled wakeup sources. To override this behaviour, the following function is provided: + +Note: on the first revision of the ESP32, RTC fast memory will always be kept enabled in deep sleep, so that the deep sleep stub can run after reset. This can be overriden, if the application doesn't need clean reset behaviour after deep sleep. + +.. doxygenfunction:: esp_deep_sleep_pd_config +.. doxygenenum:: esp_deep_sleep_pd_domain_t +.. doxygenenum:: esp_deep_sleep_pd_option_t + + +Entering deep sleep +------------------- + +The following function can be used to enter deep sleep once wakeup sources are configured. It is also possible to go into deep sleep with no wakeup sources configured, in this case the chip will be in deep sleep mode indefinetly, until external reset is applied. + +.. doxygenfunction:: esp_deep_sleep_start + diff --git a/docs/index.rst b/docs/index.rst index f6ee6a133..350d37cda 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -114,6 +114,7 @@ Contents: Ethernet Interrupt Allocation Memory Allocation + Deep Sleep deep-sleep-stub Template From 126d1642832a905c4f0dcd573f81b636b9acd492 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 16 Dec 2016 14:27:22 +0800 Subject: [PATCH 11/11] docs: fix some warnings --- docs/api/nvs_flash.rst | 1 - docs/api/pcnt.rst | 2 +- docs/index.rst | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/nvs_flash.rst b/docs/api/nvs_flash.rst index a765f7608..e2ac34ada 100644 --- a/docs/api/nvs_flash.rst +++ b/docs/api/nvs_flash.rst @@ -87,5 +87,4 @@ Functions .. doxygenfunction:: nvs_commit .. doxygenfunction:: nvs_close .. doxygenfunction:: nvs_flash_init -.. doxygenfunction:: nvs_flash_init_custom diff --git a/docs/api/pcnt.rst b/docs/api/pcnt.rst index 08450b64a..7fe73e6f4 100644 --- a/docs/api/pcnt.rst +++ b/docs/api/pcnt.rst @@ -1,5 +1,5 @@ Pulse Counter -======== +============= Overview -------- diff --git a/docs/index.rst b/docs/index.rst index 350d37cda..901187d80 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -35,6 +35,7 @@ Contents: partition-tables build_system openocd + Flash encryption Secure Boot ULP coprocessor