mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 10:12:52 +00:00
[ethernet] Skip setters that pass the default PHY address, MDC, MDIO, clock and SPI interface (#20070)
This commit is contained in:
@@ -214,6 +214,15 @@ CLK_MODES = {
|
||||
|
||||
spi_host_device_t = cg.global_ns.enum("spi_host_device_t")
|
||||
|
||||
# Must match the member initializers in ethernet_component.h; setters are skipped
|
||||
# when the config already equals them.
|
||||
DEFAULT_SPI_INTERFACE = "spi2"
|
||||
DEFAULT_PHY_ADDR = 0
|
||||
DEFAULT_MDC_PIN = 23
|
||||
DEFAULT_MDIO_PIN = 18
|
||||
DEFAULT_CLK_MODE = "CLK_EXT_IN"
|
||||
DEFAULT_CLK_PIN = 0
|
||||
|
||||
SPI_INTERFACE_MAP = {
|
||||
"spi2": spi_host_device_t.SPI2_HOST,
|
||||
"spi3": spi_host_device_t.SPI3_HOST,
|
||||
@@ -437,7 +446,9 @@ RMII_SCHEMA = cv.All(
|
||||
" GPIO17_OUT -> mode: CLK_OUT, pin: GPIO17"
|
||||
),
|
||||
cv.Required(CONF_CLK): CLK_SCHEMA,
|
||||
cv.Optional(CONF_PHY_ADDR, default=0): cv.int_range(min=0, max=31),
|
||||
cv.Optional(CONF_PHY_ADDR, default=DEFAULT_PHY_ADDR): cv.int_range(
|
||||
min=0, max=31
|
||||
),
|
||||
cv.Optional(CONF_POWER_PIN): pins.internal_gpio_output_pin_number,
|
||||
cv.Optional(CONF_PHY_REGISTERS): cv.ensure_list(PHY_REGISTER_SCHEMA),
|
||||
}
|
||||
@@ -454,7 +465,9 @@ GENERIC_SCHEMA = cv.All(
|
||||
{
|
||||
cv.Required(CONF_MDC_PIN): pins.internal_gpio_output_pin_number,
|
||||
cv.Required(CONF_MDIO_PIN): pins.internal_gpio_output_pin_number,
|
||||
cv.Optional(CONF_PHY_ADDR, default=0): cv.int_range(min=0, max=31),
|
||||
cv.Optional(CONF_PHY_ADDR, default=DEFAULT_PHY_ADDR): cv.int_range(
|
||||
min=0, max=31
|
||||
),
|
||||
cv.Optional(CONF_POWER_PIN): pins.internal_gpio_output_pin_number,
|
||||
cv.Optional(CONF_PHY_REGISTERS): cv.ensure_list(PHY_REGISTER_SCHEMA),
|
||||
}
|
||||
@@ -683,6 +696,15 @@ async def to_code(config: ConfigType) -> None:
|
||||
CORE.add_job(final_step)
|
||||
|
||||
|
||||
def _add_mdio_setters(var: cg.MockObj, config: ConfigType) -> None:
|
||||
if (phy_addr := config[CONF_PHY_ADDR]) != DEFAULT_PHY_ADDR:
|
||||
cg.add(var.set_phy_addr(phy_addr))
|
||||
if (mdc_pin := config[CONF_MDC_PIN]) != DEFAULT_MDC_PIN:
|
||||
cg.add(var.set_mdc_pin(mdc_pin))
|
||||
if (mdio_pin := config[CONF_MDIO_PIN]) != DEFAULT_MDIO_PIN:
|
||||
cg.add(var.set_mdio_pin(mdio_pin))
|
||||
|
||||
|
||||
async def _to_code_esp32(var: cg.MockObj, config: ConfigType) -> None:
|
||||
from esphome.components.esp32 import (
|
||||
add_idf_component,
|
||||
@@ -701,7 +723,8 @@ async def _to_code_esp32(var: cg.MockObj, config: ConfigType) -> None:
|
||||
cg.add(var.set_clk_pin(config[CONF_CLK_PIN]))
|
||||
cg.add(var.set_miso_pin(config[CONF_MISO_PIN]))
|
||||
cg.add(var.set_mosi_pin(config[CONF_MOSI_PIN]))
|
||||
cg.add(var.set_interface(SPI_INTERFACE_MAP[config[CONF_INTERFACE]]))
|
||||
if (interface := config[CONF_INTERFACE]) != DEFAULT_SPI_INTERFACE:
|
||||
cg.add(var.set_interface(SPI_INTERFACE_MAP[interface]))
|
||||
cg.add(var.set_cs_pin(config[CONF_CS_PIN]))
|
||||
if CONF_INTERRUPT_PIN in config:
|
||||
cg.add(var.set_interrupt_pin(config[CONF_INTERRUPT_PIN]))
|
||||
@@ -730,18 +753,16 @@ async def _to_code_esp32(var: cg.MockObj, config: ConfigType) -> None:
|
||||
add_idf_sdkconfig_option("CONFIG_ETH_USE_OPENETH", True)
|
||||
elif config[CONF_TYPE] in ("GENERIC", "YT8531"):
|
||||
# RGMII data pins come from the IDF default config; set MDC/MDIO + PHY addr.
|
||||
cg.add(var.set_phy_addr(config[CONF_PHY_ADDR]))
|
||||
cg.add(var.set_mdc_pin(config[CONF_MDC_PIN]))
|
||||
cg.add(var.set_mdio_pin(config[CONF_MDIO_PIN]))
|
||||
_add_mdio_setters(var, config)
|
||||
if CONF_POWER_PIN in config:
|
||||
cg.add(var.set_power_pin(config[CONF_POWER_PIN]))
|
||||
_add_phy_registers(var, config)
|
||||
else:
|
||||
cg.add(var.set_phy_addr(config[CONF_PHY_ADDR]))
|
||||
cg.add(var.set_mdc_pin(config[CONF_MDC_PIN]))
|
||||
cg.add(var.set_mdio_pin(config[CONF_MDIO_PIN]))
|
||||
cg.add(var.set_clk_mode(config[CONF_CLK][CONF_MODE]))
|
||||
cg.add(var.set_clk_pin(config[CONF_CLK][CONF_PIN]))
|
||||
_add_mdio_setters(var, config)
|
||||
if (clk_mode := config[CONF_CLK][CONF_MODE]) != DEFAULT_CLK_MODE:
|
||||
cg.add(var.set_clk_mode(clk_mode))
|
||||
if (clk_pin := config[CONF_CLK][CONF_PIN]) != DEFAULT_CLK_PIN:
|
||||
cg.add(var.set_clk_pin(clk_pin))
|
||||
if CONF_POWER_PIN in config:
|
||||
cg.add(var.set_power_pin(config[CONF_POWER_PIN]))
|
||||
_add_phy_registers(var, config)
|
||||
|
||||
@@ -271,7 +271,7 @@ class EthernetComponent final : public Component {
|
||||
int reset_pin_{-1};
|
||||
int phy_addr_spi_{-1};
|
||||
int clock_speed_;
|
||||
spi_host_device_t interface_{SPI2_HOST};
|
||||
spi_host_device_t interface_{SPI2_HOST}; // Must match DEFAULT_SPI_INTERFACE in __init__.py
|
||||
#ifdef USE_SPI
|
||||
// When set, the SPI bus is owned and initialized by this spi component
|
||||
// and the ethernet chip only adds a device to it.
|
||||
@@ -283,16 +283,16 @@ class EthernetComponent final : public Component {
|
||||
#else
|
||||
// Group all 32-bit members first
|
||||
int power_pin_{-1};
|
||||
emac_rmii_clock_mode_t clk_mode_{EMAC_CLK_EXT_IN};
|
||||
emac_rmii_clock_mode_t clk_mode_{EMAC_CLK_EXT_IN}; // Must match DEFAULT_CLK_MODE in __init__.py
|
||||
#ifdef ESPHOME_ETHERNET_PHY_REGISTER_COUNT
|
||||
StaticVector<PHYRegister, ESPHOME_ETHERNET_PHY_REGISTER_COUNT> phy_registers_{};
|
||||
#endif
|
||||
|
||||
// Group all 8-bit members together
|
||||
uint8_t clk_pin_{0};
|
||||
uint8_t phy_addr_{0};
|
||||
uint8_t mdc_pin_{23};
|
||||
uint8_t mdio_pin_{18};
|
||||
uint8_t clk_pin_{0}; // Must match DEFAULT_CLK_PIN in __init__.py
|
||||
uint8_t phy_addr_{0}; // Must match DEFAULT_PHY_ADDR in __init__.py
|
||||
uint8_t mdc_pin_{23}; // Must match DEFAULT_MDC_PIN in __init__.py
|
||||
uint8_t mdio_pin_{18}; // Must match DEFAULT_MDIO_PIN in __init__.py
|
||||
#endif // USE_ETHERNET_SPI
|
||||
|
||||
// ESP32 pointers
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
|
||||
ethernet:
|
||||
type: LAN8720
|
||||
mdc_pin: GPIO4
|
||||
mdio_pin: GPIO5
|
||||
phy_addr: 1
|
||||
clk:
|
||||
mode: CLK_OUT
|
||||
pin: GPIO17
|
||||
@@ -0,0 +1,13 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
|
||||
ethernet:
|
||||
type: LAN8720
|
||||
mdc_pin: GPIO23
|
||||
mdio_pin: GPIO18
|
||||
clk:
|
||||
mode: CLK_EXT_IN
|
||||
pin: GPIO0
|
||||
@@ -0,0 +1,14 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp32:
|
||||
board: esp32-s3-devkitc-1
|
||||
|
||||
ethernet:
|
||||
type: W5500
|
||||
clk_pin: GPIO12
|
||||
mosi_pin: GPIO11
|
||||
miso_pin: GPIO13
|
||||
cs_pin: GPIO10
|
||||
interrupt_pin: GPIO4
|
||||
clock_speed: 20MHz
|
||||
@@ -0,0 +1,49 @@
|
||||
"""Ethernet setters are skipped when the config matches the C++ initializers."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
_MDIO_SETTERS = ("set_phy_addr(", "set_mdc_pin(", "set_mdio_pin(")
|
||||
|
||||
|
||||
def test_rmii_defaults_are_not_emitted(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
main_cpp = generate_main(component_config_path("rmii_defaults.yaml"))
|
||||
|
||||
for setter in (*_MDIO_SETTERS, "set_clk_mode(", "set_clk_pin("):
|
||||
assert setter not in main_cpp
|
||||
|
||||
|
||||
def test_rmii_custom_values_are_emitted(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
main_cpp = generate_main(component_config_path("rmii_custom.yaml"))
|
||||
|
||||
assert "set_phy_addr(1);" in main_cpp
|
||||
assert "set_mdc_pin(4);" in main_cpp
|
||||
assert "set_mdio_pin(5);" in main_cpp
|
||||
assert "set_clk_mode(::EMAC_CLK_OUT);" in main_cpp
|
||||
assert "set_clk_pin(17);" in main_cpp
|
||||
|
||||
|
||||
def test_spi2_interface_is_not_emitted(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
"""ESP32-S3 defaults to spi2, which is the C++ initializer."""
|
||||
main_cpp = generate_main(component_config_path("spi_s3_own_bus.yaml"))
|
||||
|
||||
assert "set_interface(" not in main_cpp
|
||||
|
||||
|
||||
def test_spi3_interface_is_emitted(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
"""Classic ESP32 defaults to spi3, so the setter is still needed."""
|
||||
main_cpp = generate_main(component_config_path("spi_own_bus.yaml"))
|
||||
|
||||
assert "set_interface(::SPI3_HOST);" in main_cpp
|
||||
Reference in New Issue
Block a user