[esp32] Fix ESP32-S31 GPIO validation (#18904)

This commit is contained in:
Jonathan Swoboda
2026-08-31 07:19:20 -04:00
committed by GitHub
parent 404da26a37
commit 575a540c9f
2 changed files with 52 additions and 9 deletions
+15 -9
View File
@@ -5,11 +5,15 @@ import esphome.config_validation as cv
from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER, CONF_SCL, CONF_SDA
from esphome.pins import check_strapping_pin
# Per the ESP32-S31 datasheet (page 96):
# https://documentation.espressif.com/esp32-s31_datasheet_en.pdf
_ESP32S31_SPI_FLASH_PINS: set[int] = {27, 28, 29, 31, 32, 33}
# GPIO60/GPIO61 set the boot mode; GPIO37 selects the JTAG signal source.
_ESP32S31_STRAPPING_PINS: set[int] = {37, 60, 61}
# Per the ESP32-S31 datasheet, the SPI flash and PSRAM interfaces use
# dedicated package pins (SPICS/SPIQ/SPIWP/SPIHD/SPICLK/SPID) outside the
# GPIO matrix, so no GPIOs are reserved for them. GPIO29 and GPIO41 do not
# exist on this chip (SOC_GPIO_VALID_GPIO_MASK excludes them).
# https://documentation.espressif.com/esp32-s31_datasheet_en.html
_ESP32S31_INVALID_PINS: set[int] = {29, 41}
# GPIO60/GPIO61 set the boot mode; GPIO37 selects the JTAG signal source;
# GPIO36 sets the VDD_SPI voltage.
_ESP32S31_STRAPPING_PINS: set[int] = {36, 37, 60, 61}
# LP I2C is fixed to GPIO6 (SCL) / GPIO7 (SDA) per the datasheet IO MUX table.
_ESP32S31_I2C_LP_PINS = {"SDA": 7, "SCL": 6}
@@ -19,10 +23,8 @@ _LOGGER = logging.getLogger(__name__)
def esp32_s31_validate_gpio_pin(value: int) -> int:
if value < 0 or value > 61:
raise cv.Invalid(f"Invalid pin number: {value} (must be 0-61)")
if value in _ESP32S31_SPI_FLASH_PINS:
raise cv.Invalid(
f"GPIO{value} is reserved for the SPI flash interface on ESP32-S31 and cannot be used."
)
if value in _ESP32S31_INVALID_PINS:
raise cv.Invalid(f"GPIO{value} does not exist on ESP32-S31.")
return value
@@ -33,6 +35,10 @@ def esp32_s31_validate_supports(value: dict[str, Any]) -> dict[str, Any]:
if num < 0 or num > 61:
raise cv.Invalid(f"Invalid pin number: {num} (must be 0-61)")
# Checked here as well so ignore_pin_validation_error cannot bypass it;
# these pins are not bonded and can never work
if num in _ESP32S31_INVALID_PINS:
raise cv.Invalid(f"GPIO{num} does not exist on ESP32-S31.")
if is_input:
# All ESP32 pins support input mode
pass