mirror of
https://github.com/esphome/esphome.git
synced 2025-10-26 12:43:48 +00:00
[ethernet] Add RMII GPIO pin conflict validation (#11488)
This commit is contained in:
@@ -32,6 +32,7 @@ from esphome.const import (
|
|||||||
CONF_MISO_PIN,
|
CONF_MISO_PIN,
|
||||||
CONF_MODE,
|
CONF_MODE,
|
||||||
CONF_MOSI_PIN,
|
CONF_MOSI_PIN,
|
||||||
|
CONF_NUMBER,
|
||||||
CONF_PAGE_ID,
|
CONF_PAGE_ID,
|
||||||
CONF_PIN,
|
CONF_PIN,
|
||||||
CONF_POLLING_INTERVAL,
|
CONF_POLLING_INTERVAL,
|
||||||
@@ -52,12 +53,36 @@ from esphome.core import (
|
|||||||
coroutine_with_priority,
|
coroutine_with_priority,
|
||||||
)
|
)
|
||||||
import esphome.final_validate as fv
|
import esphome.final_validate as fv
|
||||||
|
from esphome.types import ConfigType
|
||||||
|
|
||||||
CONFLICTS_WITH = ["wifi"]
|
CONFLICTS_WITH = ["wifi"]
|
||||||
DEPENDENCIES = ["esp32"]
|
DEPENDENCIES = ["esp32"]
|
||||||
AUTO_LOAD = ["network"]
|
AUTO_LOAD = ["network"]
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# RMII pins that are hardcoded on ESP32 classic and cannot be changed
|
||||||
|
# These pins are used by the internal Ethernet MAC when using RMII PHYs
|
||||||
|
ESP32_RMII_FIXED_PINS = {
|
||||||
|
19: "EMAC_TXD0",
|
||||||
|
21: "EMAC_TX_EN",
|
||||||
|
22: "EMAC_TXD1",
|
||||||
|
25: "EMAC_RXD0",
|
||||||
|
26: "EMAC_RXD1",
|
||||||
|
27: "EMAC_RX_CRS_DV",
|
||||||
|
}
|
||||||
|
|
||||||
|
# RMII default pins for ESP32-P4
|
||||||
|
# These are the default pins used by ESP-IDF and are configurable in principle,
|
||||||
|
# but ESPHome's ethernet component currently has no way to change them
|
||||||
|
ESP32P4_RMII_DEFAULT_PINS = {
|
||||||
|
34: "EMAC_TXD0",
|
||||||
|
35: "EMAC_TXD1",
|
||||||
|
28: "EMAC_RX_CRS_DV",
|
||||||
|
29: "EMAC_RXD0",
|
||||||
|
30: "EMAC_RXD1",
|
||||||
|
49: "EMAC_TX_EN",
|
||||||
|
}
|
||||||
|
|
||||||
ethernet_ns = cg.esphome_ns.namespace("ethernet")
|
ethernet_ns = cg.esphome_ns.namespace("ethernet")
|
||||||
PHYRegister = ethernet_ns.struct("PHYRegister")
|
PHYRegister = ethernet_ns.struct("PHYRegister")
|
||||||
CONF_PHY_ADDR = "phy_addr"
|
CONF_PHY_ADDR = "phy_addr"
|
||||||
@@ -273,7 +298,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _final_validate(config):
|
def _final_validate_spi(config):
|
||||||
if config[CONF_TYPE] not in SPI_ETHERNET_TYPES:
|
if config[CONF_TYPE] not in SPI_ETHERNET_TYPES:
|
||||||
return
|
return
|
||||||
if spi_configs := fv.full_config.get().get(CONF_SPI):
|
if spi_configs := fv.full_config.get().get(CONF_SPI):
|
||||||
@@ -292,9 +317,6 @@ def _final_validate(config):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
FINAL_VALIDATE_SCHEMA = _final_validate
|
|
||||||
|
|
||||||
|
|
||||||
def manual_ip(config):
|
def manual_ip(config):
|
||||||
return cg.StructInitializer(
|
return cg.StructInitializer(
|
||||||
ManualIP,
|
ManualIP,
|
||||||
@@ -383,3 +405,57 @@ async def to_code(config):
|
|||||||
|
|
||||||
if CORE.using_arduino:
|
if CORE.using_arduino:
|
||||||
cg.add_library("WiFi", None)
|
cg.add_library("WiFi", None)
|
||||||
|
|
||||||
|
|
||||||
|
def _final_validate_rmii_pins(config: ConfigType) -> None:
|
||||||
|
"""Validate that RMII pins are not used by other components."""
|
||||||
|
# Only validate for RMII-based PHYs on ESP32/ESP32P4
|
||||||
|
if config[CONF_TYPE] in SPI_ETHERNET_TYPES or config[CONF_TYPE] == "OPENETH":
|
||||||
|
return # SPI and OPENETH don't use RMII
|
||||||
|
|
||||||
|
variant = get_esp32_variant()
|
||||||
|
if variant == VARIANT_ESP32:
|
||||||
|
rmii_pins = ESP32_RMII_FIXED_PINS
|
||||||
|
is_configurable = False
|
||||||
|
elif variant == VARIANT_ESP32P4:
|
||||||
|
rmii_pins = ESP32P4_RMII_DEFAULT_PINS
|
||||||
|
is_configurable = True
|
||||||
|
else:
|
||||||
|
return # No RMII validation needed for other variants
|
||||||
|
|
||||||
|
# Check all used pins against RMII reserved pins
|
||||||
|
for pin_list in pins.PIN_SCHEMA_REGISTRY.pins_used.values():
|
||||||
|
for pin_path, _, pin_config in pin_list:
|
||||||
|
pin_num = pin_config.get(CONF_NUMBER)
|
||||||
|
if pin_num not in rmii_pins:
|
||||||
|
continue
|
||||||
|
# Found a conflict - show helpful error message
|
||||||
|
pin_function = rmii_pins[pin_num]
|
||||||
|
component_path = ".".join(str(p) for p in pin_path)
|
||||||
|
if is_configurable:
|
||||||
|
error_msg = (
|
||||||
|
f"GPIO{pin_num} is used by Ethernet RMII "
|
||||||
|
f"({pin_function}) with the current default "
|
||||||
|
f"configuration. This conflicts with '{component_path}'. "
|
||||||
|
f"Please choose a different GPIO pin for "
|
||||||
|
f"'{component_path}'."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
error_msg = (
|
||||||
|
f"GPIO{pin_num} is reserved for Ethernet RMII "
|
||||||
|
f"({pin_function}) and cannot be used. This pin is "
|
||||||
|
f"hardcoded by ESP-IDF and cannot be changed when using "
|
||||||
|
f"RMII Ethernet PHYs. Please choose a different GPIO pin "
|
||||||
|
f"for '{component_path}'."
|
||||||
|
)
|
||||||
|
raise cv.Invalid(error_msg, path=pin_path)
|
||||||
|
|
||||||
|
|
||||||
|
def _final_validate(config: ConfigType) -> ConfigType:
|
||||||
|
"""Final validation for Ethernet component."""
|
||||||
|
_final_validate_spi(config)
|
||||||
|
_final_validate_rmii_pins(config)
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
FINAL_VALIDATE_SCHEMA = _final_validate
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: DP83848
|
type: DP83848
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: IP101
|
type: IP101
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: JL1101
|
type: JL1101
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: KSZ8081
|
type: KSZ8081
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: KSZ8081RNA
|
type: KSZ8081RNA
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: LAN8670
|
type: LAN8670
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: LAN8720
|
type: LAN8720
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: RTL8201
|
type: RTL8201
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
ethernet:
|
ethernet:
|
||||||
type: LAN8720
|
type: LAN8720
|
||||||
mdc_pin: 23
|
mdc_pin: 23
|
||||||
mdio_pin: 25
|
mdio_pin: 32
|
||||||
clk:
|
clk:
|
||||||
pin: 0
|
pin: 0
|
||||||
mode: CLK_EXT_IN
|
mode: CLK_EXT_IN
|
||||||
phy_addr: 0
|
phy_addr: 0
|
||||||
power_pin: 26
|
power_pin: 33
|
||||||
manual_ip:
|
manual_ip:
|
||||||
static_ip: 192.168.178.56
|
static_ip: 192.168.178.56
|
||||||
gateway: 192.168.178.1
|
gateway: 192.168.178.1
|
||||||
|
|||||||
Reference in New Issue
Block a user