Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a235f2d

Browse files
committedApr 16, 2024
Ethernet - Arduino Ethernet library compatibility layer
1 parent a45b5af commit a235f2d

File tree

5 files changed

+454
-13
lines changed

5 files changed

+454
-13
lines changed
 
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
Web client
3+
4+
This sketch connects to a website (http://www.google.com)
5+
using an Arduino WIZnet Ethernet shield.
6+
7+
Circuit:
8+
* Ethernet shield attached to default SPI pins
9+
10+
created 18 Dec 2009
11+
by David A. Mellis
12+
modified 9 Apr 2012
13+
by Tom Igoe, based on work by Adrian McEwen
14+
*/
15+
16+
#include <SPI.h>
17+
#include <EthernetCompat.h>
18+
19+
// Enter a MAC address for your controller below.
20+
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
21+
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
22+
23+
// if you don't want to use DNS (and reduce your sketch size)
24+
// use the numeric IP instead of the name for the server:
25+
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
26+
char server[] = "www.google.com"; // name address for Google (using DNS)
27+
28+
// Set the static IP address to use if the DHCP fails to assign
29+
IPAddress ip(192, 168, 0, 177);
30+
IPAddress myDns(192, 168, 0, 1);
31+
32+
// Initialize the Ethernet client library
33+
// with the IP address and port of the server
34+
// that you want to connect to (port 80 is default for HTTP):
35+
EthernetClient client;
36+
37+
// Variables to measure the speed
38+
unsigned long beginMicros, endMicros;
39+
unsigned long byteCount = 0;
40+
bool printWebData = true; // set to false for better speed measurement
41+
42+
void setup() {
43+
// You can use Ethernet.init to configure the pins
44+
// the values in the commented out init are the defaults
45+
// #define IRQ_PIN 4 //IRQ pin must be wired
46+
// #define RESET_PIN -1 // reset pin is optional
47+
// Ethernet.init(ETH_PHY_W5500, ETH_PHY_ADDR_AUTO, SS, IRQ_PIN, RESET_PIN);
48+
// Ethernet.init(ETH_PHY_W5500, ETH_PHY_ADDR_AUTO, SS, IRQ_PIN, RESET_PIN, SPI, SCK, MISO, MOSI);
49+
50+
// Open serial communications and wait for port to open:
51+
Serial.begin(115200);
52+
while (!Serial) {
53+
; // wait for serial port to connect. Needed for native USB port only
54+
}
55+
56+
// start the Ethernet connection:
57+
Serial.println("Initialize Ethernet with DHCP:");
58+
if (Ethernet.begin(mac) == 0) {
59+
Serial.println("Failed to configure Ethernet using DHCP");
60+
// Check for Ethernet hardware present
61+
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
62+
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
63+
while (true) {
64+
delay(1); // do nothing, no point running without Ethernet hardware
65+
}
66+
}
67+
if (Ethernet.linkStatus() == LinkOFF) {
68+
Serial.println("Ethernet cable is not connected.");
69+
}
70+
// try to configure using IP address instead of DHCP:
71+
Ethernet.begin(mac, ip, myDns);
72+
} else {
73+
Serial.print(" DHCP assigned IP ");
74+
Serial.println(Ethernet.localIP());
75+
}
76+
// give the Ethernet shield a second to initialize:
77+
delay(1000);
78+
Serial.print("connecting to ");
79+
Serial.print(server);
80+
Serial.println("...");
81+
82+
// if you get a connection, report back via serial:
83+
if (client.connect(server, 80)) {
84+
Serial.print("connected to ");
85+
Serial.println(client.remoteIP());
86+
// Make a HTTP request:
87+
client.println("GET /search?q=arduino HTTP/1.1");
88+
client.println("Host: www.google.com");
89+
client.println("Connection: close");
90+
client.println();
91+
} else {
92+
// if you didn't get a connection to the server:
93+
Serial.println("connection failed");
94+
}
95+
beginMicros = micros();
96+
}
97+
98+
void loop() {
99+
// if there are incoming bytes available
100+
// from the server, read them and print them:
101+
int len = client.available();
102+
if (len > 0) {
103+
byte buffer[80];
104+
if (len > 80) {
105+
len = 80;
106+
}
107+
client.read(buffer, len);
108+
if (printWebData) {
109+
Serial.write(buffer, len); // show in the serial monitor (slows some boards)
110+
}
111+
byteCount = byteCount + len;
112+
}
113+
114+
// if the server's disconnected, stop the client:
115+
if (!client.connected()) {
116+
endMicros = micros();
117+
Serial.println();
118+
Serial.println("disconnecting.");
119+
client.stop();
120+
Serial.print("Received ");
121+
Serial.print(byteCount);
122+
Serial.print(" bytes in ");
123+
float seconds = (float) (endMicros - beginMicros) / 1000000.0;
124+
Serial.print(seconds, 4);
125+
float rate = (float) byteCount / seconds / 1000.0;
126+
Serial.print(", rate = ");
127+
Serial.print(rate);
128+
Serial.print(" kbytes/second");
129+
Serial.println();
130+
131+
// do nothing forevermore:
132+
while (true) {
133+
delay(1);
134+
}
135+
}
136+
}

‎libraries/Ethernet/src/ETH.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ esp_err_t ETHClass::eth_spi_write(uint32_t cmd, uint32_t addr, const void *data,
415415
}
416416
#endif
417417

418-
bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst,
418+
bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, uint8_t* mac_addr_p, int cs, int irq, int rst,
419419
#if ETH_SPI_SUPPORTS_CUSTOM
420420
SPIClass *spi,
421421
#endif
@@ -611,16 +611,20 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
611611
return false;
612612
}
613613

614-
// Derive a new MAC address for this interface
615-
uint8_t base_mac_addr[ETH_ADDR_LEN];
616-
ret = esp_efuse_mac_get_default(base_mac_addr);
617-
if (ret != ESP_OK) {
618-
log_e("Get EFUSE MAC failed: %d", ret);
619-
return false;
620-
}
621614
uint8_t mac_addr[ETH_ADDR_LEN];
622-
base_mac_addr[ETH_ADDR_LEN - 1] += _eth_index; //Increment by the ETH number
623-
esp_derive_local_mac(mac_addr, base_mac_addr);
615+
if (mac_addr_p != nullptr) {
616+
memcpy(mac_addr, mac_addr_p, ETH_ADDR_LEN);
617+
} else {
618+
// Derive a new MAC address for this interface
619+
uint8_t base_mac_addr[ETH_ADDR_LEN];
620+
ret = esp_efuse_mac_get_default(base_mac_addr);
621+
if (ret != ESP_OK) {
622+
log_e("Get EFUSE MAC failed: %d", ret);
623+
return false;
624+
}
625+
base_mac_addr[ETH_ADDR_LEN - 1] += _eth_index; //Increment by the ETH number
626+
esp_derive_local_mac(mac_addr, base_mac_addr);
627+
}
624628

625629
ret = esp_eth_ioctl(_eth_handle, ETH_CMD_S_MAC_ADDR, mac_addr);
626630
if (ret != ESP_OK) {
@@ -721,13 +725,13 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
721725
#if ETH_SPI_SUPPORTS_CUSTOM
722726
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) {
723727

724-
return beginSPI(type, phy_addr, cs, irq, rst, &spi, -1, -1, -1, SPI2_HOST, spi_freq_mhz);
728+
return beginSPI(type, phy_addr, nullptr, cs, irq, rst, &spi, -1, -1, -1, SPI2_HOST, spi_freq_mhz);
725729
}
726730
#endif
727731

728732
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) {
729733

730-
return beginSPI(type, phy_addr, cs, irq, rst,
734+
return beginSPI(type, phy_addr, nullptr, cs, irq, rst,
731735
#if ETH_SPI_SUPPORTS_CUSTOM
732736
NULL,
733737
#endif

‎libraries/Ethernet/src/ETH.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,13 @@ class ETHClass : public NetworkInterface {
192192
#endif /* CONFIG_ETH_USE_ESP32_EMAC */
193193

194194
static bool ethDetachBus(void *bus_pointer);
195-
bool beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst,
195+
bool beginSPI(eth_phy_type_t type, int32_t phy_addr, uint8_t* mac_addr, int cs, int irq, int rst,
196196
#if ETH_SPI_SUPPORTS_CUSTOM
197197
SPIClass *spi,
198198
#endif
199199
int sck, int miso, int mosi, spi_host_device_t spi_host, uint8_t spi_freq_mhz);
200+
201+
friend class EthernetClass; // to access beginSPI
200202
};
201203

202204
extern ETHClass ETH;
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
EthernetCompat.cpp - Arduino Ethernet API compatibility wrapper for esp32 ETH.
3+
Based on Ethernet.h from Arduino Ethernet shield library.
4+
5+
This library is free software { you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation { either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY { without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library { if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include "EthernetCompat.h"
21+
22+
EthernetClass::EthernetClass(ETHClass &ETH) :
23+
_ETH(ETH) {
24+
25+
}
26+
27+
#if CONFIG_ETH_USE_ESP32_EMAC
28+
void EthernetClass::init(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clk_mode) {
29+
_phy_type = type;
30+
_phy_addr = phy_addr;
31+
_pin_mdc = mdc;
32+
_pin_mdio = mdio;
33+
_pin_power = power;
34+
_rmii_clk_mode = clk_mode;
35+
}
36+
#endif /* CONFIG_ETH_USE_ESP32_EMAC */
37+
38+
#if ETH_SPI_SUPPORTS_CUSTOM
39+
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) {
40+
_spi = &spi;
41+
init(type, phy_addr, cs, irq, rst, SPI_HOST_MAX, sck, miso, mosi, spi_freq_mhz);
42+
}
43+
#endif
44+
45+
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) {
46+
_phy_type = type;
47+
_phy_addr = phy_addr;
48+
_pin_cs = cs;
49+
_pin_irq = irq;
50+
_pin_rst = rst;
51+
_spi_host_device = spi_host;
52+
_pin_sck = sck;
53+
_pin_miso = miso;
54+
_pin_mosi = mosi;
55+
_spi_freq_mhz = spi_freq_mhz;
56+
}
57+
58+
int EthernetClass::begin(uint8_t *mac, unsigned long timeout) {
59+
if (_ETH.netif() != NULL) {
60+
_ETH.config(INADDR_NONE);
61+
}
62+
if (beginETH(mac)) {
63+
_hardwareStatus = EthernetHardwareFound;
64+
if (timeout) {
65+
const unsigned long start = millis();
66+
while (!_ETH.hasIP() && ((millis() - start) < timeout)) {
67+
delay(10);
68+
}
69+
}
70+
}
71+
return _ETH.hasIP();
72+
}
73+
74+
void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_ip, IPAddress gateway_ip, IPAddress netmask) {
75+
76+
if (local_ip.type() == IPv4) {
77+
// setting auto values
78+
if (dns_ip == INADDR_NONE) {
79+
dns_ip = local_ip;
80+
dns_ip[3] = 1;
81+
}
82+
if (gateway_ip == INADDR_NONE) {
83+
gateway_ip = local_ip;
84+
gateway_ip[3] = 1;
85+
}
86+
if (netmask == INADDR_NONE) {
87+
netmask = IPAddress(255, 255, 255, 0);
88+
}
89+
}
90+
if (_ETH.config(local_ip, gateway_ip, netmask, dns_ip) && beginETH(mac)) {
91+
_hardwareStatus = EthernetHardwareFound;
92+
}
93+
}
94+
95+
bool EthernetClass::beginETH(uint8_t *mac) {
96+
if (_pin_mdc != -1) {
97+
return _ETH.begin(_phy_type, _phy_addr, _pin_mdc, _pin_mdio, _pin_power, _rmii_clk_mode);
98+
}
99+
if (_spi_host_device != SPI_HOST_MAX) {
100+
return _ETH.beginSPI(_phy_type, _phy_addr, mac, _pin_cs, _pin_irq, _pin_rst,
101+
#if ETH_SPI_SUPPORTS_CUSTOM
102+
nullptr,
103+
#endif
104+
_pin_sck, _pin_miso, _pin_mosi, _spi_host_device, _spi_freq_mhz);
105+
}
106+
#if ETH_SPI_SUPPORTS_CUSTOM
107+
if (_spi == nullptr) {
108+
_spi = &SPI;
109+
}
110+
_spi->begin(_pin_sck, _pin_miso, _pin_mosi, -1);
111+
return _ETH.beginSPI(_phy_type, _phy_addr, mac, _pin_cs, _pin_irq, _pin_rst, _spi, -1, -1, -1, SPI_HOST_MAX, _spi_freq_mhz);
112+
#endif
113+
}
114+
115+
int EthernetClass::begin(unsigned long timeout) {
116+
return begin(nullptr, timeout);
117+
}
118+
119+
void EthernetClass::begin(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) {
120+
begin(nullptr, ip, dns, gateway, subnet);
121+
}
122+
123+
int EthernetClass::maintain() {
124+
return 0;
125+
}
126+
127+
EthernetLinkStatus EthernetClass::linkStatus() {
128+
if (_ETH.netif() == NULL) {
129+
return Unknown;
130+
}
131+
return _ETH.linkUp() ? LinkON : LinkOFF;
132+
}
133+
134+
EthernetHardwareStatus EthernetClass::hardwareStatus() {
135+
return _hardwareStatus;
136+
}
137+
138+
void EthernetClass::setHostname(const char *hostname) {
139+
_ETH.setHostname(hostname);
140+
}
141+
142+
void EthernetClass::MACAddress(uint8_t *mac_address) {
143+
_ETH.macAddress(mac_address);
144+
}
145+
146+
uint8_t* EthernetClass::macAddress(uint8_t *mac) {
147+
return _ETH.macAddress(mac);
148+
}
149+
150+
IPAddress EthernetClass::localIP() {
151+
return _ETH.localIP();
152+
}
153+
154+
IPAddress EthernetClass::subnetMask() {
155+
return _ETH.subnetMask();
156+
}
157+
158+
IPAddress EthernetClass::gatewayIP() {
159+
return _ETH.gatewayIP();
160+
}
161+
162+
IPAddress EthernetClass::dnsServerIP() {
163+
return _ETH.dnsIP();
164+
}
165+
166+
IPAddress EthernetClass::dnsIP(int n) {
167+
return _ETH.dnsIP(n);
168+
}
169+
170+
void EthernetClass::setDnsServerIP(const IPAddress dns_server) {
171+
_ETH.dnsIP(0, dns_server);
172+
}
173+
174+
void EthernetClass::setDNS(IPAddress dns_server, IPAddress dns_server2) {
175+
_ETH.dnsIP(0, dns_server);
176+
if (dns_server2 != INADDR_NONE) {
177+
_ETH.dnsIP(1, dns_server2);
178+
}
179+
}
180+
181+
int EthernetClass::hostByName(const char *hostname, IPAddress &result) {
182+
return Network.hostByName(hostname, result);
183+
}
184+
185+
EthernetClass Ethernet(ETH);
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
EthernetCompat.h - Arduino Ethernet API compatibility wrapper for esp32 ETH.
3+
Based on Ethernet.h from Arduino Ethernet shield library.
4+
Copyright (c) 2011-2014 Arduino. All right reserved.
5+
6+
This library is free software; you can redistribute it and/or
7+
modify it under the terms of the GNU Lesser General Public
8+
License as published by the Free Software Foundation; either
9+
version 2.1 of the License, or (at your option) any later version.
10+
11+
This library is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
Lesser General Public License for more details.
15+
16+
You should have received a copy of the GNU Lesser General Public
17+
License along with this library; if not, write to the Free Software
18+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19+
*/
20+
21+
#ifndef _ETHERNET_COMPAT_H_
22+
#define _ETHERNET_COMPAT_H_
23+
24+
#include "ETH.h"
25+
26+
#define ETH_PIN_IRQ 4
27+
28+
enum EthernetLinkStatus {
29+
Unknown, LinkON, LinkOFF
30+
};
31+
32+
enum EthernetHardwareStatus {
33+
EthernetNoHardware, EthernetHardwareFound
34+
};
35+
36+
class EthernetClass {
37+
38+
public:
39+
EthernetClass(ETHClass &ETH);
40+
41+
#if CONFIG_ETH_USE_ESP32_EMAC
42+
void init(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clk_mode);
43+
#endif /* CONFIG_ETH_USE_ESP32_EMAC */
44+
#if ETH_SPI_SUPPORTS_CUSTOM
45+
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,
46+
SPIClass &spi = SPI, int sck = -1, int miso = -1, int mosi = -1,
47+
uint8_t spi_freq_mhz = ETH_PHY_SPI_FREQ_MHZ);
48+
#endif
49+
void init(eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int rst,
50+
spi_host_device_t spi_host, int sck, int miso, int mosi, uint8_t spi_freq_mhz = ETH_PHY_SPI_FREQ_MHZ);
51+
52+
int begin(uint8_t *mac, unsigned long timeout = 60000);
53+
void begin(uint8_t *mac, IPAddress ip, IPAddress dns = INADDR_NONE, IPAddress gateway = INADDR_NONE, IPAddress subnet = INADDR_NONE);
54+
55+
int begin(unsigned long timeout = 60000);
56+
void begin(IPAddress ip, IPAddress dns = INADDR_NONE, IPAddress gateway = INADDR_NONE, IPAddress subnet = INADDR_NONE);
57+
58+
int maintain();
59+
60+
EthernetLinkStatus linkStatus();
61+
EthernetHardwareStatus hardwareStatus();
62+
63+
void setHostname(const char *hostname);
64+
65+
void MACAddress(uint8_t *mac_address); // legacy API
66+
uint8_t* macAddress(uint8_t *mac);
67+
68+
IPAddress localIP();
69+
IPAddress subnetMask();
70+
IPAddress gatewayIP();
71+
IPAddress dnsServerIP(); // legacy API
72+
IPAddress dnsIP(int n = 0);
73+
74+
void setDnsServerIP(const IPAddress dns_server); // legacy API
75+
void setDNS(IPAddress dns_server, IPAddress dns2 = INADDR_NONE);
76+
77+
int hostByName(const char *hostname, IPAddress &result);
78+
79+
private:
80+
ETHClass& _ETH;
81+
82+
eth_phy_type_t _phy_type = ETH_PHY_W5500;
83+
int32_t _phy_addr = ETH_PHY_ADDR_AUTO;
84+
#if CONFIG_ETH_USE_ESP32_EMAC
85+
int8_t _pin_mdc = -1;
86+
int8_t _pin_mdio = -1;
87+
int8_t _pin_power = -1;
88+
eth_clock_mode_t _rmii_clk_mode = ETH_CLOCK_GPIO0_IN;
89+
#endif /* CONFIG_ETH_USE_ESP32_EMAC */
90+
91+
#if ETH_SPI_SUPPORTS_CUSTOM
92+
SPIClass* _spi = nullptr;
93+
#endif
94+
spi_host_device_t _spi_host_device = SPI_HOST_MAX;
95+
int8_t _pin_cs = SS;
96+
int8_t _pin_irq = ETH_PIN_IRQ;
97+
int8_t _pin_rst = -1;
98+
int8_t _pin_sck = -1;
99+
int8_t _pin_miso = -1;
100+
int8_t _pin_mosi = -1;
101+
uint8_t _spi_freq_mhz = ETH_PHY_SPI_FREQ_MHZ;
102+
103+
EthernetHardwareStatus _hardwareStatus = EthernetNoHardware;
104+
105+
bool beginETH(uint8_t *mac);
106+
};
107+
108+
extern EthernetClass Ethernet;
109+
110+
#define EthernetUDP NetworkUDP
111+
#define EthernetServer NetworkServer
112+
#define EthernetClient NetworkClient
113+
114+
#endif /* _ETHERNET_COMPAT_H_ */

0 commit comments

Comments
 (0)
Please sign in to comment.