diff --git a/include/W5500.h b/include/W5500.h index f62c33126..d85cb016c 100644 --- a/include/W5500.h +++ b/include/W5500.h @@ -2,19 +2,28 @@ #pragma once #include +#include #include // required for esp_eth_handle_t #include +#include + class W5500 { +private: + explicit W5500(spi_device_handle_t spi, gpio_num_t pin_int); + public: - explicit W5500(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst); W5500(const W5500&) = delete; W5500& operator=(const W5500&) = delete; ~W5500(); + static std::unique_ptr setup(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst); String macAddress(); private: + static bool connection_check_spi(spi_device_handle_t spi); + static bool connection_check_interrupt(gpio_num_t pin_int); + esp_eth_handle_t eth_handle; esp_netif_t* eth_netif; }; diff --git a/src/NetworkSettings.cpp b/src/NetworkSettings.cpp index 33de9255d..75c4bb12a 100644 --- a/src/NetworkSettings.cpp +++ b/src/NetworkSettings.cpp @@ -34,7 +34,11 @@ void NetworkSettingsClass::init(Scheduler& scheduler) if (PinMapping.isValidW5500Config()) { PinMapping_t& pin = PinMapping.get(); - _w5500 = std::make_unique(pin.w5500_mosi, pin.w5500_miso, pin.w5500_sclk, pin.w5500_cs, pin.w5500_int, pin.w5500_rst); + _w5500 = W5500::setup(pin.w5500_mosi, pin.w5500_miso, pin.w5500_sclk, pin.w5500_cs, pin.w5500_int, pin.w5500_rst); + if (_w5500) + MessageOutput.println("W5500: Connection successful"); + else + MessageOutput.println("W5500: Connection error!!"); } else if (PinMapping.isValidEthConfig()) { PinMapping_t& pin = PinMapping.get(); #if ESP_ARDUINO_VERSION_MAJOR < 3 diff --git a/src/W5500.cpp b/src/W5500.cpp index 0f5b57398..fc770c447 100644 --- a/src/W5500.cpp +++ b/src/W5500.cpp @@ -12,9 +12,51 @@ void tcpipInit(); void add_esp_interface_netif(esp_interface_t interface, esp_netif_t* esp_netif); -W5500::W5500(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst) +W5500::W5500(spi_device_handle_t spi, gpio_num_t pin_int) : eth_handle(nullptr) , eth_netif(nullptr) +{ + // Arduino function to start networking stack if not already started + tcpipInit(); + + ESP_ERROR_CHECK(tcpip_adapter_set_default_eth_handlers()); + + eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi); + w5500_config.int_gpio_num = pin_int; + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); + mac_config.rx_task_stack_size = 4096; + esp_eth_mac_t* mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); + + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + phy_config.reset_gpio_num = -1; + esp_eth_phy_t* phy = esp_eth_phy_new_w5500(&phy_config); + + esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); + ESP_ERROR_CHECK(esp_eth_driver_install(ð_config, ð_handle)); + + // Configure MAC address + uint8_t mac_addr[6]; + ESP_ERROR_CHECK(esp_read_mac(mac_addr, ESP_MAC_ETH)); + ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, mac_addr)); + + esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_ETH(); + eth_netif = esp_netif_new(&netif_config); + + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); + + // Add to Arduino + add_esp_interface_netif(ESP_IF_ETH, eth_netif); + + ESP_ERROR_CHECK(esp_eth_start(eth_handle)); +} + +W5500::~W5500() +{ + // TODO(LennartF22): support cleanup at some point? +} + +std::unique_ptr W5500::setup(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst) { gpio_reset_pin(static_cast(pin_rst)); gpio_set_level(static_cast(pin_rst), 0); @@ -51,51 +93,22 @@ W5500::W5500(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, i spi_device_handle_t spi = SpiManagerInst.alloc_device("", bus_config, device_config); if (!spi) - ESP_ERROR_CHECK(ESP_FAIL); + return nullptr; // Reset sequence delayMicroseconds(500); gpio_set_level(static_cast(pin_rst), 1); delayMicroseconds(1000); - // Arduino function to start networking stack if not already started - tcpipInit(); + if (!connection_check_spi(spi)) + return nullptr; + if (!connection_check_interrupt(static_cast(pin_int))) + return nullptr; - ESP_ERROR_CHECK(tcpip_adapter_set_default_eth_handlers()); - - eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi); - w5500_config.int_gpio_num = pin_int; - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - mac_config.rx_task_stack_size = 4096; - esp_eth_mac_t* mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); - - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - phy_config.reset_gpio_num = -1; - esp_eth_phy_t* phy = esp_eth_phy_new_w5500(&phy_config); - - esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); - ESP_ERROR_CHECK(esp_eth_driver_install(ð_config, ð_handle)); - - // Configure MAC address - uint8_t mac_addr[6]; - ESP_ERROR_CHECK(esp_read_mac(mac_addr, ESP_MAC_ETH)); - ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, mac_addr)); - - esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_ETH(); - eth_netif = esp_netif_new(&netif_config); - - ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); - - // Add to Arduino - add_esp_interface_netif(ESP_IF_ETH, eth_netif); + // Return to default state once again after connection check + gpio_reset_pin(static_cast(pin_int)); - ESP_ERROR_CHECK(esp_eth_start(eth_handle)); -} - -W5500::~W5500() -{ - // TODO(LennartF22): support cleanup at some point? + return std::unique_ptr(new W5500(spi, static_cast(pin_int))); } String W5500::macAddress() @@ -109,3 +122,31 @@ String W5500::macAddress() mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); return String(mac_addr_str); } + +bool W5500::connection_check_spi(spi_device_handle_t spi) +{ + spi_transaction_t trans = { + .flags = SPI_TRANS_USE_RXDATA, + .cmd = 0x0039, // actually address (VERSIONR) + .addr = (0b00000 << 3) | (0 << 2) | (0b00 < 0), // actually command (common register, read, VDM) + .length = 8, + .rxlength = 8, + .user = nullptr, + .tx_buffer = nullptr, + .rx_data = {}, + }; + ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &trans)); + + // Version number (VERSIONR) is always 0x04 + return *reinterpret_cast(&trans.rx_data) == 0x04; +} + +bool W5500::connection_check_interrupt(gpio_num_t pin_int) +{ + gpio_set_direction(pin_int, GPIO_MODE_INPUT); + gpio_set_pull_mode(pin_int, GPIO_PULLDOWN_ONLY); + int level = gpio_get_level(pin_int); + + // Interrupt line must be high + return level == 1; +}