esp_eth: restart negotiation in esp_eth_start

This commit is contained in:
morris 2021-05-06 20:16:12 +08:00
parent 83f2d802ce
commit 0c25793b06
9 changed files with 41 additions and 41 deletions

View File

@ -269,14 +269,16 @@ esp_err_t esp_eth_start(esp_eth_handle_t hdl)
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
esp_eth_phy_t *phy = eth_driver->phy;
esp_eth_mac_t *mac = eth_driver->mac;
// check if driver has stopped
esp_eth_fsm_t expected_fsm = ESP_ETH_FSM_STOP;
ESP_GOTO_ON_FALSE(atomic_compare_exchange_strong(&eth_driver->fsm, &expected_fsm, ESP_ETH_FSM_START),
ESP_ERR_INVALID_STATE, err, TAG, "driver started already");
// reset PHY device, to put it back to LINK_DOWN state
ESP_GOTO_ON_ERROR(phy->reset(phy), err, TAG, "reset phy failed");
ESP_GOTO_ON_ERROR(phy->negotiate(phy), err, TAG, "phy negotiation failed");
ESP_GOTO_ON_ERROR(mac->start(mac), err, TAG, "start mac failed");
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_START, &eth_driver, sizeof(esp_eth_driver_t *), 0),
err, TAG, "send ETHERNET_EVENT_START event failed");
ESP_GOTO_ON_ERROR(phy->get_link(phy), err, TAG, "phy get link status failed");
ESP_GOTO_ON_ERROR(esp_timer_start_periodic(eth_driver->check_link_timer, eth_driver->check_link_period_ms * 1000),
err, TAG, "start link timer failed");
err:

View File

@ -200,6 +200,8 @@ static esp_err_t dm9051_negotiate(esp_eth_phy_t *phy)
esp_err_t ret = ESP_OK;
phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent);
esp_eth_mediator_t *eth = dm9051->eth;
/* in case any link status has changed, let's assume we're in link down status */
dm9051->link_status = ETH_LINK_DOWN;
/* Start auto negotiation */
bmcr_reg_t bmcr = {
.speed_select = 1, /* 100Mbps */
@ -212,19 +214,17 @@ static esp_err_t dm9051_negotiate(esp_eth_phy_t *phy)
bmsr_reg_t bmsr;
dscsr_reg_t dscsr;
uint32_t to = 0;
for (to = 0; to < dm9051->autonego_timeout_ms / 10; to++) {
vTaskDelay(pdMS_TO_TICKS(10));
for (to = 0; to < dm9051->autonego_timeout_ms / 100; to++) {
vTaskDelay(pdMS_TO_TICKS(100));
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCSR_REG_ADDR, &(dscsr.val)), err, TAG, "read DSCSR failed");
if (bmsr.auto_nego_complete && dscsr.anmb & 0x08) {
break;
}
}
if (to >= dm9051->autonego_timeout_ms / 10) {
if (to >= dm9051->autonego_timeout_ms / 100) {
ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout");
}
/* Updata information about link, speed, duplex */
ESP_GOTO_ON_ERROR(dm9051_update_link_duplex_speed(dm9051), err, TAG, "update link duplex speed failed");
return ESP_OK;
err:
return ret;

View File

@ -194,6 +194,8 @@ static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy)
esp_err_t ret = ESP_OK;
phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent);
esp_eth_mediator_t *eth = dp83848->eth;
/* in case any link status has changed, let's assume we're in link down status */
dp83848->link_status = ETH_LINK_DOWN;
/* Start auto negotiation */
bmcr_reg_t bmcr = {
.speed_select = 1, /* 100Mbps */
@ -206,8 +208,8 @@ static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy)
bmsr_reg_t bmsr;
physts_reg_t physts;
uint32_t to = 0;
for (to = 0; to < dp83848->autonego_timeout_ms / 10; to++) {
vTaskDelay(pdMS_TO_TICKS(10));
for (to = 0; to < dp83848->autonego_timeout_ms / 100; to++) {
vTaskDelay(pdMS_TO_TICKS(100));
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed");
if (bmsr.auto_nego_complete && physts.auto_nego_complete) {
@ -215,11 +217,9 @@ static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy)
}
}
/* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
if (to >= dp83848->autonego_timeout_ms / 10) {
if (to >= dp83848->autonego_timeout_ms / 100) {
ESP_LOGW(TAG, "auto negotiation timeout");
}
/* Updata information about link, speed, duplex */
ESP_GOTO_ON_ERROR(dp83848_update_link_duplex_speed(dp83848), err, TAG, "update link duplex speed failed");
return ESP_OK;
err:
return ret;

View File

@ -235,6 +235,8 @@ static esp_err_t ip101_negotiate(esp_eth_phy_t *phy)
esp_err_t ret = ESP_OK;
phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
esp_eth_mediator_t *eth = ip101->eth;
/* in case any link status has changed, let's assume we're in link down status */
ip101->link_status = ETH_LINK_DOWN;
/* Restart auto negotiation */
bmcr_reg_t bmcr = {
.speed_select = 1, /* 100Mbps */
@ -246,19 +248,17 @@ static esp_err_t ip101_negotiate(esp_eth_phy_t *phy)
/* Wait for auto negotiation complete */
bmsr_reg_t bmsr;
uint32_t to = 0;
for (to = 0; to < ip101->autonego_timeout_ms / 10; to++) {
vTaskDelay(pdMS_TO_TICKS(10));
for (to = 0; to < ip101->autonego_timeout_ms / 100; to++) {
vTaskDelay(pdMS_TO_TICKS(100));
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
if (bmsr.auto_nego_complete) {
break;
}
}
/* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
if (to >= ip101->autonego_timeout_ms / 10) {
if (to >= ip101->autonego_timeout_ms / 100) {
ESP_LOGW(TAG, "auto negotiation timeout");
}
/* Updata information about link, speed, duplex */
ESP_GOTO_ON_ERROR(ip101_update_link_duplex_speed(ip101), err, TAG, "update link duplex speed failed");
return ESP_OK;
err:
return ret;

View File

@ -213,6 +213,8 @@ static esp_err_t ksz80xx_negotiate(esp_eth_phy_t *phy)
esp_err_t ret = ESP_OK;
phy_ksz80xx_t *ksz80xx = __containerof(phy, phy_ksz80xx_t, parent);
esp_eth_mediator_t *eth = ksz80xx->eth;
/* in case any link status has changed, let's assume we're in link down status */
ksz80xx->link_status = ETH_LINK_DOWN;
/* Restart auto negotiation */
bmcr_reg_t bmcr = {
.speed_select = 1, /* 100Mbps */
@ -224,19 +226,17 @@ static esp_err_t ksz80xx_negotiate(esp_eth_phy_t *phy)
/* Wait for auto negotiation complete */
bmsr_reg_t bmsr;
uint32_t to = 0;
for (to = 0; to < ksz80xx->autonego_timeout_ms / 10; to++) {
vTaskDelay(pdMS_TO_TICKS(10));
for (to = 0; to < ksz80xx->autonego_timeout_ms / 100; to++) {
vTaskDelay(pdMS_TO_TICKS(100));
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz80xx->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
if (bmsr.auto_nego_complete) {
break;
}
}
/* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
if (to >= ksz80xx->autonego_timeout_ms / 10) {
if (to >= ksz80xx->autonego_timeout_ms / 100) {
ESP_LOGW(TAG, "auto negotiation timeout");
}
/* Updata information about link, speed, duplex */
ESP_GOTO_ON_ERROR(ksz80xx_update_link_duplex_speed(ksz80xx), err, TAG, "update link duplex speed failed");
return ESP_OK;
err:
return ret;

View File

@ -166,27 +166,27 @@ static esp_err_t phy_ksz8851_negotiate(esp_eth_phy_t *phy)
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
esp_eth_mediator_t *eth = ksz8851->eth;
ESP_LOGD(TAG, "restart negotiation");
/* in case any link status has changed, let's assume we're in link down status */
ksz8851->link_status = ETH_LINK_DOWN;
uint32_t control;
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control | P1CR_RESTART_AN), err, TAG, "P1CR write failed");
uint32_t status;
unsigned to;
for (to = 0; to < ksz8851->autonego_timeout_ms / 10; to++) {
vTaskDelay(pdMS_TO_TICKS(10));
for (to = 0; to < ksz8851->autonego_timeout_ms / 100; to++) {
vTaskDelay(pdMS_TO_TICKS(100));
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1SR, &status), err, TAG, "P1SR read failed");
if (status & P1SR_AN_DONE) {
break;
}
}
if (to >= ksz8851->autonego_timeout_ms / 10) {
if (to >= ksz8851->autonego_timeout_ms / 100) {
ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout");
}
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control), err, TAG, "P1CR write failed");
ESP_GOTO_ON_ERROR(ksz8851_update_link_duplex_speed(ksz8851), err, TAG, "update link duplex speed failed");
ESP_LOGD(TAG, "negotiation succeeded");
return ESP_OK;
err:

View File

@ -278,6 +278,8 @@ static esp_err_t lan8720_negotiate(esp_eth_phy_t *phy)
esp_err_t ret = ESP_OK;
phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
esp_eth_mediator_t *eth = lan8720->eth;
/* in case any link status has changed, let's assume we're in link down status */
lan8720->link_status = ETH_LINK_DOWN;
/* Restart auto negotiation */
bmcr_reg_t bmcr = {
.speed_select = 1, /* 100Mbps */
@ -290,8 +292,8 @@ static esp_err_t lan8720_negotiate(esp_eth_phy_t *phy)
bmsr_reg_t bmsr;
pscsr_reg_t pscsr;
uint32_t to = 0;
for (to = 0; to < lan8720->autonego_timeout_ms / 10; to++) {
vTaskDelay(pdMS_TO_TICKS(10));
for (to = 0; to < lan8720->autonego_timeout_ms / 100; to++) {
vTaskDelay(pdMS_TO_TICKS(100));
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_PSCSR_REG_ADDR, &(pscsr.val)), err, TAG, "read PSCSR failed");
if (bmsr.auto_nego_complete && pscsr.auto_nego_done) {
@ -299,11 +301,9 @@ static esp_err_t lan8720_negotiate(esp_eth_phy_t *phy)
}
}
/* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
if (to >= lan8720->autonego_timeout_ms / 10) {
if (to >= lan8720->autonego_timeout_ms / 100) {
ESP_LOGW(TAG, "auto negotiation timeout");
}
/* Updata information about link, speed, duplex */
ESP_GOTO_ON_ERROR(lan8720_update_link_duplex_speed(lan8720), err, TAG, "update link duplex speed failed");
return ESP_OK;
err:
return ret;

View File

@ -188,6 +188,8 @@ static esp_err_t rtl8201_negotiate(esp_eth_phy_t *phy)
esp_err_t ret = ESP_OK;
phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
esp_eth_mediator_t *eth = rtl8201->eth;
/* in case any link status has changed, let's assume we're in link down status */
rtl8201->link_status = ETH_LINK_DOWN;
/* Restart auto negotiation */
bmcr_reg_t bmcr = {
.speed_select = 1, /* 100Mbps */
@ -199,19 +201,17 @@ static esp_err_t rtl8201_negotiate(esp_eth_phy_t *phy)
/* Wait for auto negotiation complete */
bmsr_reg_t bmsr;
uint32_t to = 0;
for (to = 0; to < rtl8201->autonego_timeout_ms / 10; to++) {
vTaskDelay(pdMS_TO_TICKS(10));
for (to = 0; to < rtl8201->autonego_timeout_ms / 100; to++) {
vTaskDelay(pdMS_TO_TICKS(100));
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
if (bmsr.auto_nego_complete) {
break;
}
}
/* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
if (to >= rtl8201->autonego_timeout_ms / 10) {
if (to >= rtl8201->autonego_timeout_ms / 100) {
ESP_LOGW(TAG, "auto negotiation timeout");
}
/* Updata information about link, speed, duplex */
ESP_GOTO_ON_ERROR(rtl8201_update_link_duplex_speed(rtl8201), err, TAG, "update link duplex speed failed");
return ESP_OK;
err:
return ret;

View File

@ -148,15 +148,13 @@ static esp_err_t w5500_negotiate(esp_eth_phy_t *phy)
esp_err_t ret = ESP_OK;
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
esp_eth_mediator_t *eth = w5500->eth;
/* in case any link status has changed, let's assume we're in link down status */
w5500->link_status = ETH_LINK_DOWN;
phycfg_reg_t phycfg;
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, w5500->addr, W5500_REG_PHYCFGR, (uint32_t *) & (phycfg.val)), err, TAG, "read PHYCFG failed");
phycfg.opsel = 1; // PHY working mode configured by register
phycfg.opmode = 7; // all capable, auto-negotiation enabled
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
/* Update information about link, speed, duplex */
ESP_GOTO_ON_ERROR(w5500_update_link_duplex_speed(w5500), err, TAG, "update link duplex speed failed");
return ESP_OK;
err:
return ret;