Simple example code to dump LAN8710A registers

MikeZomo
Posts: 1
Joined: Thu Feb 22, 2024 1:20 pm

Simple example code to dump LAN8710A registers

Postby MikeZomo » Thu Feb 22, 2024 1:41 pm

Hi All,

I just getting into the EXP-IDF via Visual Studio Code, since I usually use the Arduino IDE or PlatformIO via Visual Studio Code. I need a simple code example showing how to access the internal registers of the LAN8710A, basically dump out all the LAN8710A registers contents.
Thanks in advance.

Kind Regards
Mike Zomo

PeterG76
Posts: 17
Joined: Wed May 25, 2022 10:25 am

Re: Simple example code to dump LAN8710A registers

Postby PeterG76 » Wed May 01, 2024 3:25 pm

I had to do the same thing recently to diagnose some of our ethernet faults with a SMSC LAN8710A phy chip interfacing with an ESP32-WROVER-E.

The esp-idf driver that supports LAN8710A has some code that reads Phy registers

https://github.com/espressif/esp-idf/bl ... _lan87xx.c

I'm using an old copy of esp-idf 4.1, but I modified my copy of esp_eth_phy_lan8720.c by adding a report method to dump various regsiter values to UART using ESP_LOGI(). I exposed this method to my application.

PeterG76
Posts: 17
Joined: Wed May 25, 2022 10:25 am

Re: Simple example code to dump LAN8710A registers

Postby PeterG76 » Wed May 01, 2024 3:27 pm

This is the git diff on my esp-idf

Code: Select all

diff --git a/components/esp_eth/include/esp_eth.h b/components/esp_eth/include/esp_eth.h
index 34ee91594..6e2b7c43b 100644
--- a/components/esp_eth/include/esp_eth.h
+++ b/components/esp_eth/include/esp_eth.h
@@ -147,6 +147,8 @@ esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl);
 */
 esp_err_t esp_eth_start(esp_eth_handle_t hdl);
 
+esp_err_t esp_link_report(esp_eth_handle_t hdl);
+
 /**
 * @brief Stop Ethernet driver
 *
diff --git a/components/esp_eth/include/esp_eth_phy.h b/components/esp_eth/include/esp_eth_phy.h
index 4aedff111..05caadd0a 100644
--- a/components/esp_eth/include/esp_eth_phy.h
+++ b/components/esp_eth/include/esp_eth_phy.h
@@ -171,6 +171,8 @@ struct esp_eth_phy_s {
     *
     */
     esp_err_t (*del)(esp_eth_phy_t *phy);
+
+    esp_err_t (*report_link)(esp_eth_phy_t *phy);
 };
 
 /**
diff --git a/components/esp_eth/src/esp_eth.c b/components/esp_eth/src/esp_eth.c
index a895b5b09..011dbabcd 100644
--- a/components/esp_eth/src/esp_eth.c
+++ b/components/esp_eth/src/esp_eth.c
@@ -250,6 +250,20 @@ err:
     return ret;
 }
 
+/// @brief Prints out values from registers on the Phy chip
+/// LAN8710A to give an indication of the ethernet status
+/// @param hdl ethernet driver handle
+/// @return ESP_OK
+esp_err_t esp_link_report(esp_eth_handle_t hdl)
+{
+    esp_err_t ret = ESP_OK;
+    esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
+
+    eth_driver->phy->report_link(eth_driver->phy);
+
+    return ret;
+}
+
 esp_err_t esp_eth_start(esp_eth_handle_t hdl)
 {
     esp_err_t ret = ESP_OK;
diff --git a/components/esp_eth/src/esp_eth_phy_lan8720.c b/components/esp_eth/src/esp_eth_phy_lan8720.c
index bd6437605..a48cde550 100644
--- a/components/esp_eth/src/esp_eth_phy_lan8720.c
+++ b/components/esp_eth/src/esp_eth_phy_lan8720.c
@@ -165,6 +165,56 @@ typedef struct {
     int reset_gpio_num;
 } phy_lan8720_t;
 
+static esp_err_t lan8720_report_link(esp_eth_phy_t *phy)
+{
+    phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
+    esp_eth_mediator_t *eth = lan8720->eth;
+    eth_speed_t speed = ETH_SPEED_10M;
+    eth_duplex_t duplex = ETH_DUPLEX_HALF;
+    bmsr_reg_t bmsr;
+    bmcr_reg_t bmcr;
+    pscsr_reg_t pscsr;
+    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+              "read BMSR failed", err);
+    //eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
+    ESP_LOGI(TAG, "Phy BMSR val 0x%04X, link_status %u (%s)", 
+                bmsr.val, bmsr.link_status, bmsr.link_status ? "UP" : "DOWN");
+
+    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_PSCSR_REG_ADDR, &(pscsr.val)) == ESP_OK,
+                      "read PSCSR failed", err);
+    switch (pscsr.speed_indication) {
+        case 1: //10Base-T half-duplex
+            speed = ETH_SPEED_10M;
+            duplex = ETH_DUPLEX_HALF;
+            break;
+        case 2: //100Base-TX half-duplex
+            speed = ETH_SPEED_100M;
+            duplex = ETH_DUPLEX_HALF;
+            break;
+        case 5: //10Base-T full-duplex
+            speed = ETH_SPEED_10M;
+            duplex = ETH_DUPLEX_FULL;
+            break;
+        case 6: //100Base-TX full-duplex
+            speed = ETH_SPEED_100M;
+            duplex = ETH_DUPLEX_FULL;
+            break;
+        default:
+            break;
+    }
+    ESP_LOGI(TAG, "Phy SCSR val 0x%04X, SI %u, LinkSpeed %u (%s), Duplex %u (%s)",
+            pscsr.val, pscsr.speed_indication,
+            speed, speed ? "100M" : "10M", 
+            duplex, duplex ? "FULL" : "HALF");
+    ESP_LOGI(TAG, "Phy SCSR val 0x%04X auto_neg_done %u", pscsr.val, pscsr.auto_nego_done);
+
+    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+            "read basic control reg failed", err);
+    ESP_LOGI(TAG, "Phy BMCR val 0x%04X, Loopback mode %u", bmcr.val, bmcr.en_loopback);
+    return ESP_OK;
+err:    return ESP_FAIL;
+}
+
 static esp_err_t lan8720_update_link_duplex_speed(phy_lan8720_t *lan8720)
 {
     esp_eth_mediator_t *eth = lan8720->eth;
@@ -425,6 +475,7 @@ esp_eth_phy_t *esp_eth_phy_new_lan8720(const eth_phy_config_t *config)
     lan8720->parent.get_addr = lan8720_get_addr;
     lan8720->parent.set_addr = lan8720_set_addr;
     lan8720->parent.del = lan8720_del;
+    lan8720->parent.report_link = lan8720_report_link;
 
     return &(lan8720->parent);
 err:

ESP_ondrej
Posts: 210
Joined: Fri May 07, 2021 10:35 am

Re: Simple example code to dump LAN8710A registers

Postby ESP_ondrej » Thu May 02, 2024 7:24 am

Here is a code example to dump PHY registers:

Code: Select all

esp_err_t dump_phy_regs(esp_eth_handle_t *eth_handle, uint32_t start_addr, uint32_t end_addr)
{
    esp_eth_phy_reg_rw_data_t reg;
    uint32_t reg_val;
    reg.reg_value_p = &reg_val;

    printf("--- PHY Registers Dump ---\n");
    for (uint32_t curr_addr = start_addr; curr_addr <= end_addr; curr_addr++) {
        reg.reg_addr = curr_addr;
        ESP_RETURN_ON_ERROR(esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, &reg), TAG, "ioctl read PHY register failed");
        printf("Addr: 0x%02lx, value: 0x%04lx\n", curr_addr, reg_val);
    }
    printf("\n");

    return ESP_OK;
}

Who is online

Users browsing this forum: Bing [Bot] and 78 guests