gpio: Fix IO hold function related problems

1. Fix deep sleep wakeup IOs can not be unhold issue
2. Correct hold related APIs' description
3. Fix gpio_force_hold_all API

docs: Add GPIO wakeup source to sleep_modes doc for ESP32C3 and C2
This commit is contained in:
Song Ruo Jing
2022-11-11 20:39:04 +08:00
parent 8c40017d2d
commit d0a7dc3e9f
29 changed files with 286 additions and 196 deletions
@@ -15,7 +15,7 @@ extern "C" {
/**
* @file sleep_gpio.h
*
* This file contains declarations of GPIO related functions in light sleep mode.
* This file contains declarations of GPIO related functions in sleep modes.
*/
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
@@ -41,6 +41,11 @@ void gpio_sleep_mode_config_unapply(void);
#endif // SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
/**
* @brief Call once in startup to disable the wakeup IO pins and release their holding state after waking up from Deep-sleep
*/
void esp_deep_sleep_wakeup_io_reset(void);
#ifdef __cplusplus
}
#endif
@@ -245,25 +245,25 @@ esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode
* This function enables an IO pin to wake up the chip from deep sleep.
*
* @note This function does not modify pin configuration. The pins are
* configured in esp_deep_sleep_start/esp_light_sleep_start,
* immediately before entering sleep mode.
* configured inside esp_deep_sleep_start, immediately before entering sleep mode.
*
* @note You don't need to care to pull-up or pull-down before using this
* function, because this will be done in esp_deep_sleep_start/esp_light_sleep_start
* based on param mask you give. BTW, when you use low level to wake up the
* chip, we strongly recommand you to add external registors (pull-up).
* function, because this will be set internally in esp_deep_sleep_start
* based on the wakeup mode. BTW, when you use low level to wake up the
* chip, we strongly recommend you to add external resistors (pull-up).
*
* @param gpio_pin_mask Bit mask of GPIO numbers which will cause wakeup. Only GPIOs
* which are have RTC functionality can be used in this bit map.
* which have RTC functionality (pads that powered by VDD3P3_RTC) can be used in this bit map.
* @param mode Select logic function used to determine wakeup condition:
* - ESP_GPIO_WAKEUP_GPIO_LOW: wake up when the gpio turn to low.
* - ESP_GPIO_WAKEUP_GPIO_HIGH: wake up when the gpio turn to high.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if gpio num is more than 5 or mode is invalid,
* - ESP_ERR_INVALID_ARG if the mask contains any invalid deep sleep wakeup pin or wakeup mode is invalid
*/
esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode);
#endif
/**
* @brief Enable wakeup from light sleep using GPIOs
*
+36
View File
@@ -19,6 +19,8 @@
#include "driver/gpio.h"
#include "hal/gpio_hal.h"
#include "hal/rtc_io_hal.h"
#include "hal/rtc_hal.h"
#include "esp_private/gpio.h"
#include "esp_private/sleep_gpio.h"
#include "esp_private/spi_flash_os.h"
@@ -144,3 +146,37 @@ IRAM_ATTR void esp_sleep_isolate_digital_gpio(void)
}
}
#endif
void esp_deep_sleep_wakeup_io_reset(void)
{
#if SOC_PM_SUPPORT_EXT_WAKEUP
uint32_t rtc_io_mask = rtc_hal_ext1_get_wakeup_pins();
// Disable ext1 wakeup before releasing hold, such that wakeup status can reflect the correct wakeup pin
rtc_hal_ext1_clear_wakeup_pins();
for (int gpio_num = 0; gpio_num < SOC_GPIO_PIN_COUNT && rtc_io_mask != 0; ++gpio_num) {
int rtcio_num = rtc_io_num_map[gpio_num];
if ((rtc_io_mask & BIT(rtcio_num)) == 0) {
continue;
}
rtcio_hal_hold_disable(rtcio_num);
rtc_io_mask &= ~BIT(rtcio_num);
}
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
uint32_t dl_io_mask = SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK;
gpio_hal_context_t gpio_hal = {
.dev = GPIO_HAL_GET_HW(GPIO_PORT_0)
};
while (dl_io_mask) {
int gpio_num = __builtin_ffs(dl_io_mask) - 1;
bool wakeup_io_enabled = gpio_hal_deepsleep_wakeup_is_enabled(&gpio_hal, gpio_num);
if (wakeup_io_enabled) {
// Disable the wakeup before releasing hold, such that wakeup status can reflect the correct wakeup pin
gpio_hal_deepsleep_wakeup_disable(&gpio_hal, gpio_num);
gpio_hal_hold_dis(&gpio_hal, gpio_num);
}
dl_io_mask &= ~BIT(gpio_num);
}
#endif
}
+10 -10
View File
@@ -215,7 +215,7 @@ static void timer_wakeup_prepare(void);
static void touch_wakeup_prepare(void);
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
static void esp_deep_sleep_wakeup_prepare(void);
static void gpio_deep_sleep_wakeup_prepare(void);
#endif
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
@@ -431,8 +431,8 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
if (s_config.wakeup_triggers & RTC_GPIO_TRIG_EN) {
esp_deep_sleep_wakeup_prepare();
if (deep_sleep && (s_config.wakeup_triggers & RTC_GPIO_TRIG_EN)) {
gpio_deep_sleep_wakeup_prepare();
}
#endif
@@ -1096,7 +1096,7 @@ static void ext1_wakeup_prepare(void)
}
// Clear state from previous wakeup
rtc_hal_ext1_clear_wakeup_pins();
rtc_hal_ext1_clear_wakeup_status();
// Set RTC IO pins and mode (any high, all low) to be used for wakeup
rtc_hal_ext1_set_wakeup_pins(s_config.ext1_rtc_gpio_mask, s_config.ext1_trigger_mode);
}
@@ -1106,7 +1106,7 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void)
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_EXT1) {
return 0;
}
uint32_t status = rtc_hal_ext1_get_wakeup_pins();
uint32_t status = rtc_hal_ext1_get_wakeup_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) {
@@ -1131,10 +1131,10 @@ uint64_t esp_sleep_get_gpio_wakeup_status(void)
return 0;
}
return rtc_hal_gpio_get_wakeup_pins();
return rtc_hal_gpio_get_wakeup_status();
}
static void esp_deep_sleep_wakeup_prepare(void)
static void gpio_deep_sleep_wakeup_prepare(void)
{
for (gpio_num_t gpio_idx = GPIO_NUM_0; gpio_idx < GPIO_NUM_MAX; gpio_idx++) {
if (((1ULL << gpio_idx) & s_config.gpio_wakeup_mask) == 0) {
@@ -1147,9 +1147,10 @@ static void esp_deep_sleep_wakeup_prepare(void)
ESP_ERROR_CHECK(gpio_pullup_en(gpio_idx));
ESP_ERROR_CHECK(gpio_pulldown_dis(gpio_idx));
}
rtc_hal_gpio_set_wakeup_pins();
ESP_ERROR_CHECK(gpio_hold_en(gpio_idx));
}
// Clear state from previous wakeup
rtc_hal_gpio_clear_wakeup_status();
}
esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode)
@@ -1165,7 +1166,7 @@ esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepslee
continue;
}
if (!esp_sleep_is_valid_wakeup_gpio(gpio_idx)) {
ESP_LOGE(TAG, "invalid mask, please ensure gpio number is no more than 5");
ESP_LOGE(TAG, "gpio %d is an invalid deep sleep wakeup IO", gpio_idx);
return ESP_ERR_INVALID_ARG;
}
err = gpio_deep_sleep_wakeup_enable(gpio_idx, intr_type);
@@ -1178,7 +1179,6 @@ esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepslee
}
}
s_config.wakeup_triggers |= RTC_GPIO_TRIG_EN;
rtc_hal_gpio_clear_wakeup_pins();
return err;
}