Skip to content

fix(eth): Set the ETH properties at the correct time #11182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 75 additions & 4 deletions libraries/Ethernet/src/ETH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ void ETHClass::_onEthEvent(int32_t event_id, void *event_data) {
}

ETHClass::ETHClass(uint8_t eth_index)
: _eth_handle(NULL), _eth_index(eth_index), _phy_type(ETH_PHY_MAX), _glue_handle(NULL), _mac(NULL), _phy(NULL)
: _eth_handle(NULL), _eth_index(eth_index), _phy_type(ETH_PHY_MAX), _glue_handle(NULL), _mac(NULL), _phy(NULL), _eth_started(false), _link_speed(100),
_full_duplex(true), _auto_negotiation(true)
#if ETH_SPI_SUPPORTS_CUSTOM
,
_spi(NULL)
Expand Down Expand Up @@ -351,6 +352,19 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i
return false;
}

// auto negotiation needs to be disabled to change duplex mode and link speed
if (!_auto_negotiation) {
if (!_setAutoNegotiation(_auto_negotiation)) {
return false;
}
if (!_setFullDuplex(_full_duplex)) {
return false;
}
if (!_setLinkSpeed(_link_speed)) {
return false;
}
}

if (_eth_ev_instance == NULL && esp_event_handler_instance_register(ETH_EVENT, ESP_EVENT_ANY_ID, &_eth_event_cb, NULL, &_eth_ev_instance)) {
log_e("event_handler_instance_register for ETH_EVENT Failed!");
return false;
Expand All @@ -367,6 +381,8 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i
return false;
}

_eth_started = true;

if (!perimanSetPinBus(_pin_rmii_clock, ESP32_BUS_TYPE_ETHERNET_CLK, (void *)(this), -1, -1)) {
goto err;
}
Expand Down Expand Up @@ -788,6 +804,19 @@ bool ETHClass::beginSPI(
return false;
}

// auto negotiation needs to be disabled to change duplex mode and link speed
if (!_auto_negotiation) {
if (!_setAutoNegotiation(_auto_negotiation)) {
return false;
}
if (!_setFullDuplex(_full_duplex)) {
return false;
}
if (!_setLinkSpeed(_link_speed)) {
return false;
}
}

if (_eth_ev_instance == NULL && esp_event_handler_instance_register(ETH_EVENT, ESP_EVENT_ANY_ID, &_eth_event_cb, NULL, &_eth_ev_instance)) {
log_e("event_handler_instance_register for ETH_EVENT Failed!");
return false;
Expand All @@ -803,6 +832,8 @@ bool ETHClass::beginSPI(
return false;
}

_eth_started = true;

// If Arduino's SPI is used, cs pin is in GPIO mode
#if ETH_SPI_SUPPORTS_CUSTOM
if (_spi == NULL) {
Expand Down Expand Up @@ -896,6 +927,9 @@ void ETHClass::end(void) {
while (getStatusBits() & ESP_NETIF_STARTED_BIT) {
delay(10);
}

_eth_started = false;

//delete glue first
if (_glue_handle != NULL) {
if (esp_eth_del_netif_glue(_glue_handle) != ESP_OK) {
Expand Down Expand Up @@ -1009,7 +1043,7 @@ bool ETHClass::fullDuplex() const {
return (link_duplex == ETH_DUPLEX_FULL);
}

bool ETHClass::setFullDuplex(bool on) {
bool ETHClass::_setFullDuplex(bool on) {
if (_eth_handle == NULL) {
return false;
}
Expand All @@ -1021,6 +1055,18 @@ bool ETHClass::setFullDuplex(bool on) {
return err == ESP_OK;
}

bool ETHClass::setFullDuplex(bool on) {
if (_eth_started) {
log_e("This method must be called before ETH.begin()");
return false;
}
if (_auto_negotiation) {
log_w("Auto Negotiation MUST be OFF for this setting to be applied");
}
_full_duplex = on;
return true;
}

bool ETHClass::autoNegotiation() const {
if (_eth_handle == NULL) {
return false;
Expand All @@ -1030,7 +1076,7 @@ bool ETHClass::autoNegotiation() const {
return auto_nego;
}

bool ETHClass::setAutoNegotiation(bool on) {
bool ETHClass::_setAutoNegotiation(bool on) {
if (_eth_handle == NULL) {
return false;
}
Expand All @@ -1041,6 +1087,15 @@ bool ETHClass::setAutoNegotiation(bool on) {
return err == ESP_OK;
}

bool ETHClass::setAutoNegotiation(bool on) {
if (_eth_started) {
log_e("This method must be called before ETH.begin()");
return false;
}
_auto_negotiation = on;
return true;
}

uint32_t ETHClass::phyAddr() const {
if (_eth_handle == NULL) {
return 0;
Expand All @@ -1059,7 +1114,7 @@ uint16_t ETHClass::linkSpeed() const {
return (link_speed == ETH_SPEED_10M) ? 10 : 100;
}

bool ETHClass::setLinkSpeed(uint16_t speed) {
bool ETHClass::_setLinkSpeed(uint16_t speed) {
if (_eth_handle == NULL) {
return false;
}
Expand All @@ -1071,6 +1126,22 @@ bool ETHClass::setLinkSpeed(uint16_t speed) {
return err == ESP_OK;
}

bool ETHClass::setLinkSpeed(uint16_t speed) {
if (speed != 10 && speed != 100) {
log_e("Ethernet currently supports only 10 or 100 Mbps link speed");
return false;
}
if (_eth_started) {
log_e("This method must be called before ETH.begin()");
return false;
}
if (_auto_negotiation) {
log_w("Auto Negotiation MUST be OFF for this setting to be applied");
}
_link_speed = speed;
return true;
}

// void ETHClass::getMac(uint8_t* mac)
// {
// if(_eth_handle != NULL && mac != NULL){
Expand Down
7 changes: 7 additions & 0 deletions libraries/Ethernet/src/ETH.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,10 @@ class ETHClass : public NetworkInterface {
esp_eth_netif_glue_handle_t _glue_handle;
esp_eth_mac_t *_mac;
esp_eth_phy_t *_phy;
bool _eth_started;
uint16_t _link_speed;
bool _full_duplex;
bool _auto_negotiation;
#if ETH_SPI_SUPPORTS_CUSTOM
SPIClass *_spi;
char _cs_str[10];
Expand Down Expand Up @@ -256,6 +260,9 @@ class ETHClass : public NetworkInterface {
#endif
int sck, int miso, int mosi, spi_host_device_t spi_host, uint8_t spi_freq_mhz
);
bool _setFullDuplex(bool on);
bool _setLinkSpeed(uint16_t speed);
bool _setAutoNegotiation(bool on);

friend class EthernetClass; // to access beginSPI
};
Expand Down
Loading