From eead4d53bcaa3b07c74462c97f73918e0d21c9b3 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Tue, 3 Jan 2023 16:16:38 +0100 Subject: [PATCH 1/6] PHY status API for ethernet drivers --- .../examples/EthClient/EthClient.ino | 2 ++ .../lwIP_enc28j60/src/utility/enc28j60.h | 19 +++++++++++++++++++ libraries/lwIP_w5100/src/utility/w5100.h | 18 ++++++++++++++++++ libraries/lwIP_w5500/src/utility/w5500.h | 18 ++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino b/libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino index 8ca28fa112..169930f6ef 100644 --- a/libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino +++ b/libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino @@ -52,6 +52,8 @@ void loop() { Serial.print(':'); Serial.println(port); + Serial.printf("Link sense: %d (detectable: %d)\n", eth.isLinked(), eth.isLinkDetectable()); + // Use WiFiClient class to create TCP connections // (this class could have been named TCPClient) WiFiClient client; diff --git a/libraries/lwIP_enc28j60/src/utility/enc28j60.h b/libraries/lwIP_enc28j60/src/utility/enc28j60.h index 07f71f96ff..b6c043b492 100644 --- a/libraries/lwIP_enc28j60/src/utility/enc28j60.h +++ b/libraries/lwIP_enc28j60/src/utility/enc28j60.h @@ -79,6 +79,25 @@ class ENC28J60 */ virtual uint16_t readFrame(uint8_t* buffer, uint16_t bufsize); + /** + Check physical link + @return true when physical link is up + */ + bool isLinked () const + { + return true; //XXX TODO + } + + /** + Report whether ::isLinked() API is implemented + @return true when ::isLinked() API is implemented + */ + constexpr bool isLinkDetectable () const + { + return false; + } + + protected: static constexpr bool interruptIsPossible() { diff --git a/libraries/lwIP_w5100/src/utility/w5100.h b/libraries/lwIP_w5100/src/utility/w5100.h index 6e1f2c35cd..e7e73df444 100644 --- a/libraries/lwIP_w5100/src/utility/w5100.h +++ b/libraries/lwIP_w5100/src/utility/w5100.h @@ -79,6 +79,24 @@ class Wiznet5100 */ uint16_t readFrame(uint8_t* buffer, uint16_t bufsize); + /** + Check physical link + @return true when physical link is up + */ + bool isLinked () const + { + return true; //XXX TODO + } + + /** + Report whether ::isLinked() API is implemented + @return true when ::isLinked() API is implemented + */ + constexpr bool isLinkDetectable () const + { + return false; + } + protected: static constexpr bool interruptIsPossible() { diff --git a/libraries/lwIP_w5500/src/utility/w5500.h b/libraries/lwIP_w5500/src/utility/w5500.h index f7babb51e9..a0e8c3c5c8 100644 --- a/libraries/lwIP_w5500/src/utility/w5500.h +++ b/libraries/lwIP_w5500/src/utility/w5500.h @@ -79,6 +79,24 @@ class Wiznet5500 */ uint16_t readFrame(uint8_t* buffer, uint16_t bufsize); + /** + Check physical link + @return true when physical link is up + */ + bool isLinked () + { + return wizphy_getphylink() == PHY_LINK_ON; + } + + /** + Report whether ::isLinked() API is implemented + @return true when ::isLinked() API is implemented + */ + constexpr bool isLinkDetectable () const + { + return true; + } + protected: static constexpr bool interruptIsPossible() { From 3ee0cbdbdc3f2e8c65c0041682c37147acef2e57 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Tue, 3 Jan 2023 16:27:37 +0100 Subject: [PATCH 2/6] style --- libraries/lwIP_enc28j60/src/utility/enc28j60.h | 7 +++---- libraries/lwIP_w5100/src/utility/w5100.h | 6 +++--- libraries/lwIP_w5500/src/utility/w5500.h | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/libraries/lwIP_enc28j60/src/utility/enc28j60.h b/libraries/lwIP_enc28j60/src/utility/enc28j60.h index b6c043b492..d85b61903e 100644 --- a/libraries/lwIP_enc28j60/src/utility/enc28j60.h +++ b/libraries/lwIP_enc28j60/src/utility/enc28j60.h @@ -83,21 +83,20 @@ class ENC28J60 Check physical link @return true when physical link is up */ - bool isLinked () const + bool isLinked() const { - return true; //XXX TODO + return true; //XXX TODO } /** Report whether ::isLinked() API is implemented @return true when ::isLinked() API is implemented */ - constexpr bool isLinkDetectable () const + constexpr bool isLinkDetectable() const { return false; } - protected: static constexpr bool interruptIsPossible() { diff --git a/libraries/lwIP_w5100/src/utility/w5100.h b/libraries/lwIP_w5100/src/utility/w5100.h index e7e73df444..9ed1e4cdab 100644 --- a/libraries/lwIP_w5100/src/utility/w5100.h +++ b/libraries/lwIP_w5100/src/utility/w5100.h @@ -83,16 +83,16 @@ class Wiznet5100 Check physical link @return true when physical link is up */ - bool isLinked () const + bool isLinked() const { - return true; //XXX TODO + return true; //XXX TODO } /** Report whether ::isLinked() API is implemented @return true when ::isLinked() API is implemented */ - constexpr bool isLinkDetectable () const + constexpr bool isLinkDetectable() const { return false; } diff --git a/libraries/lwIP_w5500/src/utility/w5500.h b/libraries/lwIP_w5500/src/utility/w5500.h index a0e8c3c5c8..7e8058fdb1 100644 --- a/libraries/lwIP_w5500/src/utility/w5500.h +++ b/libraries/lwIP_w5500/src/utility/w5500.h @@ -83,7 +83,7 @@ class Wiznet5500 Check physical link @return true when physical link is up */ - bool isLinked () + bool isLinked() { return wizphy_getphylink() == PHY_LINK_ON; } @@ -92,7 +92,7 @@ class Wiznet5500 Report whether ::isLinked() API is implemented @return true when ::isLinked() API is implemented */ - constexpr bool isLinkDetectable () const + constexpr bool isLinkDetectable() const { return true; } From 1c1f37d6e6d8e450b1df914ce667c80c6eb67d96 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Tue, 3 Jan 2023 23:21:05 +0100 Subject: [PATCH 3/6] +link-sense for enc28j60 with credits --- .../lwIP_enc28j60/src/utility/enc28j60.cpp | 36 +++++++++++++++++++ .../lwIP_enc28j60/src/utility/enc28j60.h | 9 +++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp b/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp index 979d88e9ea..88530ae32a 100644 --- a/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp +++ b/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp @@ -106,6 +106,7 @@ void serial_printf(const char* fmt, ...) #define MACONX_BANK 0x02 #define MACON1 0x00 +#define MACSTAT1 0x01 #define MACON3 0x02 #define MACON4 0x03 #define MABBIPG 0x04 @@ -113,6 +114,16 @@ void serial_printf(const char* fmt, ...) #define MAIPGH 0x07 #define MAMXFLL 0x0a #define MAMXFLH 0x0b +#define MACON2 0x10 +#define MACSTAT2 0x11 +#define MICMD 0x12 +#define MIREGADR 0x14 +#define MIRDL 0x18 +#define MIRDH 0x19 + +/* MICMD Register Bit Definitions */ +#define MICMD_MIISCAN 0x02 +#define MICMD_MIIRD 0x01 #define MACON1_TXPAUS 0x08 #define MACON1_RXPAUS 0x04 @@ -135,6 +146,9 @@ void serial_printf(const char* fmt, ...) #define MISTAT 0x0a #define EREVID 0x12 +/* MISTAT Register Bit Definitions */ +#define MISTAT_BUSY 0x01 + #define EPKTCNT_BANK 0x01 #define ERXFCON 0x18 #define EPKTCNT 0x19 @@ -720,3 +734,25 @@ uint16_t ENC28J60::readFrameData(uint8_t* buffer, uint16_t framesize) return _len; } + +uint16_t ENC28J60::phyread(uint8_t reg) +{ + // ( https://github.com/JAndrassy/EthernetENC/tree/master/src/utility/enc28j60.h ) + + setregbank(MACONX_BANK); + writereg(MIREGADR, reg); + writereg(MICMD, MICMD_MIIRD); + // wait until the PHY read completes + while(readreg(MISTAT) & MISTAT_BUSY) { + delayMicroseconds(15); + } + writereg(MICMD, 0); + return (readreg(MIRDL) | readreg(MIRDH) << 8); +} + +bool ENC28J60::isLinked() +{ + // ( https://github.com/JAndrassy/EthernetENC/tree/master/src/utility/enc28j60.h ) + + return !!(phyread(MACSTAT2) & 0x400); +} diff --git a/libraries/lwIP_enc28j60/src/utility/enc28j60.h b/libraries/lwIP_enc28j60/src/utility/enc28j60.h index d85b61903e..e6c65d7759 100644 --- a/libraries/lwIP_enc28j60/src/utility/enc28j60.h +++ b/libraries/lwIP_enc28j60/src/utility/enc28j60.h @@ -83,10 +83,7 @@ class ENC28J60 Check physical link @return true when physical link is up */ - bool isLinked() const - { - return true; //XXX TODO - } + bool isLinked(); /** Report whether ::isLinked() API is implemented @@ -94,7 +91,7 @@ class ENC28J60 */ constexpr bool isLinkDetectable() const { - return false; + return true; } protected: @@ -151,6 +148,8 @@ class ENC28J60 // Previously defined in contiki/core/sys/clock.h void clock_delay_usec(uint16_t dt); + uint16_t phyread(uint8_t reg); + uint8_t _bank; int8_t _cs; SPIClass& _spi; From bbef3a08863360458239bffcc641f23bba1ac368 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Tue, 3 Jan 2023 23:40:24 +0100 Subject: [PATCH 4/6] style --- libraries/lwIP_enc28j60/src/utility/enc28j60.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp b/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp index 88530ae32a..09f8ae0fe2 100644 --- a/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp +++ b/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp @@ -743,7 +743,8 @@ uint16_t ENC28J60::phyread(uint8_t reg) writereg(MIREGADR, reg); writereg(MICMD, MICMD_MIIRD); // wait until the PHY read completes - while(readreg(MISTAT) & MISTAT_BUSY) { + while (readreg(MISTAT) & MISTAT_BUSY) + { delayMicroseconds(15); } writereg(MICMD, 0); From abc8407cfc03cd7b569fc489230e38641ffbfc6e Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 4 Jan 2023 18:54:43 +0100 Subject: [PATCH 5/6] move linkStatus() from ArduinoEthernet:: to LwipIntfDev:: --- cores/esp8266/LwipIntfDev.h | 16 ++++++++++++++++ libraries/lwIP_Ethernet/src/EthernetCompat.h | 17 +---------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/cores/esp8266/LwipIntfDev.h b/cores/esp8266/LwipIntfDev.h index 00f29e9dfe..fe2b493875 100644 --- a/cores/esp8266/LwipIntfDev.h +++ b/cores/esp8266/LwipIntfDev.h @@ -46,6 +46,13 @@ #define DEFAULT_MTU 1500 #endif +enum EthernetLinkStatus +{ + Unknown, + LinkON, + LinkOFF +}; + template class LwipIntfDev: public LwipIntf, public RawDev { @@ -106,6 +113,9 @@ class LwipIntfDev: public LwipIntf, public RawDev // ESP8266WiFi API compatibility wl_status_t status(); + // Arduino Ethernet compatibility + EthernetLinkStatus linkStatus(); + protected: err_t netif_init(); void check_route(); @@ -282,6 +292,12 @@ wl_status_t LwipIntfDev::status() return _started ? (connected() ? WL_CONNECTED : WL_DISCONNECTED) : WL_NO_SHIELD; } +template +EthernetLinkStatus LwipIntfDev::linkStatus() +{ + return RawDev::isLinkDetectable() ? _started && RawDev::isLinked() ? LinkON : LinkOFF : Unknown; +} + template err_t LwipIntfDev::linkoutput_s(netif* netif, struct pbuf* pbuf) { diff --git a/libraries/lwIP_Ethernet/src/EthernetCompat.h b/libraries/lwIP_Ethernet/src/EthernetCompat.h index e398d5719d..99dca03e67 100644 --- a/libraries/lwIP_Ethernet/src/EthernetCompat.h +++ b/libraries/lwIP_Ethernet/src/EthernetCompat.h @@ -10,13 +10,6 @@ using EthernetUDP = WiFiUDP; using EthernetClient = WiFiClient; using EthernetServer = ArduinoWiFiServer; -enum EthernetLinkStatus -{ - Unknown, - LinkON, - LinkOFF -}; - enum { DHCP_CHECK_NONE = 0, @@ -40,7 +33,6 @@ class ArduinoEthernet: public LwipIntfDev LwipIntfDev(cs, spi, intr) { _hardwareStatus = EthernetNoHardware; - _linkStatus = Unknown; } // Arduino-Ethernet API compatibility, order can be either: @@ -70,7 +62,6 @@ class ArduinoEthernet: public LwipIntfDev if (ret) { _hardwareStatus = EthernetHardwareFound; - _linkStatus = LinkON; } return ret; @@ -81,19 +72,13 @@ class ArduinoEthernet: public LwipIntfDev return _hardwareStatus; } - EthernetLinkStatus linkStatus() const - { - return _linkStatus; - } - int maintain() const { return DHCP_CHECK_NONE; } protected: - HardwareStatus _hardwareStatus; - EthernetLinkStatus _linkStatus; + HardwareStatus _hardwareStatus; }; using ArduinoWiznet5500lwIP = ArduinoEthernet; From f04d5c84c9a3554ff553abd41717b1173907e74e Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 4 Jan 2023 19:04:42 +0100 Subject: [PATCH 6/6] LwipIntfDev: include link status into ::connected() --- cores/esp8266/LwipIntfDev.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cores/esp8266/LwipIntfDev.h b/cores/esp8266/LwipIntfDev.h index fe2b493875..389376c976 100644 --- a/cores/esp8266/LwipIntfDev.h +++ b/cores/esp8266/LwipIntfDev.h @@ -100,9 +100,11 @@ class LwipIntfDev: public LwipIntf, public RawDev void setDefault(bool deflt = true); // true if interface has a valid IPv4 address + // (and ethernet link status is not detectable or is up) bool connected() { - return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr)); + return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr)) + && (!RawDev::isLinkDetectable() || RawDev::isLinked()); } bool routable()