From 7684c996bc2b2521fa4bd023e4fa24622092cd5f Mon Sep 17 00:00:00 2001 From: Jonathan Hogg Date: Mon, 7 Mar 2022 09:21:11 +0000 Subject: [PATCH] esp32/machine_pin: Add new hold keyword argument and remove PULL_HOLD. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current pull=Pin.PULL_HOLD argument doesn't make a lot of sense in the context of what it actually does vs what the ESP32 quickref document says it does. This commit removes PULL_HOLD and adds a new hold=True|False keyword argument to Pin()/Pin.init(). Setting this to True will cause the ESP32 to lock the configuration of the pin – including direction, output value, drive strength, pull-up/-down – such that it can't be accidentally changed and will be retained through a watchdog or internal reset. Fixes issue #8283, and see also #8284. --- docs/esp32/quickref.rst | 12 ++++++++++++ ports/esp32/machine_pin.c | 18 +++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 0778425f2f..dd7e515f1b 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -177,6 +177,14 @@ safe maximum source/sink currents and approximate internal driver resistances: - ``Pin.DRIVE_2``: 20mA / 30 ohm (default strength if not configured) - ``Pin.DRIVE_3``: 40mA / 15 ohm +The ``hold=`` keyword argument to ``Pin()`` and ``Pin.init()`` will enable the +ESP32 "pad hold" feature. When set to ``True``, the pin configuration +(direction, pull resistors and output value) will be held and any further +changes (including changing the output level) will not be applied. Setting +``hold=False`` will immediately apply any outstanding pin configuration changes +and release the pin. Using ``hold=True`` while a pin is already held will apply +any configuration changes and then immediately reapply the hold. + Notes: * Pins 1 and 3 are REPL UART TX and RX respectively @@ -549,6 +557,10 @@ deep-sleep mode:: pin.init(pull=None) machine.deepsleep(10000) +Output-configured RTC pins will also retain their output direction and level in +deep-sleep if pad hold is enabled with the ``hold=True`` argument to +``Pin.init()``. + Non-RTC GPIO pins will be disconnected by default on entering deep-sleep. SD card diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c index 1dad398524..90dc03e69a 100644 --- a/ports/esp32/machine_pin.c +++ b/ports/esp32/machine_pin.c @@ -47,7 +47,6 @@ // Used to implement a range of pull capabilities #define GPIO_PULL_DOWN (1) #define GPIO_PULL_UP (2) -#define GPIO_PULL_HOLD (4) #if CONFIG_IDF_TARGET_ESP32 #define GPIO_FIRST_NON_OUTPUT (34) @@ -253,14 +252,15 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin mp_printf(print, "Pin(%u)", self->id); } -// pin.init(mode=None, pull=-1, *, value, drive) +// pin.init(mode=None, pull=-1, *, value, drive, hold) STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_pull, ARG_value, ARG_drive }; + enum { ARG_mode, ARG_pull, ARG_value, ARG_drive, ARG_hold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = mp_const_none}}, { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)}}, { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, { MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + { MP_QSTR_hold, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, }; // parse args @@ -325,10 +325,15 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ } else { gpio_pullup_dis(self->id); } - if (mode & GPIO_PULL_HOLD) { + } + + // configure pad hold + if (args[ARG_hold].u_obj != MP_OBJ_NULL && GPIO_IS_VALID_OUTPUT_GPIO(self->id)) { + // always disable pad hold to apply outstanding config changes + gpio_hold_dis(self->id); + // (re-)enable pad hold if requested + if (mp_obj_is_true(args[ARG_hold].u_obj)) { gpio_hold_en(self->id); - } else if (GPIO_IS_VALID_OUTPUT_GPIO(self->id)) { - gpio_hold_dis(self->id); } } @@ -480,7 +485,6 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) }, - { MP_ROM_QSTR(MP_QSTR_PULL_HOLD), MP_ROM_INT(GPIO_PULL_HOLD) }, { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, { MP_ROM_QSTR(MP_QSTR_WAKE_LOW), MP_ROM_INT(GPIO_PIN_INTR_LOLEVEL) },