feat(touch): allow RTC power down during the deep sleep

This commit is contained in:
laokaiyao 2024-11-28 11:48:01 +08:00
parent 612236bfd9
commit 678ddba550
12 changed files with 229 additions and 76 deletions

View File

@ -83,15 +83,21 @@ struct touch_sensor_s {
uint8_t sample_cfg_num; /*!< The number of sample configurations that in used */
void *user_ctx; /*!< User context that will pass to the callback function */
bool is_enabled; /*!< Flag to indicate whether the scanning is enabled */
bool is_started; /*!< Flag to indicate whether the scanning has started */
bool is_meas_timeout; /*!< Flag to indicate whether the measurement timeout, will force to stop the current measurement if the timeout is triggered */
bool sleep_en; /*!< Flag to indicate whether the sleep wake-up feature is enabled */
bool waterproof_en; /*!< Flag to indicate whether the water proof feature is enabled */
bool immersion_proof; /*!< Flag to indicate whether to disable scanning when the guard ring is triggered */
bool proximity_en; /*!< Flag to indicate whether the proximity sensing feature is enabled */
bool timeout_en; /*!< Flag to indicate whether the measurement timeout feature (hardware timeout) is enabled */
bool denoise_en; /*!< Flag to indicate whether the denoise channel feature is enabled */
union {
struct {
bool is_enabled : 1; /*!< Flag to indicate whether the scanning is enabled */
bool is_started : 1; /*!< Flag to indicate whether the scanning has started */
bool is_meas_timeout : 1; /*!< Flag to indicate whether the measurement timeout, will force to stop the current measurement if the timeout is triggered */
bool sleep_en : 1; /*!< Flag to indicate whether the sleep wake-up feature is enabled */
bool allow_pd : 1; /*!< Flag to indicate whether allow RTC_PERIPH power down during the sleep */
bool waterproof_en : 1; /*!< Flag to indicate whether the water proof feature is enabled */
bool immersion_proof : 1; /*!< Flag to indicate whether to disable scanning when the guard ring is triggered */
bool proximity_en : 1; /*!< Flag to indicate whether the proximity sensing feature is enabled */
bool timeout_en : 1; /*!< Flag to indicate whether the measurement timeout feature (hardware timeout) is enabled */
bool denoise_en : 1; /*!< Flag to indicate whether the denoise channel feature is enabled */
};
uint32_t flags;
};
};
/**

View File

@ -171,15 +171,54 @@ typedef struct {
*/
typedef touch_sensor_config_t touch_sensor_config_dslp_t;
/**
* @brief Helper macro to the default light sleep wake-up configurations
* @note RTC_PERIPH will keep power on during the light sleep.
* Any enabled touch channel can wake-up the chip from light sleep.
*/
#define TOUCH_SENSOR_DEFAULT_LSLP_CONFIG() { \
.slp_wakeup_lvl = TOUCH_LIGHT_SLEEP_WAKEUP, \
}
/**
* @brief Helper macro to the default deep sleep wake-up configurations
* @note RTC_PERIPH will keep power on during the deep sleep.
* Any enabled touch channel can wake-up the chip from deep sleep.
*/
#define TOUCH_SENSOR_DEFAULT_DSLP_CONFIG() { \
.slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, \
}
/**
* @brief Helper macro to the default deep sleep wake-up configurations
* (allow RTC_PERIPH power down in deep sleep)
* @note RTC_PERIPH might be powered down during the deep sleep.
* If the RTC_PERIPH is powered down, only the specified sleep channel can wake-up the chip from deep sleep.
* @param[in] dslp_chan The specified sleep channel that can wake-up the chip from deep sleep while RTC_PERIPH is powered down.
* @param[in] ... The threshold of each sample configuration of the specified sleep channel.
*/
#define TOUCH_SENSOR_DEFAULT_DSLP_PD_CONFIG(dslp_chan, ...) { \
.slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, \
.deep_slp_allow_pd = true, \
.deep_slp_chan = dslp_chan, \
.deep_slp_thresh = {__VA_ARGS__}, \
}
/**
* @brief Configuration of the touch sensor sleep function
*
*/
typedef struct {
touch_sleep_wakeup_level_t slp_wakeup_lvl; /*!< The sleep level that can be woke up by touch sensor. */
touch_channel_handle_t deep_slp_chan; /*!< The touch channel handle that supposed to work in the deep sleep. It can wake up the chip
* from deep sleep when this channel is activated.
bool deep_slp_allow_pd; /*!< Whether allow RTC power down during the deep sleep.
* Only effective when the `touch_sleep_config_t::slp_wakeup_lvl` is `TOUCH_DEEP_SLEEP_WAKEUP`.
* - If true, the RTC power domain will be powered down during the deep sleep.
* - If false, the RTC power domain will keep power on during the deep sleep.
*/
touch_channel_handle_t deep_slp_chan; /*!< The touch channel handle that supposed to work in the deep sleep even RTC domain is powered down.
* Only effective when the `touch_sleep_config_t::slp_wakeup_lvl` is `TOUCH_DEEP_SLEEP_WAKEUP`
* - Not NULL: Only this channel can wake up the chip from deep sleep.
* - NULL: `deep_slp_allow_pd` must be false, and any enabled channels can wake up the chip from deep sleep.
*/
uint32_t deep_slp_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The active threshold of the deep sleep channel during deep sleep,
* while the sleep channel exceed this threshold, it will be regarded as activated

View File

@ -171,9 +171,8 @@ static esp_err_t s_touch_convert_to_hal_config(touch_sensor_handle_t sens_handle
TOUCH_LL_PAD_MEASURE_WAIT_MAX : hal_cfg->power_on_wait_ticks;
hal_cfg->meas_interval_ticks = (uint32_t)(sens_cfg->meas_interval_us * src_freq_mhz);
hal_cfg->timeout_ticks = (uint32_t)sens_cfg->max_meas_time_us * src_freq_mhz;
uint32_t max_meas_time_ms = TOUCH_LL_TIMEOUT_MAX * 1000 / sens_handle->src_freq_hz;
ESP_RETURN_ON_FALSE(hal_cfg->timeout_ticks <= TOUCH_LL_TIMEOUT_MAX, ESP_ERR_INVALID_ARG, TAG,
"max_meas_time_ms should within %"PRIu32" ms", max_meas_time_ms);
"max_meas_time_ms should within %"PRIu32" ms", TOUCH_LL_TIMEOUT_MAX / (sens_handle->src_freq_hz / 1000));
hal_cfg->sample_cfg_num = sens_cfg->sample_cfg_num; // Only one sample cfg
hal_cfg->sample_cfg = (touch_hal_sample_config_t *)sens_cfg->sample_cfg;
return ESP_OK;
@ -308,6 +307,7 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co
int dp_slp_chan_id = -1;
touch_hal_config_t hal_cfg = {};
touch_hal_config_t *hal_cfg_ptr = NULL;
esp_sleep_pd_option_t slp_opt = ESP_PD_OPTION_AUTO;
xSemaphoreTakeRecursive(sens_handle->mutex, portMAX_DELAY);
ESP_GOTO_ON_FALSE(!sens_handle->is_enabled, ESP_ERR_INVALID_STATE, err, TAG, "Please disable the touch sensor first");
@ -316,17 +316,19 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co
ESP_GOTO_ON_FALSE(sleep_cfg->slp_wakeup_lvl == TOUCH_LIGHT_SLEEP_WAKEUP || sleep_cfg->slp_wakeup_lvl == TOUCH_DEEP_SLEEP_WAKEUP,
ESP_ERR_INVALID_ARG, err, TAG, "Invalid sleep level");
/* Enabled touch sensor as wake-up source */
esp_sleep_enable_touchpad_wakeup();
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
// Keep ESP_PD_DOMAIN_RTC_PERIPH power domain on during the light/deep sleep, so that to keep the touch sensor working
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
#endif // SOC_PM_SUPPORT_RC_FAST_PD
ESP_GOTO_ON_ERROR(esp_sleep_enable_touchpad_wakeup(), err, TAG, "Failed to enable touch sensor wakeup");
/* If set the deep sleep channel (i.e., enable deep sleep wake-up),
configure the deep sleep related settings. */
if (sleep_cfg->slp_wakeup_lvl == TOUCH_DEEP_SLEEP_WAKEUP) {
ESP_GOTO_ON_FALSE(sleep_cfg->deep_slp_chan, ESP_ERR_INVALID_ARG, err, TAG, "deep sleep waken channel can't be NULL");
dp_slp_chan_id = sleep_cfg->deep_slp_chan->id;
if (sleep_cfg->deep_slp_allow_pd) {
ESP_GOTO_ON_FALSE(sleep_cfg->deep_slp_chan, ESP_ERR_INVALID_ARG, err, TAG,
"deep sleep waken channel can't be NULL when allow RTC power down");
} else {
/* Keep the RTC_PERIPH power domain on in deep sleep */
slp_opt = ESP_PD_OPTION_ON;
}
sens_handle->allow_pd = sleep_cfg->deep_slp_allow_pd;
/* Check and convert the configuration to hal configurations */
if (sleep_cfg->deep_slp_sens_cfg) {
@ -334,26 +336,42 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co
ESP_GOTO_ON_ERROR(s_touch_convert_to_hal_config(sens_handle, sleep_cfg->deep_slp_sens_cfg, hal_cfg_ptr),
err, TAG, "parse the configuration failed due to the invalid configuration");
}
sens_handle->sleep_en = true;
sens_handle->deep_slp_chan = sleep_cfg->deep_slp_chan;
if (sleep_cfg->deep_slp_chan) {
dp_slp_chan_id = sleep_cfg->deep_slp_chan->id;
}
TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK);
touch_ll_sleep_set_threshold(sleep_cfg->deep_slp_thresh[0]);
TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK);
} else {
/* Keep the RTC_PERIPH power domain on in light sleep */
sens_handle->allow_pd = false;
slp_opt = ESP_PD_OPTION_ON;
}
sens_handle->sleep_en = true;
} else {
/* Disable the touch sensor as wake-up source */
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TOUCHPAD);
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO);
#endif // SOC_PM_SUPPORT_RC_FAST_PD
if (sens_handle->sleep_en && !sens_handle->allow_pd) {
/* No longer hold the RTC_PERIPH power by touch sensor */
slp_opt = ESP_PD_OPTION_OFF;
}
sens_handle->allow_pd = false;
sens_handle->deep_slp_chan = NULL;
sens_handle->sleep_en = false;
}
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
esp_sleep_pd_domain_t pd_domain = ESP_PD_DOMAIN_RTC_PERIPH;
#else
#warning "RTC_PERIPH power domain is not supported"
esp_sleep_pd_domain_t pd_domain = ESP_PD_DOMAIN_MAX;
#endif // SOC_PM_SUPPORT_RTC_PERIPH_PD
ESP_GOTO_ON_ERROR(esp_sleep_pd_config(pd_domain, slp_opt), err, TAG, "Failed to set RTC_PERIPH power domain");
/* Save or update the sleep config */
TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK);
touch_hal_save_sleep_config(dp_slp_chan_id, hal_cfg_ptr);
touch_hal_save_sleep_config(dp_slp_chan_id, hal_cfg_ptr, sens_handle->allow_pd);
TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK);
err:

View File

@ -174,15 +174,54 @@ typedef struct {
*/
typedef touch_sensor_config_t touch_sensor_config_dslp_t;
/**
* @brief Helper macro to the default light sleep wake-up configurations
* @note RTC_PERIPH will keep power on during the light sleep.
* Any enabled touch channel can wake-up the chip from light sleep.
*/
#define TOUCH_SENSOR_DEFAULT_LSLP_CONFIG() { \
.slp_wakeup_lvl = TOUCH_LIGHT_SLEEP_WAKEUP, \
}
/**
* @brief Helper macro to the default deep sleep wake-up configurations
* @note RTC_PERIPH will keep power on during the deep sleep.
* Any enabled touch channel can wake-up the chip from deep sleep.
*/
#define TOUCH_SENSOR_DEFAULT_DSLP_CONFIG() { \
.slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, \
}
/**
* @brief Helper macro to the default deep sleep wake-up configurations
* (allow RTC_PERIPH power down in deep sleep)
* @note RTC_PERIPH might be powered down during the deep sleep.
* If the RTC_PERIPH is powered down, only the specified sleep channel can wake-up the chip from deep sleep.
* @param[in] dslp_chan The specified sleep channel that can wake-up the chip from deep sleep while RTC_PERIPH is powered down.
* @param[in] ... The threshold of each sample configuration of the specified sleep channel.
*/
#define TOUCH_SENSOR_DEFAULT_DSLP_PD_CONFIG(dslp_chan, ...) { \
.slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, \
.deep_slp_allow_pd = true, \
.deep_slp_chan = dslp_chan, \
.deep_slp_thresh = {__VA_ARGS__}, \
}
/**
* @brief Configuration of the touch sensor sleep function
*
*/
typedef struct {
touch_sleep_wakeup_level_t slp_wakeup_lvl; /*!< The sleep level that can be woke up by touch sensor. */
touch_channel_handle_t deep_slp_chan; /*!< The touch channel handle that supposed to work in the deep sleep. It can wake up the chip
* from deep sleep when this channel is activated.
bool deep_slp_allow_pd; /*!< Whether allow RTC power down during the deep sleep.
* Only effective when the `touch_sleep_config_t::slp_wakeup_lvl` is `TOUCH_DEEP_SLEEP_WAKEUP`.
* - If true, the RTC power domain will be powered down during the deep sleep.
* - If false, the RTC power domain will keep power on during the deep sleep.
*/
touch_channel_handle_t deep_slp_chan; /*!< The touch channel handle that supposed to work in the deep sleep even RTC domain is powered down.
* Only effective when the `touch_sleep_config_t::slp_wakeup_lvl` is `TOUCH_DEEP_SLEEP_WAKEUP`
* - Not NULL: Only this channel can wake up the chip from deep sleep.
* - NULL: `deep_slp_allow_pd` must be false, and any enabled channels can wake up the chip from deep sleep.
*/
uint32_t deep_slp_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The active threshold of the deep sleep channel during deep sleep,
* while the sleep channel exceed this threshold, it will be regarded as activated

View File

@ -319,6 +319,7 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co
.sample_cfg = sample_cfg,
};
touch_hal_config_t *hal_cfg_ptr = NULL;
esp_sleep_pd_option_t slp_opt = ESP_PD_OPTION_AUTO;
xSemaphoreTakeRecursive(sens_handle->mutex, portMAX_DELAY);
ESP_GOTO_ON_FALSE(!sens_handle->is_enabled, ESP_ERR_INVALID_STATE, err, TAG, "Please disable the touch sensor first");
@ -328,46 +329,67 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co
ESP_ERR_INVALID_ARG, err, TAG, "Invalid sleep level");
/* Enabled touch sensor as wake-up source */
ESP_GOTO_ON_ERROR(esp_sleep_enable_touchpad_wakeup(), err, TAG, "Failed to enable touch sensor wakeup");
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
// Keep ESP_PD_DOMAIN_RTC_PERIPH power domain on during the light/deep sleep, so that to keep the touch sensor working
ESP_GOTO_ON_ERROR(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON), err, TAG, "Failed to keep touch sensor module clock during the sleep");
#endif
/* If set the deep sleep channel (i.e., enable deep sleep wake-up),
configure the deep sleep related settings. */
if (sleep_cfg->slp_wakeup_lvl == TOUCH_DEEP_SLEEP_WAKEUP) {
ESP_GOTO_ON_FALSE(sleep_cfg->deep_slp_chan, ESP_ERR_INVALID_ARG, err, TAG, "deep sleep waken channel can't be NULL");
dp_slp_chan_id = sleep_cfg->deep_slp_chan->id;
if (sleep_cfg->deep_slp_allow_pd) {
ESP_GOTO_ON_FALSE(sleep_cfg->deep_slp_chan, ESP_ERR_INVALID_ARG, err, TAG,
"deep sleep waken channel can't be NULL when allow RTC power down");
} else {
/* Keep the RTC_PERIPH power domain on in deep sleep */
slp_opt = ESP_PD_OPTION_ON;
}
sens_handle->allow_pd = sleep_cfg->deep_slp_allow_pd;
/* Check and convert the configuration to hal configurations */
if (sleep_cfg->deep_slp_sens_cfg) {
hal_cfg_ptr = &hal_cfg;
ESP_GOTO_ON_ERROR(s_touch_convert_to_hal_config(sens_handle, (const touch_sensor_config_t *)sleep_cfg->deep_slp_sens_cfg, hal_cfg_ptr),
ESP_GOTO_ON_ERROR(s_touch_convert_to_hal_config(sens_handle, sleep_cfg->deep_slp_sens_cfg, hal_cfg_ptr),
err, TAG, "parse the configuration failed due to the invalid configuration");
}
sens_handle->sleep_en = true;
sens_handle->deep_slp_chan = sleep_cfg->deep_slp_chan;
if (sleep_cfg->deep_slp_chan) {
dp_slp_chan_id = sleep_cfg->deep_slp_chan->id;
}
TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK);
/* Set sleep threshold */
for (uint8_t smp_cfg_id = 0; smp_cfg_id < TOUCH_SAMPLE_CFG_NUM; smp_cfg_id++) {
touch_ll_sleep_set_threshold(smp_cfg_id, sleep_cfg->deep_slp_thresh[smp_cfg_id]);
}
/* Set max wait ticks to ensure PMU is ready for touch measurement during the sleep.
Otherwise a small wait ticks will make the touch fail to work and can't wake-up the chip */
touch_ll_sleep_set_measure_wait_ticks(TOUCH_LL_SLP_MEASURE_WAIT_MAX);
TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK);
} else {
/* Keep the RTC_PERIPH power domain on in light sleep */
sens_handle->allow_pd = false;
slp_opt = ESP_PD_OPTION_ON;
}
sens_handle->sleep_en = true;
} else {
/* Disable the touch sensor as wake-up source */
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TOUCHPAD);
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO);
#endif
if (sens_handle->sleep_en && !sens_handle->allow_pd) {
/* No longer hold the RTC_PERIPH power by touch sensor */
slp_opt = ESP_PD_OPTION_OFF;
}
sens_handle->allow_pd = false;
sens_handle->deep_slp_chan = NULL;
sens_handle->sleep_en = false;
}
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
esp_sleep_pd_domain_t pd_domain = ESP_PD_DOMAIN_RTC_PERIPH;
#else
#warning "RTC_PERIPH power domain is not supported"
esp_sleep_pd_domain_t pd_domain = ESP_PD_DOMAIN_MAX;
#endif // SOC_PM_SUPPORT_RTC_PERIPH_PD
ESP_GOTO_ON_ERROR(esp_sleep_pd_config(pd_domain, slp_opt), err, TAG, "Failed to set RTC_PERIPH power domain");
/* Save or update the sleep config */
TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK);
touch_hal_save_sleep_config(dp_slp_chan_id, hal_cfg_ptr);
touch_hal_save_sleep_config(dp_slp_chan_id, hal_cfg_ptr, sens_handle->allow_pd);
TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK);
err:

View File

@ -866,6 +866,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
misc_modules_sleep_prepare(pd_flags, deep_sleep);
#if SOC_TOUCH_SENSOR_VERSION >= 2
bool keep_rtc_power_on = false;
if (deep_sleep) {
if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) {
touch_wakeup_prepare();
@ -873,22 +874,24 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
/* Workaround: In deep sleep, for ESP32S2, Power down the RTC_PERIPH will change the slope configuration of Touch sensor sleep pad.
* The configuration change will change the reading of the sleep pad, which will cause the touch wake-up sensor to trigger falsely.
*/
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
keep_rtc_power_on = true;
#elif CONFIG_IDF_TARGET_ESP32P4
/* Due to esp32p4 eco0 hardware bug, if LP peripheral power domain is powerdowned in sleep, there will be a possibility of
* triggering the EFUSE_CRC reset, so disable the power-down of this power domain on lightsleep for ECO0 version.
*/
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
keep_rtc_power_on = true;
}
#endif
}
} else {
/* In light sleep, the RTC_PERIPH power domain should be in the power-on state (Power on the touch circuit in light sleep),
* otherwise the touch sensor FSM will be cleared, causing touch sensor false triggering.
*/
bool keep_rtc_power_on = touch_ll_is_fsm_repeated_timer_enabled();
if (keep_rtc_power_on) { // Check if the touch sensor is working properly.
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
}
keep_rtc_power_on |= touch_ll_is_fsm_repeated_timer_enabled();
}
#elif CONFIG_IDF_TARGET_ESP32P4
/* Due to esp32p4 eco0 hardware bug, if LP peripheral power domain is powerdowned in sleep, there will be a possibility of
triggering the EFUSE_CRC reset, so disable the power-down of this power domain on lightsleep for ECO0 version. */
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
/* Whether need to keep RTC_PERIPH power on eventually */
if (keep_rtc_power_on) {
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
}
#endif

View File

@ -52,6 +52,7 @@ extern "C" {
#define TOUCH_LL_ACTIVE_THRESH_MAX (0xFFFF) // Max channel active threshold
#define TOUCH_LL_CLK_DIV_MAX (0x08) // Max clock divider value
#define TOUCH_LL_TIMEOUT_MAX (0xFFFF) // Max timeout value
#define TOUCH_LL_SLP_MEASURE_WAIT_MAX (0x1FF) // Max wait ticks to wait PMU entering HP SLEEP status during the sleep.
/**
* Enable/disable clock gate of touch sensor.
@ -944,6 +945,21 @@ static inline void touch_ll_sleep_set_threshold(uint8_t sample_cfg_id, uint32_t
}
}
/**
* Set the touch sensor wait ticks after PMU is woken up by touch timer during the sleep.
* @note The PMU will be woken up after the measure interval timer time-up,
* PMU needs some time to prepare the clock and power for the touch sensor,
* If the wait ticks is too short, the touch sensor can't work properly and fail to wakeup the chip from sleep.
*
* @param wait_ticks The wait ticks after PMU is woken up by touch FSM during the sleep.
* Typically recommended to set it to the max value,
* the PMU will start the touch sensor FSM immediately after the PMU enters HP SLEEP state.
*/
static inline void touch_ll_sleep_set_measure_wait_ticks(uint32_t wait_ticks)
{
PMU.touch_pwr_cntl.wait_cycles = wait_ticks;
}
/**
* Enable proximity sensing function for sleep channel.
*/

View File

@ -101,8 +101,9 @@ void touch_hal_config_controller(const touch_hal_config_t *cfg);
*
* @param[in] deep_slp_chan The touch sensor channel that can wake-up the chip from deep sleep
* @param[in] deep_slp_cfg The hardware configuration that takes effect during the deep sleep
* @param[in] dslp_allow_pd Whether allow RTC_PERIPH domain power down during the deep sleep
*/
void touch_hal_save_sleep_config(int deep_slp_chan, const touch_hal_config_t *deep_slp_cfg);
void touch_hal_save_sleep_config(int deep_slp_chan, const touch_hal_config_t *deep_slp_cfg, bool dslp_allow_pd);
/**
* @brief Prepare for the deep sleep

View File

@ -12,6 +12,7 @@
typedef struct {
bool deep_slp_allow_pd;
int deep_slp_chan;
touch_hal_config_t slp_cfg;
bool apply_slp_cfg;
@ -52,11 +53,12 @@ void touch_hal_config_controller(const touch_hal_config_t *cfg)
#endif
}
void touch_hal_save_sleep_config(int deep_slp_chan, const touch_hal_config_t *deep_slp_cfg)
void touch_hal_save_sleep_config(int deep_slp_chan, const touch_hal_config_t *deep_slp_cfg, bool dslp_allow_pd)
{
s_touch_slp_obj.deep_slp_chan = deep_slp_chan;
s_touch_slp_obj.deep_slp_allow_pd = dslp_allow_pd;
/* If particular deep sleep configuration is given, save it and apply it before entering the deep sleep */
if (deep_slp_chan >= 0 && deep_slp_cfg) {
if (deep_slp_cfg) {
s_touch_slp_obj.apply_slp_cfg = true;
memcpy(&s_touch_slp_obj.slp_cfg, deep_slp_cfg, sizeof(touch_hal_config_t));
} else {
@ -73,8 +75,13 @@ static void s_touch_hal_apply_sleep_config(void)
}
/* Whether to enable touch sensor wake-up the chip from deep sleep */
if (s_touch_slp_obj.deep_slp_chan >= 0) {
touch_ll_sleep_set_channel_num(s_touch_slp_obj.deep_slp_chan);
touch_ll_enable_channel_mask(BIT(s_touch_slp_obj.deep_slp_chan));
if (s_touch_slp_obj.deep_slp_allow_pd) {
touch_ll_sleep_set_channel_num(s_touch_slp_obj.deep_slp_chan);
} else {
/* If not allow power down but sleep channel is set, then only enable this channel during the deep sleep */
touch_ll_sleep_set_channel_num(TOUCH_LL_NULL_CHANNEL);
touch_ll_enable_channel_mask(BIT(s_touch_slp_obj.deep_slp_chan));
}
} else {
touch_ll_sleep_set_channel_num(TOUCH_LL_NULL_CHANNEL);
}

View File

@ -380,24 +380,26 @@ Call :cpp:func:`touch_channel_read_data` to read the data with different types.
- Light sleep wake-up: you need to set :cpp:member:`slp_wakeup_lvl` to :cpp:enumerator:`TOUCH_LIGHT_SLEEP_WAKEUP` to enable the light sleep wake-up by touch sensor. Note that any registered touch channel can wake-up the chip from light sleep.
- Deep sleep wake-up: beside setting :cpp:member:`slp_wakeup_lvl` to :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP`, you need to specify :cpp:member:`deep_slp_chan` additionally. In order to reduce the power consumption, only the specified channel can wake-up the chip from the deep sleep when RTC_PREI power domain off. And also, the driver supports to store another set of configurations for the deep sleep via :cpp:member:`deep_slp_sens_cfg`, this set of configurations only takes effect during the deep sleep, you can customize the configurations to save more power. The configurations will be reset to the previous set after waking-up from the deep sleep. Please be aware that, not only deep sleep wake-up, but also light sleep wake-up will be enabled when the :cpp:member:`slp_wakeup_lvl` is :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP`.
.. only:: not esp32
You can decide whether allow to power down RTC_PERIPH domain during the Deep-sleep by :cpp:member:`touch_sleep_config_t::deep_slp_allow_pd`. If allowed, the RTC_PERIPH domain will be powered down after the chip enters Deep-sleep, and only the specified :cpp:member:`touch_sleep_config_t::deep_slp_chan` can wake-up the chip from Deep-sleep. If not allowed, all enabled touch channels can wake-up the chip from Deep-sleep.
To deregister the sleep wake-up function, you can call :cpp:func:`touch_sensor_config_sleep_wakeup` again, and set the second parameter (i.e. :cpp:type:`touch_sleep_config_t` pointer) to ``NULL``.
.. code-block:: c
touch_sleep_config_t light_slp_cfg = {
.slp_wakeup_lvl = TOUCH_LIGHT_SLEEP_WAKEUP,
};
touch_sleep_config_t light_slp_cfg = TOUCH_SENSOR_DEFAULT_LSLP_CONFIG();
// Register the light sleep wake-up
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &light_slp_cfg));
// ...
// Deregister the light sleep wake-up
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, NULL));
touch_sleep_config_t deep_slp_cfg = {
.slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP,
.deep_slp_chan = dslp_chan_handle,
// Other deep sleep configurations
// ...
};
// Default Deep-sleep wake-up configurations: RTC_PERIPH will keep power on during the Deep-sleep,
// All enabled touch channel can wake-up the chip from Deep-sleep
touch_sleep_config_t deep_slp_cfg = TOUCH_SENSOR_DEFAULT_DSLP_CONFIG();
// Default Deep-sleep wake-up power down configurations: RTC_PERIPH will be powered down during the Deep-sleep,
// only the specified sleep pad can wake-up the chip from Deep-sleep
// touch_sleep_config_t deep_slp_cfg = TOUCH_SENSOR_DEFAULT_DSLP_PD_CONFIG(sleep_channel, slp_chan_thresh1, ...);
// Register the deep sleep wake-up
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &deep_slp_cfg));

View File

@ -380,24 +380,26 @@
- Light-sleep 状态唤醒:通过指定 :cpp:member:`slp_wakeup_lvl`:cpp:enumerator:`TOUCH_LIGHT_SLEEP_WAKEUP` 即可启用触摸传感器 Light-sleep 唤醒功能。注意任何已注册的触摸传感器通道都会在 Light-sleep 状态下保持采样并支持唤醒 Light-sleep。
- Deep-sleep 状态唤醒:启用触摸传感器 Deep-sleep 唤醒功能除了指定 :cpp:member:`slp_wakeup_lvl`:cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP` 外,还需要指定 Deep-sleep 唤醒通道 :cpp:member:`deep_slp_chan`,注意只有该指定的通道才会在 Deep-sleep 状态下保持采样以及唤醒,以此降低在 Deep-sleep 状态下的功耗。此外,若需要在深度睡眠下使用另一套低功耗的配置来进一步降低功耗,可以通过 :cpp:member:`deep_slp_sens_cfg` 额外指定一套低功耗配置,在进入 Deep-sleep 前,驱动会应用这套配置,从 Deep-sleep 状态唤醒后,则会重新配置到之前的配置。请注意当 :cpp:member:`slp_wakeup_lvl` 配置为 :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP` 后,触摸传感器不仅能唤醒 Deep-sleep 状态,还能唤醒 Light-sleep 状态。
.. only:: not esp32
Deep-sleep 状态唤醒可由 :cpp:member:`touch_sleep_config_t::deep_slp_allow_pd` 配置是否允许关闭 RTC_PERIPH 电源域。若允许关闭,则芯片进入 Deep-sleep 后触摸传感器所在的 RTC_PERIPH 电源域有可能被关闭,此时只有指定的 :cpp:member:`touch_sleep_config_t::deep_slp_chan` 可唤醒,若不允许关闭,则所有已使能的触摸通道都可以将芯片从 Deep-sleep 状态中唤醒。
若需要注销睡眠唤醒功能,可再次调用 :cpp:func:`touch_sensor_config_sleep_wakeup` 并将第二个参数(即 :cpp:type:`touch_sleep_config_t` 的配置结构体指针)设为 ``NULL`` 来注销睡眠唤醒功能。
.. code-block:: c
touch_sleep_config_t light_slp_cfg = {
.slp_wakeup_lvl = TOUCH_LIGHT_SLEEP_WAKEUP,
};
touch_sleep_config_t light_slp_cfg = TOUCH_SENSOR_DEFAULT_LSLP_CONFIG();
// 注册 Light-sleep 唤醒功能
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &light_slp_cfg));
// ...
// 注销睡眠唤醒功能
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, NULL));
touch_sleep_config_t deep_slp_cfg = {
.slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP,
.deep_slp_chan = dslp_chan_handle,
// 其他 Deep-sleep 唤醒配置
// ...
};
// 默认 Deep-sleep 唤醒配置RTC_PERIPH 电源域在 Deep-sleep 状态下保持上电,
// 且所有使能 Touch 通道都能正常唤醒
touch_sleep_config_t deep_slp_cfg = TOUCH_SENSOR_DEFAULT_DSLP_CONFIG();
// 默认 Deep-sleep 掉电唤醒配置RTC_PERIPH 电源域在 Deep-sleep 状态下掉电,
// 仅有指定的 sleep pad 能正常唤醒
// touch_sleep_config_t deep_slp_cfg = TOUCH_SENSOR_DEFAULT_DSLP_PD_CONFIG(sleep_channel, slp_chan_thresh1, ...);
// 注册 Deep-sleep 唤醒功能
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &deep_slp_cfg));

View File

@ -94,9 +94,7 @@ esp_err_t example_register_touch_wakeup(void)
};
ESP_ERROR_CHECK(touch_sensor_register_callbacks(sens_handle, &callbacks, NULL));
touch_sleep_config_t light_slp_cfg = {
.slp_wakeup_lvl = TOUCH_LIGHT_SLEEP_WAKEUP,
};
touch_sleep_config_t light_slp_cfg = TOUCH_SENSOR_DEFAULT_LSLP_CONFIG();
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &light_slp_cfg));
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));