diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e760225a04..5a99c9f9841 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,7 +140,9 @@ set(ARDUINO_LIBRARY_ESP_SR_SRCS set(ARDUINO_LIBRARY_ESPmDNS_SRCS libraries/ESPmDNS/src/ESPmDNS.cpp) -set(ARDUINO_LIBRARY_Ethernet_SRCS libraries/Ethernet/src/ETH.cpp) +set(ARDUINO_LIBRARY_Ethernet_SRCS + libraries/Ethernet/src/ETH.cpp + libraries/Ethernet/src/EthernetCompat.cpp) set(ARDUINO_LIBRARY_FFat_SRCS libraries/FFat/src/FFat.cpp) diff --git a/libraries/Ethernet/examples/EthernetLibCompatible/EthernetLibCompatible.ino b/libraries/Ethernet/examples/EthernetLibCompatible/EthernetLibCompatible.ino new file mode 100644 index 00000000000..04be3a21295 --- /dev/null +++ b/libraries/Ethernet/examples/EthernetLibCompatible/EthernetLibCompatible.ino @@ -0,0 +1,136 @@ +/* + Web client + + This sketch connects to a website (http://www.google.com) + using an Arduino WIZnet Ethernet shield. + + Circuit: + * Ethernet shield attached to default SPI pins + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe, based on work by Adrian McEwen + */ + +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; + +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS) +char server[] = "www.google.com"; // name address for Google (using DNS) + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192, 168, 0, 177); +IPAddress myDns(192, 168, 0, 1); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +EthernetClient client; + +// Variables to measure the speed +unsigned long beginMicros, endMicros; +unsigned long byteCount = 0; +bool printWebData = true; // set to false for better speed measurement + +void setup() { + // You can use Ethernet.init to configure the pins + // the values in the commented out init are the defaults + // #define IRQ_PIN 4 //IRQ pin must be wired + // #define RESET_PIN -1 // reset pin is optional + // Ethernet.init(ETH_PHY_W5500, ETH_PHY_ADDR_AUTO, SS, IRQ_PIN, RESET_PIN); + // Ethernet.init(ETH_PHY_W5500, ETH_PHY_ADDR_AUTO, SS, IRQ_PIN, RESET_PIN, SPI, SCK, MISO, MOSI); + + // Open serial communications and wait for port to open: + Serial.begin(115200); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // start the Ethernet connection: + Serial.println("Initialize Ethernet with DHCP:"); + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // Check for Ethernet hardware present + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware + } + } + if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + // try to configure using IP address instead of DHCP: + Ethernet.begin(mac, ip, myDns); + } else { + Serial.print(" DHCP assigned IP "); + Serial.println(Ethernet.localIP()); + } + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.print("connecting to "); + Serial.print(server); + Serial.println("..."); + + // if you get a connection, report back via serial: + if (client.connect(server, 80)) { + Serial.print("connected to "); + Serial.println(client.remoteIP()); + // Make a HTTP request: + client.println("GET /search?q=arduino HTTP/1.1"); + client.println("Host: www.google.com"); + client.println("Connection: close"); + client.println(); + } else { + // if you didn't get a connection to the server: + Serial.println("connection failed"); + } + beginMicros = micros(); +} + +void loop() { + // if there are incoming bytes available + // from the server, read them and print them: + int len = client.available(); + if (len > 0) { + byte buffer[80]; + if (len > 80) { + len = 80; + } + client.read(buffer, len); + if (printWebData) { + Serial.write(buffer, len); // show in the serial monitor (slows some boards) + } + byteCount = byteCount + len; + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + endMicros = micros(); + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + Serial.print("Received "); + Serial.print(byteCount); + Serial.print(" bytes in "); + float seconds = (float) (endMicros - beginMicros) / 1000000.0; + Serial.print(seconds, 4); + float rate = (float) byteCount / seconds / 1000.0; + Serial.print(", rate = "); + Serial.print(rate); + Serial.print(" kbytes/second"); + Serial.println(); + + // do nothing forevermore: + while (true) { + delay(1); + } + } +} diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 5758c37a355..e81b59aacaf 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -446,7 +446,7 @@ esp_err_t ETHClass::eth_spi_write(uint32_t cmd, uint32_t addr, const void *data, #endif bool ETHClass::beginSPI( - eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst, + eth_phy_type_t type, int32_t phy_addr, uint8_t* mac_addr_p, int cs, int irq, int rst, #if ETH_SPI_SUPPORTS_CUSTOM SPIClass *spi, #endif @@ -654,16 +654,20 @@ bool ETHClass::beginSPI( return false; } - // Derive a new MAC address for this interface - uint8_t base_mac_addr[ETH_ADDR_LEN]; - ret = esp_efuse_mac_get_default(base_mac_addr); - if (ret != ESP_OK) { - log_e("Get EFUSE MAC failed: %d", ret); - return false; - } uint8_t mac_addr[ETH_ADDR_LEN]; - base_mac_addr[ETH_ADDR_LEN - 1] += _eth_index; //Increment by the ETH number - esp_derive_local_mac(mac_addr, base_mac_addr); + if (mac_addr_p != nullptr) { + memcpy(mac_addr, mac_addr_p, ETH_ADDR_LEN); + } else { + // Derive a new MAC address for this interface + uint8_t base_mac_addr[ETH_ADDR_LEN]; + ret = esp_efuse_mac_get_default(base_mac_addr); + if (ret != ESP_OK) { + log_e("Get EFUSE MAC failed: %d", ret); + return false; + } + base_mac_addr[ETH_ADDR_LEN - 1] += _eth_index; //Increment by the ETH number + esp_derive_local_mac(mac_addr, base_mac_addr); + } ret = esp_eth_ioctl(_eth_handle, ETH_CMD_S_MAC_ADDR, mac_addr); if (ret != ESP_OK) { @@ -775,17 +779,15 @@ bool ETHClass::beginSPI( #if ETH_SPI_SUPPORTS_CUSTOM bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst, SPIClass &spi, uint8_t spi_freq_mhz) { - - return beginSPI(type, phy_addr, cs, irq, rst, &spi, -1, -1, -1, SPI2_HOST, spi_freq_mhz); + return beginSPI(type, phy_addr, nullptr, cs, irq, rst, &spi, -1, -1, -1, SPI2_HOST, spi_freq_mhz); } #endif bool ETHClass::begin( eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst, spi_host_device_t spi_host, int sck, int miso, int mosi, uint8_t spi_freq_mhz ) { - return beginSPI( - type, phy_addr, cs, irq, rst, + type, phy_addr, nullptr, cs, irq, rst, #if ETH_SPI_SUPPORTS_CUSTOM NULL, #endif diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index 2780f78e6c4..b2adf9815ea 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -201,12 +201,13 @@ class ETHClass : public NetworkInterface { static bool ethDetachBus(void *bus_pointer); bool beginSPI( - eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst, + eth_phy_type_t type, int32_t phy_addr, uint8_t* mac_addr_p, int cs, int irq, int rst, #if ETH_SPI_SUPPORTS_CUSTOM SPIClass *spi, #endif int sck, int miso, int mosi, spi_host_device_t spi_host, uint8_t spi_freq_mhz ); + friend class EthernetClass; // to access beginSPI }; extern ETHClass ETH; diff --git a/libraries/Ethernet/src/EthernetCompat.cpp b/libraries/Ethernet/src/EthernetCompat.cpp new file mode 100644 index 00000000000..efc038ff7e9 --- /dev/null +++ b/libraries/Ethernet/src/EthernetCompat.cpp @@ -0,0 +1,187 @@ +/* + EthernetCompat.cpp - Arduino Ethernet API compatibility wrapper for esp32 ETH. + Based on Ethernet.h from Arduino Ethernet shield library. + + This library is free software { you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation { either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY { without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library { if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "EthernetCompat.h" + +EthernetClass::EthernetClass(ETHClass Ð) : + _ETH(ETH) { + +} + +#if CONFIG_ETH_USE_ESP32_EMAC +void EthernetClass::init(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clk_mode) { + _phy_type = type; + _phy_addr = phy_addr; + _pin_mdc = mdc; + _pin_mdio = mdio; + _pin_power = power; + _rmii_clk_mode = clk_mode; +} +#endif /* CONFIG_ETH_USE_ESP32_EMAC */ + +#if ETH_SPI_SUPPORTS_CUSTOM +void EthernetClass::init(eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst, SPIClass &spi, int sck, int miso, int mosi, uint8_t spi_freq_mhz) { + _spi = &spi; + init(type, phy_addr, cs, irq, rst, SPI_HOST_MAX, sck, miso, mosi, spi_freq_mhz); +} +#endif + +void EthernetClass::init(eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst, spi_host_device_t spi_host, int sck, int miso, int mosi, uint8_t spi_freq_mhz) { + _phy_type = type; + _phy_addr = phy_addr; + _pin_cs = cs; + _pin_irq = irq; + _pin_rst = rst; + _spi_host_device = spi_host; + _pin_sck = sck; + _pin_miso = miso; + _pin_mosi = mosi; + _spi_freq_mhz = spi_freq_mhz; +} + +int EthernetClass::begin(uint8_t *mac, unsigned long timeout) { + if (_ETH.netif() != NULL) { + _ETH.config(INADDR_NONE); + } + if (beginETH(mac)) { + _hardwareStatus = EthernetHardwareFound; + if (timeout) { + const unsigned long start = millis(); + while (!_ETH.hasIP() && ((millis() - start) < timeout)) { + delay(10); + } + } + } + return _ETH.hasIP(); +} + +void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_ip, IPAddress gateway_ip, IPAddress netmask) { + + if (local_ip.type() == IPv4) { + // setting auto values + if (dns_ip == INADDR_NONE) { + dns_ip = local_ip; + dns_ip[3] = 1; + } + if (gateway_ip == INADDR_NONE) { + gateway_ip = local_ip; + gateway_ip[3] = 1; + } + if (netmask == INADDR_NONE) { + netmask = IPAddress(255, 255, 255, 0); + } + } + if (_ETH.config(local_ip, gateway_ip, netmask, dns_ip) && beginETH(mac)) { + _hardwareStatus = EthernetHardwareFound; + } +} + +bool EthernetClass::beginETH(uint8_t *mac) { +#if CONFIG_ETH_USE_ESP32_EMAC + if (_pin_mdc != -1) { + return _ETH.begin(_phy_type, _phy_addr, _pin_mdc, _pin_mdio, _pin_power, _rmii_clk_mode); + } +#endif + if (_spi_host_device != SPI_HOST_MAX) { + return _ETH.beginSPI(_phy_type, _phy_addr, mac, _pin_cs, _pin_irq, _pin_rst, +#if ETH_SPI_SUPPORTS_CUSTOM + nullptr, +#endif + _pin_sck, _pin_miso, _pin_mosi, _spi_host_device, _spi_freq_mhz); + } +#if ETH_SPI_SUPPORTS_CUSTOM + if (_spi == nullptr) { + _spi = &SPI; + } + _spi->begin(_pin_sck, _pin_miso, _pin_mosi, -1); + return _ETH.beginSPI(_phy_type, _phy_addr, mac, _pin_cs, _pin_irq, _pin_rst, _spi, -1, -1, -1, SPI_HOST_MAX, _spi_freq_mhz); +#endif +} + +int EthernetClass::begin(unsigned long timeout) { + return begin(nullptr, timeout); +} + +void EthernetClass::begin(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + begin(nullptr, ip, dns, gateway, subnet); +} + +int EthernetClass::maintain() { + return 0; +} + +EthernetLinkStatus EthernetClass::linkStatus() { + if (_ETH.netif() == NULL) { + return Unknown; + } + return _ETH.linkUp() ? LinkON : LinkOFF; +} + +EthernetHardwareStatus EthernetClass::hardwareStatus() { + return _hardwareStatus; +} + +void EthernetClass::setHostname(const char *hostname) { + _ETH.setHostname(hostname); +} + +void EthernetClass::MACAddress(uint8_t *mac_address) { + _ETH.macAddress(mac_address); +} + +uint8_t* EthernetClass::macAddress(uint8_t *mac) { + return _ETH.macAddress(mac); +} + +IPAddress EthernetClass::localIP() { + return _ETH.localIP(); +} + +IPAddress EthernetClass::subnetMask() { + return _ETH.subnetMask(); +} + +IPAddress EthernetClass::gatewayIP() { + return _ETH.gatewayIP(); +} + +IPAddress EthernetClass::dnsServerIP() { + return _ETH.dnsIP(); +} + +IPAddress EthernetClass::dnsIP(int n) { + return _ETH.dnsIP(n); +} + +void EthernetClass::setDnsServerIP(const IPAddress dns_server) { + _ETH.dnsIP(0, dns_server); +} + +void EthernetClass::setDNS(IPAddress dns_server, IPAddress dns_server2) { + _ETH.dnsIP(0, dns_server); + if (dns_server2 != INADDR_NONE) { + _ETH.dnsIP(1, dns_server2); + } +} + +int EthernetClass::hostByName(const char *hostname, IPAddress &result) { + return Network.hostByName(hostname, result); +} + +EthernetClass Ethernet(ETH); diff --git a/libraries/Ethernet/src/EthernetCompat.h b/libraries/Ethernet/src/EthernetCompat.h new file mode 100644 index 00000000000..20a0cca397a --- /dev/null +++ b/libraries/Ethernet/src/EthernetCompat.h @@ -0,0 +1,118 @@ +/* + EthernetCompat.h - Arduino Ethernet API compatibility wrapper for esp32 ETH. + Based on Ethernet.h from Arduino Ethernet shield library. + Copyright (c) 2011-2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ETHERNET_COMPAT_H_ +#define _ETHERNET_COMPAT_H_ + +#include "ETH.h" + +#define ETH_PIN_IRQ 4 + +enum EthernetLinkStatus { + Unknown, LinkON, LinkOFF +}; + +enum EthernetHardwareStatus { + EthernetNoHardware, EthernetHardwareFound +}; + +class EthernetClass { + +public: + EthernetClass(ETHClass Ð); + +#if CONFIG_ETH_USE_ESP32_EMAC + void init(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clk_mode); +#endif /* CONFIG_ETH_USE_ESP32_EMAC */ +#if ETH_SPI_SUPPORTS_CUSTOM + void init(eth_phy_type_t type, int32_t phy_addr = ETH_PHY_ADDR_AUTO, int cs = SS, int irq = ETH_PIN_IRQ, int rst = -1, + SPIClass &spi = SPI, int sck = -1, int miso = -1, int mosi = -1, + uint8_t spi_freq_mhz = ETH_PHY_SPI_FREQ_MHZ); +#endif + void init(eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst, + spi_host_device_t spi_host, int sck, int miso, int mosi, uint8_t spi_freq_mhz = ETH_PHY_SPI_FREQ_MHZ); + + int begin(uint8_t *mac, unsigned long timeout = 60000); + void begin(uint8_t *mac, IPAddress ip, IPAddress dns = INADDR_NONE, IPAddress gateway = INADDR_NONE, IPAddress subnet = INADDR_NONE); + + int begin(unsigned long timeout = 60000); + void begin(IPAddress ip, IPAddress dns = INADDR_NONE, IPAddress gateway = INADDR_NONE, IPAddress subnet = INADDR_NONE); + + int maintain(); + + EthernetLinkStatus linkStatus(); + EthernetHardwareStatus hardwareStatus(); + + void setHostname(const char *hostname); + + void MACAddress(uint8_t *mac_address); // legacy API + uint8_t* macAddress(uint8_t *mac); + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); // legacy API + IPAddress dnsIP(int n = 0); + + void setDnsServerIP(const IPAddress dns_server); // legacy API + void setDNS(IPAddress dns_server, IPAddress dns2 = INADDR_NONE); + + int hostByName(const char *hostname, IPAddress &result); + +private: + ETHClass& _ETH; + +#if CONFIG_ETH_SPI_ETHERNET_W5500 + eth_phy_type_t _phy_type = ETH_PHY_W5500; +#else + eth_phy_type_t _phy_type = ETH_PHY_MAX; +#endif + int32_t _phy_addr = ETH_PHY_ADDR_AUTO; +#if CONFIG_ETH_USE_ESP32_EMAC + int8_t _pin_mdc = -1; + int8_t _pin_mdio = -1; + int8_t _pin_power = -1; + eth_clock_mode_t _rmii_clk_mode = ETH_CLOCK_GPIO0_IN; +#endif /* CONFIG_ETH_USE_ESP32_EMAC */ + +#if ETH_SPI_SUPPORTS_CUSTOM + SPIClass* _spi = nullptr; +#endif + spi_host_device_t _spi_host_device = SPI_HOST_MAX; + int8_t _pin_cs = SS; + int8_t _pin_irq = ETH_PIN_IRQ; + int8_t _pin_rst = -1; + int8_t _pin_sck = -1; + int8_t _pin_miso = -1; + int8_t _pin_mosi = -1; + uint8_t _spi_freq_mhz = ETH_PHY_SPI_FREQ_MHZ; + + EthernetHardwareStatus _hardwareStatus = EthernetNoHardware; + + bool beginETH(uint8_t *mac); +}; + +extern EthernetClass Ethernet; + +#define EthernetUDP NetworkUDP +#define EthernetServer NetworkServer +#define EthernetClient NetworkClient + +#endif /* _ETHERNET_COMPAT_H_ */