espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
12.57k stars 7.02k forks source link

esp32c6 gpio wakeup stop working if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y (IDFGH-12693) #13683

Open AxelLin opened 3 weeks ago

AxelLin commented 3 weeks ago

Answers checklist.

IDF version.

v5.3-dev-3593-g64a1ed07d9, v5.4-dev-12-g3d813afa01

Espressif SoC revision.

ESP32C6

Operating System used.

Linux

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

None

Development Kit.

Custom Board

Power Supply used.

USB

What is the expected behavior?

esp32c6 gpio wakeup stop working if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y Note, this was working in v5.2.1-443-g2ba5320112

What is the actual behavior?

press the gpio button seems has no effect.(device does not wake up from sleep)

Steps to reproduce.

I test it with my application code which I cannot share here. The gpio wakeup related code are as below:

#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
gpio_hold_en(MY_GPIO_BUTTON);
#endif

esp_sleep_enable_gpio_wakeup();
esp_light_sleep_start();

#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
gpio_hold_dis(MY_GPIO_BUTTON);
#endif

esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
// check wakeup reason..

It should be easy to reproduce it with some modification of examples/system/light_sleep/ example code.

Debug Logs.

No response

More Information.

No response

esp-lis commented 3 weeks ago

@AxelLin In the design of the esp32c6 chip, GPIO (Digital IO is located in the TOP power domain), Configuring CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y means that the TOP domain will power down during sleep, it means that Digital IO cannot be used as a wake source, In this case you can use LPIO or EXT1 as the wake source, behaving in the same way as GPIO (Digital IO).

Use of EXT1 or LPIO wake configurations can be found sleep_modes.html#external-wakeup-ext1

AxelLin commented 3 weeks ago

@esp-lis I don't get it. It works if build with esp-idf-5.2 branch. It stop working after switch to 5.3+.

esp-lis commented 3 weeks ago

@AxelLin Our recently optimized power domain management strategy (which should be included in version 5.3+), I guess on esp-idf-5.2 branch, CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y doesn't really power down TOP domain.

You can you the follow code to check the TOP domain state during system go to sleep. esp_rom_printf(DRAM_STR("pd_flags:%x\n"), pd_flags) put it into sleep_modes.c#L707, the TOP domain is powered down during sleep if the pd_flags's BIT(0) is set.

AxelLin commented 3 weeks ago

@esp-lis

v5.2: pd_flags:2c15 master (v5.4-dev-12-g3d813afa01) : pd_flags:2c15

so the pd_flags is the same for v5.2 and master.

BTW, I have apply this fix for my v5.2. (https://github.com/espressif/esp-idf/issues/11858#issuecomment-1640244734 to make modem_domain_pd_allowed() return true)

esp-lis commented 3 weeks ago

@esp-lis

v5.2: pd_flags:2c15 master (v5.4-dev-12-g3d813afa01) : pd_flags:2c15

so the pd_flags is the same for v5.2 and master.

BTW, I have apply this fix for my v5.2. (#11858 (comment) to make modem_domain_pd_allowed() return true)

This is strange, pd_flags:2c15 means that the TOP domain will be powered down during sleep.

#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
gpio_hold_en(MY_GPIO_BUTTON);
#endif

esp_sleep_enable_gpio_wakeup();
esp_light_sleep_start();

#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
gpio_hold_dis(MY_GPIO_BUTTON);
#endif

esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
// check wakeup reason..

Based on the above code, I can't see any more problems, Can you share more information about GPIO wakeup configuration?

AxelLin commented 2 weeks ago

There is nothing special for the GPIO wakeup configuration. As I said the same code works if build with IDF-5.2, there must be some thing in newer IDF causes this regression.

esp-lis commented 2 weeks ago

There is nothing special for the GPIO wakeup configuration. As I said the same code works if build with IDF-5.2, there must be some thing in newer IDF causes this regression.

I'm unable to construct a case like this, could you please provide the simplest project that has this issue? It can help me locate the problem.

AxelLin commented 5 days ago

@esp-lis

I summary the issue:

  1. Build with CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y using the test code. gpio wakeup works if build with esp-idf-v5.2 branch. gpio wakeup does tno work if build with v5.3 branch.

  2. Test with v5.3 branch: If setting CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=n, gpio wakeup works. If setting CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y but comment out esp_sleep_cpu_retention_init() call, gpio wakeup also works. i.e. Calling esp_sleep_cpu_retention_init() + CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y makes the gpio wakeup stop working in v5.3+.

Below is the testing code.

#define GPIO_WAKEUP_BUTTON GPIO_NUM_5
static void gpio_wakeup_test()
{
    esp_err_t err;

#if 1
    err = esp_sleep_cpu_retention_init();
    if (err)
        ESP_LOGE(TAG, "Failed to init cpu retention: %d", err);
#endif

    do {
        ESP_LOGI(TAG, "To enter sleep");
        vTaskDelay(pdMS_TO_TICKS(1 * 1000));

        //prepare_lightsleep
        gpio_wakeup_enable(GPIO_WAKEUP_BUTTON, wakeup_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
        #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
        gpio_hold_en(GPIO_WAKEUP_BUTTON);
        #endif
        esp_sleep_enable_gpio_wakeup();

        err = esp_light_sleep_start();

        //unprepare_lightsleep
        #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
        gpio_hold_dis(GPIO_WAKEUP_BUTTON);
        #endif
        gpio_wakeup_disable(GPIO_WAKEUP_BUTTON);

        if (err) {
            ESP_LOGE(TAG, "esp_light_sleep_start err = %d", err);
        }

        if (gpio_get_level(GPIO_WAKEUP_BUTTON) == wakeup_level) {
            ESP_LOGW(TAG, "wakeup button pressed");

            //wait_until_wakeup_gpio_release
            if (gpio_get_level(GPIO_WAKEUP_BUTTON) == wakeup_level) {
            ESP_LOGD(TAG, "Waiting for GPIO%d to go high...", GPIO_WAKEUP_BUTTON);
            do {
                vTaskDelay(pdMS_TO_TICKS(30));
            } while (gpio_get_level(GPIO_WAKEUP_BUTTON) == wakeup_level);
            }
        }
        /* Check wake up reason */
        esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
        ESP_LOGI(TAG, "wakeup_reason=%d", wakeup_reason);

        vTaskDelay(pdMS_TO_TICKS(1 * 1000));
    } while (1);
}
esp-lis commented 5 days ago

Build with CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y using the test code. gpio wakeup works if build with esp-idf-v5.2 branch.

If you are using the esp-idf version before commit 470d5406 of release/v5.2, this result is as expected, otherwise, the result same as release/v5.3

gpio wakeup does tno work if build with v5.3 branch.

If setting CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=n, gpio wakeup works.

the result is as expected.

gpio wakeup does tno work if build with v5.3 branch.

If setting CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y but comment out esp_sleep_cpu_retention_init() call, gpio wakeup also works.

the result is as expected, refer to the implement of top_domain_pd_allowed, because the all modules of CPU, MODEM (WiFi, BLE and 802.15.4) and Digital peripherals are located in TOP power domain, comment out esp_sleep_cpu_retention_init() call means the CPU domain will not allow the TOP domain to power down during sleep.

gpio wakeup does tno work if build with v5.3 branch.

i.e. Calling esp_sleep_cpu_retention_init() + CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y makes the gpio wakeup stop working in v5.3+.

the result is as expected, All conditions for the TOP domain are met, TOP domain will power down during sleep.

AxelLin commented 5 days ago

Build with CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y using the test code. gpio wakeup works if build with esp-idf-v5.2 branch.

If you are using the esp-idf version before commit 470d5406 of release/v5.2, this result is as expected,

No, I test with v5.2.1-507-gf8319f08cc and it still works.

esp-lis commented 4 days ago

Build with CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y using the test code. gpio wakeup works if build with esp-idf-v5.2 branch.

If you are using the esp-idf version before commit 470d5406 of release/v5.2, this result is as expected,

No, I test with v5.2.1-507-gf8319f08cc and it still works.

I have trouble shoot for it, it was introduced in 60e985e7 and in this commit we optimized the clock configuration (disabling the clock for all modules), If you want to use it correctly, call the rtc_gpio_init interface, which will reenable the clock of LP IO (GPIO5 is a LP IO, gpio_wakeup_enable checks and calls rtc_gpio_wakeup_enable to enable LPIO5 wakeup).

AxelLin commented 2 days ago

Build with CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y using the test code. gpio wakeup works if build with esp-idf-v5.2 branch.

If you are using the esp-idf version before commit 470d5406 of release/v5.2, this result is as expected,

No, I test with v5.2.1-507-gf8319f08cc and it still works.

I have trouble shoot for it, it was introduced in 60e985e7 and in this commit we optimized the clock configuration (disabling the clock for all modules), If you want to use it correctly, call the rtc_gpio_init interface, which will reenable the clock of LP IO (GPIO5 is a LP IO, gpio_wakeup_enable checks and calls rtc_gpio_wakeup_enable to enable LPIO5 wakeup).

@esp-lis

Calling rtc_gpio_init(GPIO_WAKEUP_BUTTON) before gpio_wakeup_enable() does not work. (Looks like it fails to enter lightsleep) E (4395) LightSleep: esp_light_sleep_start err = 259 W (4395) LightSleep: wakeup button pressed

I also tried comment out the 60e985e7 changes in components/esp_system/port/soc/esp32c6/clk.c, but it still does not work.

BTW, I want to point out it's important to make existing application work in newer esp-idf versions. If there are some changes need to update application code, you must document it in migration guide.

AxelLin commented 1 day ago

@esp-lis

I tried git bisect, but there are build failure for the commits between fc9484785b..0c68b9b06c, so I stop bisect. Now I can confirm v5.3-dev-3006-gfc9484785b is good, but v5.3-dev-3049-g0c68b9b06c is bad. Maybe you can try to figure out what is wrong between above commits, I believe you can reproduce the issue using above test code.