diff --git a/ch390/README.md b/ch390/README.md index 1edbc6e..d924cb4 100644 --- a/ch390/README.md +++ b/ch390/README.md @@ -55,3 +55,20 @@ esp_eth_phy_t *phy = esp_eth_phy_new_ch390(&phy_config); and use the Ethernet driver as you are used to. For more information of how to use ESP-IDF Ethernet driver, visit [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_eth.html). + +## Version History +| **Version** | **Date** | **Description** | +|:-----------:|:----------:|-------------------------------------------------------------------------------------------------------------------- | +| 0.1.0 | 2024-03-06 | Initial Release | +| 0.2.0 | 2024-08-29 | Fix start/stop issue: cannot acquire the ip address after several start/stop loops randomly | +| 0.2.1 | 2024-11-25 | Correct some typos in comment; Fix the issue that loopback and auto-negotiation cannot be enabled at the same time | + +## Acknowledgement +In no particular order: +- ***kostaond** +- ***leeebo** +- igrr +- bogdankolendovskyy +- ShunzDai + +*Gives **TREMENDOUS** support to the project diff --git a/ch390/idf_component.yml b/ch390/idf_component.yml index 605e52e..c6b12d6 100644 --- a/ch390/idf_component.yml +++ b/ch390/idf_component.yml @@ -1,4 +1,4 @@ -version: "0.2.0" +version: "0.2.1" description: CH390 Ethernet Driver url: https://github.com/espressif/esp-eth-drivers/tree/master/ch390 dependencies: diff --git a/ch390/include/ch390.h b/ch390/include/ch390.h index 72b6ce9..57cbac3 100644 --- a/ch390/include/ch390.h +++ b/ch390/include/ch390.h @@ -23,7 +23,7 @@ extern "C" { #define NCR_WAKEEN (1<<6) // Enable wakeup function #define NCR_FDX (1<<3) // Duplex mode of the internal PHY #define NCR_LBK_MAC (1<<1) // MAC loop-back -#define NCR_RST (1<<0) // Softwate reset +#define NCR_RST (1<<0) // Software reset #define CH390_NSR 0x01 // Network status reg #define NSR_SPEED (1<<7) // Speed of internal PHY @@ -156,7 +156,7 @@ extern "C" { #define CH390_SCCR 0x50 // System clock control reg #define CH390_RSCCR 0x51 // Recover system clock control reg -#define CH390_RLENCR 0x52 // Receive data pack lenth control reg +#define CH390_RLENCR 0x52 // Receive data pack length control reg #define RLENCR_RXLEN_EN 0x80 // Enable RX data pack length filter #define RLENCR_RXLEN_DEFAULT 0x18 // Default MAX length of RX data(div by 64) diff --git a/ch390/src/esp_eth_phy_ch390.c b/ch390/src/esp_eth_phy_ch390.c index 9bb25a1..a89dfde 100644 --- a/ch390/src/esp_eth_phy_ch390.c +++ b/ch390/src/esp_eth_phy_ch390.c @@ -18,33 +18,10 @@ #include "esp_eth_phy_ch390.h" -/** - * @warning This value is NOT the same as the datasheet!!! Hoping WCH fix it - * in the furture version! -*/ #define CH390_INFO_OUI 0x1CDC64 #define CH390_INFO_MODEL 0x01 -#define ETH_PHY_PAGE_SEL_REG_ADDR 0x1F - -typedef union { - struct { - uint32_t reserved1 : 3; - uint32_t force_link : 1; - uint32_t remote_lpbk : 1; - uint32_t pcs_lpbk : 1; - uint32_t pma_lpbk : 1; - uint32_t jabber_en : 1; - uint32_t sqe_en : 1; - uint32_t reserved2 : 7; - }; - uint32_t val; -} phy_ctl1_reg_t; - -#define ETH_PHY_CTL1_REG_ADDR 0x19 -#define ETH_PHY_CTL1_REG_PAGE 0x00 - typedef struct { phy_802_3_t phy_802_3; } phy_ch390_t; @@ -110,36 +87,33 @@ static esp_err_t ch390_get_link(esp_eth_phy_t *phy) return ret; } -static esp_err_t ch390_loopback(esp_eth_phy_t *phy, bool enable) +static esp_err_t ch390_autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat) { esp_err_t ret = ESP_OK; phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); esp_eth_mediator_t *eth = phy_802_3->eth; - /* Set Loopback function */ - // Enable PMA loopback in PHY_Control1 register - bmcr_reg_t bmcr; - phy_ctl1_reg_t phy_ctl1; - ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); - ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_PAGE_SEL_REG_ADDR, ETH_PHY_CTL1_REG_PAGE), - err, TAG, "write PAGE_SEL failed"); - ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_CTL1_REG_ADDR, &(phy_ctl1.val)), err, TAG, "read PHY_CTL1 failed"); - - if (enable) { - bmcr.en_loopback = 1; - phy_ctl1.pma_lpbk = 1; - } else { - bmcr.en_loopback = 0; - phy_ctl1.pma_lpbk = 0; + if (cmd == ESP_ETH_PHY_AUTONEGO_EN) { + bmcr_reg_t bmcr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + ESP_GOTO_ON_FALSE(bmcr.en_loopback == 0, ESP_ERR_INVALID_STATE, err, TAG, "Auto-negotiation can't be enabled while in loopback operation"); } - ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed"); - ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_PAGE_SEL_REG_ADDR, ETH_PHY_CTL1_REG_PAGE), - err, TAG, "write PAGE_SEL failed"); - ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_CTL1_REG_ADDR, phy_ctl1.val), err, TAG, "write PHY_CTL1 failed"); - return ESP_OK; + return esp_eth_phy_802_3_autonego_ctrl(phy_802_3, cmd, autonego_en_stat); err: return ret; } +static esp_err_t ch390_loopback(esp_eth_phy_t *phy, bool enable) +{ + esp_err_t ret = ESP_OK; + phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy); + bool auto_nego_en = true; + ESP_GOTO_ON_ERROR(ch390_autonego_ctrl(phy, ESP_ETH_PHY_AUTONEGO_G_STAT, &auto_nego_en), err, TAG, "get status of autonegotiation failed"); + ESP_GOTO_ON_FALSE(!(auto_nego_en && enable), ESP_ERR_INVALID_STATE, err, TAG, + "Unable to set loopback while auto-negotiation is enabled. Disable it to use loopback"); + return esp_eth_phy_802_3_loopback(phy_802_3, enable); +err: + return ret; +} static esp_err_t ch390_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -168,9 +142,10 @@ esp_eth_phy_t *esp_eth_phy_new_ch390(const eth_phy_config_t *config) ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&ch390->phy_802_3, config) == ESP_OK, NULL, err, TAG, "configuration initialization of PHY 802.3 failed"); - // redefine functions which need to be customized for sake of ch390 + // override functions which need to be customized for sake of ch390 ch390->phy_802_3.parent.init = ch390_init; ch390->phy_802_3.parent.get_link = ch390_get_link; + ch390->phy_802_3.parent.autonego_ctrl = ch390_autonego_ctrl; ch390->phy_802_3.parent.loopback = ch390_loopback; return &ch390->phy_802_3.parent;