Merge branch 'feature/extend_deep_sleep_apis' into 'master'

extend deep sleep APIs

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

Add an API to control which peripherals are kept enabled in deep sleep mode:
- esp_err_t esp_deep_sleep_pd_config

Also rolled an update of rtc_io header comments into this MR, as I had to add `slpie`, `slpsel`, and `hold` fields into `rtc_gpio_desc_t` struct.

Deep sleep unit tests don’t do anything useful in CI context because we don’t have a way to check reset behavior (time till reset, reason for reset) in CI environment, yet. Also for external wakeup we would need to control some ESP32 pins from the test environment.

Currently there is one known issue:
- RTC Fast memory may be isolated from the bus after deep sleep reset. We work around this by setting FORCE_NONISO flag in RTC power control register. This is non-optimal and we will keep looking for the reason why isolation gets enabled.

See merge request !297
This commit is contained in:
Ivan Grokhotkov 2016-12-16 16:17:37 +08:00
commit 576052e5c2
20 changed files with 926 additions and 279 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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
---------------------------------------------------------------*/

View file

@ -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

View file

@ -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:

View file

@ -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);

View file

@ -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 <stddef.h>
#include <sys/lock.h>
#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;
}

View file

@ -1,67 +0,0 @@
/* Wake from deep sleep stub
See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
*/
#include <stddef.h>
#include <sys/lock.h>
#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")));

View file

@ -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 <stdint.h>
#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

View file

@ -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 <stdint.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 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"

View file

@ -18,7 +18,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "esp_deepsleep.h"
#include "esp_deep_sleep.h"
#ifdef __cplusplus
extern "C" {

View file

@ -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();
}

View file

@ -0,0 +1 @@
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View file

@ -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"

View file

@ -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
##

87
docs/api/deep_sleep.rst Normal file
View file

@ -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

View file

@ -87,5 +87,4 @@ Functions
.. doxygenfunction:: nvs_commit
.. doxygenfunction:: nvs_close
.. doxygenfunction:: nvs_flash_init
.. doxygenfunction:: nvs_flash_init_custom

View file

@ -1,5 +1,5 @@
Pulse Counter
========
=============
Overview
--------

View file

@ -35,6 +35,7 @@ Contents:
partition-tables
build_system
openocd
Flash encryption <security/flash-encryption>
Secure Boot <security/secure-boot>
ULP coprocessor <api/ulp.rst>
@ -114,6 +115,7 @@ Contents:
Ethernet <api/esp_eth>
Interrupt Allocation <api/intr_alloc>
Memory Allocation <api/mem_alloc>
Deep Sleep <api/deep_sleep>
deep-sleep-stub
Template <api/template>

View file

@ -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"