mirror of
https://github.com/esphome/esphome.git
synced 2026-05-24 01:17:02 +08:00
[ethernet] Add interface configuration variable for esp-idf (#10285)
Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
@@ -104,6 +104,8 @@ CONF_CLK_MODE = "clk_mode"
|
||||
CONF_POWER_PIN = "power_pin"
|
||||
CONF_PHY_REGISTERS = "phy_registers"
|
||||
|
||||
CONF_INTERFACE = "interface"
|
||||
|
||||
CONF_CLOCK_SPEED = "clock_speed"
|
||||
|
||||
EthernetType = ethernet_ns.enum("EthernetType")
|
||||
@@ -191,6 +193,13 @@ CLK_MODES_DEPRECATED = {
|
||||
"GPIO17_OUT": ("CLK_OUT", 17),
|
||||
}
|
||||
|
||||
spi_host_device_t = cg.global_ns.enum("spi_host_device_t")
|
||||
|
||||
SPI_INTERFACE_MAP = {
|
||||
"spi2": spi_host_device_t.SPI2_HOST,
|
||||
"spi3": spi_host_device_t.SPI3_HOST,
|
||||
}
|
||||
|
||||
MANUAL_IP_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_STATIC_IP): cv.ipv4address,
|
||||
@@ -225,6 +234,24 @@ def _is_framework_spi_polling_mode_supported() -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _validate_spi_interface(config: ConfigType) -> ConfigType:
|
||||
"""Set default SPI interface or validate user choice against the variant."""
|
||||
if not CORE.is_esp32:
|
||||
return config
|
||||
from esphome.components.esp32 import VARIANT_ESP32, get_esp32_variant
|
||||
from esphome.components.spi import get_hw_interface_list
|
||||
|
||||
has_spi3 = "spi3" in sum(get_hw_interface_list(), [])
|
||||
if CONF_INTERFACE not in config:
|
||||
# Only classic ESP32 defaults to spi3; all others default to spi2
|
||||
config[CONF_INTERFACE] = (
|
||||
"spi3" if get_esp32_variant() == VARIANT_ESP32 else "spi2"
|
||||
)
|
||||
elif config[CONF_INTERFACE] == "spi3" and not has_spi3:
|
||||
raise cv.Invalid("Interface 'spi3' is not available on this variant.")
|
||||
return config
|
||||
|
||||
|
||||
def _validate(config):
|
||||
if CONF_USE_ADDRESS not in config:
|
||||
if CONF_MANUAL_IP in config:
|
||||
@@ -368,6 +395,10 @@ SPI_SCHEMA = cv.All(
|
||||
cv.frequency,
|
||||
cv.int_range(int(8e6), int(80e6)),
|
||||
),
|
||||
cv.Optional(CONF_INTERFACE): cv.All(
|
||||
cv.only_on_esp32,
|
||||
cv.one_of(*SPI_INTERFACE_MAP.keys(), lower=True),
|
||||
),
|
||||
# Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate()
|
||||
cv.Optional(CONF_POLLING_INTERVAL): cv.All(
|
||||
cv.only_on_esp32,
|
||||
@@ -378,6 +409,7 @@ SPI_SCHEMA = cv.All(
|
||||
),
|
||||
),
|
||||
cv.only_on([Platform.ESP32, Platform.RP2040]),
|
||||
_validate_spi_interface,
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
@@ -408,37 +440,18 @@ def _final_validate_spi(config):
|
||||
return # SPI interface validation is ESP32-only
|
||||
if config[CONF_TYPE] not in SPI_ETHERNET_TYPES:
|
||||
return
|
||||
from esphome.components.esp32 import (
|
||||
VARIANT_ESP32C3,
|
||||
VARIANT_ESP32C5,
|
||||
VARIANT_ESP32C6,
|
||||
VARIANT_ESP32C61,
|
||||
VARIANT_ESP32S2,
|
||||
VARIANT_ESP32S3,
|
||||
get_esp32_variant,
|
||||
)
|
||||
from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface
|
||||
|
||||
if spi_configs := fv.full_config.get().get(CONF_SPI):
|
||||
variant = get_esp32_variant()
|
||||
if variant in (
|
||||
VARIANT_ESP32C3,
|
||||
VARIANT_ESP32C5,
|
||||
VARIANT_ESP32C6,
|
||||
VARIANT_ESP32C61,
|
||||
VARIANT_ESP32S2,
|
||||
VARIANT_ESP32S3,
|
||||
):
|
||||
spi_host = "SPI2_HOST"
|
||||
else:
|
||||
spi_host = "SPI3_HOST"
|
||||
# get_spi_interface() returns strings like "SPI2_HOST"
|
||||
spi_host = f"{config[CONF_INTERFACE].upper()}_HOST"
|
||||
for spi_conf in spi_configs:
|
||||
if (index := spi_conf.get(CONF_INTERFACE_INDEX)) is not None:
|
||||
interface = get_spi_interface(index)
|
||||
if interface == spi_host:
|
||||
raise cv.Invalid(
|
||||
f"`spi` component is using interface '{interface}'. "
|
||||
f"To use {config[CONF_TYPE]}, you must change the `interface` on the `spi` component.",
|
||||
f"The `ethernet` and `spi` components are both using interface '{interface}'. "
|
||||
f"To use {config[CONF_TYPE]}, change the `interface` on either `ethernet:` or `spi:`."
|
||||
)
|
||||
|
||||
|
||||
@@ -528,6 +541,8 @@ async def _to_code_esp32(var: cg.Pvariable, config: ConfigType) -> None:
|
||||
cg.add(var.set_clock_speed(config[CONF_CLOCK_SPEED]))
|
||||
|
||||
cg.add_define("USE_ETHERNET_SPI")
|
||||
|
||||
cg.add(var.set_interface(SPI_INTERFACE_MAP[config[CONF_INTERFACE]]))
|
||||
add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True)
|
||||
# CONFIG_ETH_SPI_ETHERNET_{TYPE} Kconfig options were removed in IDF 6.0
|
||||
# ENC28J60 was never built-in to IDF, so it has no Kconfig option
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#include "esp_eth.h"
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
#include "hal/spi_types.h"
|
||||
#endif
|
||||
#include "esp_eth_mac.h"
|
||||
#include "esp_eth_mac_esp.h"
|
||||
#include "esp_netif.h"
|
||||
@@ -135,6 +138,7 @@ class EthernetComponent final : public Component {
|
||||
void set_interrupt_pin(uint8_t interrupt_pin);
|
||||
void set_reset_pin(uint8_t reset_pin);
|
||||
void set_clock_speed(int clock_speed);
|
||||
void set_interface(spi_host_device_t interface);
|
||||
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
|
||||
void set_polling_interval(uint32_t polling_interval);
|
||||
#endif
|
||||
@@ -201,6 +205,7 @@ class EthernetComponent final : public Component {
|
||||
int reset_pin_{-1};
|
||||
int phy_addr_spi_{-1};
|
||||
int clock_speed_;
|
||||
spi_host_device_t interface_{SPI3_HOST};
|
||||
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
|
||||
uint32_t polling_interval_{0};
|
||||
#endif
|
||||
|
||||
@@ -158,12 +158,7 @@ void EthernetComponent::setup() {
|
||||
.intr_flags = 0,
|
||||
};
|
||||
|
||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || defined(USE_ESP32_VARIANT_ESP32C6) || \
|
||||
defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
auto host = SPI2_HOST;
|
||||
#else
|
||||
auto host = SPI3_HOST;
|
||||
#endif
|
||||
auto host = this->interface_;
|
||||
|
||||
err = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO);
|
||||
ESPHL_ERROR_CHECK(err, "SPI bus initialize error");
|
||||
@@ -458,6 +453,11 @@ void EthernetComponent::dump_config() {
|
||||
" MOSI Pin: %u\n"
|
||||
" CS Pin: %u",
|
||||
this->clk_pin_, this->miso_pin_, this->mosi_pin_, this->cs_pin_);
|
||||
const char *spi_interface = "spi3";
|
||||
if (this->interface_ == SPI2_HOST) {
|
||||
spi_interface = "spi2";
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Interface: %s", spi_interface);
|
||||
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
|
||||
if (this->polling_interval_ != 0) {
|
||||
ESP_LOGCONFIG(TAG, " Polling Interval: %" PRIu32 " ms", this->polling_interval_);
|
||||
@@ -760,6 +760,7 @@ void EthernetComponent::set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; }
|
||||
void EthernetComponent::set_interrupt_pin(uint8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; }
|
||||
void EthernetComponent::set_reset_pin(uint8_t reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
void EthernetComponent::set_clock_speed(int clock_speed) { this->clock_speed_ = clock_speed; }
|
||||
void EthernetComponent::set_interface(spi_host_device_t interface) { this->interface_ = interface; }
|
||||
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
|
||||
void EthernetComponent::set_polling_interval(uint32_t polling_interval) { this->polling_interval_ = polling_interval; }
|
||||
#endif
|
||||
|
||||
@@ -1 +1,20 @@
|
||||
<<: !include common-w5500.yaml
|
||||
ethernet:
|
||||
type: W5500
|
||||
clk_pin: 19
|
||||
mosi_pin: 21
|
||||
miso_pin: 23
|
||||
cs_pin: 18
|
||||
interrupt_pin: 36
|
||||
reset_pin: 22
|
||||
clock_speed: 10Mhz
|
||||
manual_ip:
|
||||
static_ip: 192.168.178.56
|
||||
gateway: 192.168.178.1
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
interface: spi2
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
Reference in New Issue
Block a user