Skip to content

Implemented GPIO wake-up for ESP32-C3 #13333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

puppet13th
Copy link

updated #9583 to current codebase.

@vencax
Copy link

vencax commented Jan 3, 2024

Hello, I started working on this and found your solution. I can verify that these changes works for XIAO ESP32C3. However there imho are few issues:

  1. RTC_VALID_EXT_PINS are only those that are "are powered by the VDD3P3_RTC power domain" see: THIS that are imho those.
  2. If you see wakeup sources DOCs there are nothing about EXT0/1 sources. This PR comment mention this issue. But the issue remains when someone tries to setup IRQ with wake=machine.DEEPSLEEP on desired pin expecting that machine will wake from deepsleep.

@puppet13th
Copy link
Author

Hello there. I'm just make new PR for the current codebase, so it can be merged.

  1. RTC_VALID_EXT_PINS are only those that are "are powered by the VDD3P3_RTC power domain" see: THIS that are imho those.

according to espressif doc any gpio pins can be used for lightsleep wakeup source, for the deepsleep only RTC_GPIO can be used as wakeup source.

  1. If you see wakeup sources DOCs there are nothing about EXT0/1 sources. This PR comment mention this issue. But the issue remains when someone tries to setup IRQ with wake=machine.DEEPSLEEP on desired pin expecting that machine will wake from deepsleep.

current PR behaviour:

  1. will raise exception when esp32.wake_on_ext0
  2. like mentioned before ,currently micropython does have method to support esp_sleep_enable_gpio_wakeup, that's why we use esp32.wake_on_ext1 for it. Maybe micropython maintainer have different plan for it, that's why it does not get merged.

Hopefully @dpgeorge @jimmo can comment on this.

@m-cas
Copy link

m-cas commented Jan 4, 2024

@puppet13th I agree: RTC_VALID_EXT_PINS macro need to allow for pins 0 to 5 for deep sleep wakeup (from the espressif docs: "RTC: GPIO0-5 can be used to wake up the chip from Deep-sleep mode. Other GPIOs can only wake up the chip from Light-sleep mode.")
I never used GitHub before so I cannot judge if .../ports/esp32/modesp32.h has been modified, I simply don't see a fix for the C3 pins in it, only for the S2 and S3 variants.

@puppet13th
Copy link
Author

@puppet13th I agree: RTC_VALID_EXT_PINS macro need to allow for pins 0 to 5 for deep sleep wakeup (from the espressif docs: "RTC: GPIO0-5 can be used to wake up the chip from Deep-sleep mode. Other GPIOs can only wake up the chip from Light-sleep mode.") I never used GitHub before so I cannot judge if .../ports/esp32/modesp32.h has been modified, I simply don't see a fix for the C3 pins in it, only for the S2 and S3 variants.

This PR already included C3, although we can only use pin 0 to 5. it will throw value error when using other pin when calling deepsleep().

MicroPython 07e52c657 on 2024-01-04; ESP32C3 module with ESP32C3

Type "help()" for more information.

>>> from machine import Pin, deepsleep
>>> import esp32
>>> esp32.wake_on_ext1( [ Pin( 6 ), ], esp32.WAKEUP_ALL_LOW )
>>> deepsleep()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: wake-up pin not supported

code example for testing deepsleep:

from machine import Pin, deepsleep, wake_reason
import esp32

print( 'wake reason :', wake_reason() )

esp32.wake_on_ext1( [ Pin( 5 ), ], esp32.WAKEUP_ALL_LOW )
deepsleep( 10_000 )

code output:

wake reason : 7
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x5 (DSLEEP),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5820,len:0xe8c
load:0x403cc710,len:0x6ec
load:0x403ce710,len:0x2b24
entry 0x403cc710
MicroPython 07e52c657 on 2024-01-04; ESP32C3 module with ESP32C3
Type "help()" for more information.

wake reason should be 4 if triggered by timer.

@m-cas
Copy link

m-cas commented Jan 4, 2024

great, looking forward to test it. Please let me know when I can download an image with the new PR...

@puppet13th
Copy link
Author

great, looking forward to test it. Please let me know when I can download an image with the new PR...

don't know when will it get merged,you can compile the firmware from my fork or use this precompiled firmware.

ESP32_GENERIC_C3-07e52c65-.zip

@m-cas
Copy link

m-cas commented Jan 4, 2024

I'll use the file as I don't have the compilation environment for micropython set up...

@m-cas
Copy link

m-cas commented Jan 4, 2024

Just installed the file mentioned above and the code seems to work as it should. See code extract below.
`
DORMANT_PIN1 = 4 # aka GPIO02, D2
DORMANT_PIN2 = 5 # aka GPIO04, D3
w1 = Pin(DORMANT_PIN1, Pin.IN, Pin.PULL_DOWN)
w2 = Pin(DORMANT_PIN2, Pin.IN, Pin.PULL_DOWN)
rc = machine.reset_cause()
ws = machine.wake_reason()
v2 = w2.value() # see which pin triggered the wakeup

if rc == machine.DEEPSLEEP_RESET:
    print("Reset: Wakeup from deep sleep - sending alert")
    send_alert( v2 )
else:
    print('Reset: Other reason - do nothing and enter deepsleep() - ', rc2str.get(rc, str(rc)), ws2str.get(ws, str(ws)))

print("before deepsleep()")
esp32.wake_on_ext1(pins = [w1,w2], level = esp32.WAKEUP_ANY_HIGH)
machine.deepsleep()
print('CODE NEVER REACHES THIS PRINT')`

@m-cas
Copy link

m-cas commented Jan 9, 2024

@dpgeorge Is there anything to do to have this branch merged into the main code line?

@vencax
Copy link

vencax commented Jan 9, 2024

One detail:
when I do:

from machine import PIN_WAKE

then PIN_WAKE is 2
when i do:

from machine import *

then PIN_WAKE is 7

it is strange and it complicates checking machine.wake_reason().

@robert-hh
Copy link
Contributor

robert-hh commented Jan 9, 2024

There is an error in modmachine.c of this PR. PIN_WAKE is defined twice in the local dictionary.

@m-cas
Copy link

m-cas commented Jan 9, 2024

pardon me if this is a dumb question: is there a way to ask for what pin(s) caused the wake up other than reading the pins at startup? It seems that machine.wake_ext1_pins() is not coded for this port... BTW there seems to be a PR (#7990) with code ready to go for this as well...

@puppet13th
Copy link
Author

Updated ESP_SLEEP_WAKEUP_GPIO QSTR to GPIO_WAKE.

MicroPython 07e52c657-dirty on 2024-01-10; ESP32C3 module with ESP32C3

Type "help()" for more information.

>>> import machine
>>> machine.GPIO_WAKE
7

@m-cas
Copy link

m-cas commented Jan 31, 2024

@dpgeorge Is there anything I can do to help having this branch merged into the main code line?

@m-cas
Copy link

m-cas commented Feb 14, 2024

@puppet13th based on SR 7990 and other discussions, I just extended your version of modmachine.c to support "machine.wake_gpio_pins()" that returns a list of pins that triggered the wakeup for the C3. Do you want the code? I think it would make this PR more complete...

@m-cas
Copy link

m-cas commented Feb 14, 2024

This is the diff between your version of modmachine.c and the one I've used. The only thing I don't know is how to write the first conditional compiling as it comes at the end of a multiline #define statement: I didn't figure out how to make it work so in my compile run I removed the #if and made this an unconditional change.
I am using this code in a project and it works really well together with your wakeup changes. I am running it on a seeed xiao esp32c3 chip.

The code is taken from sr7990 but instead of using the ...get_ext1_wakeup_status... I am using the gpio version of it.

83,85d82
< #if CONFIG_IDF_TARGET_ESP32C3
< { MP_ROM_QSTR(MP_QSTR_wake_gpio_pins), MP_ROM_PTR(&machine_wake_gpio_pins_obj) },
< #endif
275,301d271
<
< #if CONFIG_IDF_TARGET_ESP32C3
< STATIC mp_obj_t machine_wake_gpio_pins(void) {
< uint64_t status = esp_sleep_get_gpio_wakeup_status();
< int len, index;
< mp_obj_t tuple = NULL;
<
< // Only a few (~8) GPIOs might cause EXT1 wakeup.
< // Therefore, we don't allocate 64
4 = 256 bytes on the stack and calculate the
< // required space in a first pass.
< for (index = 0, len = 0; index < 64; index++) {
< len += (status & ((uint64_t)1 << index)) ? 1 : 0;
< }
< if (len) {
< tuple = alloca(len * sizeof(*tuple));
<
< for (index = 0, len = 0; index < 64; index++) {
< if (status & ((uint64_t)1 << index)) {
< tuple[len++] = MP_OBJ_NEW_SMALL_INT(index);
< }
< }
< }
< return mp_obj_new_tuple(len, tuple);
< }
<
< STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_wake_gpio_pins_obj, machine_wake_gpio_pins);
< #endif

@liangtongt
Copy link

great, looking forward to test it. Please let me know when I can download an image with the new PR...

don't know when will it get merged,you can compile the firmware from my fork or use this precompiled firmware.

ESP32_GENERIC_C3-07e52c65-.zip

This firmware works very well on esp32 c3 xiao wake up, but on the ble connection, it can connect normally for the first time, and it will be reconnected infinitely after recovery, the same code works very well on the latest version of micropython, how can you release another version of C3 wakeup compiled firmware with the latest version

@m-cas
Copy link

m-cas commented Jun 27, 2024

I did compile it for myself a few months back... I think you probably will have to go the same way...

@m-cas
Copy link

m-cas commented Jul 16, 2024

I have updated the changes from SR 13333 and 7990 (own mods to it) to the latest esp dev kit and the latest micropython code (downloaded friday). All works for my case. if you have a dropbox or something similar where I can upload it I can share the new version with you.

If someone has interest in creating a SR to try to make this go into the baseline please let me know and I will share the changed files (4 files in all).

@puppet13th puppet13th force-pushed the esp32_c3_pin_wakeup branch 2 times, most recently from 9feabef to 66df592 Compare August 1, 2024 07:40
updated micropython#9583 to current codebase( 1.22.0).
Signed-off-by: Rinaldi Jandrinata <puppet13th@gmail.com>
Signed-off-by: Rinaldi Jandrinata <puppet13th@gmail.com>
Signed-off-by: Rinaldi Jandrinata <puppet13th@gmail.com>
Signed-off-by: Rinaldi Jandrinata <puppet13th@gmail.com>
@puppet13th puppet13th force-pushed the esp32_c3_pin_wakeup branch from 66df592 to 3d0def2 Compare August 1, 2024 07:42
Copy link
Contributor

@projectgus projectgus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@puppet13th Thanks for keeping this PR up to date for a long time, and sorry no maintainer got back to you when you originally submitted this. I'll ask the same question that I asked on the original PR: Are you still interested in working on it?

(Below is the review I left on the original PR, which still applies here.)


The approach looks pretty good, and I think it should clean up even more if rebased as we've added more guards based on SoC capability macros rather than chip type. That should make it pretty minimal to have this work on C6 as well.

One thing I am wondering is whether it'd be cleaner to add this support via the machine.Pin.irq(wake=) argument (see `esp32/machine_pin.c). This is the standard non-port-specific way to do wakeup, and it's actually a good fit for the C3 because there isn't the weird distinction between EXT0 and EXT1. Let me know what you think.

@m-cas
Copy link

m-cas commented Jan 17, 2025

@projectgus You may want to check out #15498 as well. I took the liberty a while ago of unifying a couple of things and bring the code up to date...

@projectgus
Copy link
Contributor

Thanks @m-cas, I'd missed your PR was the latest incarnation. I'm going to close this one in favour of #15498. @puppet13th let me know if you'd like to resume here instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants