From c4fb5f7df131902fa1a50b07ac758a5cc5fc2778 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 17 Feb 2022 16:32:29 -0800 Subject: [PATCH] Allow ESP boards to customize how a pin is reset This allows board code to override the default pull up reset state. It is useful for pins that are already externally connected, pulled or otherwise used by the board. Fixes #5931 --- .../adafruit_feather_esp32s2_tft/board.c | 25 ++++++++----------- .../adafruit_magtag_2.9_grayscale/board.c | 19 ++++++++++++++ .../boards/microdev_micro_s2/board.c | 13 ++++++++++ .../common-hal/microcontroller/Pin.c | 13 +++++++--- .../common-hal/microcontroller/Pin.h | 8 ++++-- 5 files changed, 58 insertions(+), 20 deletions(-) diff --git a/ports/espressif/boards/adafruit_feather_esp32s2_tft/board.c b/ports/espressif/boards/adafruit_feather_esp32s2_tft/board.c index f25a2a99a8..74187899ef 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s2_tft/board.c +++ b/ports/espressif/boards/adafruit_feather_esp32s2_tft/board.c @@ -71,14 +71,6 @@ uint8_t display_init_sequence[] = { void board_init(void) { - // Never reset the I2C/TFT power pin because doing so will reset the display. - // Instead, on reset set the default value and free the pin for user use. - // Relying on the normal pin reset would briefly float/pull the pin that - // could lead to a power brownout. - common_hal_never_reset_pin(&pin_GPIO21); - - reset_board(); - busio_spi_obj_t *spi = common_hal_board_create_spi(0); displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; bus->base.type = &displayio_fourwire_type; @@ -99,7 +91,6 @@ void board_init(void) { // workaround as board_init() is called before reset_port() in main.c pwmout_reset(); - common_hal_displayio_display_construct( display, bus, @@ -138,12 +129,18 @@ bool board_requests_safe_mode(void) { return false; } -void reset_board(void) { - // Turn on TFT and I2C - gpio_set_direction(21, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(21, true); +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + // Override the I2C/TFT power pin reset to prevent resetting the display. + if (pin_number == 21) { + // Turn on TFT and I2C + gpio_set_direction(21, GPIO_MODE_DEF_OUTPUT); + gpio_set_level(21, true); + return true; + } + return false; +} - free_pin_number(21); +void reset_board(void) { } void board_deinit(void) { diff --git a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c index c55f2bf703..18dd280cea 100644 --- a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c +++ b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c @@ -172,6 +172,25 @@ void reset_board(void) { } +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + // Pin 16 is speaker enable and it's pulled down on the board. We don't want + // to pull it high because then we'll compete with the external pull down. + // So, reset without any pulls internally. + if (pin_number == 16) { + gpio_config_t cfg = { + .pin_bit_mask = BIT64(16), + .mode = GPIO_MODE_DISABLE, + // The pin is externally pulled down, so we don't need to pull it. + .pull_up_en = false, + .pull_down_en = false, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&cfg); + return true; + } + return false; +} + void board_deinit(void) { displayio_epaperdisplay_obj_t *display = &displays[0].epaper_display; if (display->base.type == &displayio_epaperdisplay_type) { diff --git a/ports/espressif/boards/microdev_micro_s2/board.c b/ports/espressif/boards/microdev_micro_s2/board.c index 6ba5d975d7..0a2b17e001 100644 --- a/ports/espressif/boards/microdev_micro_s2/board.c +++ b/ports/espressif/boards/microdev_micro_s2/board.c @@ -28,6 +28,8 @@ #include "mpconfigboard.h" #include "shared-bindings/microcontroller/Pin.h" +#include "components/driver/include/driver/gpio.h" + void board_init(void) { // Debug UART #ifdef DEBUG @@ -40,6 +42,17 @@ bool board_requests_safe_mode(void) { return false; } +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + // Pin 21 is a high side LED so pull it down to prevent lighting the LED. + if (pin_number == 21) { + gpio_reset_pin(21); + gpio_pullup_dis(21); + gpio_pulldown_en(21); + return true; + } + return false; +} + void reset_board(void) { } diff --git a/ports/espressif/common-hal/microcontroller/Pin.c b/ports/espressif/common-hal/microcontroller/Pin.c index 1ea187c795..828d85d5ee 100644 --- a/ports/espressif/common-hal/microcontroller/Pin.c +++ b/ports/espressif/common-hal/microcontroller/Pin.c @@ -50,6 +50,10 @@ void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) { never_reset_pin_number(pin->number); } +MP_WEAK bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + return false; +} + STATIC void _reset_pin(gpio_num_t pin_number) { #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) // Never ever reset pins used for flash and RAM. @@ -76,6 +80,11 @@ STATIC void _reset_pin(gpio_num_t pin_number) { } #endif + // Give the board a chance to reset the pin in a particular way. + if (espressif_board_reset_pin_number(pin_number)) { + return; + } + gpio_reset_pin(pin_number); #ifdef DOUBLE_TAP_PIN @@ -133,10 +142,6 @@ void claim_pin(const mcu_pin_obj_t *pin) { in_use[pin->number / 32] |= (1 << (pin->number % 32)); } -void free_pin_number(gpio_num_t pin_number) { - in_use[pin_number / 32] &= ~(1 << (pin_number % 32)); -} - void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) { claim_pin(pin); } diff --git a/ports/espressif/common-hal/microcontroller/Pin.h b/ports/espressif/common-hal/microcontroller/Pin.h index c6db223bb2..e74346ef65 100644 --- a/ports/espressif/common-hal/microcontroller/Pin.h +++ b/ports/espressif/common-hal/microcontroller/Pin.h @@ -39,9 +39,13 @@ void common_hal_reset_pin(const mcu_pin_obj_t *pin); void common_hal_never_reset_pin(const mcu_pin_obj_t *pin); void claim_pin(const mcu_pin_obj_t *pin); void claim_pin_number(gpio_num_t pin_number); -// Free the pin without resetting it. -void free_pin_number(gpio_num_t pin_number); bool pin_number_is_free(gpio_num_t pin_number); void never_reset_pin_number(gpio_num_t pin_number); +// Allow the board to reset a pin in a board-specific way. This can be used +// for LEDs or enable pins to put them in a state beside the default pull-up. +// Return true to indicate that the pin was reset. Returning false will lead to +// the port-default reset behavior. +bool espressif_board_reset_pin_number(gpio_num_t pin_number); + #endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_MICROCONTROLLER_PIN_H