Skip to content

Commit 7cfb551

Browse files
authored
PHY status API for ethernet drivers (#8784)
* PHY status API for W5500 & ENC28J60 drivers * move linkStatus() from ArduinoEthernet:: to LwipIntfDev:: * LwipIntfDev: include PHY status into ::connected()
1 parent c9f90a3 commit 7cfb551

File tree

7 files changed

+112
-17
lines changed

7 files changed

+112
-17
lines changed

cores/esp8266/LwipIntfDev.h

+19-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
#define DEFAULT_MTU 1500
4747
#endif
4848

49+
enum EthernetLinkStatus
50+
{
51+
Unknown,
52+
LinkON,
53+
LinkOFF
54+
};
55+
4956
template<class RawDev>
5057
class LwipIntfDev: public LwipIntf, public RawDev
5158
{
@@ -93,9 +100,11 @@ class LwipIntfDev: public LwipIntf, public RawDev
93100
void setDefault(bool deflt = true);
94101

95102
// true if interface has a valid IPv4 address
103+
// (and ethernet link status is not detectable or is up)
96104
bool connected()
97105
{
98-
return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr));
106+
return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr))
107+
&& (!RawDev::isLinkDetectable() || RawDev::isLinked());
99108
}
100109

101110
bool routable()
@@ -106,6 +115,9 @@ class LwipIntfDev: public LwipIntf, public RawDev
106115
// ESP8266WiFi API compatibility
107116
wl_status_t status();
108117

118+
// Arduino Ethernet compatibility
119+
EthernetLinkStatus linkStatus();
120+
109121
protected:
110122
err_t netif_init();
111123
void check_route();
@@ -282,6 +294,12 @@ wl_status_t LwipIntfDev<RawDev>::status()
282294
return _started ? (connected() ? WL_CONNECTED : WL_DISCONNECTED) : WL_NO_SHIELD;
283295
}
284296

297+
template<class RawDev>
298+
EthernetLinkStatus LwipIntfDev<RawDev>::linkStatus()
299+
{
300+
return RawDev::isLinkDetectable() ? _started && RawDev::isLinked() ? LinkON : LinkOFF : Unknown;
301+
}
302+
285303
template<class RawDev>
286304
err_t LwipIntfDev<RawDev>::linkoutput_s(netif* netif, struct pbuf* pbuf)
287305
{

libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ void loop() {
5252
Serial.print(':');
5353
Serial.println(port);
5454

55+
Serial.printf("Link sense: %d (detectable: %d)\n", eth.isLinked(), eth.isLinkDetectable());
56+
5557
// Use WiFiClient class to create TCP connections
5658
// (this class could have been named TCPClient)
5759
WiFiClient client;

libraries/lwIP_Ethernet/src/EthernetCompat.h

+1-16
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,6 @@ using EthernetUDP = WiFiUDP;
1010
using EthernetClient = WiFiClient;
1111
using EthernetServer = ArduinoWiFiServer;
1212

13-
enum EthernetLinkStatus
14-
{
15-
Unknown,
16-
LinkON,
17-
LinkOFF
18-
};
19-
2013
enum
2114
{
2215
DHCP_CHECK_NONE = 0,
@@ -40,7 +33,6 @@ class ArduinoEthernet: public LwipIntfDev<RawDev>
4033
LwipIntfDev<RawDev>(cs, spi, intr)
4134
{
4235
_hardwareStatus = EthernetNoHardware;
43-
_linkStatus = Unknown;
4436
}
4537

4638
// Arduino-Ethernet API compatibility, order can be either:
@@ -70,7 +62,6 @@ class ArduinoEthernet: public LwipIntfDev<RawDev>
7062
if (ret)
7163
{
7264
_hardwareStatus = EthernetHardwareFound;
73-
_linkStatus = LinkON;
7465
}
7566

7667
return ret;
@@ -81,19 +72,13 @@ class ArduinoEthernet: public LwipIntfDev<RawDev>
8172
return _hardwareStatus;
8273
}
8374

84-
EthernetLinkStatus linkStatus() const
85-
{
86-
return _linkStatus;
87-
}
88-
8975
int maintain() const
9076
{
9177
return DHCP_CHECK_NONE;
9278
}
9379

9480
protected:
95-
HardwareStatus _hardwareStatus;
96-
EthernetLinkStatus _linkStatus;
81+
HardwareStatus _hardwareStatus;
9782
};
9883

9984
using ArduinoWiznet5500lwIP = ArduinoEthernet<Wiznet5500>;

libraries/lwIP_enc28j60/src/utility/enc28j60.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,24 @@ void serial_printf(const char* fmt, ...)
106106
#define MACONX_BANK 0x02
107107

108108
#define MACON1 0x00
109+
#define MACSTAT1 0x01
109110
#define MACON3 0x02
110111
#define MACON4 0x03
111112
#define MABBIPG 0x04
112113
#define MAIPGL 0x06
113114
#define MAIPGH 0x07
114115
#define MAMXFLL 0x0a
115116
#define MAMXFLH 0x0b
117+
#define MACON2 0x10
118+
#define MACSTAT2 0x11
119+
#define MICMD 0x12
120+
#define MIREGADR 0x14
121+
#define MIRDL 0x18
122+
#define MIRDH 0x19
123+
124+
/* MICMD Register Bit Definitions */
125+
#define MICMD_MIISCAN 0x02
126+
#define MICMD_MIIRD 0x01
116127

117128
#define MACON1_TXPAUS 0x08
118129
#define MACON1_RXPAUS 0x04
@@ -135,6 +146,9 @@ void serial_printf(const char* fmt, ...)
135146
#define MISTAT 0x0a
136147
#define EREVID 0x12
137148

149+
/* MISTAT Register Bit Definitions */
150+
#define MISTAT_BUSY 0x01
151+
138152
#define EPKTCNT_BANK 0x01
139153
#define ERXFCON 0x18
140154
#define EPKTCNT 0x19
@@ -720,3 +734,26 @@ uint16_t ENC28J60::readFrameData(uint8_t* buffer, uint16_t framesize)
720734

721735
return _len;
722736
}
737+
738+
uint16_t ENC28J60::phyread(uint8_t reg)
739+
{
740+
// ( https://github.com/JAndrassy/EthernetENC/tree/master/src/utility/enc28j60.h )
741+
742+
setregbank(MACONX_BANK);
743+
writereg(MIREGADR, reg);
744+
writereg(MICMD, MICMD_MIIRD);
745+
// wait until the PHY read completes
746+
while (readreg(MISTAT) & MISTAT_BUSY)
747+
{
748+
delayMicroseconds(15);
749+
}
750+
writereg(MICMD, 0);
751+
return (readreg(MIRDL) | readreg(MIRDH) << 8);
752+
}
753+
754+
bool ENC28J60::isLinked()
755+
{
756+
// ( https://github.com/JAndrassy/EthernetENC/tree/master/src/utility/enc28j60.h )
757+
758+
return !!(phyread(MACSTAT2) & 0x400);
759+
}

libraries/lwIP_enc28j60/src/utility/enc28j60.h

+17
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,21 @@ class ENC28J60
7979
*/
8080
virtual uint16_t readFrame(uint8_t* buffer, uint16_t bufsize);
8181

82+
/**
83+
Check physical link
84+
@return true when physical link is up
85+
*/
86+
bool isLinked();
87+
88+
/**
89+
Report whether ::isLinked() API is implemented
90+
@return true when ::isLinked() API is implemented
91+
*/
92+
constexpr bool isLinkDetectable() const
93+
{
94+
return true;
95+
}
96+
8297
protected:
8398
static constexpr bool interruptIsPossible()
8499
{
@@ -133,6 +148,8 @@ class ENC28J60
133148
// Previously defined in contiki/core/sys/clock.h
134149
void clock_delay_usec(uint16_t dt);
135150

151+
uint16_t phyread(uint8_t reg);
152+
136153
uint8_t _bank;
137154
int8_t _cs;
138155
SPIClass& _spi;

libraries/lwIP_w5100/src/utility/w5100.h

+18
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,24 @@ class Wiznet5100
7979
*/
8080
uint16_t readFrame(uint8_t* buffer, uint16_t bufsize);
8181

82+
/**
83+
Check physical link
84+
@return true when physical link is up
85+
*/
86+
bool isLinked() const
87+
{
88+
return true; //XXX TODO
89+
}
90+
91+
/**
92+
Report whether ::isLinked() API is implemented
93+
@return true when ::isLinked() API is implemented
94+
*/
95+
constexpr bool isLinkDetectable() const
96+
{
97+
return false;
98+
}
99+
82100
protected:
83101
static constexpr bool interruptIsPossible()
84102
{

libraries/lwIP_w5500/src/utility/w5500.h

+18
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,24 @@ class Wiznet5500
7979
*/
8080
uint16_t readFrame(uint8_t* buffer, uint16_t bufsize);
8181

82+
/**
83+
Check physical link
84+
@return true when physical link is up
85+
*/
86+
bool isLinked()
87+
{
88+
return wizphy_getphylink() == PHY_LINK_ON;
89+
}
90+
91+
/**
92+
Report whether ::isLinked() API is implemented
93+
@return true when ::isLinked() API is implemented
94+
*/
95+
constexpr bool isLinkDetectable() const
96+
{
97+
return true;
98+
}
99+
82100
protected:
83101
static constexpr bool interruptIsPossible()
84102
{

0 commit comments

Comments
 (0)