Skip to content

Commit

Permalink
Add connection check for W5500 before full initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
LennartF22 committed Sep 28, 2024
1 parent b206cee commit 251bb7b
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 40 deletions.
11 changes: 10 additions & 1 deletion include/W5500.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,28 @@
#pragma once

#include <Arduino.h>
#include <driver/spi_master.h>
#include <esp_eth.h> // required for esp_eth_handle_t
#include <esp_netif.h>

#include <memory>

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<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);
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;
};
6 changes: 5 additions & 1 deletion src/NetworkSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ void NetworkSettingsClass::init(Scheduler& scheduler)

if (PinMapping.isValidW5500Config()) {
PinMapping_t& pin = PinMapping.get();
_w5500 = std::make_unique<W5500>(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
Expand Down
117 changes: 79 additions & 38 deletions src/W5500.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(&eth_config, &eth_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> 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<gpio_num_t>(pin_rst));
gpio_set_level(static_cast<gpio_num_t>(pin_rst), 0);
Expand Down Expand Up @@ -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<gpio_num_t>(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<gpio_num_t>(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(&eth_config, &eth_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<gpio_num_t>(pin_int));

ESP_ERROR_CHECK(esp_eth_start(eth_handle));
}

W5500::~W5500()
{
// TODO(LennartF22): support cleanup at some point?
return std::unique_ptr<W5500>(new W5500(spi, static_cast<gpio_num_t>(pin_int)));
}

String W5500::macAddress()
Expand All @@ -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<uint8_t*>(&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;
}

0 comments on commit 251bb7b

Please sign in to comment.