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 5196b058a..3fc328764 100644 --- a/components/driver/include/driver/rtc_io.h +++ b/components/driver/include/driver/rtc_io.h @@ -27,139 +27,160 @@ 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; /*!< 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; /*!< 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 */ } 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); +/** + * @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 ecb7e434d..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, 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, 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/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/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: 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/deep_sleep.c b/components/esp32/deep_sleep.c new file mode 100644 index 000000000..7f59c2163 --- /dev/null +++ b/components/esp32/deep_sleep.c @@ -0,0 +1,350 @@ +// 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. + +#include +#include +#include "esp_attr.h" +#include "esp_deep_sleep.h" +#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" +#include "driver/rtc_io.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#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 const char* TAG = "deepsleep"; + +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. +*/ +esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void) +{ + _lock_acquire(&lock_rtc_memory_crc); + uint32_t stored_crc = REG_READ(RTC_MEMORY_CRC_REG); + set_rtc_memory_crc(); + uint32_t calc_crc = REG_READ(RTC_MEMORY_CRC_REG); + REG_WRITE(RTC_MEMORY_CRC_REG, stored_crc); + _lock_release(&lock_rtc_memory_crc); + + if(stored_crc == calc_crc) { + return (esp_deep_sleep_wake_stub_fn_t)REG_READ(RTC_ENTRY_ADDR_REG); + } else { + return NULL; + } +} + +void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub) +{ + _lock_acquire(&lock_rtc_memory_crc); + REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub); + set_rtc_memory_crc(); + _lock_release(&lock_rtc_memory_crc); +} + +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); + // 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 +} + +void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void); + +void esp_deep_sleep(uint64_t time_in_us) +{ + esp_deep_sleep_enable_timer_wakeup(time_in_us); + esp_deep_sleep_start(); +} + +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); + + if (esp_get_deep_sleep_wake_stub() == NULL) { + esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); + } + + rtc_set_cpu_freq(CPU_XTAL); + uint32_t cycle_h = 0; + uint32_t cycle_l = 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_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_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) { + ; + } +} + +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_config.wakeup_triggers |= RTC_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_config.wakeup_triggers |= RTC_TIMER_EXPIRE_EN; + s_config.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; + } + 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) { + 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; + } + rtc_gpio_mask |= BIT(rtc_gpio_desc[gpio].rtc_num); + } + 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); + 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 < GPIO_PIN_COUNT; ++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; +} + +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_config.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_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; + } + } + + // 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_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_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_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON; + } + } + + 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_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_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] != ESP_PD_OPTION_ON) { + pd_flags |= DEEP_SLEEP_PD_RTC_FAST_MEM; + } + 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_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) { + pd_flags |= DEEP_SLEEP_PD_RTC_PERIPH; + } + return pd_flags; +} diff --git a/components/esp32/deepsleep.c b/components/esp32/deepsleep.c deleted file mode 100644 index b8b73a3b1..000000000 --- a/components/esp32/deepsleep.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Wake from deep sleep stub - - See esp_deepsleep.h esp_wake_deep_sleep() comments for details. -*/ -#include -#include -#include "rom/cache.h" -#include "rom/rtc.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/dport_reg.h" -#include "esp_attr.h" -#include "esp_deepsleep.h" -#include "rtc.h" - -/* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc() - is not thread-safe. */ -static _lock_t lock_rtc_memory_crc; - -esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void) -{ - _lock_acquire(&lock_rtc_memory_crc); - uint32_t stored_crc = REG_READ(RTC_MEMORY_CRC_REG); - set_rtc_memory_crc(); - uint32_t calc_crc = REG_READ(RTC_MEMORY_CRC_REG); - REG_WRITE(RTC_MEMORY_CRC_REG, stored_crc); - _lock_release(&lock_rtc_memory_crc); - - if(stored_crc == calc_crc) { - return (esp_deep_sleep_wake_stub_fn_t)REG_READ(RTC_ENTRY_ADDR_REG); - } else { - return NULL; - } -} - -void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub) -{ - _lock_acquire(&lock_rtc_memory_crc); - REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub); - set_rtc_memory_crc(); - _lock_release(&lock_rtc_memory_crc); -} - -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); -} - -void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void); - -void esp_deep_sleep(uint64_t time_in_us) -{ - rtc_set_cpu_freq(CPU_XTAL); - 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); - while (1) { - ; - } -} - -void system_deep_sleep(uint64_t) __attribute__((alias("esp_deep_sleep"))); diff --git a/components/esp32/include/esp_deep_sleep.h b/components/esp32/include/esp_deep_sleep.h new file mode 100644 index 000000000..a6251e2de --- /dev/null +++ b/components/esp32/include/esp_deep_sleep.h @@ -0,0 +1,233 @@ +// 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 + + +/** + * @brief Logic function used for EXT1 wakeup mode. + */ +typedef enum { + 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 Power domains which can be powered down in deep sleep + */ +typedef enum { + 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 Power down options + */ +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 + * @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. + * + * @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 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); + +/** + * @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 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. + * @param mode select logic function used to determine wakeup condition: + * - 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 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); + + +/** + * @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 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. + * + * @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 + * + * This function does not return. + */ +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 + * + * 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 051ad14c3..fe5364996 100644 --- a/components/esp32/include/esp_deepsleep.h +++ b/components/esp32/include/esp_deepsleep.h @@ -1,114 +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. - -#ifndef __ESP_DEEPSLEEP_H__ -#define __ESP_DEEPSLEEP_H_ - -#include - -#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 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. - * - * 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 - * - * 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 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. -*/ -void esp_default_wake_deep_sleep(void); - -/** - * @} - */ - - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __ESP_SYSTEM_H__ */ +#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_deep_sleep.c b/components/esp32/test/test_deep_sleep.c new file mode 100644 index 000000000..a47b6daf3 --- /dev/null +++ b/components/esp32/test/test_deep_sleep.c @@ -0,0 +1,93 @@ +#include "unity.h" +#include "esp_deep_sleep.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("wake up using timer", "[deepsleep]") +{ + esp_deep_sleep_enable_timer_wakeup(2000000); + esp_deep_sleep_start(); +} + +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("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)); + 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("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)); + 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("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(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 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(); +} 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" 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/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 f6ee6a133..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 @@ -114,6 +115,7 @@ Contents: Ethernet Interrupt Allocation Memory Allocation + Deep Sleep deep-sleep-stub Template 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"