Skip to content

Commit a12c15c

Browse files
committed
esp32: Add esp32.wake_on_gpio.
Some boards support waking up via GPIO pins, but this is not currently supported by MicroPython. This commit adds support for waking with GPIO in a similar interface to waking with ext0, ext1, touch and ulp. This commit adds documentation for this new function as well. Signed-off-by: Meir Armon <meirarmon@gmail.com>
1 parent 09541b7 commit a12c15c

File tree

5 files changed

+103
-3
lines changed

5 files changed

+103
-3
lines changed

docs/library/esp32.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ Functions
4343

4444
.. note:: This is only available for boards that have ext1 support.
4545

46+
.. function:: wake_on_gpio(pins, level)
47+
48+
Configure how GPIO wakes the device from sleep. *pins* can be ``None``
49+
or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW``
50+
or ``esp32.WAKEUP_ANY_HIGH``.
51+
52+
.. note:: Some boards don't support waking on GPIO from deep sleep,
53+
on those boards, the pins set here can only be used to wake from light sleep.
54+
4655
.. function:: gpio_deep_sleep_hold(enable)
4756

4857
Configure whether non-RTC GPIO pin configuration is retained during

ports/esp32/machine_rtc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ machine_rtc_config_t machine_rtc_config = {
8686
.ext1_pins = 0,
8787
#endif
8888
#if SOC_PM_SUPPORT_EXT0_WAKEUP
89-
.ext0_pin = -1
89+
.ext0_pin = -1,
9090
#endif
91+
.gpio_pins = 0,
9192
};
9293

9394
static mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {

ports/esp32/machine_rtc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ typedef struct {
3737
#if SOC_PM_SUPPORT_EXT0_WAKEUP
3838
int8_t ext0_pin; // just the pin#, -1 == None
3939
#endif
40+
uint64_t gpio_pins; // set bit == pin#
4041
#if SOC_TOUCH_SENSOR_SUPPORTED
4142
bool wake_on_touch : 1;
4243
#endif
@@ -50,6 +51,7 @@ typedef struct {
5051
#if SOC_PM_SUPPORT_EXT1_WAKEUP
5152
bool ext1_level : 1;
5253
#endif
54+
bool gpio_level : 1;
5355
} machine_rtc_config_t;
5456

5557
extern machine_rtc_config_t machine_rtc_config;

ports/esp32/modesp32.c

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,13 @@
4646
#define MULTI_HEAP_FREERTOS
4747
#include "../multi_heap_platform.h"
4848
#include "../heap_private.h"
49+
#include "driver/rtc_io.h"
4950

5051
#if SOC_TOUCH_SENSOR_SUPPORTED
5152
static mp_obj_t esp32_wake_on_touch(const mp_obj_t wake) {
5253

5354
#if SOC_PM_SUPPORT_EXT0_WAKEUP
54-
if (machine_rtc_config.ext0_pin != -1) {
55+
if (machine_rtc_config.ext0_pin != -1 || machine_rtc_config.gpio_pins != 0) {
5556
mp_raise_ValueError(MP_ERROR_TEXT("no resources"));
5657
}
5758
#endif
@@ -140,7 +141,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_ext1_obj, 0, esp32_wake_on_ext1)
140141
#if SOC_ULP_SUPPORTED
141142
static mp_obj_t esp32_wake_on_ulp(const mp_obj_t wake) {
142143
#if SOC_PM_SUPPORT_EXT0_WAKEUP
143-
if (machine_rtc_config.ext0_pin != -1) {
144+
if (machine_rtc_config.ext0_pin != -1 || machine_rtc_config.gpio_pins != 0) {
144145
mp_raise_ValueError(MP_ERROR_TEXT("no resources"));
145146
}
146147
#endif
@@ -150,6 +151,51 @@ static mp_obj_t esp32_wake_on_ulp(const mp_obj_t wake) {
150151
static MP_DEFINE_CONST_FUN_OBJ_1(esp32_wake_on_ulp_obj, esp32_wake_on_ulp);
151152
#endif
152153

154+
static mp_obj_t esp32_wake_on_gpio(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
155+
enum {ARG_pins, ARG_level};
156+
const mp_arg_t allowed_args[] = {
157+
{ MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = mp_const_none} },
158+
{ MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.gpio_level} },
159+
};
160+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
161+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
162+
uint64_t gpio_pins = machine_rtc_config.gpio_pins;
163+
164+
#if SOC_ULP_SUPPORTED
165+
if (machine_rtc_config.wake_on_ulp) {
166+
mp_raise_ValueError(MP_ERROR_TEXT("no resources"));
167+
}
168+
#endif
169+
170+
#if SOC_TOUCH_SENSOR_SUPPORTED
171+
if (machine_rtc_config.wake_on_touch) {
172+
mp_raise_ValueError(MP_ERROR_TEXT("no resources"));
173+
}
174+
#endif
175+
176+
// Check that all pins are allowed
177+
if (args[ARG_pins].u_obj != mp_const_none) {
178+
size_t len = 0;
179+
mp_obj_t *elem;
180+
mp_obj_get_array(args[ARG_pins].u_obj, &len, &elem);
181+
gpio_pins = 0;
182+
183+
for (int i = 0; i < len; i++) {
184+
// Don't validate the pins at this point, since we can be using
185+
// gpio pins for deepsleep or light sleep.
186+
// Validations happen in the relevant sleep functions.
187+
gpio_num_t pin_id = machine_pin_get_id(elem[i]);
188+
gpio_pins |= (1ll << pin_id);
189+
}
190+
}
191+
192+
machine_rtc_config.gpio_level = args[ARG_level].u_bool;
193+
machine_rtc_config.gpio_pins = gpio_pins;
194+
195+
return mp_const_none;
196+
}
197+
static MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_gpio_obj, 0, esp32_wake_on_gpio);
198+
153199
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
154200
static mp_obj_t esp32_gpio_deep_sleep_hold(const mp_obj_t enable) {
155201
if (mp_obj_is_true(enable)) {
@@ -284,6 +330,7 @@ static const mp_rom_map_elem_t esp32_module_globals_table[] = {
284330
#if SOC_ULP_SUPPORTED
285331
{ MP_ROM_QSTR(MP_QSTR_wake_on_ulp), MP_ROM_PTR(&esp32_wake_on_ulp_obj) },
286332
#endif
333+
{ MP_ROM_QSTR(MP_QSTR_wake_on_gpio), MP_ROM_PTR(&esp32_wake_on_gpio_obj) },
287334
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
288335
{ MP_ROM_QSTR(MP_QSTR_gpio_deep_sleep_hold), MP_ROM_PTR(&esp32_gpio_deep_sleep_hold_obj) },
289336
#endif

ports/esp32/modmachine.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) {
125125
}
126126

127127
static void machine_sleep_helper(wake_type_t wake_type, size_t n_args, const mp_obj_t *args) {
128+
#if !SOC_DEEP_SLEEP_SUPPORTED
129+
if (MACHINE_WAKE_DEEPSLEEP == wake_type) {
130+
mp_raise_ValueError(MP_ERROR_TEXT("DEEPSLEEP not supported on this chip"));
131+
}
132+
#endif
133+
128134
// First, disable any previously set wake-up source
129135
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
130136

@@ -164,6 +170,41 @@ static void machine_sleep_helper(wake_type_t wake_type, size_t n_args, const mp_
164170
}
165171
#endif
166172

173+
if (machine_rtc_config.gpio_pins != 0) {
174+
#if !SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
175+
if (MACHINE_WAKE_DEEPSLEEP == wake_type) {
176+
mp_raise_ValueError(MP_ERROR_TEXT("DEEPSLEEP with gpio pins not supported on this chip"));
177+
}
178+
#endif
179+
180+
gpio_int_type_t intr_type = machine_rtc_config.gpio_level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL;
181+
182+
for (int i = 0; i < GPIO_NUM_MAX; ++i) {
183+
gpio_num_t gpio = (gpio_num_t)i;
184+
uint64_t bm = 1ULL << i;
185+
186+
if (machine_rtc_config.gpio_pins & bm) {
187+
gpio_sleep_set_direction(gpio, GPIO_MODE_INPUT);
188+
189+
if (MACHINE_WAKE_SLEEP == wake_type) {
190+
gpio_wakeup_enable(gpio, intr_type);
191+
}
192+
}
193+
}
194+
195+
if (MACHINE_WAKE_DEEPSLEEP == wake_type) {
196+
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
197+
if (ESP_OK != esp_deep_sleep_enable_gpio_wakeup(
198+
machine_rtc_config.gpio_pins,
199+
machine_rtc_config.gpio_level ? ESP_GPIO_WAKEUP_GPIO_HIGH : ESP_GPIO_WAKEUP_GPIO_LOW)) {
200+
mp_raise_ValueError(MP_ERROR_TEXT("wake-up pin not supported"));
201+
}
202+
#endif
203+
} else {
204+
esp_sleep_enable_gpio_wakeup();
205+
}
206+
}
207+
167208
switch (wake_type) {
168209
case MACHINE_WAKE_SLEEP:
169210
esp_light_sleep_start();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy