mirror of
https://github.com/esphome/esphome.git
synced 2025-10-28 21:53:48 +00:00
Adding W5500 support to ethernet component (#4424)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
@@ -9,6 +9,11 @@
|
||||
#include <lwip/dns.h>
|
||||
#include "esp_event.h"
|
||||
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
#include <driver/gpio.h>
|
||||
#include <driver/spi_master.h>
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace ethernet {
|
||||
|
||||
@@ -33,6 +38,36 @@ void EthernetComponent::setup() {
|
||||
}
|
||||
|
||||
esp_err_t err;
|
||||
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
// Install GPIO ISR handler to be able to service SPI Eth modules interrupts
|
||||
gpio_install_isr_service(0);
|
||||
|
||||
spi_bus_config_t buscfg = {
|
||||
.mosi_io_num = this->mosi_pin_,
|
||||
.miso_io_num = this->miso_pin_,
|
||||
.sclk_io_num = this->clk_pin_,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.data4_io_num = -1,
|
||||
.data5_io_num = -1,
|
||||
.data6_io_num = -1,
|
||||
.data7_io_num = -1,
|
||||
.max_transfer_sz = 0,
|
||||
.flags = 0,
|
||||
.intr_flags = 0,
|
||||
};
|
||||
|
||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
auto host = SPI2_HOST;
|
||||
#else
|
||||
auto host = SPI3_HOST;
|
||||
#endif
|
||||
|
||||
err = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO);
|
||||
ESPHL_ERROR_CHECK(err, "SPI bus initialize error");
|
||||
#endif
|
||||
|
||||
err = esp_netif_init();
|
||||
ESPHL_ERROR_CHECK(err, "ETH netif init error");
|
||||
err = esp_event_loop_create_default();
|
||||
@@ -43,10 +78,40 @@ void EthernetComponent::setup() {
|
||||
|
||||
// Init MAC and PHY configs to default
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
|
||||
#ifdef USE_ETHERNET_SPI // Configure SPI interface and Ethernet driver for specific SPI module
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 16, // Actually it's the address phase in W5500 SPI frame
|
||||
.address_bits = 8, // Actually it's the control phase in W5500 SPI frame
|
||||
.dummy_bits = 0,
|
||||
.mode = 0,
|
||||
.duty_cycle_pos = 0,
|
||||
.cs_ena_pretrans = 0,
|
||||
.cs_ena_posttrans = 0,
|
||||
.clock_speed_hz = this->clock_speed_,
|
||||
.input_delay_ns = 0,
|
||||
.spics_io_num = this->cs_pin_,
|
||||
.flags = 0,
|
||||
.queue_size = 20,
|
||||
.pre_cb = nullptr,
|
||||
.post_cb = nullptr,
|
||||
};
|
||||
|
||||
spi_device_handle_t spi_handle = nullptr;
|
||||
err = spi_bus_add_device(host, &devcfg, &spi_handle);
|
||||
ESPHL_ERROR_CHECK(err, "SPI bus add device error");
|
||||
|
||||
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
|
||||
w5500_config.int_gpio_num = this->interrupt_pin_;
|
||||
phy_config.phy_addr = this->phy_addr_spi_;
|
||||
phy_config.reset_gpio_num = this->reset_pin_;
|
||||
|
||||
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||
#else
|
||||
phy_config.phy_addr = this->phy_addr_;
|
||||
phy_config.reset_gpio_num = this->power_pin_;
|
||||
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||
esp32_emac_config.smi_mdc_gpio_num = this->mdc_pin_;
|
||||
@@ -62,9 +127,11 @@ void EthernetComponent::setup() {
|
||||
mac_config.clock_config.rmii.clock_gpio = this->clk_gpio_;
|
||||
|
||||
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
switch (this->type_) {
|
||||
#if CONFIG_ETH_USE_ESP32_EMAC
|
||||
case ETHERNET_TYPE_LAN8720: {
|
||||
this->phy_ = esp_eth_phy_new_lan87xx(&phy_config);
|
||||
break;
|
||||
@@ -94,6 +161,13 @@ void EthernetComponent::setup() {
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
case ETHERNET_TYPE_W5500: {
|
||||
this->phy_ = esp_eth_phy_new_w5500(&phy_config);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
this->mark_failed();
|
||||
return;
|
||||
@@ -105,10 +179,18 @@ void EthernetComponent::setup() {
|
||||
err = esp_eth_driver_install(ð_config, &this->eth_handle_);
|
||||
ESPHL_ERROR_CHECK(err, "ETH driver install error");
|
||||
|
||||
#ifndef USE_ETHERNET_SPI
|
||||
if (this->type_ == ETHERNET_TYPE_KSZ8081RNA && this->clk_mode_ == EMAC_CLK_OUT) {
|
||||
// KSZ8081RNA default is incorrect. It expects a 25MHz clock instead of the 50MHz we provide.
|
||||
this->ksz8081_set_clock_reference_(mac);
|
||||
}
|
||||
#endif
|
||||
|
||||
// use ESP internal eth mac
|
||||
uint8_t mac_addr[6];
|
||||
esp_read_mac(mac_addr, ESP_MAC_ETH);
|
||||
err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_S_MAC_ADDR, mac_addr);
|
||||
ESPHL_ERROR_CHECK(err, "set mac address error");
|
||||
|
||||
/* attach Ethernet driver to TCP/IP stack */
|
||||
err = esp_netif_attach(this->eth_netif_, esp_eth_new_netif_glue(this->eth_handle_));
|
||||
@@ -200,6 +282,10 @@ void EthernetComponent::dump_config() {
|
||||
eth_type = "KSZ8081RNA";
|
||||
break;
|
||||
|
||||
case ETHERNET_TYPE_W5500:
|
||||
eth_type = "W5500";
|
||||
break;
|
||||
|
||||
default:
|
||||
eth_type = "Unknown";
|
||||
break;
|
||||
@@ -207,13 +293,23 @@ void EthernetComponent::dump_config() {
|
||||
|
||||
ESP_LOGCONFIG(TAG, "Ethernet:");
|
||||
this->dump_connect_params_();
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
ESP_LOGCONFIG(TAG, " CLK Pin: %u", this->clk_pin_);
|
||||
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_);
|
||||
ESP_LOGCONFIG(TAG, " Reset Pin: %d", this->reset_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Clock Speed: %d MHz", this->clock_speed_ / 1000000);
|
||||
#else
|
||||
if (this->power_pin_ != -1) {
|
||||
ESP_LOGCONFIG(TAG, " Power Pin: %u", this->power_pin_);
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " MDC Pin: %u", this->mdc_pin_);
|
||||
ESP_LOGCONFIG(TAG, " MDIO Pin: %u", this->mdio_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Type: %s", eth_type);
|
||||
ESP_LOGCONFIG(TAG, " PHY addr: %u", this->phy_addr_);
|
||||
#endif
|
||||
ESP_LOGCONFIG(TAG, " Type: %s", eth_type);
|
||||
}
|
||||
|
||||
float EthernetComponent::get_setup_priority() const { return setup_priority::WIFI; }
|
||||
@@ -407,15 +503,25 @@ void EthernetComponent::dump_connect_params_() {
|
||||
ESP_LOGCONFIG(TAG, " Link Speed: %u", speed == ETH_SPEED_100M ? 100 : 10);
|
||||
}
|
||||
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; }
|
||||
void EthernetComponent::set_miso_pin(uint8_t miso_pin) { this->miso_pin_ = miso_pin; }
|
||||
void EthernetComponent::set_mosi_pin(uint8_t mosi_pin) { this->mosi_pin_ = mosi_pin; }
|
||||
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; }
|
||||
#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; }
|
||||
void EthernetComponent::set_mdc_pin(uint8_t mdc_pin) { this->mdc_pin_ = mdc_pin; }
|
||||
void EthernetComponent::set_mdio_pin(uint8_t mdio_pin) { this->mdio_pin_ = mdio_pin; }
|
||||
void EthernetComponent::set_type(EthernetType type) { this->type_ = type; }
|
||||
void EthernetComponent::set_clk_mode(emac_rmii_clock_mode_t clk_mode, emac_rmii_clock_gpio_t clk_gpio) {
|
||||
this->clk_mode_ = clk_mode;
|
||||
this->clk_gpio_ = clk_gpio;
|
||||
}
|
||||
#endif
|
||||
void EthernetComponent::set_type(EthernetType type) { this->type_ = type; }
|
||||
void EthernetComponent::set_manual_ip(const ManualIP &manual_ip) { this->manual_ip_ = manual_ip; }
|
||||
|
||||
std::string EthernetComponent::get_use_address() const {
|
||||
@@ -442,6 +548,7 @@ bool EthernetComponent::powerdown() {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef USE_ETHERNET_SPI
|
||||
void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) {
|
||||
#define KSZ80XX_PC2R_REG_ADDR (0x1F)
|
||||
|
||||
@@ -472,6 +579,7 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) {
|
||||
|
||||
#undef KSZ80XX_PC2R_REG_ADDR
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ethernet
|
||||
} // namespace esphome
|
||||
|
||||
Reference in New Issue
Block a user