Skip to content

Commit

Permalink
Support W5500 SPI-Ethernet polling mode if framework is supported (#7503
Browse files Browse the repository at this point in the history
)
  • Loading branch information
slakichi authored Oct 29, 2024
1 parent df750d0 commit 302ba28
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 3 deletions.
56 changes: 55 additions & 1 deletion esphome/components/ethernet/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
from esphome import pins
import esphome.codegen as cg
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant
Expand All @@ -23,20 +24,24 @@
CONF_MISO_PIN,
CONF_MOSI_PIN,
CONF_PAGE_ID,
CONF_POLLING_INTERVAL,
CONF_RESET_PIN,
CONF_SPI,
CONF_STATIC_IP,
CONF_SUBNET,
CONF_TYPE,
CONF_USE_ADDRESS,
CONF_VALUE,
KEY_CORE,
KEY_FRAMEWORK_VERSION,
)
from esphome.core import CORE, coroutine_with_priority
from esphome.core import CORE, TimePeriodMilliseconds, coroutine_with_priority
import esphome.final_validate as fv

CONFLICTS_WITH = ["wifi"]
DEPENDENCIES = ["esp32"]
AUTO_LOAD = ["network"]
LOGGER = logging.getLogger(__name__)

ethernet_ns = cg.esphome_ns.namespace("ethernet")
PHYRegister = ethernet_ns.struct("PHYRegister")
Expand All @@ -63,6 +68,7 @@
}

SPI_ETHERNET_TYPES = ["W5500"]
SPI_ETHERNET_DEFAULT_POLLING_INTERVAL = TimePeriodMilliseconds(milliseconds=10)

emac_rmii_clock_mode_t = cg.global_ns.enum("emac_rmii_clock_mode_t")
emac_rmii_clock_gpio_t = cg.global_ns.enum("emac_rmii_clock_gpio_t")
Expand Down Expand Up @@ -100,13 +106,52 @@
ManualIP = ethernet_ns.struct("ManualIP")


def _is_framework_spi_polling_mode_supported():
# SPI Ethernet without IRQ feature is added in
# esp-idf >= (5.3+ ,5.2.1+, 5.1.4) and arduino-esp32 >= 3.0.0
framework_version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]
if CORE.using_esp_idf:
if framework_version >= cv.Version(5, 3, 0):
return True
if cv.Version(5, 3, 0) > framework_version >= cv.Version(5, 2, 1):
return True
if cv.Version(5, 2, 0) > framework_version >= cv.Version(5, 1, 4):
return True
return False
if CORE.using_arduino:
return framework_version >= cv.Version(3, 0, 0)
# fail safe: Unknown framework
return False


def _validate(config):
if CONF_USE_ADDRESS not in config:
if CONF_MANUAL_IP in config:
use_address = str(config[CONF_MANUAL_IP][CONF_STATIC_IP])
else:
use_address = CORE.name + config[CONF_DOMAIN]
config[CONF_USE_ADDRESS] = use_address
if config[CONF_TYPE] in SPI_ETHERNET_TYPES:
if _is_framework_spi_polling_mode_supported():
if CONF_POLLING_INTERVAL in config and CONF_INTERRUPT_PIN in config:
raise cv.Invalid(
f"Cannot specify more than one of {CONF_INTERRUPT_PIN}, {CONF_POLLING_INTERVAL}"
)
if CONF_POLLING_INTERVAL not in config and CONF_INTERRUPT_PIN not in config:
config[CONF_POLLING_INTERVAL] = SPI_ETHERNET_DEFAULT_POLLING_INTERVAL
else:
if CONF_POLLING_INTERVAL in config:
raise cv.Invalid(
"In this version of the framework "
f"({CORE.target_framework} {CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}), "
f"'{CONF_POLLING_INTERVAL}' is not supported."
)
if CONF_INTERRUPT_PIN not in config:
raise cv.Invalid(
"In this version of the framework "
f"({CORE.target_framework} {CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}), "
f"'{CONF_INTERRUPT_PIN}' is a required option for [ethernet]."
)
return config


Expand Down Expand Up @@ -157,6 +202,11 @@ def _validate(config):
cv.Optional(CONF_CLOCK_SPEED, default="26.67MHz"): cv.All(
cv.frequency, cv.int_range(int(8e6), int(80e6))
),
# Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate()
cv.Optional(CONF_POLLING_INTERVAL): cv.All(
cv.positive_time_period_milliseconds,
cv.Range(min=TimePeriodMilliseconds(milliseconds=1)),
),
}
),
)
Expand Down Expand Up @@ -234,6 +284,10 @@ async def to_code(config):
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]))
else:
cg.add(var.set_polling_interval(config[CONF_POLLING_INTERVAL]))
if _is_framework_spi_polling_mode_supported():
cg.add_define("USE_ETHERNET_SPI_POLLING_SUPPORT")
if CONF_RESET_PIN in config:
cg.add(var.set_reset_pin(config[CONF_RESET_PIN]))
cg.add(var.set_clock_speed(config[CONF_CLOCK_SPEED]))
Expand Down
15 changes: 14 additions & 1 deletion esphome/components/ethernet/ethernet_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ void EthernetComponent::setup() {
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
#endif
w5500_config.int_gpio_num = this->interrupt_pin_;
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
w5500_config.poll_period_ms = this->polling_interval_;
#endif
phy_config.phy_addr = this->phy_addr_spi_;
phy_config.reset_gpio_num = this->reset_pin_;

Expand Down Expand Up @@ -327,7 +330,14 @@ void EthernetComponent::dump_config() {
ESP_LOGCONFIG(TAG, " MISO Pin: %u", this->miso_pin_);
ESP_LOGCONFIG(TAG, " MOSI Pin: %u", this->mosi_pin_);
ESP_LOGCONFIG(TAG, " CS Pin: %u", this->cs_pin_);
ESP_LOGCONFIG(TAG, " IRQ Pin: %u", this->interrupt_pin_);
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
if (this->polling_interval_ != 0) {
ESP_LOGCONFIG(TAG, " Polling Interval: %lu ms", this->polling_interval_);
} else
#endif
{
ESP_LOGCONFIG(TAG, " IRQ Pin: %d", this->interrupt_pin_);
}
ESP_LOGCONFIG(TAG, " Reset Pin: %d", this->reset_pin_);
ESP_LOGCONFIG(TAG, " Clock Speed: %d MHz", this->clock_speed_ / 1000000);
#else
Expand Down Expand Up @@ -536,6 +546,9 @@ 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; }
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
void EthernetComponent::set_polling_interval(uint32_t polling_interval) { this->polling_interval_ = polling_interval; }
#endif
#else
void EthernetComponent::set_phy_addr(uint8_t phy_addr) { this->phy_addr_ = phy_addr; }
void EthernetComponent::set_power_pin(int power_pin) { this->power_pin_ = power_pin; }
Expand Down
8 changes: 7 additions & 1 deletion esphome/components/ethernet/ethernet_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ class EthernetComponent : 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);
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
void set_polling_interval(uint32_t polling_interval);
#endif
#else
void set_phy_addr(uint8_t phy_addr);
void set_power_pin(int power_pin);
Expand Down Expand Up @@ -108,10 +111,13 @@ class EthernetComponent : public Component {
uint8_t miso_pin_;
uint8_t mosi_pin_;
uint8_t cs_pin_;
uint8_t interrupt_pin_;
int interrupt_pin_{-1};
int reset_pin_{-1};
int phy_addr_spi_{-1};
int clock_speed_;
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
uint32_t polling_interval_{0};
#endif
#else
uint8_t phy_addr_{0};
int power_pin_{-1};
Expand Down
1 change: 1 addition & 0 deletions esphome/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@
CONF_PMC_10_0 = "pmc_10_0"
CONF_PMC_2_5 = "pmc_2_5"
CONF_PMC_4_0 = "pmc_4_0"
CONF_POLLING_INTERVAL = "polling_interval"
CONF_PORT = "port"
CONF_POSITION = "position"
CONF_POSITION_ACTION = "position_action"
Expand Down

0 comments on commit 302ba28

Please sign in to comment.