Skip to content
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

fix(ch390): memory distribution error of phy_ctl1_reg_t; loopback not work properly (IDFGH-13804) #42

Merged
merged 1 commit into from
Dec 9, 2024
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
17 changes: 17 additions & 0 deletions ch390/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion ch390/idf_component.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
4 changes: 2 additions & 2 deletions ch390/include/ch390.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down
65 changes: 20 additions & 45 deletions ch390/src/esp_eth_phy_ch390.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -110,36 +87,33 @@ static esp_err_t ch390_get_link(esp_eth_phy_t *phy)
return ret;
}

SergeyKharenko marked this conversation as resolved.
Show resolved Hide resolved
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);
kostaond marked this conversation as resolved.
Show resolved Hide resolved
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;
Expand Down Expand Up @@ -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;
Expand Down