diff --git a/components/services/services.c b/components/services/services.c index fd469b6c..b301d8d3 100644 --- a/components/services/services.c +++ b/components/services/services.c @@ -45,6 +45,7 @@ pwm_system_t pwm_system = { static EXT_RAM_ATTR struct { uint64_t wake_gpio, wake_level; + uint64_t rtc_gpio, rtc_level; uint32_t delay; } sleep_config; @@ -136,6 +137,28 @@ static void sleep_init(void) { ESP_LOGI(TAG, "Sleep wake-up gpio bitmap 0x%llx (active 0x%llx)", sleep_config.wake_gpio, sleep_config.wake_level); } } + + // get the rtc-pull criteria + if ((p = strcasestr(config, "rtc"))) { + char list[32] = "", item[8]; + sscanf(p, "%*[^=]=%31[^,]", list); + p = list - 1; + while (p++ && sscanf(p, "%7[^|]", item)) { + int level = 0, gpio = atoi(item); + if (!rtc_gpio_is_valid_gpio(gpio)) { + ESP_LOGE(TAG, "invalid rtc GPIO %d", gpio); + } else { + sleep_config.rtc_gpio |= 1LL << gpio; + } + if (sscanf(item, "%*[^:]:%d", &level)) sleep_config.rtc_level |= level << gpio; + p = strchr(p, '|'); + } + + // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done + if (sleep_config.rtc_gpio) { + ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_config.rtc_gpio, sleep_config.rtc_level); + } + } // then get the gpio that activate sleep (we could check that we have a valid wake) if ((p = strcasestr(config, "sleep"))) { @@ -165,11 +188,24 @@ void services_sleep_activate(sleep_cause_e cause) { // call all sleep hooks that might want to do something for (void (**hook)(void) = sleep_hooks; *hook; hook++) (*hook)(); - // isolate all possible GPIOs, except the wake-up ones + // isolate all possible GPIOs, except the wake-up and RTC-maintaines ones esp_sleep_config_gpio_isolate(); + + // keep RTC domain up if we need to maintain pull-up/down of some GPIO from RTC + if (sleep_config.rtc_gpio) esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + for (int i = 0; i < GPIO_NUM_MAX; i++) { - if (!rtc_gpio_is_valid_gpio(i) || ((1LL << i) & sleep_config.wake_gpio)) continue; - rtc_gpio_isolate(i); + // must be a RTC GPIO + if (!rtc_gpio_is_valid_gpio(i)) continue; + + // do we need to maintain a pull-up or down of that GPIO + if ((1LL << i) & sleep_config.rtc_gpio) { + if ((sleep_config.rtc_level >> i) & 0x01) rtc_gpio_pullup_en(i); + else rtc_gpio_pulldown_en(i); + // or is this not wake-up GPIO, just isolate it + } else if (!((1LL << i) & sleep_config.wake_gpio)) { + rtc_gpio_isolate(i); + } } // is there just one GPIO