mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 18:10:57 +02:00
Merge branch 'feat/remove_eth_drivers' into 'master'
Feat/remove eth drivers Closes IDF-13553 and IDF-5865 See merge request espressif/esp-idf!42021
This commit is contained in:
@@ -30,32 +30,12 @@ if(CONFIG_ETH_ENABLED)
|
|||||||
list(APPEND srcs "src/mac/esp_eth_mac_esp.c"
|
list(APPEND srcs "src/mac/esp_eth_mac_esp.c"
|
||||||
"src/mac/esp_eth_mac_esp_dma.c"
|
"src/mac/esp_eth_mac_esp_dma.c"
|
||||||
"src/mac/esp_eth_mac_esp_gpio.c"
|
"src/mac/esp_eth_mac_esp_gpio.c"
|
||||||
"src/phy/esp_eth_phy_generic.c"
|
"src/phy/esp_eth_phy_generic.c")
|
||||||
"src/phy/esp_eth_phy_dp83848.c"
|
|
||||||
"src/phy/esp_eth_phy_ip101.c"
|
|
||||||
"src/phy/esp_eth_phy_ksz80xx.c"
|
|
||||||
"src/phy/esp_eth_phy_lan87xx.c"
|
|
||||||
"src/phy/esp_eth_phy_rtl8201.c")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CONFIG_ETH_SPI_ETHERNET_DM9051)
|
|
||||||
list(APPEND srcs "src/spi/dm9051/esp_eth_mac_dm9051.c"
|
|
||||||
"src/spi/dm9051/esp_eth_phy_dm9051.c")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CONFIG_ETH_SPI_ETHERNET_W5500)
|
|
||||||
list(APPEND srcs "src/spi/w5500/esp_eth_mac_w5500.c"
|
|
||||||
"src/spi/w5500/esp_eth_phy_w5500.c")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL)
|
|
||||||
list(APPEND srcs "src/spi/ksz8851snl/esp_eth_mac_ksz8851snl.c"
|
|
||||||
"src/spi/ksz8851snl/esp_eth_phy_ksz8851snl.c")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_ETH_USE_OPENETH)
|
if(CONFIG_ETH_USE_OPENETH)
|
||||||
list(APPEND srcs "src/openeth/esp_eth_mac_openeth.c"
|
list(APPEND srcs "src/openeth/esp_eth_mac_openeth.c"
|
||||||
"src/phy/esp_eth_phy_dp83848.c")
|
"src/phy/esp_eth_phy_generic.c")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -57,38 +57,13 @@ menu "Ethernet"
|
|||||||
If disabled, all functions are placed into FLASH.
|
If disabled, all functions are placed into FLASH.
|
||||||
|
|
||||||
endif # ETH_USE_ESP32_EMAC
|
endif # ETH_USE_ESP32_EMAC
|
||||||
|
|
||||||
menuconfig ETH_USE_SPI_ETHERNET
|
menuconfig ETH_USE_SPI_ETHERNET
|
||||||
bool "Support SPI to Ethernet Module"
|
bool "Support SPI to Ethernet Module"
|
||||||
default y
|
default y
|
||||||
select ETH_ENABLED
|
select ETH_ENABLED
|
||||||
help
|
help
|
||||||
ESP-IDF can also support some SPI-Ethernet modules.
|
ESP-IDF can also support SPI-Ethernet. Actual chip drivers are available as components in
|
||||||
|
Component Registry.
|
||||||
if ETH_USE_SPI_ETHERNET
|
|
||||||
config ETH_SPI_ETHERNET_DM9051
|
|
||||||
bool "Use DM9051"
|
|
||||||
help
|
|
||||||
DM9051 is a fast Ethernet controller with an SPI interface.
|
|
||||||
It's also integrated with a 10/100M PHY and MAC.
|
|
||||||
Select this to enable DM9051 driver.
|
|
||||||
|
|
||||||
config ETH_SPI_ETHERNET_W5500
|
|
||||||
bool "Use W5500 (MAC RAW)"
|
|
||||||
help
|
|
||||||
W5500 is a HW TCP/IP embedded Ethernet controller.
|
|
||||||
TCP/IP stack, 10/100 Ethernet MAC and PHY are embedded in a single chip.
|
|
||||||
However the driver in ESP-IDF only enables the RAW MAC mode,
|
|
||||||
making it compatible with the software TCP/IP stack.
|
|
||||||
Say yes to enable W5500 driver.
|
|
||||||
|
|
||||||
config ETH_SPI_ETHERNET_KSZ8851SNL
|
|
||||||
bool "Use KSZ8851SNL"
|
|
||||||
help
|
|
||||||
The KSZ8851SNL is a single-chip Fast Ethernet controller consisting of
|
|
||||||
a 10/100 physical layer transceiver (PHY), a MAC, and a Serial Peripheral Interface (SPI).
|
|
||||||
Select this to enable KSZ8851SNL driver.
|
|
||||||
endif # ETH_USE_SPI_ETHERNET
|
|
||||||
|
|
||||||
menuconfig ETH_USE_OPENETH
|
menuconfig ETH_USE_OPENETH
|
||||||
bool "Support OpenCores Ethernet MAC (for use with QEMU)"
|
bool "Support OpenCores Ethernet MAC (for use with QEMU)"
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -9,15 +9,14 @@
|
|||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "esp_eth_com.h"
|
#include "esp_eth_com.h"
|
||||||
#include "esp_eth_mac.h"
|
#include "esp_eth_mac.h"
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "driver/spi_master.h"
|
#include "driver/spi_master.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ETH_USE_SPI_ETHERNET
|
#if CONFIG_ETH_USE_SPI_ETHERNET
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom SPI Driver Configuration.
|
* @brief Custom SPI Driver Configuration.
|
||||||
* This structure declares configuration and callback functions to access Ethernet SPI module via
|
* This structure declares configuration and callback functions to access Ethernet SPI module via
|
||||||
@@ -112,125 +111,8 @@ typedef struct
|
|||||||
.read = NULL, \
|
.read = NULL, \
|
||||||
.write = NULL \
|
.write = NULL \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
||||||
|
|
||||||
#if CONFIG_ETH_SPI_ETHERNET_DM9051
|
|
||||||
/**
|
|
||||||
* @brief DM9051 specific configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int int_gpio_num; /*!< Interrupt GPIO number, set -1 to not use interrupt and to poll rx status periodically */
|
|
||||||
uint32_t poll_period_ms; /*!< Period in ms to poll rx status when interrupt mode is not used */
|
|
||||||
spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined) */
|
|
||||||
spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined) */
|
|
||||||
eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */
|
|
||||||
} eth_dm9051_config_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default DM9051 specific configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ETH_DM9051_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \
|
|
||||||
{ \
|
|
||||||
.int_gpio_num = 4, \
|
|
||||||
.poll_period_ms = 0, \
|
|
||||||
.spi_host_id = spi_host, \
|
|
||||||
.spi_devcfg = spi_devcfg_p, \
|
|
||||||
.custom_spi_driver = ETH_DEFAULT_SPI, \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create DM9051 Ethernet MAC instance
|
|
||||||
*
|
|
||||||
* @param dm9051_config: DM9051 specific configuration
|
|
||||||
* @param mac_config: Ethernet MAC configuration
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create MAC instance successfully
|
|
||||||
* - NULL: create MAC instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, const eth_mac_config_t *mac_config);
|
|
||||||
#endif // CONFIG_ETH_SPI_ETHERNET_DM9051
|
|
||||||
|
|
||||||
#if CONFIG_ETH_SPI_ETHERNET_W5500
|
|
||||||
/**
|
|
||||||
* @brief W5500 specific configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int int_gpio_num; /*!< Interrupt GPIO number, set -1 to not use interrupt and to poll rx status periodically */
|
|
||||||
uint32_t poll_period_ms; /*!< Period in ms to poll rx status when interrupt mode is not used */
|
|
||||||
spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined)*/
|
|
||||||
spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined)*/
|
|
||||||
eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */
|
|
||||||
} eth_w5500_config_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default W5500 specific configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ETH_W5500_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \
|
|
||||||
{ \
|
|
||||||
.int_gpio_num = 4, \
|
|
||||||
.poll_period_ms = 0, \
|
|
||||||
.spi_host_id = spi_host, \
|
|
||||||
.spi_devcfg = spi_devcfg_p, \
|
|
||||||
.custom_spi_driver = ETH_DEFAULT_SPI, \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create W5500 Ethernet MAC instance
|
|
||||||
*
|
|
||||||
* @param w5500_config: W5500 specific configuration
|
|
||||||
* @param mac_config: Ethernet MAC configuration
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create MAC instance successfully
|
|
||||||
* - NULL: create MAC instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, const eth_mac_config_t *mac_config);
|
|
||||||
#endif // CONFIG_ETH_SPI_ETHERNET_W5500
|
|
||||||
|
|
||||||
#if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL
|
|
||||||
/**
|
|
||||||
* @brief KSZ8851SNL specific configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int int_gpio_num; /*!< Interrupt GPIO number, set -1 to not use interrupt and to poll rx status periodically */
|
|
||||||
uint32_t poll_period_ms; /*!< Period in ms to poll rx status when interrupt mode is not used */
|
|
||||||
spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined) */
|
|
||||||
spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined) */
|
|
||||||
eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */
|
|
||||||
} eth_ksz8851snl_config_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default KSZ8851SNL specific configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \
|
|
||||||
{ \
|
|
||||||
.int_gpio_num = 4, \
|
|
||||||
.poll_period_ms = 0, \
|
|
||||||
.spi_host_id = spi_host, \
|
|
||||||
.spi_devcfg = spi_devcfg_p, \
|
|
||||||
.custom_spi_driver = ETH_DEFAULT_SPI, \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create KSZ8851SNL Ethernet MAC instance
|
|
||||||
*
|
|
||||||
* @param ksz8851snl_config: KSZ8851SNL specific configuration
|
|
||||||
* @param mac_config: Ethernet MAC configuration
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create MAC instance successfully
|
|
||||||
* - NULL: create MAC instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_mac_t *esp_eth_mac_new_ksz8851snl(const eth_ksz8851snl_config_t *ksz8851snl_config, const eth_mac_config_t *mac_config);
|
|
||||||
#endif // CONFIG_ETH_SPI_ETHERNET_KSZ8851
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -299,7 +299,7 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* @brief Create a PHY instance of generic chip which conforms with IEEE 802.3
|
* @brief Create a PHY instance of generic chip which conforms with IEEE 802.3
|
||||||
*
|
*
|
||||||
* @note Default reset timing configuration is set conservatively( @c DEFAULT_PHY_RESET_ASSERTION_TIME_US ).
|
* @note Default reset timing configuration is set conservatively(see internals of the function).
|
||||||
* If you need faster response and your chip supports it, configure it via @c config parameter.
|
* If you need faster response and your chip supports it, configure it via @c config parameter.
|
||||||
*
|
*
|
||||||
* @warning While basic functionality should always work, some specific features might be limited,
|
* @warning While basic functionality should always work, some specific features might be limited,
|
||||||
@@ -313,105 +313,6 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
esp_eth_phy_t *esp_eth_phy_new_generic(const eth_phy_config_t *config);
|
esp_eth_phy_t *esp_eth_phy_new_generic(const eth_phy_config_t *config);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a PHY instance of IP101
|
|
||||||
*
|
|
||||||
* @param[in] config: configuration of PHY
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create PHY instance successfully
|
|
||||||
* - NULL: create PHY instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_ip101(const eth_phy_config_t *config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a PHY instance of RTL8201
|
|
||||||
*
|
|
||||||
* @param[in] config: configuration of PHY
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create PHY instance successfully
|
|
||||||
* - NULL: create PHY instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_rtl8201(const eth_phy_config_t *config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a PHY instance of LAN87xx
|
|
||||||
*
|
|
||||||
* @param[in] config: configuration of PHY
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create PHY instance successfully
|
|
||||||
* - NULL: create PHY instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_lan87xx(const eth_phy_config_t *config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a PHY instance of DP83848
|
|
||||||
*
|
|
||||||
* @param[in] config: configuration of PHY
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create PHY instance successfully
|
|
||||||
* - NULL: create PHY instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a PHY instance of KSZ80xx
|
|
||||||
*
|
|
||||||
* The phy model from the KSZ80xx series is detected automatically. If the driver
|
|
||||||
* is unable to detect a supported model, \c NULL is returned.
|
|
||||||
*
|
|
||||||
* Currently, the following models are supported:
|
|
||||||
* KSZ8001, KSZ8021, KSZ8031, KSZ8041, KSZ8051, KSZ8061, KSZ8081, KSZ8091
|
|
||||||
*
|
|
||||||
* @param[in] config: configuration of PHY
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create PHY instance successfully
|
|
||||||
* - NULL: create PHY instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_ksz80xx(const eth_phy_config_t *config);
|
|
||||||
|
|
||||||
#if CONFIG_ETH_SPI_ETHERNET_DM9051
|
|
||||||
/**
|
|
||||||
* @brief Create a PHY instance of DM9051
|
|
||||||
*
|
|
||||||
* @param[in] config: configuration of PHY
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create PHY instance successfully
|
|
||||||
* - NULL: create PHY instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_ETH_SPI_ETHERNET_W5500
|
|
||||||
/**
|
|
||||||
* @brief Create a PHY instance of W5500
|
|
||||||
*
|
|
||||||
* @param[in] config: configuration of PHY
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create PHY instance successfully
|
|
||||||
* - NULL: create PHY instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_w5500(const eth_phy_config_t *config);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL
|
|
||||||
/**
|
|
||||||
* @brief Create a PHY instance of KSZ8851SNL
|
|
||||||
*
|
|
||||||
* @param[in] config: configuration of PHY
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - instance: create PHY instance successfully
|
|
||||||
* - NULL: create PHY instance failed because some error occurred
|
|
||||||
*/
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_ksz8851snl(const eth_phy_config_t *config);
|
|
||||||
#endif
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,195 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_eth_phy_802_3.h"
|
|
||||||
|
|
||||||
static const char *TAG = "dp83848";
|
|
||||||
|
|
||||||
/***************Vendor Specific Register***************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PHYSTS(PHY Status Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t link_status : 1; /* Link Status */
|
|
||||||
uint32_t speed_status : 1; /* Speed Status */
|
|
||||||
uint32_t duplex_status : 1; /* Duplex Status */
|
|
||||||
uint32_t loopback_status : 1; /* MII Loopback */
|
|
||||||
uint32_t auto_nego_complete : 1; /* Auto-Negotiation Complete */
|
|
||||||
uint32_t jabber_detect : 1; /* Jabber Detect */
|
|
||||||
uint32_t remote_fault : 1; /* Remote Fault */
|
|
||||||
uint32_t mii_interrupt : 1; /* MII Interrupt Pending */
|
|
||||||
uint32_t page_received : 1; /* Link Code Word Page Received */
|
|
||||||
uint32_t descrambler_lock : 1; /* Descrambler Lock */
|
|
||||||
uint32_t signal_detect : 1; /* Signal Detect */
|
|
||||||
uint32_t false_carrier_sense_latch : 1; /* False Carrier Sense Latch */
|
|
||||||
uint32_t polarity_status : 1; /* Polarity Status */
|
|
||||||
uint32_t receive_error_latch : 1; /* Receive Error Latch */
|
|
||||||
uint32_t mdix_mode : 1; /* MDI-X mode reported by auto-negotiation */
|
|
||||||
uint32_t reserved : 1; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} physts_reg_t;
|
|
||||||
#define ETH_PHY_STS_REG_ADDR (0x10)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PHYCR(PHY Control Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t phy_addr : 5; /* PHY Address */
|
|
||||||
uint32_t led_cfg : 2; /* LED Configuration Modes */
|
|
||||||
uint32_t bypass_led_stretching : 1; /* Bypass LED Stretching */
|
|
||||||
uint32_t bist_start : 1; /* BIST Start */
|
|
||||||
uint32_t bist_status : 1; /* BIST Test Status */
|
|
||||||
uint32_t psr_15 : 1; /* BIST Sequence select */
|
|
||||||
uint32_t bist_force_error : 1; /* BIST Force Error */
|
|
||||||
uint32_t pause_trans_negotiate : 1; /* Pause Transmit Negotiated Status */
|
|
||||||
uint32_t pause_receive_negotiat : 1; /* Pause Receive Negotiated Status */
|
|
||||||
uint32_t force_mdix : 1; /* Force MDIX */
|
|
||||||
uint32_t en_auto_mdix : 1; /* Auto-MDIX Enable */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} phycr_reg_t;
|
|
||||||
#define ETH_PHY_CR_REG_ADDR (0x19)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
phy_802_3_t phy_802_3;
|
|
||||||
} phy_dp83848_t;
|
|
||||||
|
|
||||||
static esp_err_t dp83848_update_link_duplex_speed(phy_dp83848_t *dp83848)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = dp83848->phy_802_3.eth;
|
|
||||||
uint32_t addr = dp83848->phy_802_3.addr;
|
|
||||||
eth_speed_t speed = ETH_SPEED_10M;
|
|
||||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
|
||||||
uint32_t peer_pause_ability = false;
|
|
||||||
anlpar_reg_t anlpar;
|
|
||||||
physts_reg_t physts;
|
|
||||||
bmsr_reg_t bmsr;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
|
|
||||||
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
|
||||||
/* check if link status changed */
|
|
||||||
if (dp83848->phy_802_3.link_status != link) {
|
|
||||||
/* when link up, read negotiation result */
|
|
||||||
if (link == ETH_LINK_UP) {
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed");
|
|
||||||
if (physts.speed_status) {
|
|
||||||
speed = ETH_SPEED_10M;
|
|
||||||
} else {
|
|
||||||
speed = ETH_SPEED_100M;
|
|
||||||
}
|
|
||||||
if (physts.duplex_status) {
|
|
||||||
duplex = ETH_DUPLEX_FULL;
|
|
||||||
} else {
|
|
||||||
duplex = ETH_DUPLEX_HALF;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed");
|
|
||||||
/* if we're in duplex mode, and peer has the flow control ability */
|
|
||||||
if (duplex == ETH_DUPLEX_FULL && anlpar.symmetric_pause) {
|
|
||||||
peer_pause_ability = 1;
|
|
||||||
} else {
|
|
||||||
peer_pause_ability = 0;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_PAUSE, (void *)peer_pause_ability), err, TAG, "change pause ability failed");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed");
|
|
||||||
dp83848->phy_802_3.link_status = link;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t dp83848_get_link(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_dp83848_t *dp83848 = __containerof(esp_eth_phy_into_phy_802_3(phy), phy_dp83848_t, phy_802_3);
|
|
||||||
/* Update 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t dp83848_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;
|
|
||||||
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, "Autonegotiation can't be enabled while in loopback operation");
|
|
||||||
}
|
|
||||||
return esp_eth_phy_802_3_autonego_ctrl(phy_802_3, cmd, autonego_en_stat);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t dp83848_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(dp83848_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 autonegotiation 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 dp83848_init(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
|
|
||||||
|
|
||||||
/* Basic PHY init */
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_basic_phy_init(phy_802_3), err, TAG, "failed to init PHY");
|
|
||||||
|
|
||||||
/* Check PHY ID */
|
|
||||||
uint32_t oui;
|
|
||||||
uint8_t model;
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_oui(phy_802_3, &oui), err, TAG, "read OUI failed");
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_manufac_info(phy_802_3, &model, NULL), err, TAG, "read manufacturer's info failed");
|
|
||||||
ESP_GOTO_ON_FALSE(oui == 0x80017 && model == 0x09, ESP_FAIL, err, TAG, "wrong chip ID");
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config)
|
|
||||||
{
|
|
||||||
esp_eth_phy_t *ret = NULL;
|
|
||||||
phy_dp83848_t *dp83848 = calloc(1, sizeof(phy_dp83848_t));
|
|
||||||
ESP_GOTO_ON_FALSE(dp83848, NULL, err, TAG, "calloc dp83848 failed");
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&dp83848->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 dp83848
|
|
||||||
dp83848->phy_802_3.parent.init = dp83848_init;
|
|
||||||
dp83848->phy_802_3.parent.get_link = dp83848_get_link;
|
|
||||||
dp83848->phy_802_3.parent.autonego_ctrl = dp83848_autonego_ctrl;
|
|
||||||
dp83848->phy_802_3.parent.loopback = dp83848_loopback;
|
|
||||||
|
|
||||||
return &dp83848->phy_802_3.parent;
|
|
||||||
err:
|
|
||||||
if (dp83848 != NULL) {
|
|
||||||
free(dp83848);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
@@ -1,222 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_eth_phy_802_3.h"
|
|
||||||
|
|
||||||
static const char *TAG = "ip101";
|
|
||||||
|
|
||||||
#define IP101_PHY_RESET_ASSERTION_TIME_US 10000
|
|
||||||
#define IP101_PHY_POST_RESET_INIT_TIME_MS 10
|
|
||||||
|
|
||||||
/***************Vendor Specific Register***************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PCR(Page Control Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t register_page_select : 5; /* Select register page, default is 16 */
|
|
||||||
uint32_t reserved : 11; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} pcr_reg_t;
|
|
||||||
#define ETH_PHY_PCR_REG_ADDR (0x14)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief ISR(Interrupt Status Register), Page 16
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t link_changed : 1; /* Flag to indicate link status change interrupt */
|
|
||||||
uint32_t duplex_changed : 1; /* Flag to indicate duplex change interrupt */
|
|
||||||
uint32_t speed_changed : 1; /* Flag to indicate speed change interrupt */
|
|
||||||
uint32_t intr_status : 1; /* Flag to indicate interrupt status */
|
|
||||||
uint32_t reserved1 : 4; /* Reserved */
|
|
||||||
uint32_t link_mask : 1; /* Mask link change interrupt */
|
|
||||||
uint32_t duplex_mask : 1; /* Mask duplex change interrupt */
|
|
||||||
uint32_t speed_mask : 1; /* Mask speed change interrupt */
|
|
||||||
uint32_t all_mask : 1; /* Mask all interrupt */
|
|
||||||
uint32_t reserved2 : 3; /* Reserved */
|
|
||||||
uint32_t use_intr_pin : 1; /* Set high to use INTR and INTR_32 as an interrupt pin */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} isr_reg_t;
|
|
||||||
#define ETH_PHY_ISR_REG_ADDR (0x11)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PHY MDI/MDIX Control and Specific Status Register, Page 16
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t op_mode : 3; /* Operation Mode Indicator */
|
|
||||||
uint32_t force_mdix : 1; /* Force the MDIX channel to be selected */
|
|
||||||
uint32_t reserved1 : 4; /* Reserved */
|
|
||||||
uint32_t link_up : 1; /* Indicate the link status is OK or FAIL */
|
|
||||||
uint32_t reserved2 : 7; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} cssr_reg_t;
|
|
||||||
#define ETH_PHY_CSSR_REG_ADDR (0x1E)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PSCR(PHY Specific Control Register), Page 1
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved1 : 7; /* Reserved */
|
|
||||||
uint32_t force_link_100 : 1; /* Force Link 100 */
|
|
||||||
uint32_t force_link_10 : 1; /* Force Link 10 */
|
|
||||||
uint32_t reserved2 : 7; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} pscr_reg_t;
|
|
||||||
#define ETH_PHY_PSCR_REG_ADDR (0x11)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
phy_802_3_t phy_802_3;
|
|
||||||
} phy_ip101_t;
|
|
||||||
|
|
||||||
static esp_err_t ip101_page_select(phy_ip101_t *ip101, uint32_t page)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = ip101->phy_802_3.eth;
|
|
||||||
pcr_reg_t pcr = {
|
|
||||||
.register_page_select = page
|
|
||||||
};
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ip101->phy_802_3.addr, ETH_PHY_PCR_REG_ADDR, pcr.val), err, TAG, "write PCR failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ip101_update_link_duplex_speed(phy_ip101_t *ip101)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = ip101->phy_802_3.eth;
|
|
||||||
uint32_t addr = ip101->phy_802_3.addr;
|
|
||||||
eth_speed_t speed = ETH_SPEED_10M;
|
|
||||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
|
||||||
uint32_t peer_pause_ability = false;
|
|
||||||
cssr_reg_t cssr;
|
|
||||||
anlpar_reg_t anlpar;
|
|
||||||
|
|
||||||
ESP_GOTO_ON_ERROR(ip101_page_select(ip101, 16), err, TAG, "select page 16 failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_CSSR_REG_ADDR, &(cssr.val)), err, TAG, "read CSSR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
|
||||||
eth_link_t link = cssr.link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
|
|
||||||
/* check if link status changed */
|
|
||||||
if (ip101->phy_802_3.link_status != link) {
|
|
||||||
/* when link up, read negotiation result */
|
|
||||||
if (link == ETH_LINK_UP) {
|
|
||||||
switch (cssr.op_mode) {
|
|
||||||
case 1: //10M Half
|
|
||||||
speed = ETH_SPEED_10M;
|
|
||||||
duplex = ETH_DUPLEX_HALF;
|
|
||||||
break;
|
|
||||||
case 2: //100M Half
|
|
||||||
speed = ETH_SPEED_100M;
|
|
||||||
duplex = ETH_DUPLEX_HALF;
|
|
||||||
break;
|
|
||||||
case 5: //10M Full
|
|
||||||
speed = ETH_SPEED_10M;
|
|
||||||
duplex = ETH_DUPLEX_FULL;
|
|
||||||
break;
|
|
||||||
case 6: //100M Full
|
|
||||||
speed = ETH_SPEED_100M;
|
|
||||||
duplex = ETH_DUPLEX_FULL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed");
|
|
||||||
/* if we're in duplex mode, and peer has the flow control ability */
|
|
||||||
if (duplex == ETH_DUPLEX_FULL && anlpar.symmetric_pause) {
|
|
||||||
peer_pause_ability = 1;
|
|
||||||
} else {
|
|
||||||
peer_pause_ability = 0;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_PAUSE, (void *)peer_pause_ability), err, TAG, "change pause ability failed");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed");
|
|
||||||
ip101->phy_802_3.link_status = link;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ip101_get_link(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ip101_t *ip101 = __containerof(esp_eth_phy_into_phy_802_3(phy), phy_ip101_t, phy_802_3);
|
|
||||||
|
|
||||||
/* Update 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ip101_init(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
|
|
||||||
|
|
||||||
/* Basic PHY init */
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_basic_phy_init(phy_802_3), err, TAG, "failed to init PHY");
|
|
||||||
|
|
||||||
/* Check PHY ID */
|
|
||||||
uint32_t oui;
|
|
||||||
uint8_t model;
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_oui(phy_802_3, &oui), err, TAG, "read OUI failed");
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_manufac_info(phy_802_3, &model, NULL), err, TAG, "read manufacturer's info failed");
|
|
||||||
ESP_GOTO_ON_FALSE(oui == 0x90C3 && model == 0x5, ESP_FAIL, err, TAG, "wrong chip ID");
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_ip101(const eth_phy_config_t *config)
|
|
||||||
{
|
|
||||||
esp_eth_phy_t *ret = NULL;
|
|
||||||
phy_ip101_t *ip101 = calloc(1, sizeof(phy_ip101_t));
|
|
||||||
ESP_GOTO_ON_FALSE(ip101, NULL, err, TAG, "calloc ip101 failed");
|
|
||||||
eth_phy_config_t ip101_config = *config;
|
|
||||||
// default chip specific configuration
|
|
||||||
if (config->hw_reset_assert_time_us == 0) {
|
|
||||||
ip101_config.hw_reset_assert_time_us = IP101_PHY_RESET_ASSERTION_TIME_US;
|
|
||||||
}
|
|
||||||
if (config->post_hw_reset_delay_ms == 0) {
|
|
||||||
ip101_config.post_hw_reset_delay_ms = IP101_PHY_POST_RESET_INIT_TIME_MS;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&ip101->phy_802_3, &ip101_config) == ESP_OK,
|
|
||||||
NULL, err, TAG, "configuration initialization of PHY 802.3 failed");
|
|
||||||
|
|
||||||
// redefine functions which need to be customized for sake of IP101
|
|
||||||
ip101->phy_802_3.parent.init = ip101_init;
|
|
||||||
ip101->phy_802_3.parent.get_link = ip101_get_link;
|
|
||||||
|
|
||||||
return &ip101->phy_802_3.parent;
|
|
||||||
err:
|
|
||||||
if (ip101 != NULL) {
|
|
||||||
free(ip101);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
@@ -1,219 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_eth_phy_802_3.h"
|
|
||||||
|
|
||||||
#define KSZ80XX_PHY_ID_MSB (0x22)
|
|
||||||
#define KSZ80XX_PHY_ID_LSB (0x05)
|
|
||||||
#define KSZ80XX_PHY_OUI (KSZ80XX_PHY_ID_MSB << 6 | KSZ80XX_PHY_ID_LSB)
|
|
||||||
|
|
||||||
#define KSZ80XX_PC1R_REG_ADDR (0x1E)
|
|
||||||
#define KSZ80XX_PC2R_REG_ADDR (0x1F)
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
KSZ80XX_MODEL_NUMBER_11 = 0x11, // KSZ8041
|
|
||||||
KSZ80XX_MODEL_NUMBER_13 = 0x13, // KSZ8041RLNI
|
|
||||||
KSZ80XX_MODEL_NUMBER_15 = 0x15, // KSZ8021/31
|
|
||||||
KSZ80XX_MODEL_NUMBER_16 = 0x16, // KSZ8051/81/91
|
|
||||||
KSZ80XX_MODEL_NUMBER_17 = 0x17, // KSZ8061
|
|
||||||
KSZ80XX_MODEL_NUMBER_21 = 0x21, // KSZ8001
|
|
||||||
} ksz80xx_model_number_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
phy_802_3_t phy_802_3;
|
|
||||||
uint8_t model_number;
|
|
||||||
uint32_t op_mode_reg;
|
|
||||||
uint32_t op_mode_offset;
|
|
||||||
} phy_ksz80xx_t;
|
|
||||||
|
|
||||||
static const uint8_t supported_model_numbers[] =
|
|
||||||
{
|
|
||||||
KSZ80XX_MODEL_NUMBER_11,
|
|
||||||
KSZ80XX_MODEL_NUMBER_13,
|
|
||||||
KSZ80XX_MODEL_NUMBER_15,
|
|
||||||
KSZ80XX_MODEL_NUMBER_16,
|
|
||||||
KSZ80XX_MODEL_NUMBER_17,
|
|
||||||
KSZ80XX_MODEL_NUMBER_21,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *model_names[] = {
|
|
||||||
"41", // models with model number 0x11
|
|
||||||
"41RLNI", // models with model number 0x13
|
|
||||||
"21/31", // models with model number 0x15
|
|
||||||
"51/81/91", // models with model number 0x16
|
|
||||||
"61", // models with model number 0x17
|
|
||||||
"01", // models with model number 0x21
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *TAG = "ksz80xx";
|
|
||||||
|
|
||||||
static esp_err_t ksz80xx_update_link_duplex_speed(phy_ksz80xx_t * ksz80xx)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = ksz80xx->phy_802_3.eth;
|
|
||||||
uint32_t addr = ksz80xx->phy_802_3.addr;
|
|
||||||
eth_speed_t speed = ETH_SPEED_10M;
|
|
||||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
|
||||||
uint32_t peer_pause_ability = false;
|
|
||||||
anlpar_reg_t anlpar;
|
|
||||||
bmsr_reg_t bmsr;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
|
|
||||||
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
|
||||||
/* check if link status changed */
|
|
||||||
if (ksz80xx->phy_802_3.link_status != link) {
|
|
||||||
/* when link up, read negotiation result */
|
|
||||||
if (link == ETH_LINK_UP) {
|
|
||||||
uint32_t reg_value = 0;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ksz80xx->op_mode_reg, ®_value), err, TAG, "read %#04" PRIx32 " failed", ksz80xx->op_mode_reg);
|
|
||||||
uint8_t op_mode = (reg_value >> ksz80xx->op_mode_offset) & 0x07;
|
|
||||||
switch (op_mode) {
|
|
||||||
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_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed");
|
|
||||||
/* if we're in duplex mode, and peer has the flow control ability */
|
|
||||||
if (duplex == ETH_DUPLEX_FULL && anlpar.symmetric_pause) {
|
|
||||||
peer_pause_ability = 1;
|
|
||||||
} else {
|
|
||||||
peer_pause_ability = 0;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_PAUSE, (void *)peer_pause_ability), err, TAG, "change pause ability failed");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed");
|
|
||||||
ksz80xx->phy_802_3.link_status = link;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ksz80xx_get_link(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz80xx_t *ksz80xx = __containerof(esp_eth_phy_into_phy_802_3(phy), phy_ksz80xx_t, phy_802_3);
|
|
||||||
/* Update 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ksz80xx_init_model(phy_ksz80xx_t *ksz80xx)
|
|
||||||
{
|
|
||||||
// set variables for op_mode access
|
|
||||||
switch (ksz80xx->model_number) {
|
|
||||||
case KSZ80XX_MODEL_NUMBER_21: // models KSZ8001
|
|
||||||
case KSZ80XX_MODEL_NUMBER_11: // models KSZ8041
|
|
||||||
case KSZ80XX_MODEL_NUMBER_13: // models KSZ8041RLNI
|
|
||||||
ksz80xx->op_mode_reg = KSZ80XX_PC2R_REG_ADDR;
|
|
||||||
ksz80xx->op_mode_offset = 2; // bits 4:2
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KSZ80XX_MODEL_NUMBER_15: // models KSZ8021/31
|
|
||||||
case KSZ80XX_MODEL_NUMBER_16: // models KSZ8051/81/91
|
|
||||||
case KSZ80XX_MODEL_NUMBER_17: // models KSZ8061
|
|
||||||
ksz80xx->op_mode_reg = KSZ80XX_PC1R_REG_ADDR;
|
|
||||||
ksz80xx->op_mode_offset = 0; // bits 2:0
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ksz80xx_init(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
|
|
||||||
phy_ksz80xx_t *ksz80xx = __containerof(phy_802_3, phy_ksz80xx_t, phy_802_3);
|
|
||||||
/* Basic PHY init */
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_basic_phy_init(phy_802_3), err, TAG, "failed to init PHY");
|
|
||||||
|
|
||||||
/* Check PHY ID */
|
|
||||||
uint32_t oui;
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_oui(phy_802_3, &oui), err, TAG, "read OUI failed");
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_manufac_info(phy_802_3, &ksz80xx->model_number, NULL), err, TAG, "read manufacturer's info failed");
|
|
||||||
ESP_GOTO_ON_FALSE(oui == KSZ80XX_PHY_OUI, ESP_FAIL, err, TAG, "wrong chip ID");
|
|
||||||
|
|
||||||
const char* supported_model_name = NULL;
|
|
||||||
for (size_t i = 0; i < sizeof(supported_model_numbers); i++) {
|
|
||||||
if (ksz80xx->model_number == supported_model_numbers[i]) {
|
|
||||||
supported_model_name = model_names[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_FALSE(supported_model_name != NULL && ksz80xx_init_model(ksz80xx), ESP_FAIL, err, TAG, "unsupported model number: %#04" PRIx8, ksz80xx->model_number);
|
|
||||||
ESP_LOGI(TAG, "auto detected phy KSZ80%s", supported_model_name);
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ksz80xx_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* Check if loopback is enabled, and if so, can it work with proposed speed or not */
|
|
||||||
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");
|
|
||||||
if (bmcr.en_loopback) {
|
|
||||||
ESP_GOTO_ON_FALSE(speed == ETH_SPEED_100M, ESP_ERR_INVALID_STATE, err, TAG, "Speed must be 100M for loopback operation");
|
|
||||||
}
|
|
||||||
|
|
||||||
return esp_eth_phy_802_3_set_speed(phy_802_3, speed);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_ksz80xx(const eth_phy_config_t *config)
|
|
||||||
{
|
|
||||||
esp_eth_phy_t *ret = NULL;
|
|
||||||
phy_ksz80xx_t *ksz80xx = calloc(1, sizeof(phy_ksz80xx_t));
|
|
||||||
ESP_GOTO_ON_FALSE(ksz80xx, NULL, err, TAG, "calloc ksz80xx failed");
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&ksz80xx->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 ksz80xx
|
|
||||||
ksz80xx->phy_802_3.parent.init = ksz80xx_init;
|
|
||||||
ksz80xx->phy_802_3.parent.get_link = ksz80xx_get_link;
|
|
||||||
ksz80xx->phy_802_3.parent.set_speed = ksz80xx_set_speed;
|
|
||||||
|
|
||||||
return &ksz80xx->phy_802_3.parent;
|
|
||||||
err:
|
|
||||||
if (ksz80xx != NULL) {
|
|
||||||
free(ksz80xx);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
@@ -1,390 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_eth_phy_802_3.h"
|
|
||||||
|
|
||||||
static const char *TAG = "lan87xx";
|
|
||||||
|
|
||||||
/* It was observed that assert nRST signal on LAN87xx needs to be a little longer than the minimum specified in datasheet */
|
|
||||||
#define LAN87XX_PHY_RESET_ASSERTION_TIME_US 150
|
|
||||||
|
|
||||||
/***************List of Supported Models***************/
|
|
||||||
|
|
||||||
// See Microchip's Application Note AN25.3 summarizing differences among below models
|
|
||||||
#define LAN8710A_MODEL_NUM 0x0F
|
|
||||||
#define LAN8720A_MODEL_NUM 0x0F
|
|
||||||
#define LAN8740A_MODEL_NUM 0x11
|
|
||||||
#define LAN8741A_MODEL_NUM 0x12
|
|
||||||
#define LAN8742A_MODEL_NUM 0x13
|
|
||||||
|
|
||||||
static const uint8_t supported_models[] = {
|
|
||||||
LAN8710A_MODEL_NUM,
|
|
||||||
#if (LAN8710A_MODEL_NUM != LAN8720A_MODEL_NUM)
|
|
||||||
LAN8720A_MODEL_NUM,
|
|
||||||
#endif
|
|
||||||
LAN8740A_MODEL_NUM,
|
|
||||||
LAN8741A_MODEL_NUM,
|
|
||||||
LAN8742A_MODEL_NUM
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************Vendor Specific Register***************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief MCSR(Mode Control Status Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved1 : 1; /* Reserved */
|
|
||||||
uint32_t energy_is_on : 1; /* Energy is On */
|
|
||||||
uint32_t reserved2 : 4; /* Reserved */
|
|
||||||
uint32_t en_alternate_interrupt : 1; /* Enable Alternate Interrupt Mode */
|
|
||||||
uint32_t reserved3 : 2; /* Reserved */
|
|
||||||
uint32_t en_far_loopback : 1; /* Enable Far Loopback Mode */
|
|
||||||
uint32_t reserved4 : 3; /* Reserved */
|
|
||||||
uint32_t en_energy_detect_powerdown : 1; /* Enable Energy Detect Power Down */
|
|
||||||
uint32_t reserved5 : 2; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} mcsr_reg_t;
|
|
||||||
#define ETH_PHY_MCSR_REG_ADDR (0x11)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief SMR(Special Modes Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t phy_addr : 5; /* PHY Address */
|
|
||||||
uint32_t mode : 3; /* Transceiver Mode of Operation */
|
|
||||||
uint32_t reserved_1 : 6; /* Reserved */
|
|
||||||
uint32_t mii_mode : 1; /* Mode of the digital interface (only LAN8710A/LAN8740A/LAN8741A) */
|
|
||||||
uint32_t reserved_2 : 1; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} smr_reg_t;
|
|
||||||
#define ETH_PHY_SMR_REG_ADDR (0x12)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Time Domain Reflectometry Patterns/Delay Control Register
|
|
||||||
* Only available in LAN8740A/LAN8742A
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t tdr_pattern_low : 6; /* Data pattern sent in TDR mode for the low cycle */
|
|
||||||
uint32_t tdr_pattern_high : 6; /* Data pattern sent in TDR mode for the high cycle */
|
|
||||||
uint32_t tdr_line_break_counter : 3; /* Increments of 256ms of break time */
|
|
||||||
uint32_t tdr_delay_in : 1; /* Line break counter used */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} tdr_pattern_reg_t;
|
|
||||||
#define EHT_PHY_TDRPD_REG_ADDR (0x18)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Time Domain Reflectometry Control/Status Register)
|
|
||||||
* Only available in LAN8740A/LAN8742A
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t tdr_channel_length : 8; /* TDR channel length */
|
|
||||||
uint32_t tdr_channel_status : 1; /* TDR channel status */
|
|
||||||
uint32_t tdr_channel_cable_type : 2; /* TDR channel cable type */
|
|
||||||
uint32_t reserved : 3; /* Reserved */
|
|
||||||
uint32_t tdr_a2d_filter_enable: 1; /* Analog to Digital Filter Enabled */
|
|
||||||
uint32_t tdr_enable : 1; /* Enable TDR */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} tdr_control_reg_t;
|
|
||||||
#define EHT_PHY_TDRC_REG_ADDR (0x19)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief SECR(Symbol Error Counter Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t symbol_err_count : 16; /* Symbol Error Counter */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} secr_reg_t;
|
|
||||||
#define EHT_PHY_SECR_REG_ADDR (0x1A)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CSIR(Control Status Indications Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved1 : 4; /* Reserved */
|
|
||||||
uint32_t base10_t_polarity : 1; /* Polarity State of 10Base-T */
|
|
||||||
uint32_t reserved2 : 6; /* Reserved */
|
|
||||||
uint32_t dis_sqe : 1; /* Disable SQE test(Heartbeat) */
|
|
||||||
uint32_t reserved3 : 1; /* Reserved */
|
|
||||||
uint32_t select_channel : 1; /* Manual channel select:MDI(0) or MDIX(1) */
|
|
||||||
uint32_t reserved4 : 1; /* Reserved */
|
|
||||||
uint32_t auto_mdix_ctrl : 1; /* Auto-MDIX Control: EN(0) or DE(1) */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} scsir_reg_t;
|
|
||||||
#define ETH_PHY_CSIR_REG_ADDR (0x1B)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Cable Length Register
|
|
||||||
* Only available in LAN8740A/LAN8742A
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved : 12; /* Reserved */
|
|
||||||
uint32_t cable_length : 4; /* Cable length */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} cbln_reg_t;
|
|
||||||
#define EHT_PHY_CBLN_REG_ADDR (0x1C)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief ISR(Interrupt Source Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved1 : 1; /* Reserved */
|
|
||||||
uint32_t auto_nego_page_received : 1; /* Auto-Negotiation Page Received */
|
|
||||||
uint32_t parallel_detect_fault : 1; /* Parallel Detection Fault */
|
|
||||||
uint32_t auto_nego_lp_acknowledge : 1; /* Auto-Negotiation LP Acknowledge */
|
|
||||||
uint32_t link_down : 1; /* Link Down */
|
|
||||||
uint32_t remote_fault_detect : 1; /* Remote Fault Detect */
|
|
||||||
uint32_t auto_nego_complete : 1; /* Auto-Negotiation Complete */
|
|
||||||
uint32_t energy_on_generate : 1; /* ENERGY ON generated */
|
|
||||||
uint32_t wake_on_lan : 1; /* Wake on Lan (WOL) event detected (only LAN8740A/LAN8742A) */
|
|
||||||
uint32_t reserved2 : 7; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} isfr_reg_t;
|
|
||||||
#define ETH_PHY_ISR_REG_ADDR (0x1D)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief IMR(Interrupt Mask Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved1 : 1; /* Reserved */
|
|
||||||
uint32_t auto_nego_page_received : 1; /* Auto-Negotiation Page Received */
|
|
||||||
uint32_t parallel_detect_fault : 1; /* Parallel Detection Fault */
|
|
||||||
uint32_t auto_nego_lp_acknowledge : 1; /* Auto-Negotiation LP Acknowledge */
|
|
||||||
uint32_t link_down : 1; /* Link Down */
|
|
||||||
uint32_t remote_fault_detect : 1; /* Remote Fault Detect */
|
|
||||||
uint32_t auto_nego_complete : 1; /* Auto-Negotiation Complete */
|
|
||||||
uint32_t energy_on_generate : 1; /* ENERGY ON generated */
|
|
||||||
uint32_t wake_on_lan : 1; /* Wake on Lan (WOL) event detected (only LAN8740A/LAN8742A) */
|
|
||||||
uint32_t reserved2 : 7; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} imr_reg_t;
|
|
||||||
#define ETH_PHY_IMR_REG_ADDR (0x1E)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PSCSR(PHY Special Control Status Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved1 : 2; /* Reserved */
|
|
||||||
uint32_t speed_indication : 3; /* Speed Indication */
|
|
||||||
uint32_t reserved2 : 1; /* Reserved */
|
|
||||||
uint32_t enable_4b5b : 1; /* Enable 4B5B encoder (only LAN8740A/LAN8741A) */
|
|
||||||
uint32_t reserved3 : 5; /* Reserved */
|
|
||||||
uint32_t auto_nego_done : 1; /* Auto Negotiation Done */
|
|
||||||
uint32_t reserved4 : 3; /* Reserved */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} pscsr_reg_t;
|
|
||||||
#define ETH_PHY_PSCSR_REG_ADDR (0x1F)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
phy_802_3_t phy_802_3;
|
|
||||||
} phy_lan87xx_t;
|
|
||||||
|
|
||||||
static esp_err_t lan87xx_update_link_duplex_speed(phy_lan87xx_t *lan87xx)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = lan87xx->phy_802_3.eth;
|
|
||||||
uint32_t addr = lan87xx->phy_802_3.addr;
|
|
||||||
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;
|
|
||||||
uint32_t peer_pause_ability = false;
|
|
||||||
anlpar_reg_t anlpar;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
|
|
||||||
/* link status is forced up because LAN87xx reports link down when loopback is enabled and cable is unplugged */
|
|
||||||
eth_link_t link;
|
|
||||||
if(bmcr.en_loopback) {
|
|
||||||
link = ETH_LINK_UP;
|
|
||||||
} else {
|
|
||||||
link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
|
||||||
}
|
|
||||||
/* check if link status changed */
|
|
||||||
if (lan87xx->phy_802_3.link_status != link) {
|
|
||||||
/* when link up, read negotiation result */
|
|
||||||
if (link == ETH_LINK_UP) {
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_PSCSR_REG_ADDR, &(pscsr.val)), err, TAG, "read PSCSR failed");
|
|
||||||
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_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed");
|
|
||||||
/* if we're in duplex mode, and peer has the flow control ability */
|
|
||||||
if (duplex == ETH_DUPLEX_FULL && anlpar.symmetric_pause) {
|
|
||||||
peer_pause_ability = 1;
|
|
||||||
} else {
|
|
||||||
peer_pause_ability = 0;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_PAUSE, (void *)peer_pause_ability), err, TAG, "change pause ability failed");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed");
|
|
||||||
lan87xx->phy_802_3.link_status = link;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t lan87xx_get_link(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_lan87xx_t *lan87xx = __containerof(esp_eth_phy_into_phy_802_3(phy), phy_lan87xx_t, phy_802_3);
|
|
||||||
/* Updata information about link, speed, duplex */
|
|
||||||
ESP_GOTO_ON_ERROR(lan87xx_update_link_duplex_speed(lan87xx), err, TAG, "update link duplex speed failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t lan87xx_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;
|
|
||||||
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, "Autonegotiation can't be enabled while in loopback operation");
|
|
||||||
}
|
|
||||||
return esp_eth_phy_802_3_autonego_ctrl(phy_802_3, cmd, autonego_en_stat);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t lan87xx_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;
|
|
||||||
ESP_GOTO_ON_ERROR(lan87xx_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 autonegotiation 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 lan87xx_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
|
|
||||||
|
|
||||||
/* It was observed that a delay needs to be introduced after setting speed and prior driver's start.
|
|
||||||
Otherwise, the very first read of PHY registers is not valid data (0xFFFF's). */
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_set_speed(phy_802_3, speed), err, TAG, "set speed failed");
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t lan87xx_init(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
|
|
||||||
|
|
||||||
/* Basic PHY init */
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_basic_phy_init(phy_802_3), err, TAG, "failed to init PHY");
|
|
||||||
|
|
||||||
/* Check PHY ID */
|
|
||||||
uint32_t oui;
|
|
||||||
uint8_t model;
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_oui(phy_802_3, &oui), err, TAG, "read OUI failed");
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_manufac_info(phy_802_3, &model, NULL), err, TAG, "read manufacturer's info failed");
|
|
||||||
ESP_GOTO_ON_FALSE(oui == 0x1F0, ESP_FAIL, err, TAG, "wrong chip OUI");
|
|
||||||
|
|
||||||
bool supported_model = false;
|
|
||||||
for (unsigned int i = 0; i < sizeof(supported_models); i++) {
|
|
||||||
if (model == supported_models[i]) {
|
|
||||||
supported_model = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_FALSE(supported_model, ESP_FAIL, err, TAG, "unsupported chip model");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_lan87xx(const eth_phy_config_t *config)
|
|
||||||
{
|
|
||||||
esp_eth_phy_t *ret = NULL;
|
|
||||||
phy_lan87xx_t *lan87xx = calloc(1, sizeof(phy_lan87xx_t));
|
|
||||||
ESP_GOTO_ON_FALSE(lan87xx, NULL, err, TAG, "calloc lan87xx failed");
|
|
||||||
eth_phy_config_t lan87xx_config = *config;
|
|
||||||
// default chip specific configuration
|
|
||||||
if (config->hw_reset_assert_time_us == 0) {
|
|
||||||
lan87xx_config.hw_reset_assert_time_us = LAN87XX_PHY_RESET_ASSERTION_TIME_US;
|
|
||||||
}
|
|
||||||
if (config->post_hw_reset_delay_ms == 0) {
|
|
||||||
lan87xx_config.post_hw_reset_delay_ms = ESP_ETH_NO_POST_HW_RESET_DELAY;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&lan87xx->phy_802_3, &lan87xx_config) == ESP_OK,
|
|
||||||
NULL, err, TAG, "configuration initialization of PHY 802.3 failed");
|
|
||||||
|
|
||||||
// redefine functions which need to be customized for sake of LAN87xx
|
|
||||||
lan87xx->phy_802_3.parent.init = lan87xx_init;
|
|
||||||
lan87xx->phy_802_3.parent.get_link = lan87xx_get_link;
|
|
||||||
lan87xx->phy_802_3.parent.autonego_ctrl = lan87xx_autonego_ctrl;
|
|
||||||
lan87xx->phy_802_3.parent.loopback = lan87xx_loopback;
|
|
||||||
lan87xx->phy_802_3.parent.set_speed = lan87xx_set_speed;
|
|
||||||
|
|
||||||
return &lan87xx->phy_802_3.parent;
|
|
||||||
err:
|
|
||||||
if (lan87xx != NULL) {
|
|
||||||
free(lan87xx);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
@@ -1,200 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_eth_phy_802_3.h"
|
|
||||||
|
|
||||||
#define RTL8201_PHY_RESET_ASSERTION_TIME_US 10000
|
|
||||||
#define RTL8201_PHY_POST_RESET_INIT_TIME_MS 150
|
|
||||||
|
|
||||||
static const char *TAG = "rtl8201";
|
|
||||||
|
|
||||||
/***************Vendor Specific Register***************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PSMR(Power Saving Mode Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint16_t reserved : 15; /* Reserved */
|
|
||||||
uint16_t en_pwr_save : 1; /* Enable power saving mode */
|
|
||||||
};
|
|
||||||
uint16_t val;
|
|
||||||
} psmr_reg_t;
|
|
||||||
#define ETH_PHY_PSMR_REG_ADDR (0x18)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PSR(Page Select Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint16_t page_select : 8; /* Select register page, default is 0 */
|
|
||||||
uint16_t reserved : 8; /* Reserved */
|
|
||||||
};
|
|
||||||
uint16_t val;
|
|
||||||
} psr_reg_t;
|
|
||||||
#define ETH_PHY_PSR_REG_ADDR (0x1F)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
phy_802_3_t phy_802_3;
|
|
||||||
} phy_rtl8201_t;
|
|
||||||
|
|
||||||
static esp_err_t rtl8201_page_select(phy_rtl8201_t *rtl8201, uint32_t page)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = rtl8201->phy_802_3.eth;
|
|
||||||
psr_reg_t psr = {
|
|
||||||
.page_select = page
|
|
||||||
};
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, rtl8201->phy_802_3.addr, ETH_PHY_PSR_REG_ADDR, psr.val), err, TAG, "write PSR failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t rtl8201_update_link_duplex_speed(phy_rtl8201_t *rtl8201)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = rtl8201->phy_802_3.eth;
|
|
||||||
uint32_t addr = rtl8201->phy_802_3.addr;
|
|
||||||
eth_speed_t speed = ETH_SPEED_10M;
|
|
||||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
|
||||||
bmcr_reg_t bmcr;
|
|
||||||
bmsr_reg_t bmsr;
|
|
||||||
uint32_t peer_pause_ability = false;
|
|
||||||
anlpar_reg_t anlpar;
|
|
||||||
ESP_GOTO_ON_ERROR(rtl8201_page_select(rtl8201, 0), err, TAG, "select page 0 failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
|
||||||
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
|
||||||
/* check if link status changed */
|
|
||||||
if (rtl8201->phy_802_3.link_status != link) {
|
|
||||||
/* when link up, read negotiation result */
|
|
||||||
if (link == ETH_LINK_UP) {
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
|
|
||||||
if (bmcr.speed_select) {
|
|
||||||
speed = ETH_SPEED_100M;
|
|
||||||
} else {
|
|
||||||
speed = ETH_SPEED_10M;
|
|
||||||
}
|
|
||||||
if (bmcr.duplex_mode) {
|
|
||||||
duplex = ETH_DUPLEX_FULL;
|
|
||||||
} else {
|
|
||||||
duplex = ETH_DUPLEX_HALF;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed");
|
|
||||||
/* if we're in duplex mode, and peer has the flow control ability */
|
|
||||||
if (duplex == ETH_DUPLEX_FULL && anlpar.symmetric_pause) {
|
|
||||||
peer_pause_ability = 1;
|
|
||||||
} else {
|
|
||||||
peer_pause_ability = 0;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_PAUSE, (void *)peer_pause_ability), err, TAG, "change pause ability failed");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed");
|
|
||||||
rtl8201->phy_802_3.link_status = link;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t rtl8201_get_link(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_rtl8201_t *rtl8201 = __containerof(esp_eth_phy_into_phy_802_3(phy), phy_rtl8201_t, phy_802_3);
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t rtl8201_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;
|
|
||||||
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, "Autonegotiation can't be enabled while in loopback operation");
|
|
||||||
}
|
|
||||||
return esp_eth_phy_802_3_autonego_ctrl(phy_802_3, cmd, autonego_en_stat);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t rtl8201_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;
|
|
||||||
ESP_GOTO_ON_ERROR(rtl8201_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 autonegotiation 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 rtl8201_init(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
|
|
||||||
|
|
||||||
/* Basic PHY init */
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_basic_phy_init(phy_802_3), err, TAG, "failed to init PHY");
|
|
||||||
|
|
||||||
/* Check PHY ID */
|
|
||||||
uint32_t oui;
|
|
||||||
uint8_t model;
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_oui(phy_802_3, &oui), err, TAG, "read OUI failed");
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_manufac_info(phy_802_3, &model, NULL), err, TAG, "read manufacturer's info failed");
|
|
||||||
ESP_GOTO_ON_FALSE(oui == 0x732 && model == 0x1, ESP_FAIL, err, TAG, "wrong chip ID");
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_rtl8201(const eth_phy_config_t *config)
|
|
||||||
{
|
|
||||||
esp_eth_phy_t *ret = NULL;
|
|
||||||
phy_rtl8201_t *rtl8201 = calloc(1, sizeof(phy_rtl8201_t));
|
|
||||||
ESP_GOTO_ON_FALSE(rtl8201, NULL, err, TAG, "calloc rtl8201 failed");
|
|
||||||
eth_phy_config_t rtl8201_config = *config;
|
|
||||||
// default chip specific configuration
|
|
||||||
if (config->hw_reset_assert_time_us == 0) {
|
|
||||||
rtl8201_config.hw_reset_assert_time_us = RTL8201_PHY_RESET_ASSERTION_TIME_US;
|
|
||||||
}
|
|
||||||
if (config->post_hw_reset_delay_ms == 0) {
|
|
||||||
rtl8201_config.post_hw_reset_delay_ms = RTL8201_PHY_POST_RESET_INIT_TIME_MS;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&rtl8201->phy_802_3, &rtl8201_config) == ESP_OK,
|
|
||||||
NULL, err, TAG, "configuration initialization of PHY 802.3 failed");
|
|
||||||
|
|
||||||
// redefine functions which need to be customized for sake of RTL8201
|
|
||||||
rtl8201->phy_802_3.parent.init = rtl8201_init;
|
|
||||||
rtl8201->phy_802_3.parent.get_link = rtl8201_get_link;
|
|
||||||
rtl8201->phy_802_3.parent.autonego_ctrl = rtl8201_autonego_ctrl;
|
|
||||||
rtl8201->phy_802_3.parent.loopback = rtl8201_loopback;
|
|
||||||
|
|
||||||
return &rtl8201->phy_802_3.parent;
|
|
||||||
err:
|
|
||||||
if (rtl8201 != NULL) {
|
|
||||||
free(rtl8201);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
@@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Registers in DM9051
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define DM9051_NCR (0x00) // Network Control Register
|
|
||||||
#define DM9051_NSR (0x01) // Network Status Register
|
|
||||||
#define DM9051_TCR (0x02) // Tx Control Register
|
|
||||||
#define DM9051_TSR1 (0x03) // Tx Status Register I
|
|
||||||
#define DM9051_TSR2 (0x04) // Tx Status Register II
|
|
||||||
#define DM9051_RCR (0x05) // Rx Control Register
|
|
||||||
#define DM9051_RSR (0x06) // Rx Status Register
|
|
||||||
#define DM9051_ROCR (0x07) // Receive Overflow Counter Register
|
|
||||||
#define DM9051_BPTR (0x08) // Back Pressure Threshold Register
|
|
||||||
#define DM9051_FCTR (0x09) // Flow Control Threshold Register
|
|
||||||
#define DM9051_FCR (0x0A) // Rx/Tx Flow Control Register
|
|
||||||
#define DM9051_EPCR (0x0B) // EEPROM & PHY Control Register
|
|
||||||
#define DM9051_EPAR (0x0C) // EEPROM & PHY Address Register
|
|
||||||
#define DM9051_EPDRL (0x0D) // EEPROM & PHY Data Register Low
|
|
||||||
#define DM9051_EPDRH (0x0E) // EEPROM & PHY Data Register High
|
|
||||||
#define DM9051_WCR (0x0F) // Wake Up Control Register
|
|
||||||
#define DM9051_PAR (0x10) // Physical Address Register
|
|
||||||
#define DM9051_MAR (0x16) // Multicast Address Hash Table Register
|
|
||||||
#define DM9051_GPCR (0x1E) // General Purpose Control Register
|
|
||||||
#define DM9051_GPR (0x1F) // General Purpose Register
|
|
||||||
#define DM9051_TRPAL (0x22) // Tx Memory Read Pointer Address Low Byte
|
|
||||||
#define DM9051_TRPAH (0x23) // Tx Memory Read Pointer Address High Byte
|
|
||||||
#define DM9051_RWPAL (0x24) // Rx Memory Read Pointer Address Low Byte
|
|
||||||
#define DM9051_RWPAH (0x25) // Rx Memory Read Pointer Address High Byte
|
|
||||||
#define DM9051_VIDL (0x28) // Vendor ID Low Byte
|
|
||||||
#define DM9051_VIDH (0x29) // Vendor ID High Byte
|
|
||||||
#define DM9051_PIDL (0x2A) // Product ID Low Byte
|
|
||||||
#define DM9051_PIDH (0x2B) // Product ID High Byte
|
|
||||||
#define DM9051_CHIPR (0x2C) // CHIP Revision
|
|
||||||
#define DM9051_TCR2 (0x2D) // Transmit Control Register 2
|
|
||||||
#define DM9051_ATCR (0x30) // Auto-Transmit Control Register
|
|
||||||
#define DM9051_TCSCR (0x31) // Transmit Check Sum Control Register
|
|
||||||
#define DM9051_RCSCSR (0x32) // Receive Check Sum Control Status Register
|
|
||||||
#define DM9051_SBCR (0x38) // SPI Bus Control Register
|
|
||||||
#define DM9051_INTCR (0x39) // INT Pin Control Register
|
|
||||||
#define DM9051_PPCSR (0x3D) // Pause Packet Control Status Register
|
|
||||||
#define DM9051_EEE_IN (0x3E) // IEEE 802.3az Enter Counter Register
|
|
||||||
#define DM9051_EEE_OUT (0x3F) // IEEE 802.3az Leave Counter Register
|
|
||||||
#define DM9051_ALNCR (0x4A) // SPI Byte Align Error Counter Register
|
|
||||||
#define DM9051_RLENCR (0x52) // Rx Packet Length Control Register
|
|
||||||
#define DM9051_BCASTCR (0x53) // RX Broadcast Control Register
|
|
||||||
#define DM9051_INTCKCR (0x54) // INT Pin Clock Output Control Register
|
|
||||||
#define DM9051_MPTRCR (0x55) // Memory Pointer Control Register
|
|
||||||
#define DM9051_MLEDCR (0x57) // More LED Control Register
|
|
||||||
#define DM9051_MEMSCR (0x59) // Memory Control Register
|
|
||||||
#define DM9051_TMEMR (0x5A) // Transmit Memory Size Register
|
|
||||||
#define DM9051_MBSR (0x5D) // Memory BIST Status Register
|
|
||||||
#define DM9051_MRCMDX (0x70) // Memory Data Pre-Fetch Read Command Without Address Increment Register
|
|
||||||
#define DM9051_MRCMDX1 (0x71) // Memory Read Command Without Pre-Fetch and Without Address Increment Register
|
|
||||||
#define DM9051_MRCMD (0x72) // Memory Data Read Command With Address Increment Register
|
|
||||||
#define DM9051_SDR_DLY (0x73) // SPI Data Read Delay Counter Register
|
|
||||||
#define DM9051_MRRL (0x74) // Memory Data Read Address Register Low Byte
|
|
||||||
#define DM9051_MRRH (0x75) // Memory Data Read Address Register High Byte
|
|
||||||
#define DM9051_MWCMDX (0x76) // Memory Data Write Command Without Address Increment Register
|
|
||||||
#define DM9051_MWCMD (0x78) // Memory Data Write Command With Address Increment Register
|
|
||||||
#define DM9051_MWRL (0x7A) // Memory Data Write Address Register Low Byte
|
|
||||||
#define DM9051_MWRH (0x7B) // Memory Data Write Address Register High Byte
|
|
||||||
#define DM9051_TXPLL (0x7C) // TX Packet Length Low Byte Register
|
|
||||||
#define DM9051_TXPLH (0x7D) // TX Packet Length High Byte Register
|
|
||||||
#define DM9051_ISR (0x7E) // Interrupt Status Register
|
|
||||||
#define DM9051_IMR (0x7F) // Interrupt Mask Register
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief status and flag of DM9051 specific registers
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define DM9051_SPI_RD (0) // Burst Read Command
|
|
||||||
#define DM9051_SPI_WR (1) // Burst Write Command
|
|
||||||
|
|
||||||
#define NCR_WAKEEN (1 << 6) // Enable Wakeup Function
|
|
||||||
#define NCR_FDX (1 << 3) // Duplex Mode of the Internal PHY
|
|
||||||
#define NCR_RST (1 << 0) // Software Reset and Auto-Clear after 10us
|
|
||||||
|
|
||||||
#define NSR_SPEED (1 << 7) // Speed of Internal PHY
|
|
||||||
#define NSR_LINKST (1 << 6) // Link Status of Internal PHY
|
|
||||||
#define NSR_WAKEST (1 << 5) // Wakeup Event Status
|
|
||||||
#define NSR_TX2END (1 << 3) // TX Packet Index II Complete Status
|
|
||||||
#define NSR_TX1END (1 << 2) // TX Packet Index I Complete Status
|
|
||||||
#define NSR_RXOV (1 << 1) // RX Memory Overflow Status
|
|
||||||
#define NSR_RXRDY (1 << 0) // RX Packet Ready
|
|
||||||
|
|
||||||
#define TCR_TXREQ (1 << 0) // TX Request. Auto-Clear after Sending Completely
|
|
||||||
|
|
||||||
#define RCR_WTDIS (1 << 6) // Watchdog Timer Disable
|
|
||||||
#define RCR_DIS_LONG (1 << 5) // Discard Long Packet
|
|
||||||
#define RCR_DIS_CRC (1 << 4) // Discard CRC Error Packet
|
|
||||||
#define RCR_ALL_MCAST (1 << 3) // Receive All Multicast
|
|
||||||
#define RCR_RUNT (1 << 2) // Receive Runt Packet
|
|
||||||
#define RCR_PRMSC (1 << 1) // Promiscuous Mode
|
|
||||||
#define RCR_RXEN (1 << 0) // RX Enable
|
|
||||||
|
|
||||||
#define RSR_RF (1 << 7) // Runt Frame
|
|
||||||
#define RSR_MF (1 << 6) // Multicast Frame
|
|
||||||
#define RSR_LCS (1 << 5) // Late Collision Seen
|
|
||||||
#define RSR_RWTO (1 << 4) // Receive Watchdog Time-Out
|
|
||||||
#define RSR_PLE (1 << 3) // Physical Layer Error
|
|
||||||
#define RSR_AE (1 << 2) // Alignment Error
|
|
||||||
#define RSR_CE (1 << 1) // CRC Error
|
|
||||||
#define RSR_FOE (1 << 0) // RX Memory Overflow Error
|
|
||||||
|
|
||||||
#define FCR_FLOW_ENABLE (0x39) // Enable Flow Control
|
|
||||||
|
|
||||||
#define EPCR_REEP (1 << 5) // Reload EEPROM
|
|
||||||
#define EPCR_WEP (1 << 4) // Write EEPROM Enable
|
|
||||||
#define EPCR_EPOS (1 << 3) // EEPROM or PHY Operation Select
|
|
||||||
#define EPCR_ERPRR (1 << 2) // EEPROM Read or PHY Register Read Command
|
|
||||||
#define EPCR_ERPRW (1 << 1) // EEPROM Write or PHY Register Write Command
|
|
||||||
#define EPCR_ERRE (1 << 0) // EEPROM Access Status or PHY Access Status
|
|
||||||
|
|
||||||
#define TCR2_RLCP (1 << 6) // Retry Late Collision Packet
|
|
||||||
|
|
||||||
#define ATCR_AUTO_TX (1 << 7) // Auto-Transmit Control
|
|
||||||
|
|
||||||
#define TCSCR_UDPCSE (1 << 2) // UDP CheckSum Generation
|
|
||||||
#define TCSCR_TCPCSE (1 << 1) // TCP CheckSum Generation
|
|
||||||
#define TCSCR_IPCSE (1 << 0) // IPv4 CheckSum Generation
|
|
||||||
|
|
||||||
#define MPTRCR_RST_TX (1 << 1) // Reset TX Memory Pointer
|
|
||||||
#define MPTRCR_RST_RX (1 << 0) // Reset RX Memory Pointer
|
|
||||||
|
|
||||||
#define ISR_LNKCHGS (1 << 5) // Link Status Change
|
|
||||||
#define ISR_ROO (1 << 3) // Receive Overflow Counter Overflow
|
|
||||||
#define ISR_ROS (1 << 2) // Receive Overflow
|
|
||||||
#define ISR_PT (1 << 1) // Packet Transmitted
|
|
||||||
#define ISR_PR (1 << 0) // Packet Received
|
|
||||||
#define ISR_CLR_STATUS (ISR_LNKCHGS | ISR_ROO | ISR_ROS | ISR_PT | ISR_PR)
|
|
||||||
|
|
||||||
#define IMR_PAR (1 << 7) // Pointer Auto-Return Mode
|
|
||||||
#define IMR_LNKCHGI (1 << 5) // Enable Link Status Change Interrupt
|
|
||||||
#define IMR_ROOI (1 << 3) // Enable Receive Overflow Counter Overflow Interrupt
|
|
||||||
#define IMR_ROI (1 << 2) // Enable Receive Overflow Interrupt
|
|
||||||
#define IMR_PTI (1 << 1) // Enable Packet Transmitted Interrupt
|
|
||||||
#define IMR_PRI (1 << 0) // Enable Packet Received Interrupt
|
|
||||||
#define IMR_ALL (IMR_PAR | IMR_LNKCHGI | IMR_ROOI | IMR_ROI | IMR_PTI | IMR_PRI)
|
|
||||||
|
|
||||||
#define MLEDCR_MOD3 (1 << 7) // New LED mode
|
|
||||||
#define MLEDCR_POL (1 << 2) // Reverse Polarity of LED Type
|
|
||||||
|
|
||||||
// | LED Type | LNKLED (pin 25) | SPDLED (pin 26) | FDXLED (pin 16) |
|
|
||||||
// |-----------------------------------|------------------|-----------------|-----------------|
|
|
||||||
#define MLEDCR_LED_TYPE_00 (0x00 << 0) // | Link | Traffic | Full-Duplex |
|
|
||||||
#define MLEDCR_LED_TYPE_01 (0x01 << 0) // | Link & Traffic | Speed100M | Full-Duplex |
|
|
||||||
#define MLEDCR_LED_TYPE_10 (0x02 << 0) // | Traffic | Speeed100M | Speed10M |
|
|
||||||
#define MLEDCR_LED_TYPE_11 (0x03 << 0) // | Link | Traffic100M | Traffic10M |
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,256 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_eth_phy_802_3.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
|
|
||||||
static const char *TAG = "dm9051.phy";
|
|
||||||
|
|
||||||
/***************Vendor Specific Register***************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief DSCR(DAVICOM Specified Configuration Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved1 : 1; /* Reserved */
|
|
||||||
uint32_t sleep : 1; /* Set 1 to enable PHY into sleep mode */
|
|
||||||
uint32_t mfpsc : 1; /* MII frame preamble suppression control bit */
|
|
||||||
uint32_t smrst : 1; /* Set 1 to reset all state machines of PHY */
|
|
||||||
uint32_t rpdctr_en : 1; /* Set 1 to enable automatic reduced power down */
|
|
||||||
uint32_t reserved2 : 2; /* Reserved */
|
|
||||||
uint32_t flink100 : 1; /* Force Good Link in 100Mbps */
|
|
||||||
uint32_t reserved3 : 2; /* Reserved */
|
|
||||||
uint32_t tx_fx : 1; /* 100BASE-TX or FX Mode Control */
|
|
||||||
uint32_t reserved4 : 1; /* Reserved */
|
|
||||||
uint32_t bp_adpok : 1; /* BYPASS ADPOK */
|
|
||||||
uint32_t bp_align : 1; /* Bypass Symbol Alignment Function */
|
|
||||||
uint32_t bp_scr : 1; /* Bypass Scrambler/Descrambler Function */
|
|
||||||
uint32_t bp_4b5b : 1; /* Bypass 4B5B Encoding and 5B4B Decoding */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} dscr_reg_t;
|
|
||||||
#define ETH_PHY_DSCR_REG_ADDR (0x10)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief DSCSR(DAVICOM Specified Configuration and Status Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t anmb : 4; /* Auto-Negotiation Monitor Bits */
|
|
||||||
uint32_t phy_addr : 5; /* PHY Address */
|
|
||||||
uint32_t reserved : 3; /* Reserved */
|
|
||||||
uint32_t hdx10 : 1; /* 10M Half-Duplex Operation Mode */
|
|
||||||
uint32_t fdx10 : 1; /* 10M Full-Duplex Operation Mode */
|
|
||||||
uint32_t hdx100 : 1; /* 100M Half-Duplex Operation Mode */
|
|
||||||
uint32_t fdx100 : 1; /* 100M Full-Duplex Operation Mode */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} dscsr_reg_t;
|
|
||||||
#define ETH_PHY_DSCSR_REG_ADDR (0x11)
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t pd_value : 1; /* 1 in this bit indicates power down */
|
|
||||||
uint32_t reserved1 : 1; /* Reserved */
|
|
||||||
uint32_t monsel0 : 1; /* Vendor monitor select */
|
|
||||||
uint32_t monsel1 : 1; /* Vendor monitor select */
|
|
||||||
uint32_t mdix_down : 1; /* Set 1 to disable HP Auto-MDIX */
|
|
||||||
uint32_t mdix_fix : 1; /* When mdix_down = 1, MDIX_CNTL value depend on the register value. */
|
|
||||||
uint32_t autoneg_lpbk : 1; /* Set 1 to enable autonegotiation loopback */
|
|
||||||
uint32_t mdxi_cntl : 1; /* Polarity of MDI/MDIX value */
|
|
||||||
uint32_t reserved2 : 1; /* Reserved */
|
|
||||||
uint32_t nway_pwr : 1; /* Set 1 to enable power savings during autonegotiation period */
|
|
||||||
uint32_t tx10m_pwr : 1; /* Set 1 to enable transmit power savings in 10BASE-T mode */
|
|
||||||
uint32_t preamblex : 1; /* When tx10m_pwr is set, the 10BASE-T transmit preamble count is reduced */
|
|
||||||
uint32_t force_fef : 1; /* Vendor test select control */
|
|
||||||
uint32_t force_txsd : 1; /* Set 1 to force SD signal OK in 100M */
|
|
||||||
uint32_t tstse0 : 1; /* Vendor test select control */
|
|
||||||
uint32_t tstse1 : 1; /* Vendor test select control */
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} scr_reg_t;
|
|
||||||
#define ETH_PHY_SCR_REG_ADDR 0x14
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
phy_802_3_t phy_802_3;
|
|
||||||
} phy_dm9051_t;
|
|
||||||
|
|
||||||
static esp_err_t dm9051_update_link_duplex_speed(phy_dm9051_t *dm9051)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = dm9051->phy_802_3.eth;
|
|
||||||
uint32_t addr = dm9051->phy_802_3.addr;
|
|
||||||
eth_speed_t speed = ETH_SPEED_10M;
|
|
||||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
|
||||||
uint32_t peer_pause_ability = false;
|
|
||||||
bmsr_reg_t bmsr;
|
|
||||||
bmcr_reg_t bmcr;
|
|
||||||
anlpar_reg_t anlpar;
|
|
||||||
// BMSR is a latch low register
|
|
||||||
// after power up, the first latched value must be 0, which means down
|
|
||||||
// to speed up power up link speed, double read this register as a workaround
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
|
||||||
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
|
||||||
/* check if link status changed */
|
|
||||||
if (dm9051->phy_802_3.link_status != link) {
|
|
||||||
/* when link up, read negotiation result */
|
|
||||||
if (link == ETH_LINK_UP) {
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
|
|
||||||
speed = bmcr.speed_select == 1 ? ETH_SPEED_100M : ETH_SPEED_10M;
|
|
||||||
duplex = bmcr.duplex_mode == 1 ? ETH_DUPLEX_FULL : ETH_DUPLEX_HALF;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed");
|
|
||||||
/* if we're in duplex mode, and peer has the flow control ability */
|
|
||||||
if (duplex == ETH_DUPLEX_FULL && anlpar.symmetric_pause) {
|
|
||||||
peer_pause_ability = 1;
|
|
||||||
} else {
|
|
||||||
peer_pause_ability = 0;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_PAUSE, (void *)peer_pause_ability), err, TAG, "change pause ability failed");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed");
|
|
||||||
dm9051->phy_802_3.link_status = link;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t dm9051_get_link(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_dm9051_t *dm9051 = __containerof(esp_eth_phy_into_phy_802_3(phy), phy_dm9051_t, phy_802_3);
|
|
||||||
/* Update 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t dm9051_reset(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_dm9051_t *dm9051 = __containerof(esp_eth_phy_into_phy_802_3(phy), phy_dm9051_t, phy_802_3);
|
|
||||||
uint32_t addr = dm9051->phy_802_3.addr;
|
|
||||||
dm9051->phy_802_3.link_status = ETH_LINK_DOWN;
|
|
||||||
esp_eth_mediator_t *eth = dm9051->phy_802_3.eth;
|
|
||||||
dscr_reg_t dscr;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_DSCR_REG_ADDR, &(dscr.val)), err, TAG, "read DSCR failed");
|
|
||||||
dscr.smrst = 1;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, addr, ETH_PHY_DSCR_REG_ADDR, dscr.val), err, TAG, "write DSCR failed");
|
|
||||||
bmcr_reg_t bmcr = {.reset = 1};
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed");
|
|
||||||
/* Wait for reset complete */
|
|
||||||
uint32_t to = 0;
|
|
||||||
for (to = 0; to < dm9051->phy_802_3.reset_timeout_ms / 10; to++) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_DSCR_REG_ADDR, &(dscr.val)), err, TAG, "read DSCR failed");
|
|
||||||
if (!bmcr.reset && !dscr.smrst) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_FALSE(to < dm9051->phy_802_3.reset_timeout_ms / 10, ESP_FAIL, err, TAG, "PHY reset timeout");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t dm9051_init(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
|
|
||||||
|
|
||||||
/* Basic PHY init */
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_basic_phy_init(phy_802_3), err, TAG, "failed to init PHY");
|
|
||||||
|
|
||||||
/* Check PHY ID */
|
|
||||||
uint32_t oui;
|
|
||||||
uint8_t model;
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_oui(phy_802_3, &oui), err, TAG, "read OUI failed");
|
|
||||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_manufac_info(phy_802_3, &model, NULL), err, TAG, "read manufacturer's info failed");
|
|
||||||
ESP_GOTO_ON_FALSE(oui == 0x606E && model == 0x0A, ESP_FAIL, err, TAG, "wrong chip ID");
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t dm9051_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);
|
|
||||||
esp_eth_mediator_t *eth = phy_802_3->eth;
|
|
||||||
/* Set Loopback function */
|
|
||||||
// Enable Auto-negotiation loopback in Specific control register
|
|
||||||
bmcr_reg_t bmcr;
|
|
||||||
scr_reg_t scr;
|
|
||||||
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_read(eth, phy_802_3->addr, ETH_PHY_SCR_REG_ADDR, &(scr.val)), err, TAG, "read SCR failed");
|
|
||||||
if (enable) {
|
|
||||||
bmcr.en_loopback = 1;
|
|
||||||
scr.autoneg_lpbk = 1;
|
|
||||||
} else {
|
|
||||||
bmcr.en_loopback = 0;
|
|
||||||
scr.autoneg_lpbk = 0;
|
|
||||||
}
|
|
||||||
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_SCR_REG_ADDR, scr.val), err, TAG, "write SCR failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t dm9051_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* Check if loopback is enabled, and if so, can it work with proposed speed or not */
|
|
||||||
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");
|
|
||||||
if (bmcr.en_loopback) {
|
|
||||||
ESP_GOTO_ON_FALSE(speed == ETH_SPEED_100M, ESP_ERR_INVALID_STATE, err, TAG, "Speed must be 100M for loopback operation");
|
|
||||||
}
|
|
||||||
|
|
||||||
return esp_eth_phy_802_3_set_speed(phy_802_3, speed);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config)
|
|
||||||
{
|
|
||||||
esp_eth_phy_t *ret = NULL;
|
|
||||||
phy_dm9051_t *dm9051 = calloc(1, sizeof(phy_dm9051_t));
|
|
||||||
ESP_GOTO_ON_FALSE(dm9051, NULL, err, TAG, "calloc dm9051 failed");
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_phy_802_3_obj_config_init(&dm9051->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 dm9051
|
|
||||||
dm9051->phy_802_3.parent.init = dm9051_init;
|
|
||||||
dm9051->phy_802_3.parent.reset = dm9051_reset;
|
|
||||||
dm9051->phy_802_3.parent.get_link = dm9051_get_link;
|
|
||||||
dm9051->phy_802_3.parent.loopback = dm9051_loopback;
|
|
||||||
dm9051->phy_802_3.parent.set_speed = dm9051_set_speed;
|
|
||||||
|
|
||||||
return &dm9051->phy_802_3.parent;
|
|
||||||
err:
|
|
||||||
if (dm9051 != NULL) {
|
|
||||||
free(dm9051);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,392 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2021 Vladimir Chistyakov
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*
|
|
||||||
* SPDX-FileContributor: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*/
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "esp_eth_phy.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_heap_caps.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "esp_private/gpio.h"
|
|
||||||
#include "soc/io_mux_reg.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "ksz8851.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
esp_eth_phy_t parent;
|
|
||||||
esp_eth_mediator_t *eth;
|
|
||||||
int32_t addr;
|
|
||||||
uint32_t reset_timeout_ms;
|
|
||||||
uint32_t autonego_timeout_ms;
|
|
||||||
eth_link_t link_status;
|
|
||||||
int reset_gpio_num;
|
|
||||||
} phy_ksz8851snl_t;
|
|
||||||
|
|
||||||
|
|
||||||
static const char *TAG = "ksz8851snl-phy";
|
|
||||||
|
|
||||||
|
|
||||||
static esp_err_t ksz8851_update_link_duplex_speed(phy_ksz8851snl_t *ksz8851)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
eth_speed_t speed = ETH_SPEED_10M;
|
|
||||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
|
||||||
uint32_t status;
|
|
||||||
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1SR, &status), err, TAG, "P1SR read failed");
|
|
||||||
eth_link_t link = (status & P1SR_LINK_GOOD) ? ETH_LINK_UP : ETH_LINK_DOWN;
|
|
||||||
if (ksz8851->link_status != link) {
|
|
||||||
if (link == ETH_LINK_UP) {
|
|
||||||
if (status & P1SR_OPERATION_SPEED) {
|
|
||||||
speed = ETH_SPEED_100M;
|
|
||||||
ESP_LOGD(TAG, "speed 100M");
|
|
||||||
} else {
|
|
||||||
speed = ETH_SPEED_10M;
|
|
||||||
ESP_LOGD(TAG, "speed 10M");
|
|
||||||
}
|
|
||||||
if (status & P1SR_OPERATION_DUPLEX) {
|
|
||||||
duplex = ETH_DUPLEX_FULL;
|
|
||||||
ESP_LOGD(TAG, "duplex full");
|
|
||||||
} else {
|
|
||||||
duplex = ETH_DUPLEX_HALF;
|
|
||||||
ESP_LOGD(TAG, "duplex half");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed");
|
|
||||||
ksz8851->link_status = link;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_GOTO_ON_FALSE(eth, ESP_ERR_INVALID_ARG, err, TAG, "mediator can not be null");
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
ksz8851->eth = eth;
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_reset(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
ksz8851->link_status = ETH_LINK_DOWN;
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
ESP_LOGD(TAG, "soft reset");
|
|
||||||
// NOTE(v.chistyakov): PHY_RESET bit is self-clearing
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_PHYRR, PHYRR_PHY_RESET), err, TAG, "PHYRR write failed");
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(ksz8851->reset_timeout_ms));
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_reset_hw(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
// NOTE(v.chistyakov): set reset_gpio_num to a negative value can skip hardware reset phy chip
|
|
||||||
if (ksz8851->reset_gpio_num >= 0) {
|
|
||||||
ESP_LOGD(TAG, "hard reset");
|
|
||||||
gpio_func_sel(ksz8851->reset_gpio_num, PIN_FUNC_GPIO);
|
|
||||||
gpio_set_level(ksz8851->reset_gpio_num, 0);
|
|
||||||
gpio_output_enable(ksz8851->reset_gpio_num);
|
|
||||||
esp_rom_delay_us(ksz8851->reset_timeout_ms * 1000);
|
|
||||||
gpio_set_level(ksz8851->reset_gpio_num, 1);
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_pwrctl(esp_eth_phy_t *phy, bool enable)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
if (enable) {
|
|
||||||
ESP_LOGD(TAG, "normal mode");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_PMECR, PMECR_PME_MODE_POWER_SAVING), err, TAG, "PMECR write failed");
|
|
||||||
} else {
|
|
||||||
ESP_LOGD(TAG, "power saving mode");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_PMECR, PMECR_PME_MODE_NORMAL), err, TAG, "PMECR write failed");
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_init(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_LOGD(TAG, "initializing PHY");
|
|
||||||
ESP_GOTO_ON_ERROR(phy_ksz8851_pwrctl(phy, true), err, TAG, "power control failed");
|
|
||||||
ESP_GOTO_ON_ERROR(phy_ksz8851_reset(phy), err, TAG, "reset failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_deinit(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_LOGD(TAG, "deinitializing PHY");
|
|
||||||
ESP_GOTO_ON_ERROR(phy_ksz8851_pwrctl(phy, false), err, TAG, "power control failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @note This function is responsible for restarting a new auto-negotiation,
|
|
||||||
* the result of negotiation won't be reflected to upper layers.
|
|
||||||
* Instead, the negotiation result is fetched by linker timer, see `phy_ksz8851_get_link()`
|
|
||||||
*/
|
|
||||||
static esp_err_t phy_ksz8851_autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
|
|
||||||
uint32_t control;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
|
|
||||||
|
|
||||||
switch (cmd) {
|
|
||||||
case ESP_ETH_PHY_AUTONEGO_RESTART:
|
|
||||||
ESP_GOTO_ON_FALSE(control & P1CR_AUTO_NEGOTIATION_ENABLE, ESP_ERR_INVALID_STATE, err, TAG, "auto negotiation is disabled");
|
|
||||||
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;
|
|
||||||
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 / 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 / 100) && (ksz8851->link_status == ETH_LINK_UP)) {
|
|
||||||
ESP_LOGW(TAG, "auto negotiation timeout");
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control), err, TAG, "P1CR write failed");
|
|
||||||
|
|
||||||
ESP_LOGD(TAG, "negotiation succeeded");
|
|
||||||
break;
|
|
||||||
case ESP_ETH_PHY_AUTONEGO_DIS:
|
|
||||||
if (control & P1CR_AUTO_NEGOTIATION_ENABLE) {
|
|
||||||
control &= ~P1CR_AUTO_NEGOTIATION_ENABLE; /* Disable Auto Negotiation */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control), err, TAG, "P1CR write failed");
|
|
||||||
/* read configuration back */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
|
|
||||||
ESP_GOTO_ON_FALSE((control & P1CR_AUTO_NEGOTIATION_ENABLE) == 0, ESP_FAIL, err, TAG, "disable auto-negotiation failed");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ESP_ETH_PHY_AUTONEGO_EN:
|
|
||||||
if (!(control & P1CR_AUTO_NEGOTIATION_ENABLE)) {
|
|
||||||
control |= P1CR_AUTO_NEGOTIATION_ENABLE; /* Enable Auto Negotiation */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control), err, TAG, "P1CR write failed");
|
|
||||||
/* read configuration back */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
|
|
||||||
ESP_GOTO_ON_FALSE(control & P1CR_AUTO_NEGOTIATION_ENABLE, ESP_FAIL, err, TAG, "disable auto-negotiation failed");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ESP_ETH_PHY_AUTONEGO_G_STAT:
|
|
||||||
/* do nothing autonego_en_stat is set at the function end */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*autonego_en_stat = (control & P1CR_AUTO_NEGOTIATION_ENABLE) != 0;
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_get_link(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
return ksz8851_update_link_duplex_speed(ksz8851);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_set_link(esp_eth_phy_t *phy, eth_link_t link)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
|
|
||||||
if (ksz8851->link_status != link) {
|
|
||||||
ksz8851->link_status = link;
|
|
||||||
// link status changed, inmiedately report to upper layers
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)ksz8851->link_status), err, TAG, "change link failed");
|
|
||||||
}
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_set_addr(esp_eth_phy_t *phy, uint32_t addr)
|
|
||||||
{
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
ksz8851->addr = addr;
|
|
||||||
ESP_LOGD(TAG, "setting PHY addr to %" PRIu32, addr);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_get_addr(esp_eth_phy_t *phy, uint32_t *addr)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_GOTO_ON_FALSE(addr, ESP_ERR_INVALID_ARG, err, TAG, "addr can not be null");
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
*addr = ksz8851->addr;
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_advertise_pause_ability(esp_eth_phy_t *phy, uint32_t ability)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
|
|
||||||
uint32_t anar;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1ANAR, &anar), err, TAG, "P1ANAR read failed");
|
|
||||||
if (ability) {
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1ANAR, anar | P1ANAR_PAUSE), err, TAG, "P1ANAR write failed");
|
|
||||||
ESP_LOGD(TAG, "start advertising pause ability");
|
|
||||||
} else {
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1ANAR, anar & ~P1ANAR_PAUSE), err, TAG, "P1ANAR write failed");
|
|
||||||
ESP_LOGD(TAG, "stop advertising pause ability");
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_loopback(esp_eth_phy_t *phy, bool enable)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
|
|
||||||
uint32_t mbcr;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1MBCR, &mbcr), err, TAG, "P1MBCR read failed");
|
|
||||||
if (enable) {
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1MBCR, mbcr | P1MBCR_LOCAL_LOOPBACK), err, TAG, "P1MBCR write failed");
|
|
||||||
ESP_LOGD(TAG, "set Local (far-end) loopback");
|
|
||||||
} else {
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1MBCR, mbcr & ~P1MBCR_LOCAL_LOOPBACK), err, TAG, "P1MBCR write failed");
|
|
||||||
ESP_LOGD(TAG, "disabled Local (far-end) loopback");
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
|
|
||||||
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
|
||||||
ksz8851->link_status = ETH_LINK_DOWN;
|
|
||||||
|
|
||||||
/* Set speed */
|
|
||||||
uint32_t control;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
|
|
||||||
if (speed == ETH_SPEED_100M) {
|
|
||||||
control |= P1CR_FORCE_SPEED;
|
|
||||||
} else {
|
|
||||||
control &= ~P1CR_FORCE_SPEED;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control), err, TAG, "P1CR write failed");
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
|
||||||
|
|
||||||
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
|
||||||
ksz8851->link_status = ETH_LINK_DOWN;
|
|
||||||
|
|
||||||
/* Set duplex mode */
|
|
||||||
uint32_t control;
|
|
||||||
uint32_t mbcr;
|
|
||||||
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_read(eth, ksz8851->addr, KSZ8851_P1MBCR, &mbcr), err, TAG, "P1MBCR read failed");
|
|
||||||
if (mbcr & P1MBCR_LOCAL_LOOPBACK) {
|
|
||||||
ESP_GOTO_ON_FALSE(duplex == ETH_DUPLEX_FULL, ESP_ERR_INVALID_STATE, err, TAG, "Duplex mode must be FULL for loopback operation");
|
|
||||||
}
|
|
||||||
if (duplex == ETH_DUPLEX_FULL) {
|
|
||||||
control |= P1CR_FORCE_DUPLEX;
|
|
||||||
} else {
|
|
||||||
control &= ~P1CR_FORCE_DUPLEX;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control), err, TAG, "P1CR write failed");
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t phy_ksz8851_del(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "deleting PHY");
|
|
||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
|
||||||
free(ksz8851);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_ksz8851snl(const eth_phy_config_t *config)
|
|
||||||
{
|
|
||||||
esp_eth_phy_t *ret = NULL;
|
|
||||||
ESP_GOTO_ON_FALSE(config, NULL, err, TAG, "config can not be null");
|
|
||||||
phy_ksz8851snl_t *ksz8851 = calloc(1, sizeof(phy_ksz8851snl_t));
|
|
||||||
ESP_GOTO_ON_FALSE(ksz8851, NULL, err, TAG, "no mem for PHY instance");
|
|
||||||
ksz8851->addr = config->phy_addr;
|
|
||||||
ksz8851->reset_timeout_ms = config->reset_timeout_ms;
|
|
||||||
ksz8851->reset_gpio_num = config->reset_gpio_num;
|
|
||||||
ksz8851->link_status = ETH_LINK_DOWN;
|
|
||||||
ksz8851->autonego_timeout_ms = config->autonego_timeout_ms;
|
|
||||||
ksz8851->parent.set_mediator = phy_ksz8851_set_mediator;
|
|
||||||
ksz8851->parent.reset = phy_ksz8851_reset;
|
|
||||||
ksz8851->parent.reset_hw = phy_ksz8851_reset_hw;
|
|
||||||
ksz8851->parent.init = phy_ksz8851_init;
|
|
||||||
ksz8851->parent.deinit = phy_ksz8851_deinit;
|
|
||||||
ksz8851->parent.autonego_ctrl = phy_ksz8851_autonego_ctrl;
|
|
||||||
ksz8851->parent.get_link = phy_ksz8851_get_link;
|
|
||||||
ksz8851->parent.set_link = phy_ksz8851_set_link;
|
|
||||||
ksz8851->parent.pwrctl = phy_ksz8851_pwrctl;
|
|
||||||
ksz8851->parent.set_addr = phy_ksz8851_set_addr;
|
|
||||||
ksz8851->parent.get_addr = phy_ksz8851_get_addr;
|
|
||||||
ksz8851->parent.advertise_pause_ability = phy_ksz8851_advertise_pause_ability;
|
|
||||||
ksz8851->parent.loopback = phy_ksz8851_loopback;
|
|
||||||
ksz8851->parent.set_speed = phy_ksz8851_set_speed;
|
|
||||||
ksz8851->parent.set_duplex = phy_ksz8851_set_duplex;
|
|
||||||
ksz8851->parent.del = phy_ksz8851_del;
|
|
||||||
return &(ksz8851->parent);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
@@ -1,351 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2021 Vladimir Chistyakov
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*
|
|
||||||
* SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KSZ8851_CCR = 0x08, ///< Chip Configuration Register
|
|
||||||
KSZ8851_MARL = 0x10, ///< Host MAC Address Register Low
|
|
||||||
KSZ8851_MARM = 0x12, ///< Host MAC Address Register Middle
|
|
||||||
KSZ8851_MARH = 0x14, ///< Host MAC Address Register High
|
|
||||||
KSZ8851_OBCR = 0x20, ///< On-Chip Bus Control Register
|
|
||||||
KSZ8851_EEPCR = 0x22, ///< EEPROM Control Register
|
|
||||||
KSZ8851_MBIR = 0x24, ///< Memory Built-In Self-Test (BIST) Info Register
|
|
||||||
KSZ8851_GRR = 0x26, ///< Global Reset Register
|
|
||||||
KSZ8851_WFCR = 0x2A, ///< Wakeup Frame Control Register
|
|
||||||
KSZ8851_WF0CRC0 = 0x30, ///< Wakeup Frame 0 CRC0 Register (lower 16 bits)
|
|
||||||
KSZ8851_WF0CRC1 = 0x32, ///< Wakeup Frame 0 CRC1 Register (upper 16 bits)
|
|
||||||
KSZ8851_WF0BM0 = 0x34, ///< Wakeup Frame 0 Byte Mask 0 Register (0-15)
|
|
||||||
KSZ8851_WF0BM1 = 0x36, ///< Wakeup Frame 0 Byte Mask 1 Register (16-31)
|
|
||||||
KSZ8851_WF0BM2 = 0x38, ///< Wakeup Frame 0 Byte Mask 2 Register (32-47)
|
|
||||||
KSZ8851_WF0BM3 = 0x3A, ///< Wakeup Frame 0 Byte Mask 3 Register (48-63)
|
|
||||||
KSZ8851_WF1CRC0 = 0x40, ///< Wakeup Frame 1 CRC0 Register (lower 16 bits)
|
|
||||||
KSZ8851_WF1CRC1 = 0x42, ///< Wakeup Frame 1 CRC1 Register (upper 16 bits)
|
|
||||||
KSZ8851_WF1BM0 = 0x44, ///< Wakeup Frame 1 Byte Mask 0 Register (0-15)
|
|
||||||
KSZ8851_WF1BM1 = 0x46, ///< Wakeup Frame 1 Byte Mask 1 Register (16-31)
|
|
||||||
KSZ8851_WF1BM2 = 0x48, ///< Wakeup Frame 1 Byte Mask 2 Register (32-47)
|
|
||||||
KSZ8851_WF1BM3 = 0x4A, ///< Wakeup Frame 1 Byte Mask 3 Register (48-63)
|
|
||||||
KSZ8851_WF2CRC0 = 0x50, ///< Wakeup Frame 2 CRC0 Register (lower 16 bits)
|
|
||||||
KSZ8851_WF2CRC1 = 0x52, ///< Wakeup Frame 2 CRC1 Register (upper 16 bits)
|
|
||||||
KSZ8851_WF2BM0 = 0x54, ///< Wakeup Frame 2 Byte Mask 0 Register (0-15)
|
|
||||||
KSZ8851_WF2BM1 = 0x56, ///< Wakeup Frame 2 Byte Mask 1 Register (16-31)
|
|
||||||
KSZ8851_WF2BM2 = 0x58, ///< Wakeup Frame 2 Byte Mask 2 Register (32-47)
|
|
||||||
KSZ8851_WF2BM3 = 0x5A, ///< Wakeup Frame 2 Byte Mask 3 Register (48-63)
|
|
||||||
KSZ8851_WF3CRC0 = 0x60, ///< Wakeup Frame 3 CRC0 Register (lower 16 bits)
|
|
||||||
KSZ8851_WF3CRC1 = 0x62, ///< Wakeup Frame 3 CRC1 Register (upper 16 bits)
|
|
||||||
KSZ8851_WF3BM0 = 0x64, ///< Wakeup Frame 3 Byte Mask 0 Register (0-15)
|
|
||||||
KSZ8851_WF3BM1 = 0x66, ///< Wakeup Frame 3 Byte Mask 1 Register (16-31)
|
|
||||||
KSZ8851_WF3BM2 = 0x68, ///< Wakeup Frame 3 Byte Mask 2 Register (32-47)
|
|
||||||
KSZ8851_WF3BM3 = 0x6A, ///< Wakeup Frame 3 Byte Mask 3 Register (48-63)
|
|
||||||
KSZ8851_TXCR = 0x70, ///< Transmit Control Register
|
|
||||||
KSZ8851_TXSR = 0x72, ///< Transmit Status Register
|
|
||||||
KSZ8851_RXCR1 = 0x74, ///< Receive Control Register 1
|
|
||||||
KSZ8851_RXCR2 = 0x76, ///< Receive Control Register 2
|
|
||||||
KSZ8851_TXMIR = 0x78, ///< TXQ Memory Information Register
|
|
||||||
KSZ8851_RXFHSR = 0x7C, ///< Receive Frame Header Status Register
|
|
||||||
KSZ8851_RXFHBCR = 0x7E, ///< Receive Frame Header Byte Count Register
|
|
||||||
KSZ8851_TXQCR = 0x80, ///< TXQ Command Register
|
|
||||||
KSZ8851_RXQCR = 0x82, ///< RXQ Command Register
|
|
||||||
KSZ8851_TXFDPR = 0x84, ///< TX Frame Data Pointer Register
|
|
||||||
KSZ8851_RXFDPR = 0x86, ///< RX Frame Data Pointer Register
|
|
||||||
KSZ8851_RXDTTR = 0x8C, ///< RX Duration Timer Threshold Register
|
|
||||||
KSZ8851_RXDBCTR = 0x8E, ///< RX Data Byte Count Threshold Register
|
|
||||||
KSZ8851_IER = 0x90, ///< Interrupt Enable Register
|
|
||||||
KSZ8851_ISR = 0x92, ///< Interrupt Status Register
|
|
||||||
KSZ8851_RXFCTR = 0x9C, ///< RX Frame Count & Threshold Register
|
|
||||||
KSZ8851_TXNTFSR = 0x9E, ///< TX Next Total Frames Size Register
|
|
||||||
KSZ8851_MAHTR0 = 0xA0, ///< MAC Address Hash Table Register 0
|
|
||||||
KSZ8851_MAHTR1 = 0xA2, ///< MAC Address Hash Table Register 1
|
|
||||||
KSZ8851_MAHTR2 = 0xA4, ///< MAC Address Hash Table Register 2
|
|
||||||
KSZ8851_MAHTR3 = 0xA6, ///< MAC Address Hash Table Register 3
|
|
||||||
KSZ8851_FCLWR = 0xB0, ///< Flow Control Low Watermark Register
|
|
||||||
KSZ8851_FCHWR = 0xB2, ///< Flow Control High Watermark Register
|
|
||||||
KSZ8851_FCOWR = 0xB4, ///< Flow Control Overrun Watermark Register
|
|
||||||
KSZ8851_CIDER = 0xC0, ///< Chip ID and Enable Register
|
|
||||||
KSZ8851_CGCR = 0xC6, ///< Chip Global Control Register
|
|
||||||
KSZ8851_IACR = 0xC8, ///< Indirect Access Control Register
|
|
||||||
KSZ8851_IADLR = 0xD0, ///< Indirect Access Data Low Register
|
|
||||||
KSZ8851_IADHR = 0xD2, ///< Indirect Access Data High Register
|
|
||||||
KSZ8851_PMECR = 0xD4, ///< Power Management Event Control Register
|
|
||||||
KSZ8851_GSWUTR = 0xD6, ///< Go-Sleep & Wake-Up Time Register
|
|
||||||
KSZ8851_PHYRR = 0xD8, ///< PHY Reset Register
|
|
||||||
KSZ8851_P1MBCR = 0xE4, ///< PHY 1 MII-Register Basic Control Register
|
|
||||||
KSZ8851_P1MBSR = 0xE6, ///< PHY 1 MII-Register Basic Status Register
|
|
||||||
KSZ8851_PHY1ILR = 0xE8, ///< PHY 1 PHY ID Low Register
|
|
||||||
KSZ8851_PHY1IHR = 0xEA, ///< PHY 1 PHY ID High Register
|
|
||||||
KSZ8851_P1ANAR = 0xEC, ///< PHY 1 Auto-Negotiation Advertisement Register
|
|
||||||
KSZ8851_P1ANLPR = 0xEE, ///< PHY 1 Auto-Negotiation Link Partner Ability Register
|
|
||||||
KSZ8851_P1SCLMD = 0xF4, ///< Port 1 PHY Special Control/Status, LinkMD
|
|
||||||
KSZ8851_P1CR = 0xF6, ///< Port 1 Control Register
|
|
||||||
KSZ8851_P1SR = 0xF8, ///< Port 1 Status Register
|
|
||||||
KSZ8851_VALID_ADDRESS_MASK = 0xFE, ///< All register addresses are under this mask
|
|
||||||
} ksz8851_registers_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CCR_EEPROM_PRESENCE = 0x0200U, ///< RO EEPROM presence
|
|
||||||
CCR_SPI_BUS_MODE = 0x0100U, ///< RO SPI bus mode
|
|
||||||
CCR_32PIN_CHIP_PACKAGE = 0x0001U, ///< RO 32-Pin Chip Package
|
|
||||||
|
|
||||||
OBCR_OUTPUT_PIN_DRIVE_STRENGTH = 0x0040U, ///< RW Output Pin Drive Strength: 8mA (0) or 16mA (1)
|
|
||||||
OBCR_ONCHIP_BUS_CLOCK_SELECTION = 0X0004U, ///< RW On-Chip Bus Clock Selection: 125MHz (0)
|
|
||||||
OBCR_ONCHIP_BUS_CLOCK_DIVIDE_BY_1 = 0x0000U, ///< RW On-Chip Bus Clock Divider Selection
|
|
||||||
OBCR_ONCHIP_BUS_CLCOK_DIVIDE_BY_2 = 0x0001U, ///< Rw On-Chip Bus Clock Divider Selection
|
|
||||||
OBCR_ONCHIP_BUS_CLCOK_DIVIDE_BY_3 = 0x0002U, ///< RW On-Chip Bus Clock Divider Selection
|
|
||||||
|
|
||||||
EEPCR_EESRWA = 0x0020U, ///< RW EEPROM Software Read (0) or Write (1) Access
|
|
||||||
EEPCR_EESA = 0x0010U, ///< RW EEPROM Software Access
|
|
||||||
EEPCR_EESB = 0x0008U, ///< RO EEPROM Data receive
|
|
||||||
EEPCR_EECB2 = 0x0004U, ///< RW EEPROM Data transmit
|
|
||||||
EEPCR_EECB1 = 0x0002U, ///< RW EEPROM Serial clock
|
|
||||||
EEPCR_EECB0 = 0x0001U, ///< RW EEPROM Chip select
|
|
||||||
|
|
||||||
MBIR_TXMBF = 0x1000U, ///< RO TX Memory BIST Test Finish
|
|
||||||
MBIR_TXMBFA = 0x0800U, ///< RO TX Memory BIST Test Fail
|
|
||||||
MBIR_TXMBFC_SHIFT = 8U, ///< RO TX Memory BIST Test Fail Count Shift
|
|
||||||
MBIR_TXMBFC_MASK = 0x7 << MBIR_TXMBFC_SHIFT, ///< RO TX Memory BIST Test Fail Count Mask
|
|
||||||
MBIR_RXMBF = 0x0010U, ///< RO RX Memory Bist Finish
|
|
||||||
MBIR_RXMBFA = 0x0008U, ///< RO RX Memory Bist Fail
|
|
||||||
MBIR_RXMBFC = 0x7U, ///< RO RX Memory BIST Test Fail Count
|
|
||||||
|
|
||||||
GRR_QMU_MODULE_SOFT_RESET = 0x0002U, ///< RW QMU Module Soft Reset
|
|
||||||
GRR_GLOBAL_SOFT_RESET = 0x0001U, ///< Rw Global Soft Reset
|
|
||||||
|
|
||||||
WFCR_MPRXE = 0x0080U, ///< RW Magic Packet RX Enable
|
|
||||||
WFCR_WF3E = 0x0008U, ///< RW Wake up Frame 3 Enable
|
|
||||||
WFCR_WF2E = 0x0004U, ///< RW Wake up Frame 2 Enable
|
|
||||||
WFCR_WF1E = 0x0002U, ///< RW Wake up Frame 1 Enable
|
|
||||||
WFCR_WF0E = 0x0001U, ///< RW Wake up Frame 0 Enable
|
|
||||||
|
|
||||||
TXCR_TCGICMP = 0x0100U, ///< RW Transmit Checksum Generation for ICMP
|
|
||||||
TXCR_TCGTCP = 0x0040U, ///< RW Transmit Checksum Generation for TCP
|
|
||||||
TXCR_TCGIP = 0x0020U, ///< RW Transmit Checksum Generation for IP
|
|
||||||
TXCR_FTXQ = 0x0010U, ///< RW Flush Transmit Queue
|
|
||||||
TXCR_TXFCE = 0x0008U, ///< RW Transmit Flow Control Enable
|
|
||||||
TXCR_TXPE = 0x0004U, ///< RW Transmit Padding Enable
|
|
||||||
TXCR_TXCE = 0x0002U, ///< RW Transmit CRC Enable
|
|
||||||
TXCR_TXE = 0x0001U, ///< RW Transmit Enable
|
|
||||||
|
|
||||||
TXSR_TXLC = 0x2000U, ///< RO Transmit Late Collision
|
|
||||||
TXSR_TXMC = 0x1000U, ///< RO Transmit Maximum Collision
|
|
||||||
TXSR_TXFID_MASK = 0x003FU, ///< RO Transmit Frame ID Mask
|
|
||||||
|
|
||||||
RXCR1_FRXQ = 0x8000U, ///< RW Flush Receive Queue
|
|
||||||
RXCR1_RXUDPFCC = 0x4000U, ///< RW Receive UDP Frame Checksum Check Enable
|
|
||||||
RXCR1_RXTCPFCC = 0x2000U, ///< RW Receive TCP Frame Checksum Check Enable
|
|
||||||
RXCR1_RXIPFCC = 0x1000U, ///< RW Receive IP Frame Checksum Check Enable
|
|
||||||
RXCR1_RXPAFMA = 0x0800U, ///< RW Receive Physical Address Filtering with MAC Address Enable
|
|
||||||
RXCR1_RXFCE = 0x0400U, ///< RW Receive Flow Control Enable
|
|
||||||
RXCR1_RXEFE = 0x0200U, ///< RW Receive Error Frame Enable
|
|
||||||
RXCR1_RXMAFMA = 0x0100U, ///< RW Receive Multicast Address Filtering with MAC Address Enable
|
|
||||||
RXCR1_RXBE = 0x0080U, ///< RW Receive Broadcast Enable
|
|
||||||
RXCR1_RXME = 0x0040U, ///< RW Receive Multicast Enable
|
|
||||||
RXCR1_RXUE = 0x0020U, ///< RW Receive Unicast Enable
|
|
||||||
RXCR1_RXAE = 0x0010U, ///< RW Receive All Enable
|
|
||||||
RXCR1_RXINVF = 0x0002U, ///< RW Receive Inverse Filtering
|
|
||||||
RXCR1_RXE = 0x0001U, ///< RW Receive Enable
|
|
||||||
|
|
||||||
RXCR2_SRDBL_SHIFT = 5U, ///< WO SPI Receive Data Burst Length: 4/8/16/32/frame (0-4)
|
|
||||||
RXCR2_IUFFP = 0x0010U, ///< RW IPv4/IPv6/UDP Fragment Frame Pass
|
|
||||||
RXCR2_RXIUFCEZ = 0x0008U, ///< RW Receive IPv4/IPv6/UDP Frame Checksum Equal Zero
|
|
||||||
RXCR2_UDPLFE = 0x0004U, ///< RW Lite Frame Enable
|
|
||||||
RXCR2_RXICMPFCC = 0x0002U, ///< RW Receive ICMP Frame Checksum Check Enable
|
|
||||||
RXCR2_RXSAF = 0x0001U, ///< RW Receive Source Address Filtering
|
|
||||||
|
|
||||||
TXMIR_TXMA_MASK = 0x1FFFU, ///< RO Transmit Memory Available Mask
|
|
||||||
|
|
||||||
RXFHSR_RXFV = 0x8000U, ///< RO Receive Frame Valid
|
|
||||||
RXFHSR_RXICMPFCS = 0x2000U, ///< RO Receive ICMP Frame Checksum Status
|
|
||||||
RXFHSR_RXIPFCS = 0x1000U, ///< RO Receive IP Frame Checksum Status
|
|
||||||
RXFHSR_RXTCPFCS = 0x0800U, ///< RO Receive TCP Frame Checksum Status
|
|
||||||
RXFHSR_RXUDPFCS = 0x0400U, ///< RO Receive UDP Frame Checksum Status
|
|
||||||
RXFHSR_RXBF = 0x0080U, ///< RO Receive Broadcast Frame
|
|
||||||
RXFHSR_RXMF = 0x0040U, ///< RO Receive Multicast Frame
|
|
||||||
RXFHSR_RXUF = 0x0020U, ///< RO Receive Unicast Frame
|
|
||||||
RXFHSR_RXMR = 0x0010U, ///< RO Receive MII Error
|
|
||||||
RXFHSR_RXFT = 0x0008U, ///< RO Receive Frame Type
|
|
||||||
RXFHSR_RXFTL = 0x0004U, ///< RO Receive Frame Too Long
|
|
||||||
RXFHSR_RXRF = 0x0002U, ///< RO Receive Runt Frame
|
|
||||||
RXFHSR_RXCE = 0x0001U, ///< RO Receive CRC Error
|
|
||||||
|
|
||||||
RXFHBCR_RXBC_MASK = 0x0FFFU, ///< RO Receive Byte Count Mask
|
|
||||||
|
|
||||||
TXQCR_AETFE = 0x0004U, ///< RW Auto-Enqueue TXQ Frame Enable
|
|
||||||
TXQCR_TXQMAM = 0x0002U, ///< RW TXQ Memory Available Monitor
|
|
||||||
TXQCR_METFE = 0x0001U, ///< RW (SC) Manual Enqueue TXQ Frame Enable
|
|
||||||
|
|
||||||
RXQCR_RXDTTS = 0x1000U, ///< RO RX Duration Timer Threshold Status
|
|
||||||
RXQCR_RXDBCTS = 0x0800U, ///< RO RX Data Byte Count Threshold Status
|
|
||||||
RXQCR_RXFCTS = 0x0400U, ///< RO RX Frame Count Threshold Status
|
|
||||||
RXQCR_RXIPHTOE = 0x0200U, ///< RW RX IP Header Two-Byte Offset Enable
|
|
||||||
RXQCR_RXDTTE = 0x0080U, ///< RW RX Duration Timer Threshold Enable
|
|
||||||
RXQCR_RXDBCTE = 0x0040U, ///< RW RX Data Byte Count Threshold Enable
|
|
||||||
RXQCR_RXFCTE = 0x0020U, ///< RW RX Frame Count Threshold Enable
|
|
||||||
RXQCR_ADRFE = 0x0010U, ///< RW Auto-Dequeue RXQ Frame Enable
|
|
||||||
RXQCR_SDA = 0x0008U, ///< WO Start DMA Access
|
|
||||||
RXQCR_RRXEF = 0x0001U, ///< RW Release RX Error Frame
|
|
||||||
|
|
||||||
TXFDPR_TXFPAI = 0x4000U, ///< RW TX Frame Data Pointer Auto Increment
|
|
||||||
TXFDPR_TXFP_MASK = 0x07FFU, ///< RO TX Frame Pointer Mask
|
|
||||||
|
|
||||||
RXFDPR_RXFPAI = 0x4000U, ///< RW RX Frame Pointer Auto Increment
|
|
||||||
RXFDPR_RXFP_MASK = 0x07FFU, ///< WO RX Frame Pointer Mask
|
|
||||||
|
|
||||||
IER_LCIE = 0x8000U, ///< RW Link Change Interrupt Enable
|
|
||||||
IER_TXIE = 0x4000U, ///< RW Transmit Interrupt Enable
|
|
||||||
IER_RXIE = 0x2000U, ///< RW Receive Interrupt Enable
|
|
||||||
IER_RXOIE = 0x0800U, ///< RW Receive Overrun Interrupt Enable
|
|
||||||
IER_TXPSIE = 0x0200U, ///< RW Transmit Process Stopped Interrupt Enable
|
|
||||||
IER_RXPSIE = 0x0100U, ///< RW Receive Process Stopped Interrupt Enable
|
|
||||||
IER_TXSAIE = 0x0040U, ///< RW Transmit Space Available Interrupt Enable
|
|
||||||
IER_RXWFDIE = 0x0020U, ///< RW Receive Wake-up Frame Detect Interrupt Enable
|
|
||||||
IER_RXMPDIE = 0x0010U, ///< RW Receive Magic Packet Detect Interrupt Enable
|
|
||||||
IER_LDIE = 0x0008U, ///< RW Linkup Detect Interrupt Enable
|
|
||||||
IER_EDIE = 0x0004U, ///< RW Energy Detect Interrupt Enable
|
|
||||||
IER_SPIBEIE = 0x0002U, ///< RW SPI Bus Error Interrupt Enable
|
|
||||||
IER_DEDIE = 0x0001U, ///< RW Delay Energy Detect Interrupt Enable
|
|
||||||
|
|
||||||
ISR_LCIS = 0x8000U, ///< RO (W1C) Link Change Interrupt Status
|
|
||||||
ISR_TXIS = 0x4000U, ///< RO (W1C) Transmit Interrupt Status
|
|
||||||
ISR_RXIS = 0x2000U, ///< RO (W1C) Receive Interrupt Status
|
|
||||||
ISR_RXOIS = 0x0800U, ///< RO (W1C) Receive Overrun Interrupt Status
|
|
||||||
ISR_TXPSIS = 0x0200U, ///< RO (W1C) Transmit Process Stopped Interrupt Status
|
|
||||||
ISR_RXPSIS = 0x0100U, ///< RO (W1C) Receive Process Stopped Interrupt Status
|
|
||||||
ISR_TXSAIS = 0x0040U, ///< RO (W1C) Transmit Space Available Interrupt Status
|
|
||||||
ISR_RXWFDIS = 0x0020U, ///< RO (W1C) Receive Wakeup Frame Detect Interrupt Status
|
|
||||||
ISR_RXMPDIS = 0x0010U, ///< RO (W1C) Receive Magic Packet Detect Interrupt Status
|
|
||||||
ISR_LDIS = 0x0008U, ///< RO (W1C) Linkup Detect Interrupt Status
|
|
||||||
ISR_EDIS = 0x0004U, ///< RO (W1C) Energy Detect Interrupt Status
|
|
||||||
ISR_SPIBEIS = 0x0002U, ///< RO (W1C) SPI Bus Error Interrupt Status
|
|
||||||
ISR_ALL = 0xFFFFU, ///< WO Clear register value
|
|
||||||
|
|
||||||
RXFCTR_RXFC_SHIFT = 8U, ///< RO RX Frame Count Shift
|
|
||||||
RXFCTR_RXFC_MASK = 0xFF << RXFCTR_RXFC_SHIFT, ///< RO RX Frame Count Mask
|
|
||||||
RXFCTR_RXFCT_MASK = 0xFFU, ///< RW Receive Frame Count Threshold
|
|
||||||
|
|
||||||
FCLWR_MASK = 0x0FFFU, ///< RW Flow Control Low Watermark Configuration Mask
|
|
||||||
FCHWR_MASK = 0x0FFFU, ///< RW Flow Control High Watermark Configuration Mask
|
|
||||||
FCOWR_MASK = 0x0FFFU, ///< RW Flow Control Overrun Watermark Configuration Mask
|
|
||||||
|
|
||||||
CIDER_KSZ8851SNL_FAMILY_ID = 0x88U, ///< KSZ8851SNL Family ID
|
|
||||||
CIDER_KSZ8851SNL_CHIP_ID = 0x7U, ///< KSZ8851SNL Chip ID
|
|
||||||
CIDER_FAMILY_ID_SHIFT = 8U, ///< RO Family ID Shift
|
|
||||||
CIDER_FAMILY_ID_MASK = 0xFF << CIDER_FAMILY_ID_SHIFT, ///< RO Family ID Mask
|
|
||||||
CIDER_CHIP_ID_SHIFT = 4U, ///< RO Chip ID Shift
|
|
||||||
CIDER_CHIP_ID_MASK = 0xF << CIDER_CHIP_ID_SHIFT, ///< RO Chip ID Mask
|
|
||||||
CIDER_REVISION_ID_SHIFT = 1U, ///< RO Revision ID Shift
|
|
||||||
CIDER_REVISION_ID_MASK = 0x7 << CIDER_REVISION_ID_SHIFT, ///< RO Revision ID Mask
|
|
||||||
|
|
||||||
CGCR_LEDSEL0 = 0x0200U, ///< RW PHY LED Mode: 0 - 100BT + LINK/ACTU, 1 - ACT + LINK
|
|
||||||
|
|
||||||
IACR_READ_ENABLE = 0x1000U, ///< RW Read Enable
|
|
||||||
IACR_MIB_COUNTER_SELECT = 0x0C00U, ///< RW Table Select
|
|
||||||
IACR_INDIRECT_ADDRESS_MASK = 0x001FU, ///< RW Indirect Address Mask
|
|
||||||
|
|
||||||
PMECR_PME_DELAY_ENABLE = 0x4000U, ///< RW PME Delay Enable
|
|
||||||
PMECR_PME_OUTPUT_POLARITY = 0x1000U, ///< RW PME Output Polarity
|
|
||||||
PMECR_WUP_FRAME_EN = 0x0800U, ///< RW Wake-on-LAN to PME Output Enable receive wake-up frame
|
|
||||||
PMECR_MAGIC_PACKET = 0x0400U, ///< RW Wake-on-LAN to PME Output Enable receive magic packet
|
|
||||||
PMECR_LINK_CHANGE_TO_UP = 0x0200U, ///< RW Wake-on-LAN to PME Output Enable link change to up
|
|
||||||
PMECR_SIGNAL_ENERGY_DETECTED = 0x0100U, ///< RW Wake-on-LAN to PME Output Enable energy detected
|
|
||||||
PMECR_AUTO_WAKEUP_ENABLE = 0x0080U, ///< RW Auto Wake-Up Enable
|
|
||||||
PMECR_WAKEUP_TO_NORMAL = 0x0040U, ///< RW Wake-Up to Normal Operation Mode
|
|
||||||
PMECR_WAKEUP_FRAME_EVENT = 0x0020U, ///< RO (W1C) Wake-Up Event Indication wakeup frame event detected
|
|
||||||
PMECR_WAKEUP_MAGIC_PACKET = 0x0010U, ///< RO (W1C) Wake-Up Event Indication magic packet event detected
|
|
||||||
PMECR_WAKEUP_LINK = 0x0008U, ///< RO (W1C) Wake-Up Event Indication link up event detected
|
|
||||||
PMECR_WAKEUP_ENERGY = 0x0004U, ///< RO (W1C) Wake-Up Event Indication energy event detected
|
|
||||||
PMECR_PME_MODE_MASK = 0x0003U, ///< RW Power Management Mode Mask
|
|
||||||
PMECR_PME_MODE_NORMAL = 0x0000U, ///< RW Normal Operation Mode
|
|
||||||
PMECR_PME_MODE_ENERGY_DETECT = 0x0001U, ///< RW Energy Detect Mode
|
|
||||||
PMECR_PME_MODE_SOFT_POWER_DOWN = 0x0002U, ///< RW Soft Power Down Mode
|
|
||||||
PMECR_PME_MODE_POWER_SAVING = 0x0003U, ///< RW Power Saving Mode
|
|
||||||
|
|
||||||
GSWUTR_WAKE_UP_TIME_SHIFT = 8U, ///< RW Wake-up Time Shift
|
|
||||||
GSWUTR_WAKE_UP_TIME_MASK = 0xFF << GSWUTR_WAKE_UP_TIME_SHIFT, ///< RW Wake-up Time Mask
|
|
||||||
GSWUTR_GO_SLEEP_TIME_MASK = 0x0003U, ///< RW Go-sleep Time Mask
|
|
||||||
|
|
||||||
PHYRR_PHY_RESET = 0x0001U, ///< WO (SC) PHY Reset Bit
|
|
||||||
|
|
||||||
P1MBCR_LOCAL_LOOPBACK = 0x4000U, ///< RW Local (far-end) loopback (llb)
|
|
||||||
P1MBCR_FORCE100 = 0x2000U, ///< RW Force 100
|
|
||||||
P1MBCR_AN_ENABLE = 0x1000U, ///< RW AN Enable
|
|
||||||
P1MBCR_RESTART_AN = 0x0200U, ///< RW Restart AN
|
|
||||||
P1MBCR_FORCE_FULL_DUPLEX = 0x0100U, ///< RW Force Full-Duplex
|
|
||||||
P1MBCR_HP_MDIX = 0x0020U, ///< RW HP Auto MDI-X mode
|
|
||||||
P1MBCR_FORCE_MDIX = 0x0010U, ///< RWForce MDI-X
|
|
||||||
P1MBCR_DISABLE_MDIX = 0x0008U, ///< RW Disable MDI-X
|
|
||||||
P1MBCR_DISABLE_TRANSMIT = 0x0002U, ///< RW Disable Transmit
|
|
||||||
P1MBCR_DISABLE_LED = 0x0001U, ///< RW Disable LED
|
|
||||||
|
|
||||||
P1MBSR_T4_CAPABLE = 0x8000U, ///< RO T4 Capable
|
|
||||||
P1MBSR_100_FULL_CAPABLE = 0x4000U, ///< RO 100 Full Capable
|
|
||||||
P1MBSR_100_HALF_CAPABLE = 0x2000U, ///< RO 100 Half Capable
|
|
||||||
P1MBSR_10_FULL_CAPABLE = 0x1000U, ///< RO 10 Full Capable
|
|
||||||
P1MBSR_10_HALF_CAPABLE = 0x0800U, ///< RO 10 Half Capable
|
|
||||||
P1MBSR_PREAMBLE_SUPPRESSED = 0x0040U, ///< RO Preamble suppressed (not supported)
|
|
||||||
P1MBSR_AN_COMPLETE = 0x0020U, ///< RO AN Complete
|
|
||||||
P1MBSR_AN_CAPABLE = 0x0008U, ///< RO AN Capable
|
|
||||||
P1MBSR_LINK_STATUS = 0x0004U, ///< RO Link Status
|
|
||||||
P1MBSR_JABBER_TEST = 0x0002U, ///< RO Jabber test (not supported)
|
|
||||||
P1MBSR_EXTENDED_CAPABLE = 0x0001U, ///< RO Extended Capable
|
|
||||||
|
|
||||||
P1ANAR_NEXT_PAGE = 0x8000U, ///< RO Next page (not supported)
|
|
||||||
P1ANAR_REMOTE_FAULT = 0x2000U, ///< RO Remote fault (not supported)
|
|
||||||
P1ANAR_PAUSE = 0x0400U, ///< RW Pause (flow control capability)
|
|
||||||
P1ANAR_ADV_100_FULL = 0x0100U, ///< RW Adv 100 Full
|
|
||||||
P1ANAR_ADV_100_HALF = 0x0080U, ///< RW Adv 100 Half
|
|
||||||
P1ANAR_ADV_10_FULL = 0x0040U, ///< RW Adv 10 Full
|
|
||||||
P1ANAR_ADV_10_HALF = 0x0020U, ///< RW Adv 10 Half
|
|
||||||
|
|
||||||
P1ANLPR_NEXT_PAGE = 0x8000U, ///< RO Next page (not supported)
|
|
||||||
P1ANLPR_LP_ACK = 0x4000U, ///< RO LP ACK (not supported)
|
|
||||||
P1ANLPR_REMOTE_FAULT = 0x2000U, ///< RO Remote fault (not supported)
|
|
||||||
P1ANLPR_PAUSE = 0x0400U, ///< RO Pause
|
|
||||||
P1ANLPR_ADV_100_FULL = 0x0100U, ///< RO Adv 100 Full
|
|
||||||
P1ANLPR_ADV_100_HALF = 0x0080U, ///< RO Adv 100 Half
|
|
||||||
P1ANLPR_ADV_10_FULL = 0x0040U, ///< RO Adv 10 Full
|
|
||||||
P1ANLPR_ADV_10_HALF = 0x0020U, ///< RO Adv 10 Half
|
|
||||||
|
|
||||||
P1SCLMD_VCT_RESULT_SHIFT = 13U, ///< RO VCT result Shift
|
|
||||||
P1SCLMD_VCT_RESULT_MASK = 0x3 << P1SCLMD_VCT_RESULT_SHIFT, ///< RO VCT result Mask
|
|
||||||
P1SCLMD_VCT_RESULT_NORMAL = 0x0U, ///< RO VCT result normal condition
|
|
||||||
P1SCLMD_VCT_RESULT_OPEN = 0x1U, ///< RO VCT result open cable condition
|
|
||||||
P1SCLMD_VCT_RESULT_SHORT = 0x2U, ///< RO VCT result short cable condition
|
|
||||||
P1SCLMD_VCT_RESULT_TEST_FAILED = 0x3U, ///< RO VCT result test failed
|
|
||||||
P1SCLMD_VCT_ENABLE = 0x1000U, ///< RW (SC) VCT Enable
|
|
||||||
P1SCLMD_FORCE_LINK = 0x0800U, ///< RW Force link
|
|
||||||
P1SCLMD_REMOTE_LOOPBACK = 0x0200U, ///< RW Remote (Near-end) loopback (rlb)
|
|
||||||
P1SCLMD_VCT_FAULT_COUNT_MASK = 0x1FU, ///< RO Distance to the fault * 0.4m
|
|
||||||
|
|
||||||
P1CR_LED_OFF = 0x8000U, ///< RW Turn off all of the port 1 LEDs
|
|
||||||
P1CR_TXIDS = 0x4000U, ///< RW Disable the port’s transmitter.
|
|
||||||
P1CR_RESTART_AN = 0x2000U, ///< RW Restart AN
|
|
||||||
P1CR_DISABLE_AUTO_MDI_MDIX = 0x0400U, ///< RW Disable auto MDI/MDI-X
|
|
||||||
P1CR_FORCE_MDIX = 0x0200U, ///< RW Force MDI-X
|
|
||||||
P1CR_AUTO_NEGOTIATION_ENABLE = 0x0080U, ///< RW Auto Negotiation Enable
|
|
||||||
P1CR_FORCE_SPEED = 0x0040U, ///< RW Force Speed 100
|
|
||||||
P1CR_FORCE_DUPLEX = 0x0020U, ///< RW Force Full Duplex
|
|
||||||
P1CR_ADVERTISED_FLOW_CONTROL_CAPABILITY = 0x0010U, ///< RW Advertise flow control capability
|
|
||||||
P1CR_ADVERTISED_100BT_FULL_DUPLEX_CAPABILITY = 0x0008U, ///< RW Advertise 100BT full-duplex capability
|
|
||||||
P1CR_ADVERTISED_100BT_HALF_DUPLEX_CAPABILITY = 0x0004U, ///< RW Advertise 100BT half-duplex capability
|
|
||||||
P1CR_ADVERTISED_10BT_FULL_DUPLEX_CAPABILITY = 0x0002U, ///< RW Advertise 10BT full-duplex capability
|
|
||||||
P1CR_ADVERTISED_10BT_HALF_DUPLEX_CAPABILITY = 0x0001U, ///< RW Advertise 10BT half-duplex capability
|
|
||||||
|
|
||||||
P1SR_HP_MDIX = 0x8000U, ///< RW HP Auto MDI-X mode
|
|
||||||
P1SR_POLARITY_REVERSE = 0x2000U, ///< RO Polarity Reverse
|
|
||||||
P1SR_OPERATION_SPEED = 0x0400U, ///< RO Operation Speed 100
|
|
||||||
P1SR_OPERATION_DUPLEX = 0x0200U, ///< RO Operation Duplex Full
|
|
||||||
P1SR_MDIX_STATUS = 0x0080U, ///< RO MDI status
|
|
||||||
P1SR_AN_DONE = 0x0040U, ///< RO AN Done
|
|
||||||
P1SR_LINK_GOOD = 0x0020U, ///< RO Link Good
|
|
||||||
P1SR_PARTNER_FLOW_CONTROL_CAPABILITY = 0x0010U, ///< RO Partner flow control capability
|
|
||||||
P1SR_PARTNER_100BT_FULL_DUPLEX_CAPABILITY = 0x0008U, ///< RO Partner 100BT full-duplex capability
|
|
||||||
P1SR_PARTNER_100BT_HALF_DUPLEX_CAPABILITY = 0x0004U, ///< RO Partner 100BT half-duplex capability
|
|
||||||
P1SR_PARTNER_10BT_FULL_DUPLEX_CAPABILITY = 0x0002U, ///< RO Partner 10BT full-duplex capability
|
|
||||||
P1SR_PARTNER_10BT_HALF_DUPLEX_CAPABILITY = 0x0001U, ///< RO Partner 10BT half-duplex capability
|
|
||||||
} ksz8851_register_bits_t;
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,393 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include "esp_eth_phy.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "esp_private/gpio.h"
|
|
||||||
#include "soc/io_mux_reg.h"
|
|
||||||
#include "esp_rom_sys.h"
|
|
||||||
#include "w5500.h"
|
|
||||||
|
|
||||||
#define W5500_WAIT_FOR_RESET_MS (10) // wait for W5500 internal PLL to be Locked after reset assert
|
|
||||||
|
|
||||||
static const char *TAG = "w5500.phy";
|
|
||||||
|
|
||||||
/***************Vendor Specific Register***************/
|
|
||||||
/**
|
|
||||||
* @brief PHYCFGR(PHY Configuration Register)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint8_t link: 1; /*!< Link status */
|
|
||||||
uint8_t speed: 1; /*!< Speed status */
|
|
||||||
uint8_t duplex: 1; /*!< Duplex status */
|
|
||||||
uint8_t opmode: 3; /*!< Operation mode */
|
|
||||||
uint8_t opsel: 1; /*!< Operation select */
|
|
||||||
uint8_t reset: 1; /*!< Reset, when this bit is '0', PHY will get reset */
|
|
||||||
};
|
|
||||||
uint8_t val;
|
|
||||||
} phycfg_reg_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
W5500_OP_MODE_10BT_HALF_AUTO_DIS,
|
|
||||||
W5500_OP_MODE_10BT_FULL_AUTO_DIS,
|
|
||||||
W5500_OP_MODE_100BT_HALF_AUTO_DIS,
|
|
||||||
W5500_OP_MODE_100BT_FULL_AUTO_DIS,
|
|
||||||
W5500_OP_MODE_100BT_HALF_AUTO_EN,
|
|
||||||
W5500_OP_MODE_NOT_USED,
|
|
||||||
W5500_OP_MODE_PWR_DOWN,
|
|
||||||
W5500_OP_MODE_ALL_CAPABLE,
|
|
||||||
} phy_w5500_op_mode_e;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
esp_eth_phy_t parent;
|
|
||||||
esp_eth_mediator_t *eth;
|
|
||||||
int addr;
|
|
||||||
uint32_t reset_timeout_ms;
|
|
||||||
uint32_t autonego_timeout_ms;
|
|
||||||
eth_link_t link_status;
|
|
||||||
int reset_gpio_num;
|
|
||||||
} phy_w5500_t;
|
|
||||||
|
|
||||||
static esp_err_t w5500_update_link_duplex_speed(phy_w5500_t *w5500)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_mediator_t *eth = w5500->eth;
|
|
||||||
eth_speed_t speed = ETH_SPEED_10M;
|
|
||||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
|
||||||
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");
|
|
||||||
eth_link_t link = phycfg.link ? ETH_LINK_UP : ETH_LINK_DOWN;
|
|
||||||
/* check if link status changed */
|
|
||||||
if (w5500->link_status != link) {
|
|
||||||
/* when link up, read negotiation result */
|
|
||||||
if (link == ETH_LINK_UP) {
|
|
||||||
if (phycfg.speed) {
|
|
||||||
speed = ETH_SPEED_100M;
|
|
||||||
} else {
|
|
||||||
speed = ETH_SPEED_10M;
|
|
||||||
}
|
|
||||||
if (phycfg.duplex) {
|
|
||||||
duplex = ETH_DUPLEX_FULL;
|
|
||||||
} else {
|
|
||||||
duplex = ETH_DUPLEX_HALF;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed), err, TAG, "change speed failed");
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex), err, TAG, "change duplex failed");
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link), err, TAG, "change link failed");
|
|
||||||
w5500->link_status = link;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_GOTO_ON_FALSE(eth, ESP_ERR_INVALID_ARG, err, TAG, "mediator can't be null");
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
w5500->eth = eth;
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_get_link(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
/* Updata 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_set_link(esp_eth_phy_t *phy, eth_link_t link)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = w5500->eth;
|
|
||||||
|
|
||||||
if (w5500->link_status != link) {
|
|
||||||
w5500->link_status = link;
|
|
||||||
// link status changed, inmiedately report to upper layers
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)w5500->link_status), err, TAG, "change link failed");
|
|
||||||
}
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_reset(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
w5500->link_status = ETH_LINK_DOWN;
|
|
||||||
esp_eth_mediator_t *eth = w5500->eth;
|
|
||||||
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.reset = 0; // set to '0' will reset internal PHY
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(W5500_WAIT_FOR_RESET_MS));
|
|
||||||
phycfg.reset = 1; // set to '1' after reset
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_reset_hw(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
// set reset_gpio_num to a negative value can skip hardware reset phy chip
|
|
||||||
if (w5500->reset_gpio_num >= 0) {
|
|
||||||
gpio_func_sel(w5500->reset_gpio_num, PIN_FUNC_GPIO);
|
|
||||||
gpio_set_level(w5500->reset_gpio_num, 0);
|
|
||||||
gpio_output_enable(w5500->reset_gpio_num);
|
|
||||||
esp_rom_delay_us(100); // insert min input assert time
|
|
||||||
gpio_set_level(w5500->reset_gpio_num, 1);
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = w5500->eth;
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
switch (cmd) {
|
|
||||||
case ESP_ETH_PHY_AUTONEGO_RESTART:
|
|
||||||
ESP_GOTO_ON_FALSE(phycfg.opmode == W5500_OP_MODE_ALL_CAPABLE || phycfg.opmode == W5500_OP_MODE_100BT_HALF_AUTO_EN,
|
|
||||||
ESP_ERR_INVALID_STATE, err, TAG, "auto negotiation is disabled");
|
|
||||||
/* in case any link status has changed, let's assume we're in link down status */
|
|
||||||
w5500->link_status = ETH_LINK_DOWN;
|
|
||||||
|
|
||||||
phycfg.opsel = 1; // Configure PHY Operation Mode based on registry setting
|
|
||||||
phycfg.reset = 0; // PHY needs to be reset after configuring opsel and opmode
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(W5500_WAIT_FOR_RESET_MS));
|
|
||||||
phycfg.reset = 1; // reset flag needs to be put back to 1
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
|
|
||||||
*autonego_en_stat = phycfg.opmode == W5500_OP_MODE_ALL_CAPABLE || phycfg.opmode == W5500_OP_MODE_100BT_HALF_AUTO_EN;
|
|
||||||
break;
|
|
||||||
case ESP_ETH_PHY_AUTONEGO_DIS:
|
|
||||||
/* W5500 autonegotiation cannot be separately disabled, only specific speed/duplex mode needs to be configured. Hence set the
|
|
||||||
last used configuration */
|
|
||||||
if (phycfg.duplex) { // Full duplex
|
|
||||||
if (phycfg.speed) { // 100 Mbps speed
|
|
||||||
phycfg.opmode = W5500_OP_MODE_100BT_FULL_AUTO_DIS;
|
|
||||||
} else {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_10BT_FULL_AUTO_DIS;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (phycfg.speed) { // 100 Mbps speed
|
|
||||||
phycfg.opmode = W5500_OP_MODE_100BT_HALF_AUTO_DIS;
|
|
||||||
} else {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_10BT_HALF_AUTO_DIS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
phycfg.opsel = 1;
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
*autonego_en_stat = false;
|
|
||||||
break;
|
|
||||||
case ESP_ETH_PHY_AUTONEGO_EN:
|
|
||||||
phycfg.opsel = 1; // PHY working mode configured by register
|
|
||||||
phycfg.opmode = W5500_OP_MODE_ALL_CAPABLE; // 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");
|
|
||||||
*autonego_en_stat = true;
|
|
||||||
break;
|
|
||||||
case ESP_ETH_PHY_AUTONEGO_G_STAT:
|
|
||||||
*autonego_en_stat = phycfg.opmode == W5500_OP_MODE_ALL_CAPABLE || phycfg.opmode == W5500_OP_MODE_100BT_HALF_AUTO_EN;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_pwrctl(esp_eth_phy_t *phy, bool enable)
|
|
||||||
{
|
|
||||||
// power control is not supported for W5500 internal PHY
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_set_addr(esp_eth_phy_t *phy, uint32_t addr)
|
|
||||||
{
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
w5500->addr = addr;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_get_addr(esp_eth_phy_t *phy, uint32_t *addr)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_GOTO_ON_FALSE(addr, ESP_ERR_INVALID_ARG, err, TAG, "addr can't be null");
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
*addr = w5500->addr;
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_del(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
free(w5500);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_advertise_pause_ability(esp_eth_phy_t *phy, uint32_t ability)
|
|
||||||
{
|
|
||||||
// pause ability advertisement is not supported for W5500 internal PHY
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_loopback(esp_eth_phy_t *phy, bool enable)
|
|
||||||
{
|
|
||||||
// Loopback is not supported for W5500 internal PHY
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = w5500->eth;
|
|
||||||
|
|
||||||
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
|
||||||
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");
|
|
||||||
if (phycfg.duplex) { // Full duplex
|
|
||||||
if (speed == ETH_SPEED_100M) {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_100BT_FULL_AUTO_DIS;
|
|
||||||
} else {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_10BT_FULL_AUTO_DIS;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (speed == ETH_SPEED_100M) {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_100BT_HALF_AUTO_DIS;
|
|
||||||
} else {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_10BT_HALF_AUTO_DIS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
phycfg.opsel = 1; // PHY working mode configured by register
|
|
||||||
phycfg.reset = 0; // PHY needs to be reset after configuring opsel and opmode
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(W5500_WAIT_FOR_RESET_MS));
|
|
||||||
phycfg.reset = 1; // reset flag needs to be put back to 1
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
|
||||||
esp_eth_mediator_t *eth = w5500->eth;
|
|
||||||
|
|
||||||
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
|
||||||
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");
|
|
||||||
if (phycfg.speed) { // 100Mbps
|
|
||||||
if (duplex == ETH_DUPLEX_FULL) {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_100BT_FULL_AUTO_DIS;
|
|
||||||
} else {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_100BT_HALF_AUTO_DIS;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (duplex == ETH_DUPLEX_FULL) {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_10BT_FULL_AUTO_DIS;
|
|
||||||
} else {
|
|
||||||
phycfg.opmode = W5500_OP_MODE_10BT_HALF_AUTO_DIS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
phycfg.opsel = 1; // PHY working mode configured by register
|
|
||||||
phycfg.reset = 0; // PHY needs to be reset after configuring opsel and opmode
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(W5500_WAIT_FOR_RESET_MS));
|
|
||||||
phycfg.reset = 1; // reset flag needs to be put back to 1
|
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, w5500->addr, W5500_REG_PHYCFGR, phycfg.val), err, TAG, "write PHYCFG failed");
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_init(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
/* Power on Ethernet PHY */
|
|
||||||
ESP_GOTO_ON_ERROR(w5500_pwrctl(phy, true), err, TAG, "power control failed");
|
|
||||||
/* Reset Ethernet PHY */
|
|
||||||
ESP_GOTO_ON_ERROR(w5500_reset(phy), err, TAG, "reset failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t w5500_deinit(esp_eth_phy_t *phy)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
/* Power off Ethernet PHY */
|
|
||||||
ESP_GOTO_ON_ERROR(w5500_pwrctl(phy, false), err, TAG, "power control failed");
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_eth_phy_t *esp_eth_phy_new_w5500(const eth_phy_config_t *config)
|
|
||||||
{
|
|
||||||
esp_eth_phy_t *ret = NULL;
|
|
||||||
ESP_GOTO_ON_FALSE(config, NULL, err, TAG, "invalid arguments");
|
|
||||||
phy_w5500_t *w5500 = calloc(1, sizeof(phy_w5500_t));
|
|
||||||
ESP_GOTO_ON_FALSE(w5500, NULL, err, TAG, "no mem for PHY instance");
|
|
||||||
w5500->addr = config->phy_addr;
|
|
||||||
w5500->reset_timeout_ms = config->reset_timeout_ms;
|
|
||||||
w5500->reset_gpio_num = config->reset_gpio_num;
|
|
||||||
w5500->link_status = ETH_LINK_DOWN;
|
|
||||||
w5500->autonego_timeout_ms = config->autonego_timeout_ms;
|
|
||||||
w5500->parent.reset = w5500_reset;
|
|
||||||
w5500->parent.reset_hw = w5500_reset_hw;
|
|
||||||
w5500->parent.init = w5500_init;
|
|
||||||
w5500->parent.deinit = w5500_deinit;
|
|
||||||
w5500->parent.set_mediator = w5500_set_mediator;
|
|
||||||
w5500->parent.autonego_ctrl = w5500_autonego_ctrl;
|
|
||||||
w5500->parent.get_link = w5500_get_link;
|
|
||||||
w5500->parent.set_link = w5500_set_link;
|
|
||||||
w5500->parent.pwrctl = w5500_pwrctl;
|
|
||||||
w5500->parent.get_addr = w5500_get_addr;
|
|
||||||
w5500->parent.set_addr = w5500_set_addr;
|
|
||||||
w5500->parent.advertise_pause_ability = w5500_advertise_pause_ability;
|
|
||||||
w5500->parent.loopback = w5500_loopback;
|
|
||||||
w5500->parent.set_speed = w5500_set_speed;
|
|
||||||
w5500->parent.set_duplex = w5500_set_duplex;
|
|
||||||
w5500->parent.del = w5500_del;
|
|
||||||
return &(w5500->parent);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define W5500_ADDR_OFFSET (16) // Address length
|
|
||||||
#define W5500_BSB_OFFSET (3) // Block Select Bits offset
|
|
||||||
#define W5500_RWB_OFFSET (2) // Read Write Bits offset
|
|
||||||
|
|
||||||
#define W5500_CHIP_VERSION (0x4) // Chip version that VERSIONR returns
|
|
||||||
|
|
||||||
#define W5500_BSB_COM_REG (0x00) // Common Register
|
|
||||||
#define W5500_BSB_SOCK_REG(s) ((s)*4+1) // Socket Register
|
|
||||||
#define W5500_BSB_SOCK_TX_BUF(s) ((s)*4+2) // Socket TX Buffer
|
|
||||||
#define W5500_BSB_SOCK_RX_BUF(s) ((s)*4+3) // Socket RX Buffer
|
|
||||||
|
|
||||||
#define W5500_ACCESS_MODE_READ (0) // Read Mode
|
|
||||||
#define W5500_ACCESS_MODE_WRITE (1) // Write Mode
|
|
||||||
|
|
||||||
#define W5500_SPI_OP_MODE_VDM (0x00) // Variable Data Length Mode (SPI frame is controlled by CS line)
|
|
||||||
#define W5500_SPI_OP_MODE_FDM_1 (0x01) // Fixed Data Length Mode, 1 Byte Length
|
|
||||||
#define W5500_SPI_OP_MODE_FDM_2 (0x02) // Fixed Data Length Mode, 2 Bytes Length
|
|
||||||
#define W5500_SPI_OP_MODE_FDM_4 (0x03) // Fixed Data Length Mode, 4 Bytes Length
|
|
||||||
|
|
||||||
#define W5500_MAKE_MAP(offset, bsb) ((offset) << W5500_ADDR_OFFSET | (bsb) << W5500_BSB_OFFSET)
|
|
||||||
|
|
||||||
#define W5500_REG_MR W5500_MAKE_MAP(0x0000, W5500_BSB_COM_REG) // Mode
|
|
||||||
#define W5500_REG_MAC W5500_MAKE_MAP(0x0009, W5500_BSB_COM_REG) // MAC Address
|
|
||||||
#define W5500_REG_INTLEVEL W5500_MAKE_MAP(0x0013, W5500_BSB_COM_REG) // Interrupt Level Timeout
|
|
||||||
#define W5500_REG_IR W5500_MAKE_MAP(0x0015, W5500_BSB_COM_REG) // Interrupt
|
|
||||||
#define W5500_REG_IMR W5500_MAKE_MAP(0x0016, W5500_BSB_COM_REG) // Interrupt Mask
|
|
||||||
#define W5500_REG_SIR W5500_MAKE_MAP(0x0017, W5500_BSB_COM_REG) // Socket Interrupt
|
|
||||||
#define W5500_REG_SIMR W5500_MAKE_MAP(0x0018, W5500_BSB_COM_REG) // Socket Interrupt Mask
|
|
||||||
#define W5500_REG_RTR W5500_MAKE_MAP(0x0019, W5500_BSB_COM_REG) // Retry Time
|
|
||||||
#define W5500_REG_RCR W5500_MAKE_MAP(0x001B, W5500_BSB_COM_REG) // Retry Count
|
|
||||||
#define W5500_REG_PHYCFGR W5500_MAKE_MAP(0x002E, W5500_BSB_COM_REG) // PHY Configuration
|
|
||||||
#define W5500_REG_VERSIONR W5500_MAKE_MAP(0x0039, W5500_BSB_COM_REG) // Chip version
|
|
||||||
|
|
||||||
#define W5500_REG_SOCK_MR(s) W5500_MAKE_MAP(0x0000, W5500_BSB_SOCK_REG(s)) // Socket Mode
|
|
||||||
#define W5500_REG_SOCK_CR(s) W5500_MAKE_MAP(0x0001, W5500_BSB_SOCK_REG(s)) // Socket Command
|
|
||||||
#define W5500_REG_SOCK_IR(s) W5500_MAKE_MAP(0x0002, W5500_BSB_SOCK_REG(s)) // Socket Interrupt
|
|
||||||
#define W5500_REG_SOCK_SR(s) W5500_MAKE_MAP(0x0004, W5500_BSB_SOCK_REG(s)) // Socket Status
|
|
||||||
#define W5500_REG_SOCK_RXBUF_SIZE(s) W5500_MAKE_MAP(0x001E, W5500_BSB_SOCK_REG(s)) // Socket Receive Buffer Size
|
|
||||||
#define W5500_REG_SOCK_TXBUF_SIZE(s) W5500_MAKE_MAP(0x001F, W5500_BSB_SOCK_REG(s)) // Socket Transmit Buffer Size
|
|
||||||
#define W5500_REG_SOCK_TX_FSR(s) W5500_MAKE_MAP(0x0020, W5500_BSB_SOCK_REG(s)) // Socket TX Free Size
|
|
||||||
#define W5500_REG_SOCK_TX_RD(s) W5500_MAKE_MAP(0x0022, W5500_BSB_SOCK_REG(s)) // Socket TX Read Pointer
|
|
||||||
#define W5500_REG_SOCK_TX_WR(s) W5500_MAKE_MAP(0x0024, W5500_BSB_SOCK_REG(s)) // Socket TX Write Pointer
|
|
||||||
#define W5500_REG_SOCK_RX_RSR(s) W5500_MAKE_MAP(0x0026, W5500_BSB_SOCK_REG(s)) // Socket RX Received Size
|
|
||||||
#define W5500_REG_SOCK_RX_RD(s) W5500_MAKE_MAP(0x0028, W5500_BSB_SOCK_REG(s)) // Socket RX Read Pointer
|
|
||||||
#define W5500_REG_SOCK_RX_WR(s) W5500_MAKE_MAP(0x002A, W5500_BSB_SOCK_REG(s)) // Socket RX Write Pointer
|
|
||||||
#define W5500_REG_SOCK_IMR(s) W5500_MAKE_MAP(0x002C, W5500_BSB_SOCK_REG(s)) // Socket Interrupt Mask
|
|
||||||
|
|
||||||
#define W5500_MEM_SOCK_TX(s,addr) W5500_MAKE_MAP(addr, W5500_BSB_SOCK_TX_BUF(s)) // Socket TX buffer address
|
|
||||||
#define W5500_MEM_SOCK_RX(s,addr) W5500_MAKE_MAP(addr, W5500_BSB_SOCK_RX_BUF(s)) // Socket RX buffer address
|
|
||||||
|
|
||||||
#define W5500_MR_RST (1<<7) // Software reset
|
|
||||||
#define W5500_MR_PB (1<<4) // Ping block (block the response to a ping request)
|
|
||||||
|
|
||||||
#define W5500_SIMR_SOCK0 (1<<0) // Socket 0 interrupt
|
|
||||||
|
|
||||||
#define W5500_SMR_MAC_RAW (1<<2) // MAC RAW mode
|
|
||||||
#define W5500_SMR_MAC_FILTER (1<<7) // MAC filter
|
|
||||||
#define W5500_SMR_MAC_BLOCK_MCAST (1<<5) // Block multicast
|
|
||||||
|
|
||||||
#define W5500_SCR_OPEN (0x01) // Open command
|
|
||||||
#define W5500_SCR_CLOSE (0x10) // Close command
|
|
||||||
#define W5500_SCR_SEND (0x20) // Send command
|
|
||||||
#define W5500_SCR_RECV (0x40) // Recv command
|
|
||||||
|
|
||||||
#define W5500_SIR_RECV (1<<2) // Receive done
|
|
||||||
#define W5500_SIR_SEND (1<<4) // Send done
|
|
@@ -24,10 +24,12 @@ menu "esp_eth TEST_APPS Configuration"
|
|||||||
if TARGET_USE_INTERNAL_ETHERNET
|
if TARGET_USE_INTERNAL_ETHERNET
|
||||||
choice TARGET_ETH_PHY_DEVICE
|
choice TARGET_ETH_PHY_DEVICE
|
||||||
prompt "Ethernet PHY"
|
prompt "Ethernet PHY"
|
||||||
default TARGET_ETH_PHY_DEVICE_IP101
|
default TARGET_ETH_PHY_DEVICE_GENERIC
|
||||||
help
|
help
|
||||||
Select one of the devices listed here
|
Select one of the devices listed here
|
||||||
|
|
||||||
|
config TARGET_ETH_PHY_DEVICE_GENERIC
|
||||||
|
bool "Generic IEEE802.3"
|
||||||
config TARGET_ETH_PHY_DEVICE_IP101
|
config TARGET_ETH_PHY_DEVICE_IP101
|
||||||
bool "IP101"
|
bool "IP101"
|
||||||
config TARGET_ETH_PHY_DEVICE_LAN8720
|
config TARGET_ETH_PHY_DEVICE_LAN8720
|
||||||
|
@@ -114,7 +114,10 @@ esp_eth_phy_t *phy_init(eth_phy_config_t *phy_config)
|
|||||||
}
|
}
|
||||||
#if CONFIG_TARGET_USE_INTERNAL_ETHERNET
|
#if CONFIG_TARGET_USE_INTERNAL_ETHERNET
|
||||||
phy_config->phy_addr = ESP_ETH_PHY_ADDR_AUTO;
|
phy_config->phy_addr = ESP_ETH_PHY_ADDR_AUTO;
|
||||||
#if CONFIG_TARGET_ETH_PHY_DEVICE_IP101
|
#if CONFIG_TARGET_ETH_PHY_DEVICE_GENERIC
|
||||||
|
phy = esp_eth_phy_new_generic(phy_config);
|
||||||
|
ESP_LOGI(TAG, "DUT PHY: Generic");
|
||||||
|
#elif CONFIG_TARGET_ETH_PHY_DEVICE_IP101
|
||||||
phy = esp_eth_phy_new_ip101(phy_config);
|
phy = esp_eth_phy_new_ip101(phy_config);
|
||||||
ESP_LOGI(TAG, "DUT PHY: IP101");
|
ESP_LOGI(TAG, "DUT PHY: IP101");
|
||||||
#elif CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720
|
#elif CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720
|
||||||
|
@@ -251,7 +251,7 @@ def ethernet_heap_alloc_test(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
# ----------- IP101 -----------
|
# ----------- IP101 -----------
|
||||||
@pytest.mark.ethernet
|
@pytest.mark.ethernet
|
||||||
@pytest.mark.parametrize('config', ['default_ip101', 'release_ip101', 'single_core_ip101'], indirect=True)
|
@pytest.mark.parametrize('config', ['default_generic', 'release_generic', 'single_core_generic'], indirect=True)
|
||||||
@pytest.mark.flaky(reruns=3, reruns_delay=5)
|
@pytest.mark.flaky(reruns=3, reruns_delay=5)
|
||||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||||
def test_esp_ethernet(dut: IdfDut) -> None:
|
def test_esp_ethernet(dut: IdfDut) -> None:
|
||||||
@@ -262,7 +262,7 @@ def test_esp_ethernet(dut: IdfDut) -> None:
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
[
|
[
|
||||||
'default_ip101',
|
'default_generic',
|
||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@@ -277,7 +277,7 @@ def test_esp_emac(dut: IdfDut) -> None:
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
[
|
[
|
||||||
'default_ip101',
|
'default_generic',
|
||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@@ -291,7 +291,7 @@ def test_esp_eth_ip101(dut: IdfDut) -> None:
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
[
|
[
|
||||||
'default_ip101_esp32p4',
|
'default_generic_esp32p4',
|
||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@@ -306,7 +306,7 @@ def test_esp32p4_ethernet(dut: IdfDut) -> None:
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
[
|
[
|
||||||
'default_ip101_esp32p4',
|
'default_generic_esp32p4',
|
||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@@ -331,6 +331,7 @@ def test_esp32p4_emac_clko(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
# ----------- LAN8720 -----------
|
# ----------- LAN8720 -----------
|
||||||
|
@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDF-14124')
|
||||||
@pytest.mark.eth_lan8720
|
@pytest.mark.eth_lan8720
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@@ -347,6 +348,7 @@ def test_esp_eth_lan8720(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
# ----------- RTL8201 -----------
|
# ----------- RTL8201 -----------
|
||||||
|
@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDF-14124')
|
||||||
@pytest.mark.eth_rtl8201
|
@pytest.mark.eth_rtl8201
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@@ -363,6 +365,7 @@ def test_esp_eth_rtl8201(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
# ----------- KSZ8041 -----------
|
# ----------- KSZ8041 -----------
|
||||||
|
@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDF-14124')
|
||||||
@pytest.mark.eth_ksz8041
|
@pytest.mark.eth_ksz8041
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@@ -379,6 +382,7 @@ def test_esp_eth_ksz8041(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
# ----------- DP83848 -----------
|
# ----------- DP83848 -----------
|
||||||
|
@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDF-14124')
|
||||||
@pytest.mark.eth_dp83848
|
@pytest.mark.eth_dp83848
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@@ -395,6 +399,7 @@ def test_esp_eth_dp83848(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
# ----------- W5500 -----------
|
# ----------- W5500 -----------
|
||||||
|
@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDF-14124')
|
||||||
@pytest.mark.eth_w5500
|
@pytest.mark.eth_w5500
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@@ -414,6 +419,7 @@ def test_esp_eth_w5500(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
# ----------- KSZ8851SNL -----------
|
# ----------- KSZ8851SNL -----------
|
||||||
|
@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDF-14124')
|
||||||
@pytest.mark.eth_ksz8851snl
|
@pytest.mark.eth_ksz8851snl
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@@ -433,6 +439,7 @@ def test_esp_eth_ksz8851snl(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
# ----------- DM9051 -----------
|
# ----------- DM9051 -----------
|
||||||
|
@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDF-14124')
|
||||||
@pytest.mark.eth_dm9051
|
@pytest.mark.eth_dm9051
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_SPI_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_DM9051=y
|
|
@@ -1,11 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ETH_USE_ESP32_EMAC=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_DP83848=y
|
|
||||||
CONFIG_TARGET_RMII_CLK_OUT=y
|
|
||||||
CONFIG_TARGET_RMII_CLK_OUT_GPIO=17
|
|
@@ -6,4 +6,4 @@ CONFIG_ETH_USE_ESP32_EMAC=y
|
|||||||
CONFIG_ESP_TASK_WDT_EN=n
|
CONFIG_ESP_TASK_WDT_EN=n
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8041=y
|
CONFIG_TARGET_ETH_PHY_DEVICE_GENERIC=y
|
@@ -6,6 +6,6 @@ CONFIG_ETH_USE_ESP32_EMAC=y
|
|||||||
CONFIG_ESP_TASK_WDT_EN=n
|
CONFIG_ESP_TASK_WDT_EN=n
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y
|
CONFIG_TARGET_ETH_PHY_DEVICE_GENERIC=y
|
||||||
|
|
||||||
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y
|
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y
|
@@ -1,9 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ETH_USE_ESP32_EMAC=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y
|
|
@@ -1,8 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_SPI_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL=y
|
|
@@ -1,11 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ETH_USE_ESP32_EMAC=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720=y
|
|
||||||
CONFIG_TARGET_RMII_CLK_OUT=y
|
|
||||||
CONFIG_TARGET_RMII_CLK_OUT_GPIO=17
|
|
@@ -1,13 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ETH_USE_ESP32_EMAC=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_RTL8201=y
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=n
|
|
||||||
CONFIG_TARGET_IO_MDC=16
|
|
||||||
CONFIG_TARGET_IO_MDIO=17
|
|
@@ -1,8 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_SPI_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_W5500=y
|
|
@@ -4,7 +4,7 @@ CONFIG_ESP_TASK_WDT_EN=n
|
|||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y
|
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y
|
CONFIG_TARGET_ETH_PHY_DEVICE_GENERIC=y
|
||||||
|
|
||||||
CONFIG_ESP_SLEEP_DEBUG=y
|
CONFIG_ESP_SLEEP_DEBUG=y
|
||||||
|
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_SPI_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_DM9051=y
|
|
||||||
|
|
||||||
CONFIG_TARGET_ETH_SPI_POLL_MS=10
|
|
@@ -1,10 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_SPI_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL=y
|
|
||||||
|
|
||||||
CONFIG_TARGET_ETH_SPI_POLL_MS=10
|
|
@@ -1,10 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32"
|
|
||||||
|
|
||||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
|
||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
|
||||||
CONFIG_ESP_TASK_WDT_EN=n
|
|
||||||
|
|
||||||
CONFIG_TARGET_USE_SPI_ETHERNET=y
|
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_W5500=y
|
|
||||||
|
|
||||||
CONFIG_TARGET_ETH_SPI_POLL_MS=10
|
|
@@ -9,4 +9,4 @@ CONFIG_ETH_USE_ESP32_EMAC=y
|
|||||||
CONFIG_ESP_TASK_WDT_EN=n
|
CONFIG_ESP_TASK_WDT_EN=n
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y
|
CONFIG_TARGET_ETH_PHY_DEVICE_GENERIC=y
|
@@ -6,7 +6,7 @@ CONFIG_ETH_USE_ESP32_EMAC=y
|
|||||||
CONFIG_ESP_TASK_WDT_EN=n
|
CONFIG_ESP_TASK_WDT_EN=n
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y
|
CONFIG_TARGET_ETH_PHY_DEVICE_GENERIC=y
|
||||||
|
|
||||||
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y
|
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y
|
||||||
|
|
||||||
|
@@ -9,4 +9,4 @@ CONFIG_ETH_USE_ESP32_EMAC=y
|
|||||||
CONFIG_ESP_TASK_WDT_EN=n
|
CONFIG_ESP_TASK_WDT_EN=n
|
||||||
|
|
||||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y
|
CONFIG_TARGET_ETH_PHY_DEVICE_GENERIC=y
|
@@ -195,7 +195,7 @@ static void ethernet_init(test_vfs_eth_network_t *network_hndls)
|
|||||||
#ifdef CONFIG_IDF_TARGET_ESP32P4
|
#ifdef CONFIG_IDF_TARGET_ESP32P4
|
||||||
phy_config.reset_gpio_num = 51;
|
phy_config.reset_gpio_num = 51;
|
||||||
#endif // CONFIG_IDF_TARGET_ESP32P4
|
#endif // CONFIG_IDF_TARGET_ESP32P4
|
||||||
network_hndls->phy = esp_eth_phy_new_ip101(&phy_config);
|
network_hndls->phy = esp_eth_phy_new_generic(&phy_config);
|
||||||
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(network_hndls->mac, network_hndls->phy);
|
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(network_hndls->mac, network_hndls->phy);
|
||||||
network_hndls->eth_handle = NULL;
|
network_hndls->eth_handle = NULL;
|
||||||
// install Ethernet driver
|
// install Ethernet driver
|
||||||
|
@@ -104,7 +104,7 @@ void connect_test_fixture_setup(void)
|
|||||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||||
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
s_phy = esp_eth_phy_new_ip101(&phy_config);
|
s_phy = esp_eth_phy_new_generic(&phy_config);
|
||||||
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
||||||
|
|
||||||
// install Ethernet driver
|
// install Ethernet driver
|
||||||
|
@@ -305,15 +305,13 @@ The Ethernet driver is implemented in an Object-Oriented style. Any operation on
|
|||||||
phy_config.phy_addr = CONFIG_ETHERNET_PHY_ADDR; // alter the PHY address according to your board design
|
phy_config.phy_addr = CONFIG_ETHERNET_PHY_ADDR; // alter the PHY address according to your board design
|
||||||
phy_config.reset_gpio_num = CONFIG_ETHERNET_PHY_RST_GPIO; // alter the GPIO used for PHY reset
|
phy_config.reset_gpio_num = CONFIG_ETHERNET_PHY_RST_GPIO; // alter the GPIO used for PHY reset
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config); // create generic PHY instance
|
esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config); // create generic PHY instance
|
||||||
// ESP-IDF officially supports several different specific Ethernet PHY chip driver
|
|
||||||
// esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
|
||||||
// esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
|
|
||||||
// esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config);
|
|
||||||
// esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Any Ethernet PHY chip compliant with IEEE 802.3 can be used when creating new PHY instance with :cpp:func:`esp_eth_phy_new_generic`. However, while basic functionality should always work, some specific features might be limited, even if the PHY meets IEEE 802.3 standard. A typical example is loopback functionality, where certain PHYs may require setting a specific speed mode to operate correctly. If this is the concern and you need PHY driver specifically tailored to your chip needs, use drivers for PHY chips the ESP-IDF already officially supports or consult with :ref:`Custom PHY Driver <custom-phy-driver>` section to create a new custom driver.
|
Any Ethernet PHY chip compliant with IEEE 802.3 can be used when creating new PHY instance with :cpp:func:`esp_eth_phy_new_generic`. However, while basic functionality should always work, some specific features might be limited, even if the PHY meets IEEE 802.3 standard. A typical example is loopback functionality, where certain PHYs may require setting a specific speed mode to operate correctly. If this is the concern and you need PHY driver specifically tailored to your chip needs, use drivers for PHY chips the ESP-IDF already officially supports or consult with :ref:`Custom PHY Driver <custom-phy-driver>` section to create a new custom driver.
|
||||||
|
|
||||||
|
.. tip::
|
||||||
|
Espressif provides drivers for several specific Ethernet PHY chips in the `esp-eth-drivers <https://github.com/espressif/esp-eth-drivers>`_ repository. Drivers are distributed as components and are available in the `ESP Component Registry <https://components.espressif.com/>`_.
|
||||||
|
|
||||||
Optional Runtime MAC Clock Configuration
|
Optional Runtime MAC Clock Configuration
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@@ -329,7 +327,7 @@ The Ethernet driver is implemented in an Object-Oriented style. Any operation on
|
|||||||
|
|
||||||
esp32_emac_config.interface = EMAC_DATA_INTERFACE_RMII; // alter EMAC Data Interface
|
esp32_emac_config.interface = EMAC_DATA_INTERFACE_RMII; // alter EMAC Data Interface
|
||||||
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT; // select EMAC REF_CLK mode
|
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT; // select EMAC REF_CLK mode
|
||||||
esp32_emac_config.clock_config.rmii.clock_gpio = EMAC_CLK_OUT_GPIO; // select GPIO number used to input/output EMAC REF_CLK
|
esp32_emac_config.clock_config.rmii.clock_gpio = 17; // select GPIO number used to input/output EMAC REF_CLK
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // create MAC instance
|
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // create MAC instance
|
||||||
|
|
||||||
|
|
||||||
@@ -375,6 +373,8 @@ SPI-Ethernet Module
|
|||||||
|
|
||||||
* The SPI device configuration (i.e., `spi_device_interface_config_t`) may slightly differ for other Ethernet modules or to meet SPI timing on specific PCB. Please check out your module's specs and the examples in ESP-IDF.
|
* The SPI device configuration (i.e., `spi_device_interface_config_t`) may slightly differ for other Ethernet modules or to meet SPI timing on specific PCB. Please check out your module's specs and the examples in ESP-IDF.
|
||||||
|
|
||||||
|
.. tip::
|
||||||
|
Espressif provides drivers for various SPI-Ethernet modules in the `esp-eth-drivers <https://github.com/espressif/esp-eth-drivers>`_ repository. Drivers are distributed as components and are available in the `ESP Component Registry <https://components.espressif.com/>`_.
|
||||||
|
|
||||||
Install Driver
|
Install Driver
|
||||||
--------------
|
--------------
|
||||||
@@ -383,7 +383,7 @@ To install the Ethernet driver, we need to combine the instance of MAC and PHY a
|
|||||||
|
|
||||||
* :cpp:member:`esp_eth_config_t::mac`: instance that created from MAC generator (e.g., :cpp:func:`esp_eth_mac_new_esp32`).
|
* :cpp:member:`esp_eth_config_t::mac`: instance that created from MAC generator (e.g., :cpp:func:`esp_eth_mac_new_esp32`).
|
||||||
|
|
||||||
* :cpp:member:`esp_eth_config_t::phy`: instance that created from PHY generator (e.g., :cpp:func:`esp_eth_phy_new_ip101`).
|
* :cpp:member:`esp_eth_config_t::phy`: instance that created from PHY generator (e.g., :cpp:func:`esp_eth_phy_new_generic`).
|
||||||
|
|
||||||
* :cpp:member:`esp_eth_config_t::check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds.
|
* :cpp:member:`esp_eth_config_t::check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds.
|
||||||
|
|
||||||
@@ -644,11 +644,11 @@ The majority of PHY management functionality required by the ESP-IDF Ethernet dr
|
|||||||
|
|
||||||
**Steps to create a custom PHY driver:**
|
**Steps to create a custom PHY driver:**
|
||||||
|
|
||||||
1. Define vendor-specific registry layout based on the PHY datasheet. See :component_file:`esp_eth/src/phy/esp_eth_phy_ip101.c` as an example.
|
1. Define vendor-specific registry layout based on the PHY datasheet.
|
||||||
2. Prepare derived PHY management object info structure which:
|
2. Prepare derived PHY management object info structure which:
|
||||||
|
|
||||||
* must contain at least parent IEEE 802.3 :cpp:class:`phy_802_3_t` object
|
* must contain at least parent IEEE 802.3 :cpp:class:`phy_802_3_t` object
|
||||||
* optionally contain additional variables needed to support non-IEEE 802.3 or customized functionality. See :component_file:`esp_eth/src/phy/esp_eth_phy_ksz80xx.c` as an example.
|
* optionally contain additional variables needed to support non-IEEE 802.3 or customized functionality.
|
||||||
|
|
||||||
3. Define chip-specific management call-back functions.
|
3. Define chip-specific management call-back functions.
|
||||||
4. Initialize parent IEEE 802.3 object and re-assign chip-specific management call-back functions.
|
4. Initialize parent IEEE 802.3 object and re-assign chip-specific management call-back functions.
|
||||||
|
@@ -43,6 +43,32 @@ Removed the following RMII clock Kconfig options from `components/esp_eth`. Cloc
|
|||||||
**Impact**: Applications using ``ETH_ESP32_EMAC_DEFAULT_CONFIG()`` continue to work. Custom clock configurations must be set explicitly in the EMAC config structure or use the `Ethernet Init component <https://components.espressif.com/components/espressif/ethernet_init>`_.
|
**Impact**: Applications using ``ETH_ESP32_EMAC_DEFAULT_CONFIG()`` continue to work. Custom clock configurations must be set explicitly in the EMAC config structure or use the `Ethernet Init component <https://components.espressif.com/components/espressif/ethernet_init>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Ethernet PHY and Ethernet SPI Module drivers are moved from ESP-IDF to external repo
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The Ethernet PHY and Ethernet SPI Module drivers have been removed from ESP-IDF and have been migrated to `esp-eth-drivers <https://github.com/espressif/esp-eth-drivers>`_ repository. If you are using these drivers, you need to use the drivers as component in your project. The drivers are now available in the `ESP Component Registry <https://components.espressif.com/>`_.
|
||||||
|
|
||||||
|
**Removed APIs**:
|
||||||
|
- :cpp:func:`esp_eth_phy_new_ip101`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_lan87xx`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_rtl8201`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_dp83848`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_ksz80xx`
|
||||||
|
- :cpp:func:`esp_eth_mac_new_dm9051`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_dm9051`
|
||||||
|
- :cpp:func:`esp_eth_mac_new_ksz8851snl`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_ksz8851snl`
|
||||||
|
- :cpp:func:`esp_eth_mac_new_w5500`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_w5500`
|
||||||
|
|
||||||
|
|
||||||
|
**Impact**: Applications using Ethernet PHY and Ethernet SPI Module drivers that used to be part of ESP-IDF will no longer work.
|
||||||
|
|
||||||
|
**Migration**:
|
||||||
|
|
||||||
|
Add driver component from `IDF Component Manager <https://components.espressif.com/>`_ to your project using `idf.py add-dependency` and include `esp_eth_phy_xxxx.h` and `esp_eth_mac_xxxx.h` or use the `Ethernet Init component <https://components.espressif.com/components/espressif/ethernet_init>`_.
|
||||||
|
|
||||||
|
|
||||||
ESP-NETIF
|
ESP-NETIF
|
||||||
*********
|
*********
|
||||||
|
|
||||||
|
@@ -305,15 +305,13 @@ ESP-IDF 在宏 :c:macro:`ETH_MAC_DEFAULT_CONFIG` 和 :c:macro:`ETH_PHY_DEFAULT_C
|
|||||||
phy_config.phy_addr = CONFIG_ETHERNET_PHY_ADDR; // 根据开发板设计更改 PHY 地址
|
phy_config.phy_addr = CONFIG_ETHERNET_PHY_ADDR; // 根据开发板设计更改 PHY 地址
|
||||||
phy_config.reset_gpio_num = CONFIG_ETHERNET_PHY_RST_GPIO; // 更改用于 PHY 复位的 GPIO
|
phy_config.reset_gpio_num = CONFIG_ETHERNET_PHY_RST_GPIO; // 更改用于 PHY 复位的 GPIO
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config); // 创建通用 PHY 实例
|
esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config); // 创建通用 PHY 实例
|
||||||
// ESP-IDF 为数种特定以太网 PHY 芯片驱动提供官方支持
|
|
||||||
// esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
|
||||||
// esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
|
|
||||||
// esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config);
|
|
||||||
// esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
使用 :cpp:func:`esp_eth_phy_new_generic` 创建新的 PHY 实例时,可以使用任何符合 IEEE 802.3 标准的以太网 PHY 芯片。然而,尽管 PHY 芯片符合 IEEE 802.3 标准,能提供基本功能,但某些特定的功能可能无法完全实现。例如,某些以太网 PHY 芯片可能需要配置特定的速度模式才能启用环回功能。遇到这种情况,需要配置 PHY 驱动程序以满足特定芯片需求,请使用 ESP-IDF 官方支持的 PHY 芯片驱动程序,或参阅 :ref:`Custom PHY Driver <custom-phy-driver>` 小节以创建新的自定义驱动程序。
|
使用 :cpp:func:`esp_eth_phy_new_generic` 创建新的 PHY 实例时,可以使用任何符合 IEEE 802.3 标准的以太网 PHY 芯片。然而,尽管 PHY 芯片符合 IEEE 802.3 标准,能提供基本功能,但某些特定的功能可能无法完全实现。例如,某些以太网 PHY 芯片可能需要配置特定的速度模式才能启用环回功能。遇到这种情况,需要配置 PHY 驱动程序以满足特定芯片需求,请使用 ESP-IDF 官方支持的 PHY 芯片驱动程序,或参阅 :ref:`Custom PHY Driver <custom-phy-driver>` 小节以创建新的自定义驱动程序。
|
||||||
|
|
||||||
|
.. tip::
|
||||||
|
乐鑫为多种特定的以太网 PHY 芯片提供了驱动程序,这些驱动程序可在 `esp-eth-drivers <https://github.com/espressif/esp-eth-drivers>`_ 仓库中获取。驱动以组件形式分发,并可在 `ESP 组件库 <https://components.espressif.com/>`_ 上获取。
|
||||||
|
|
||||||
可选的运行时 MAC 时钟配置
|
可选的运行时 MAC 时钟配置
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@@ -329,7 +327,7 @@ ESP-IDF 在宏 :c:macro:`ETH_MAC_DEFAULT_CONFIG` 和 :c:macro:`ETH_PHY_DEFAULT_C
|
|||||||
|
|
||||||
esp32_emac_config.interface = EMAC_DATA_INTERFACE_RMII; // 更改 EMAC 数据接口
|
esp32_emac_config.interface = EMAC_DATA_INTERFACE_RMII; // 更改 EMAC 数据接口
|
||||||
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT; // 配置 EMAC REF_CLK 模式
|
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT; // 配置 EMAC REF_CLK 模式
|
||||||
esp32_emac_config.clock_config.rmii.clock_gpio = EMAC_CLK_OUT_GPIO; // 配置用于输入/输出 EMAC REF_CLK 的 GPIO 编号
|
esp32_emac_config.clock_config.rmii.clock_gpio = 17; // 配置用于输入/输出 EMAC REF_CLK 的 GPIO 编号
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // 创建 MAC 实例
|
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // 创建 MAC 实例
|
||||||
|
|
||||||
|
|
||||||
@@ -375,6 +373,8 @@ SPI-Ethernet 模块
|
|||||||
|
|
||||||
* 针对不同的以太网模块,或是为了满足特定 PCB 上的 SPI 时序,SPI 从机设备配置(即 `spi_device_interface_config_t`)可能略有不同。具体配置请查看模块规格以及 ESP-IDF 中的示例。
|
* 针对不同的以太网模块,或是为了满足特定 PCB 上的 SPI 时序,SPI 从机设备配置(即 `spi_device_interface_config_t`)可能略有不同。具体配置请查看模块规格以及 ESP-IDF 中的示例。
|
||||||
|
|
||||||
|
.. tip::
|
||||||
|
乐鑫为多种 SPI-Ethernet 模块提供了驱动程序,这些驱动程序可在 `esp-eth-drivers <https://github.com/espressif/esp-eth-drivers>`_ 仓库中获取。驱动以组件形式分发,并可在 `ESP 组件库 <https://components.espressif.com/>`_ 上获取。
|
||||||
|
|
||||||
安装驱动程序
|
安装驱动程序
|
||||||
--------------
|
--------------
|
||||||
@@ -383,7 +383,7 @@ SPI-Ethernet 模块
|
|||||||
|
|
||||||
* :cpp:member:`esp_eth_config_t::mac`:由 MAC 生成器创建的实例(例如 :cpp:func:`esp_eth_mac_new_esp32`)。
|
* :cpp:member:`esp_eth_config_t::mac`:由 MAC 生成器创建的实例(例如 :cpp:func:`esp_eth_mac_new_esp32`)。
|
||||||
|
|
||||||
* :cpp:member:`esp_eth_config_t::phy`:由 PHY 生成器创建的实例(例如 :cpp:func:`esp_eth_phy_new_ip101`)。
|
* :cpp:member:`esp_eth_config_t::phy`:由 PHY 生成器创建的实例(例如 :cpp:func:`esp_eth_phy_new_generic`)。
|
||||||
|
|
||||||
* :cpp:member:`esp_eth_config_t::check_link_period_ms`:以太网驱动程序会启用操作系统定时器来定期检查链接状态。该字段用于设置间隔时间,单位为毫秒。
|
* :cpp:member:`esp_eth_config_t::check_link_period_ms`:以太网驱动程序会启用操作系统定时器来定期检查链接状态。该字段用于设置间隔时间,单位为毫秒。
|
||||||
|
|
||||||
@@ -644,11 +644,11 @@ ESP-IDF 以太网驱动程序所需的大部分 PHY 管理功能都已涵盖在
|
|||||||
|
|
||||||
**创建自定义 PHY 驱动程序的步骤:**
|
**创建自定义 PHY 驱动程序的步骤:**
|
||||||
|
|
||||||
1. 请根据 PHY 数据手册,定义针对供应商的特定注册表布局。示例请参见 :component_file:`esp_eth/src/phy/esp_eth_phy_ip101.c`。
|
1. 请根据 PHY 数据手册,定义厂家私有的寄存器。
|
||||||
2. 准备衍生的 PHY 管理对象信息结构,该结构:
|
2. 准备衍生的 PHY 管理对象信息结构,该结构:
|
||||||
|
|
||||||
* 必须至少包含 IEEE 802.3 :cpp:class:`phy_802_3_t` 父对象
|
* 必须至少包含 IEEE 802.3 :cpp:class:`phy_802_3_t` 父对象
|
||||||
* 可选择包含额外的变量,以支持非 IEEE 802.3 或定制功能。示例请参见 :component_file:`esp_eth/src/phy/esp_eth_phy_ksz80xx.c`。
|
* 可选择包含额外的变量,以支持非 IEEE 802.3 或定制功能。
|
||||||
|
|
||||||
3. 定义针对芯片的特定管理回调功能。
|
3. 定义针对芯片的特定管理回调功能。
|
||||||
4. 初始化 IEEE 802.3 父对象并重新分配针对芯片的特定管理回调功能。
|
4. 初始化 IEEE 802.3 父对象并重新分配针对芯片的特定管理回调功能。
|
||||||
|
@@ -43,6 +43,32 @@
|
|||||||
**影响**:使用 ``ETH_ESP32_EMAC_DEFAULT_CONFIG()`` 的应用程序可继续正常工作。自定义时钟配置需在 EMAC 配置结构体中显式设置,或使用 `Ethernet Init 组件 <https://components.espressif.com/components/espressif/ethernet_init>`_。
|
**影响**:使用 ``ETH_ESP32_EMAC_DEFAULT_CONFIG()`` 的应用程序可继续正常工作。自定义时钟配置需在 EMAC 配置结构体中显式设置,或使用 `Ethernet Init 组件 <https://components.espressif.com/components/espressif/ethernet_init>`_。
|
||||||
|
|
||||||
|
|
||||||
|
以太网 PHY 和以太网 SPI 模块驱动已从 ESP-IDF 移至外部仓库
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
以太网 PHY 和以太网 SPI 模块驱动已从 ESP-IDF 中移除,并迁移至 `esp-eth-drivers <https://github.com/espressif/esp-eth-drivers>`_ 仓库。如果你在项目中使用这些驱动,需要将其作为组件集成。相关驱动现已在 `ESP 组件库 <https://components.espressif.com/>`_ 上提供。
|
||||||
|
|
||||||
|
**移除的 API**:
|
||||||
|
- :cpp:func:`esp_eth_phy_new_ip101`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_lan87xx`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_rtl8201`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_dp83848`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_ksz80xx`
|
||||||
|
- :cpp:func:`esp_eth_mac_new_dm9051`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_dm9051`
|
||||||
|
- :cpp:func:`esp_eth_mac_new_ksz8851snl`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_ksz8851snl`
|
||||||
|
- :cpp:func:`esp_eth_mac_new_w5500`
|
||||||
|
- :cpp:func:`esp_eth_phy_new_w5500`
|
||||||
|
|
||||||
|
|
||||||
|
**影响**:原本依赖 ESP-IDF 内置以太网 PHY 和以太网 SPI 模块驱动的应用将无法继续工作。
|
||||||
|
|
||||||
|
**迁移方式**:
|
||||||
|
|
||||||
|
请通过 `idf.py add-dependency` 命令,从 `IDF 组件管理器 <https://components.espressif.com/>`_ 添加驱动组件到你的项目,并包含相应的 `esp_eth_phy_xxxx.h` 和 `esp_eth_mac_xxxx.h` 头文件,或使用 `Ethernet Init 组件 <https://components.espressif.com/components/espressif/ethernet_init>`_。
|
||||||
|
|
||||||
|
|
||||||
ESP-NETIF
|
ESP-NETIF
|
||||||
*********
|
*********
|
||||||
|
|
||||||
|
@@ -137,7 +137,7 @@ menu "Example Connection Configuration"
|
|||||||
choice EXAMPLE_ETHERNET_TYPE
|
choice EXAMPLE_ETHERNET_TYPE
|
||||||
prompt "Ethernet Type"
|
prompt "Ethernet Type"
|
||||||
default EXAMPLE_USE_INTERNAL_ETHERNET if SOC_EMAC_SUPPORTED
|
default EXAMPLE_USE_INTERNAL_ETHERNET if SOC_EMAC_SUPPORTED
|
||||||
default EXAMPLE_USE_W5500
|
default EXAMPLE_USE_DUMMY
|
||||||
help
|
help
|
||||||
Select which kind of Ethernet will be used in the example.
|
Select which kind of Ethernet will be used in the example.
|
||||||
|
|
||||||
@@ -148,21 +148,11 @@ menu "Example Connection Configuration"
|
|||||||
help
|
help
|
||||||
Select internal Ethernet MAC controller.
|
Select internal Ethernet MAC controller.
|
||||||
|
|
||||||
config EXAMPLE_USE_DM9051
|
config EXAMPLE_USE_DUMMY
|
||||||
bool "DM9051 Module"
|
bool "DUMMY Module"
|
||||||
select EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
select ETH_USE_SPI_ETHERNET
|
select ETH_USE_SPI_ETHERNET
|
||||||
select ETH_SPI_ETHERNET_DM9051
|
|
||||||
help
|
help
|
||||||
Select external SPI-Ethernet module.
|
Dummy option to just to pass builds, will be fixed by IDF-14059
|
||||||
|
|
||||||
config EXAMPLE_USE_W5500
|
|
||||||
bool "W5500 Module"
|
|
||||||
select EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
select ETH_USE_SPI_ETHERNET
|
|
||||||
select ETH_SPI_ETHERNET_W5500
|
|
||||||
help
|
|
||||||
Select external SPI-Ethernet module (W5500).
|
|
||||||
|
|
||||||
config EXAMPLE_USE_OPENETH
|
config EXAMPLE_USE_OPENETH
|
||||||
bool "OpenCores Ethernet MAC (EXPERIMENTAL)"
|
bool "OpenCores Ethernet MAC (EXPERIMENTAL)"
|
||||||
@@ -179,7 +169,7 @@ menu "Example Connection Configuration"
|
|||||||
if EXAMPLE_USE_INTERNAL_ETHERNET
|
if EXAMPLE_USE_INTERNAL_ETHERNET
|
||||||
choice EXAMPLE_ETH_PHY_MODEL
|
choice EXAMPLE_ETH_PHY_MODEL
|
||||||
prompt "Ethernet PHY Device"
|
prompt "Ethernet PHY Device"
|
||||||
default EXAMPLE_ETH_PHY_IP101
|
default EXAMPLE_ETH_PHY_GENERIC
|
||||||
help
|
help
|
||||||
Select the Ethernet PHY device to use in the example.
|
Select the Ethernet PHY device to use in the example.
|
||||||
|
|
||||||
@@ -191,46 +181,6 @@ menu "Example Connection Configuration"
|
|||||||
even if the PHY meets IEEE 802.3 standard. A typical example is loopback
|
even if the PHY meets IEEE 802.3 standard. A typical example is loopback
|
||||||
functionality, where certain PHYs may require setting a specific speed mode to
|
functionality, where certain PHYs may require setting a specific speed mode to
|
||||||
operate correctly.
|
operate correctly.
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_IP101
|
|
||||||
bool "IP101"
|
|
||||||
help
|
|
||||||
IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver.
|
|
||||||
Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_RTL8201
|
|
||||||
bool "RTL8201/SR8201"
|
|
||||||
help
|
|
||||||
RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX.
|
|
||||||
Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_LAN87XX
|
|
||||||
bool "LAN87xx"
|
|
||||||
help
|
|
||||||
Below chips are supported:
|
|
||||||
LAN8710A is a small footprint MII/RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and
|
|
||||||
flexPWR® Technology.
|
|
||||||
LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support.
|
|
||||||
LAN8740A/LAN8741A is a small footprint MII/RMII 10/100 Energy Efficient Ethernet Transceiver
|
|
||||||
with HP Auto-MDIX and flexPWR® Technology.
|
|
||||||
LAN8742A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and
|
|
||||||
flexPWR® Technology.
|
|
||||||
Goto https://www.microchip.com for more information about them.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_DP83848
|
|
||||||
bool "DP83848"
|
|
||||||
help
|
|
||||||
DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver.
|
|
||||||
Goto http://www.ti.com/product/DP83848J for more information about it.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_KSZ80XX
|
|
||||||
bool "KSZ80xx"
|
|
||||||
help
|
|
||||||
With the KSZ80xx series, Microchip offers single-chip 10BASE-T/100BASE-TX
|
|
||||||
Ethernet Physical Layer Transceivers (PHY).
|
|
||||||
The following chips are supported: KSZ8001, KSZ8021, KSZ8031, KSZ8041,
|
|
||||||
KSZ8051, KSZ8061, KSZ8081, KSZ8091
|
|
||||||
Goto https://www.microchip.com for more information about them.
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config EXAMPLE_ETH_MDC_GPIO
|
config EXAMPLE_ETH_MDC_GPIO
|
||||||
@@ -250,65 +200,6 @@ menu "Example Connection Configuration"
|
|||||||
Set the GPIO number used by SMI MDIO.
|
Set the GPIO number used by SMI MDIO.
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
config EXAMPLE_ETH_SPI_HOST
|
|
||||||
int "SPI Host Number"
|
|
||||||
range 0 2
|
|
||||||
default 1
|
|
||||||
help
|
|
||||||
Set the SPI host used to communicate with the SPI Ethernet Controller.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_SCLK_GPIO
|
|
||||||
int "SPI SCLK GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 14
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI SCLK.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_MOSI_GPIO
|
|
||||||
int "SPI MOSI GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 13
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI MOSI.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_MISO_GPIO
|
|
||||||
int "SPI MISO GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
|
||||||
default 12
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI MISO.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_CS_GPIO
|
|
||||||
int "SPI CS GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 15
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI CS.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_CLOCK_MHZ
|
|
||||||
int "SPI clock speed (MHz)"
|
|
||||||
range 5 80
|
|
||||||
default 36
|
|
||||||
help
|
|
||||||
Set the clock speed (MHz) of SPI interface.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_INT_GPIO
|
|
||||||
int "Interrupt GPIO number"
|
|
||||||
range -1 ENV_GPIO_IN_RANGE_MAX
|
|
||||||
default 4
|
|
||||||
help
|
|
||||||
Set the GPIO number used by the SPI Ethernet module interrupt line.
|
|
||||||
Set -1 to use SPI Ethernet module in polling mode.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_POLLING_MS_VAL
|
|
||||||
depends on EXAMPLE_ETH_SPI_INT_GPIO < 0
|
|
||||||
int "Polling period in msec of SPI Ethernet Module"
|
|
||||||
default 10
|
|
||||||
help
|
|
||||||
Set SPI Ethernet module polling period.
|
|
||||||
endif # EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_RST_GPIO
|
config EXAMPLE_ETH_PHY_RST_GPIO
|
||||||
int "PHY Reset GPIO number"
|
int "PHY Reset GPIO number"
|
||||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
range -1 ENV_GPIO_OUT_RANGE_MAX
|
||||||
|
@@ -9,9 +9,6 @@
|
|||||||
#include "example_common_private.h"
|
#include "example_common_private.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_eth.h"
|
#include "esp_eth.h"
|
||||||
#if CONFIG_ETH_USE_SPI_ETHERNET
|
|
||||||
#include "driver/spi_master.h"
|
|
||||||
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_mac.h"
|
#include "esp_mac.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
@@ -82,6 +79,10 @@ static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
|
|||||||
|
|
||||||
static esp_netif_t *eth_start(void)
|
static esp_netif_t *eth_start(void)
|
||||||
{
|
{
|
||||||
|
// TODO just to pass builds, will be fixed by IDF-14059
|
||||||
|
#if CONFIG_EXAMPLE_USE_DUMMY
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
|
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
|
||||||
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
|
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
|
||||||
esp_netif_config.if_desc = EXAMPLE_NETIF_DESC_ETH;
|
esp_netif_config.if_desc = EXAMPLE_NETIF_DESC_ETH;
|
||||||
@@ -105,72 +106,17 @@ static esp_netif_t *eth_start(void)
|
|||||||
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||||
#if CONFIG_EXAMPLE_ETH_PHY_GENERIC
|
#if CONFIG_EXAMPLE_ETH_PHY_GENERIC
|
||||||
s_phy = esp_eth_phy_new_generic(&phy_config);
|
s_phy = esp_eth_phy_new_generic(&phy_config);
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_IP101
|
|
||||||
s_phy = esp_eth_phy_new_ip101(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
|
|
||||||
s_phy = esp_eth_phy_new_rtl8201(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
|
|
||||||
s_phy = esp_eth_phy_new_lan87xx(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
|
|
||||||
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
|
|
||||||
s_phy = esp_eth_phy_new_ksz80xx(&phy_config);
|
|
||||||
#endif // CONFIG_EXAMPLE_ETH_PHY_GENERIC
|
#endif // CONFIG_EXAMPLE_ETH_PHY_GENERIC
|
||||||
#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
gpio_install_isr_service(0);
|
|
||||||
spi_bus_config_t buscfg = {
|
|
||||||
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
|
|
||||||
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
|
|
||||||
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
|
|
||||||
.quadwp_io_num = -1,
|
|
||||||
.quadhd_io_num = -1,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
|
||||||
spi_device_interface_config_t spi_devcfg = {
|
|
||||||
.mode = 0,
|
|
||||||
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
|
||||||
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
|
|
||||||
.queue_size = 20
|
|
||||||
};
|
|
||||||
#if CONFIG_EXAMPLE_USE_DM9051
|
|
||||||
/* dm9051 ethernet driver is based on spi driver */
|
|
||||||
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
|
||||||
dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
|
||||||
#if CONFIG_EXAMPLE_ETH_SPI_INT_GPIO < 0
|
|
||||||
dm9051_config.poll_period_ms = CONFIG_EXAMPLE_ETH_SPI_POLLING_MS_VAL;
|
|
||||||
#endif // CONFIG_EXAMPLE_ETH_SPI_INT_GPIO
|
|
||||||
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
|
||||||
s_phy = esp_eth_phy_new_dm9051(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_USE_W5500
|
|
||||||
/* w5500 ethernet driver is based on spi driver */
|
|
||||||
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
|
||||||
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
|
||||||
#if CONFIG_EXAMPLE_ETH_SPI_INT_GPIO < 0
|
|
||||||
w5500_config.poll_period_ms = CONFIG_EXAMPLE_ETH_SPI_POLLING_MS_VAL;
|
|
||||||
#endif // CONFIG_EXAMPLE_ETH_SPI_INT_GPIO
|
|
||||||
s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
|
||||||
s_phy = esp_eth_phy_new_w5500(&phy_config);
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_DM9051
|
|
||||||
#elif CONFIG_EXAMPLE_USE_OPENETH
|
#elif CONFIG_EXAMPLE_USE_OPENETH
|
||||||
phy_config.autonego_timeout_ms = 100;
|
phy_config.autonego_timeout_ms = 100;
|
||||||
s_mac = esp_eth_mac_new_openeth(&mac_config);
|
s_mac = esp_eth_mac_new_openeth(&mac_config);
|
||||||
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
s_phy = esp_eth_phy_new_generic(&phy_config);
|
||||||
#endif // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
#endif // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
||||||
|
|
||||||
// Install Ethernet driver
|
// Install Ethernet driver
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
||||||
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
|
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
|
|
||||||
We set the ESP_MAC_ETH mac address as the default, if you want to use ESP_MAC_EFUSE_CUSTOM mac address, please enable the
|
|
||||||
configuration: `ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC`
|
|
||||||
*/
|
|
||||||
uint8_t eth_mac[6] = {0};
|
|
||||||
ESP_ERROR_CHECK(esp_read_mac(eth_mac, ESP_MAC_ETH));
|
|
||||||
ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_MAC_ADDR, eth_mac));
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
|
|
||||||
// combine driver with netif
|
// combine driver with netif
|
||||||
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
|
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
|
||||||
esp_netif_attach(netif, s_eth_glue);
|
esp_netif_attach(netif, s_eth_glue);
|
||||||
@@ -184,6 +130,7 @@ static esp_netif_t *eth_start(void)
|
|||||||
|
|
||||||
esp_eth_start(s_eth_handle);
|
esp_eth_start(s_eth_handle);
|
||||||
return netif;
|
return netif;
|
||||||
|
#endif // CONFIG_EXAMPLE_USE_DUMMY
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eth_stop(void)
|
static void eth_stop(void)
|
||||||
|
@@ -4,20 +4,13 @@ examples/ethernet/basic:
|
|||||||
enable:
|
enable:
|
||||||
- if: INCLUDE_DEFAULT == 1
|
- if: INCLUDE_DEFAULT == 1
|
||||||
disable:
|
disable:
|
||||||
- if: IDF_TARGET in ["esp32h21", "esp32h4"]
|
- if: IDF_TARGET not in ["esp32", "esp32p4"]
|
||||||
temporary: true
|
|
||||||
reason: not supported yet # TODO: [ESP32H21] IDF-11581 [ESP32H4] IDF-12360
|
|
||||||
disable_test:
|
|
||||||
- if: IDF_TARGET not in ["esp32"]
|
|
||||||
temporary: true
|
|
||||||
reason: lack of runners
|
|
||||||
depends_components:
|
depends_components:
|
||||||
- esp_eth
|
- esp_eth
|
||||||
- esp_netif
|
- esp_netif
|
||||||
- lwip
|
- lwip
|
||||||
- esp_event
|
- esp_event
|
||||||
- esp_driver_gpio
|
- esp_driver_gpio
|
||||||
- esp_driver_spi
|
|
||||||
|
|
||||||
examples/ethernet/iperf:
|
examples/ethernet/iperf:
|
||||||
disable:
|
disable:
|
||||||
|
@@ -5,86 +5,32 @@
|
|||||||
|
|
||||||
See the [README.md](../README.md) file in the upper level [examples](../) directory for more information about examples.
|
See the [README.md](../README.md) file in the upper level [examples](../) directory for more information about examples.
|
||||||
|
|
||||||
## Common Pin Assignments
|
Ethernet examples demonstrate basic features related to Ethernet layer, such as:
|
||||||
|
|
||||||
### Using ESP32 internal MAC
|
* basic Ethernet initialization and binding to IP stack via ESP-NETIF
|
||||||
|
|
||||||
* RMII PHY wiring is fixed and can not be changed through either IOMUX or GPIO Matrix. By default, they're connected as follows:
|
* tools for performance measurement, i.e. `iperf`
|
||||||
|
|
||||||
| GPIO | RMII Signal | Notes |
|
* hardware time synchronization
|
||||||
| ------ | ----------- | ------------ |
|
|
||||||
| GPIO21 | TX_EN | EMAC_TX_EN |
|
|
||||||
| GPIO19 | TX0 | EMAC_TXD0 |
|
|
||||||
| GPIO22 | TX1 | EMAC_TXD1 |
|
|
||||||
| GPIO25 | RX0 | EMAC_RXD0 |
|
|
||||||
| GPIO26 | RX1 | EMAC_RXD1 |
|
|
||||||
| GPIO27 | CRS_DV | EMAC_RX_DRV |
|
|
||||||
|
|
||||||
* One of the following GPIO pins can be used as RMII REF_CLK input/output:
|
## ESP-IDF Ethernet Driver
|
||||||
|
|
||||||
| GPIO | Function | Notes |
|
By default, ESP-IDF offers drivers for its internal Ethernet MAC (see Espressif documentation for supported chips) and for Generic IEEE 802.3 compliant PHYs. However, it does not limit users to use just those options. It is possible to create specific MAC and PHY layer drivers tailored for specific chip needs, including SPI Ethernet modules. Espressif maintains additional Ethernet drivers at [esp-eth-drivers repository](https://github.com/espressif/esp-eth-drivers) and the drivers are accessible via [The ESP Component Registry](https://components.espressif.com/) from users' projects.
|
||||||
| ------ | -------------------- | ------------ |
|
|
||||||
| GPIO0 | EMAC_TX_CLK/CLK_OUT1 | input/output |
|
|
||||||
| GPIO16 | EMAC_CLK_OUT | output |
|
|
||||||
| GPIO17 | EMAC_CLK_180 | output |
|
|
||||||
|
|
||||||
* SMI (Serial Management Interface) wiring is not fixed. You may need to changed it according to your board schematic. By default they're connected as follows:
|
## Component for Ethernet Initialization
|
||||||
|
|
||||||
| GPIO | SMI Signal | Notes |
|
The `Component for Ethernet Initialization` is a component intended for simple initialization of a wide range of Ethernet PHY chips, including SPI Ethernet modules and for advanced Ethernet configuration options, see [its homepage](https://components.espressif.com/components/espressif/ethernet_init/) for more information.
|
||||||
| ------ | ----------- | ------------- |
|
|
||||||
| GPIO23 | MDC | Output to PHY |
|
|
||||||
| GPIO18 | MDIO | Bidirectional |
|
|
||||||
|
|
||||||
* PHY chip has a reset pin, if want to do a hardware reset during initialization, then you have to connect it with one GPIO on ESP32. See more information from [here](#configure-the-project). The default GPIO used for resetting PHY chip is GPIO5.
|
|
||||||
|
|
||||||
### Using SPI ethernet modules
|
|
||||||
|
|
||||||
* SPI Ethernet modules (DM9051, W5500, ...) typically consume one SPI interface plus an interrupt and reset GPIO. They can be connected as follows for ESP32 as an example. However, they can be remapped to any pin using the GPIO Matrix.
|
|
||||||
|
|
||||||
| GPIO | DM9051 |
|
|
||||||
| ------ | ----------- |
|
|
||||||
| GPIO14 | SPI_CLK |
|
|
||||||
| GPIO13 | SPI_MOSI |
|
|
||||||
| GPIO12 | SPI_MISO |
|
|
||||||
| GPIO15 | SPI_CS |
|
|
||||||
| GPIO4 | Interrupt |
|
|
||||||
| NC | Reset |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Warning:**
|
|
||||||
Please consult Espressif Technical reference manual along with datasheet for specific ESP Module you use when assigning any other pins, especially when choosing from system configuration menu for the ethernet examples, some pins cannot be used (they may already be utilized for different purpose like SPI Flash/RAM, some pins might be inputs only, etc.).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Common Configurations
|
|
||||||
|
|
||||||
1. In the `Example Ethernet Configuration` menu:
|
|
||||||
* Choose the kind of Ethernet.
|
|
||||||
* If `Internal EMAC` is selected:
|
|
||||||
* Choose PHY device under `Ethernet PHY Device`, by default, the **ESP32-Ethernet-Kit** has an `IP101` on board.
|
|
||||||
* Set GPIO number used by SMI signal under `SMI MDC GPIO number` and `SMI MDIO GPIO number` respectively.
|
|
||||||
* If `SPI Ethernet` is selected:
|
|
||||||
* Set SPI specific configuration, including SPI host number, GPIO numbers and clock rate.
|
|
||||||
* Multiple Ethernet SPI modules of the same type can be connected to single SPI interface at a time. The modules then share data and CLK signals. The CS, interrupt and reset pins need to be specifically configured for each module separately.
|
|
||||||
* Set GPIO number used by PHY chip reset under `PHY Reset GPIO number`, you may have to change the default value according to your board schematic. **PHY hardware reset can be disabled by set this value to -1**.
|
|
||||||
* Set PHY address under `PHY Address`, you may have to change the default value according to your board schematic.
|
|
||||||
|
|
||||||
2. In the `Component config > Ethernet` menu:
|
|
||||||
* Under `Support ESP32 internal EMAC controller` sub-menu:
|
|
||||||
* In the `PHY interface`, select `Reduced Media Independent Interface (RMII)`, ESP-IDF currently only support RMII mode.
|
|
||||||
* In the `RMII clock mode`, select one of the source that RMII clock (50MHz) comes from: `Input RMII clock from external` or `Output RMII clock from internal`.
|
|
||||||
* If `Output RMII clock from internal` is enabled, you also have to set the GPIO number that used to output the RMII clock, under `RMII clock GPIO number`. In this case, you can set the GPIO number to 16 or 17.
|
|
||||||
* If `Output RMII clock from GPIO0 (Experimental!)` is also enabled, then you have no choice but GPIO0 to output the RMII clock.
|
|
||||||
* In `Amount of Ethernet DMA Rx buffers` and `Amount of Ethernet DMA Tx buffers`, you can set the amount of DMA buffers used for Tx and Rx.
|
|
||||||
* Under `Support SPI to Ethernet Module` sub-menu, select the SPI module that you used for this example. Currently ESP-IDF only supports `DM9051`, `W5500` and `KSZ8851SNL`.
|
|
||||||
|
|
||||||
## Common Troubleshooting
|
## Common Troubleshooting
|
||||||
|
|
||||||
* The data panel between ESP32's MAC and PHY needs a fixed 50MHz clock to do synchronization, which also called RMII clock. It can either be provided by an external oscillator or generated from internal APLL. The signal integrity of RMII clock is strict, so keep the trace as short as possible!
|
* The data path between ESP32's MAC and PHY needs a fixed 50MHz clock for synchronization, which is also called RMII REF clock. It can either be provided by an external oscillator or generated from internal PLL. The signal integrity of RMII clock is strict, so keep the trace as short as possible!
|
||||||
* If the RMII clock is generated from internal APLL, then APLL can't be used for other purpose (e.g. I2S).
|
* If you observe undefined behavior (e.g. LCD glitches) of any **SPI device** which works normally when Ethernet is not connected over internal EMAC, you need to adjust EMAC DMA burst length (the DMA is a shared resource between EMAC and the SPI). The same applies when you observe Ethernet frame corruption at the output of SPI Ethernet module and you use a combination of internal EMAC and SPI Ethernet module as network interfaces. To configure the EMAC DMA burst length, modify internal Ethernet initialization as follows:
|
||||||
* If you observe undefined behavior (e.g. LCD glitches) of any **SPI device** which works normally when Ethernet is not connected over internal EMAC, you need to adjust EMAC DMA burst length (the DMA is shared resource between EMAC and the SPI). The same applies when you observe Ethernet frames corruption at the output of SPI Ethernet module and you use combination of internal EMAC and SPI Ethernet module as network interfaces. To configure the EMAC DMA burst length, modify internal Ethernet initialization as follows:
|
|
||||||
|
|
||||||
```c
|
```c
|
||||||
esp32_emac_config.dma_burst_len = ETH_DMA_BURST_LEN_4; // or other appropriate value
|
esp32_emac_config.dma_burst_len = ETH_DMA_BURST_LEN_4; // or other appropriate value
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* ESP32 limitations:
|
||||||
|
* If the RMII clock is generated from internal APLL, then APLL can't be used for other purposes (e.g. I2S).
|
||||||
|
* If Wi-Fi or Bluetooth are used simultaneously with Ethernet, the RMII clock cannot be generated by the internal APLL clock, as it would result in clock instability. See [ESP32 errata](https://docs.espressif.com/projects/esp-chip-errata/en/latest/esp32/03-errata-description/index.html#clock-esp32-cannot-be-used-as-the-phy-clock-source-if-wi-fi-and-ethernet-are-used-at-the-same-time) for more information.
|
@@ -1,38 +1,35 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
| Supported Targets | ESP32 | ESP32-P4 |
|
||||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- |
|
||||||
|
|
||||||
# Ethernet Example
|
# Basic Ethernet Example
|
||||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This example demonstrates basic usage of `Ethernet driver` together with `esp_netif`. Initialization of the `Ethernet driver` is wrapped in separate [sub-component](./components/ethernet_init/ethernet_init.c) of this project to clearly distinguish between the driver's and `esp_netif` initializations. The work flow of the example could be as follows:
|
This example demonstrates basic usage of internal EMAC and `Ethernet driver` together with `esp_netif`. The workflow of the example is as follows:
|
||||||
|
|
||||||
1. Install Ethernet driver
|
1. Install Ethernet driver
|
||||||
2. Attach the driver to `esp_netif`
|
2. Attach the driver to `esp_netif`
|
||||||
3. Send DHCP requests and wait for a DHCP lease
|
3. Send DHCP requests and wait for a DHCP lease
|
||||||
4. If get IP address successfully, then you will be able to ping the device
|
4. If get IP address successfully, then you will be able to ping the device
|
||||||
|
|
||||||
If you have a new Ethernet application to go (for example, connect to IoT cloud via Ethernet), try this as a basic template, then add your own code.
|
If you have a new simple Ethernet application to go (for example, connect to IoT cloud via Ethernet), try this as a basic template, then add your own code.
|
||||||
|
|
||||||
|
>[!TIP]
|
||||||
|
> For initialization of a wider range of Ethernet PHY chips, including SPI Ethernet modules and for advanced Ethernet configuration options, please use [Component for Ethernet Initialization](https://components.espressif.com/components/espressif/ethernet_init/).
|
||||||
|
|
||||||
## How to use example
|
## How to use example
|
||||||
|
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a supported Ethernet PHY chip. Up until now, ESP-IDF supports up to four Ethernet PHY: `LAN8720`, `IP101`, `DP83848` and `RTL8201`, additional PHY drivers should be implemented by users themselves.
|
To run this example, it's recommended that you have an official Espressif Ethernet capable development board - either [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp32-ethernet-kit/index.html) or [ESP32-P4-Function-EV-Board](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/index.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a IEEE 802.3 compliant Ethernet PHY chip and with the default RMII dataplane GPIO configuration.
|
||||||
|
|
||||||
Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). This example will take the `DM9051`, `W5500` or `KSZ8851SNL` SPI modules as an example, illustrating how to install the Ethernet driver in the same manner.
|
> [!NOTE]
|
||||||
|
> `Generic 802.3 PHY` basic functionality should always work for PHY compliant with IEEE 802.3. However, some specific features might be limited. A typical example is loopback functionality, where certain PHYs may require setting a specific speed mode to operate correctly. If this is a case, use driver tailored to that specific chip.
|
||||||
The ESP-IDF supports the usage of multiple Ethernet interfaces at a time when external modules are utilized which is also demonstrated by this example. There are several options you can combine:
|
|
||||||
* Internal EMAC and one SPI Ethernet module.
|
|
||||||
* Two SPI Ethernet modules of the same type connected to single SPI interface and accessed by switching appropriate CS.
|
|
||||||
* Internal EMAC and two SPI Ethernet modules of the same type.
|
|
||||||
|
|
||||||
#### Pin Assignment
|
#### Pin Assignment
|
||||||
|
|
||||||
See common pin assignments for Ethernet examples from [upper level](../README.md#common-pin-assignments).
|
This example uses the default RMII GPIO configuration as defined by `ETH_ESP32_EMAC_DEFAULT_CONFIG` for the specific ESP32 chip (ESP32, ESP32P4, etc.).
|
||||||
|
|
||||||
When using two Ethernet SPI modules at a time, they are to be connected to single SPI interface. Both modules then share data (MOSI/MISO) and CLK signals. However, the CS, interrupt and reset pins need to be connected to separate GPIO for each Ethernet SPI module.
|
|
||||||
|
|
||||||
### Configure the project
|
### Configure the project
|
||||||
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
idf_component_register(SRCS "ethernet_init.c"
|
|
||||||
PRIV_REQUIRES esp_driver_gpio esp_eth
|
|
||||||
INCLUDE_DIRS ".")
|
|
@@ -1,308 +0,0 @@
|
|||||||
menu "Example Ethernet Configuration"
|
|
||||||
|
|
||||||
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
|
|
||||||
|
|
||||||
config EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
depends on SOC_EMAC_SUPPORTED
|
|
||||||
select ETH_USE_ESP32_EMAC
|
|
||||||
default y
|
|
||||||
bool "Internal EMAC"
|
|
||||||
help
|
|
||||||
Use internal Ethernet MAC controller.
|
|
||||||
|
|
||||||
if EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
choice EXAMPLE_ETH_PHY_MODEL
|
|
||||||
prompt "Ethernet PHY Device"
|
|
||||||
default EXAMPLE_ETH_PHY_IP101
|
|
||||||
help
|
|
||||||
Select the Ethernet PHY device to use in the example.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_GENERIC
|
|
||||||
bool "Generic 802.3 PHY"
|
|
||||||
help
|
|
||||||
Any Ethernet PHY chip compliant with IEEE 802.3 can be used. However, while
|
|
||||||
basic functionality should always work, some specific features might be limited,
|
|
||||||
even if the PHY meets IEEE 802.3 standard. A typical example is loopback
|
|
||||||
functionality, where certain PHYs may require setting a specific speed mode to
|
|
||||||
operate correctly.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_IP101
|
|
||||||
bool "IP101"
|
|
||||||
help
|
|
||||||
IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver.
|
|
||||||
Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_RTL8201
|
|
||||||
bool "RTL8201/SR8201"
|
|
||||||
help
|
|
||||||
RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX.
|
|
||||||
Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_LAN87XX
|
|
||||||
bool "LAN87xx"
|
|
||||||
help
|
|
||||||
Below chips are supported:
|
|
||||||
LAN8710A is a small footprint MII/RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and
|
|
||||||
flexPWR® Technology.
|
|
||||||
LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support.
|
|
||||||
LAN8740A/LAN8741A is a small footprint MII/RMII 10/100 Energy Efficient Ethernet Transceiver
|
|
||||||
with HP Auto-MDIX and flexPWR® Technology.
|
|
||||||
LAN8742A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and
|
|
||||||
flexPWR® Technology.
|
|
||||||
Goto https://www.microchip.com for more information about them.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_DP83848
|
|
||||||
bool "DP83848"
|
|
||||||
help
|
|
||||||
DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver.
|
|
||||||
Goto http://www.ti.com/product/DP83848J for more information about it.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_KSZ80XX
|
|
||||||
bool "KSZ80xx"
|
|
||||||
help
|
|
||||||
With the KSZ80xx series, Microchip offers single-chip 10BASE-T/100BASE-TX
|
|
||||||
Ethernet Physical Layer Transceivers (PHY).
|
|
||||||
The following chips are supported: KSZ8001, KSZ8021, KSZ8031, KSZ8041,
|
|
||||||
KSZ8051, KSZ8061, KSZ8081, KSZ8091
|
|
||||||
Goto https://www.microchip.com for more information about them.
|
|
||||||
endchoice # EXAMPLE_ETH_PHY_MODEL
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_MDC_GPIO
|
|
||||||
int "SMI MDC GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 23 if IDF_TARGET_ESP32
|
|
||||||
default 31 if IDF_TARGET_ESP32P4
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SMI MDC.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_MDIO_GPIO
|
|
||||||
int "SMI MDIO GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 18 if IDF_TARGET_ESP32
|
|
||||||
default 52 if IDF_TARGET_ESP32P4
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SMI MDIO.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_RST_GPIO
|
|
||||||
int "PHY Reset GPIO number"
|
|
||||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 5 if IDF_TARGET_ESP32
|
|
||||||
default 51 if IDF_TARGET_ESP32P4
|
|
||||||
help
|
|
||||||
Set the GPIO number used to reset PHY chip.
|
|
||||||
Set to -1 to disable PHY chip hardware reset.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_PHY_ADDR
|
|
||||||
int "PHY Address"
|
|
||||||
range -1 31
|
|
||||||
default 1
|
|
||||||
help
|
|
||||||
Set PHY address according your board schematic.
|
|
||||||
Set to -1 to driver find the PHY address automatically.
|
|
||||||
endif # EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
|
|
||||||
config EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
bool "SPI Ethernet"
|
|
||||||
default n
|
|
||||||
select ETH_USE_SPI_ETHERNET
|
|
||||||
help
|
|
||||||
Use external SPI-Ethernet module(s).
|
|
||||||
|
|
||||||
if EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
config EXAMPLE_SPI_ETHERNETS_NUM
|
|
||||||
int "Number of SPI Ethernet modules to use at a time"
|
|
||||||
range 1 2
|
|
||||||
default 1
|
|
||||||
help
|
|
||||||
Set the number of SPI Ethernet modules you want to use at a time. Multiple SPI modules can be connected
|
|
||||||
to one SPI interface and can be separately accessed based on state of associated Chip Select (CS).
|
|
||||||
|
|
||||||
choice EXAMPLE_ETHERNET_TYPE_SPI
|
|
||||||
prompt "Ethernet SPI"
|
|
||||||
default EXAMPLE_USE_W5500
|
|
||||||
help
|
|
||||||
Select which kind of Ethernet will be used in the example.
|
|
||||||
|
|
||||||
config EXAMPLE_USE_DM9051
|
|
||||||
bool "DM9051 Module"
|
|
||||||
select ETH_SPI_ETHERNET_DM9051
|
|
||||||
help
|
|
||||||
Select external SPI-Ethernet module (DM9051).
|
|
||||||
|
|
||||||
config EXAMPLE_USE_KSZ8851SNL
|
|
||||||
bool "KSZ8851SNL Module"
|
|
||||||
select ETH_SPI_ETHERNET_KSZ8851SNL
|
|
||||||
help
|
|
||||||
Select external SPI-Ethernet module (KSZ8851SNL).
|
|
||||||
|
|
||||||
config EXAMPLE_USE_W5500
|
|
||||||
bool "W5500 Module"
|
|
||||||
select ETH_SPI_ETHERNET_W5500
|
|
||||||
help
|
|
||||||
Select external SPI-Ethernet module (W5500).
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_HOST
|
|
||||||
int "SPI Host Number"
|
|
||||||
range 0 2
|
|
||||||
default 1
|
|
||||||
help
|
|
||||||
Set the SPI host used to communicate with the SPI Ethernet Controller.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_SCLK_GPIO
|
|
||||||
int "SPI SCLK GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 14 if IDF_TARGET_ESP32
|
|
||||||
default 12 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 6 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32C61
|
|
||||||
default 4 if IDF_TARGET_ESP32H2
|
|
||||||
default 33 if IDF_TARGET_ESP32P4
|
|
||||||
default 8 if IDF_TARGET_ESP32C5
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI SCLK.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_MOSI_GPIO
|
|
||||||
int "SPI MOSI GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 13 if IDF_TARGET_ESP32
|
|
||||||
default 11 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 7 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32C61
|
|
||||||
default 5 if IDF_TARGET_ESP32H2
|
|
||||||
default 32 if IDF_TARGET_ESP32P4
|
|
||||||
default 10 if IDF_TARGET_ESP32C5
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI MOSI.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_MISO_GPIO
|
|
||||||
int "SPI MISO GPIO number"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
|
||||||
default 12 if IDF_TARGET_ESP32
|
|
||||||
default 13 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 2 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32C61
|
|
||||||
default 0 if IDF_TARGET_ESP32H2
|
|
||||||
default 24 if IDF_TARGET_ESP32P4
|
|
||||||
default 9 if IDF_TARGET_ESP32C5
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI MISO.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_CLOCK_MHZ
|
|
||||||
int "SPI clock speed (MHz)"
|
|
||||||
range 5 80
|
|
||||||
default 16
|
|
||||||
help
|
|
||||||
Set the clock speed (MHz) of SPI interface.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_CS0_GPIO
|
|
||||||
int "SPI CS0 GPIO number for SPI Ethernet module #1"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 15 if IDF_TARGET_ESP32
|
|
||||||
default 10 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C2
|
|
||||||
default 3 if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C61
|
|
||||||
default 1 if IDF_TARGET_ESP32H2
|
|
||||||
default 21 if IDF_TARGET_ESP32P4
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI CS0, i.e. Chip Select associated with the first SPI Eth module).
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_CS1_GPIO
|
|
||||||
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
|
|
||||||
int "SPI CS1 GPIO number for SPI Ethernet module #2"
|
|
||||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default 32 if IDF_TARGET_ESP32
|
|
||||||
default 7 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 8 if IDF_TARGET_ESP32C3
|
|
||||||
default 21 if IDF_TARGET_ESP32C6
|
|
||||||
default 3 if IDF_TARGET_ESP32C2
|
|
||||||
default 11 if IDF_TARGET_ESP32H2
|
|
||||||
default 23 if IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61
|
|
||||||
default 1 if IDF_TARGET_ESP32C5
|
|
||||||
help
|
|
||||||
Set the GPIO number used by SPI CS1, i.e. Chip Select associated with the second SPI Eth module.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_INT0_GPIO
|
|
||||||
int "Interrupt GPIO number SPI Ethernet module #1"
|
|
||||||
range -1 ENV_GPIO_IN_RANGE_MAX
|
|
||||||
default 4 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3
|
|
||||||
default 4 if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32C5
|
|
||||||
default 10 if IDF_TARGET_ESP32H2
|
|
||||||
default 48 if IDF_TARGET_ESP32P4
|
|
||||||
default 0 if IDF_TARGET_ESP32C61
|
|
||||||
help
|
|
||||||
Set the GPIO number used by the first SPI Ethernet module interrupt line.
|
|
||||||
Set -1 to use SPI Ethernet module in polling mode.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_INT1_GPIO
|
|
||||||
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
|
|
||||||
int "Interrupt GPIO number SPI Ethernet module #2"
|
|
||||||
range -1 ENV_GPIO_IN_RANGE_MAX
|
|
||||||
default 33 if IDF_TARGET_ESP32
|
|
||||||
default 5 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C2
|
|
||||||
default 5 if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32C5
|
|
||||||
default 9 if IDF_TARGET_ESP32H2
|
|
||||||
default 47 if IDF_TARGET_ESP32P4
|
|
||||||
default 1 if IDF_TARGET_ESP32C61
|
|
||||||
help
|
|
||||||
Set the GPIO number used by the second SPI Ethernet module interrupt line.
|
|
||||||
Set -1 to use SPI Ethernet module in polling mode.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_POLLING0_MS_VAL
|
|
||||||
depends on EXAMPLE_ETH_SPI_INT0_GPIO < 0
|
|
||||||
int "Polling period in msec of SPI Ethernet Module #1"
|
|
||||||
default 10
|
|
||||||
help
|
|
||||||
Set SPI Ethernet module polling period.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_POLLING1_MS_VAL
|
|
||||||
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1 && EXAMPLE_ETH_SPI_INT1_GPIO < 0
|
|
||||||
int "Polling period in msec of SPI Ethernet Module #2"
|
|
||||||
default 10
|
|
||||||
help
|
|
||||||
Set SPI Ethernet module polling period.
|
|
||||||
|
|
||||||
# Hidden variable to ensure that polling period option is visible only when interrupt is set disabled and
|
|
||||||
# it is set to known value (0) when interrupt is enabled at the same time.
|
|
||||||
config EXAMPLE_ETH_SPI_POLLING0_MS
|
|
||||||
int
|
|
||||||
default EXAMPLE_ETH_SPI_POLLING0_MS_VAL if EXAMPLE_ETH_SPI_POLLING0_MS_VAL > 0
|
|
||||||
default 0
|
|
||||||
|
|
||||||
# Hidden variable to ensure that polling period option is visible only when interrupt is set disabled and
|
|
||||||
# it is set to known value (0) when interrupt is enabled at the same time.
|
|
||||||
config EXAMPLE_ETH_SPI_POLLING1_MS
|
|
||||||
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
|
|
||||||
int
|
|
||||||
default EXAMPLE_ETH_SPI_POLLING1_MS_VAL if EXAMPLE_ETH_SPI_POLLING1_MS_VAL > 0
|
|
||||||
default 0
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_PHY_RST0_GPIO
|
|
||||||
int "PHY Reset GPIO number of SPI Ethernet Module #1"
|
|
||||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default -1
|
|
||||||
help
|
|
||||||
Set the GPIO number used to reset PHY chip on the first SPI Ethernet module.
|
|
||||||
Set to -1 to disable PHY chip hardware reset.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_PHY_RST1_GPIO
|
|
||||||
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
|
|
||||||
int "PHY Reset GPIO number of SPI Ethernet Module #2"
|
|
||||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
|
||||||
default -1
|
|
||||||
help
|
|
||||||
Set the GPIO number used to reset PHY chip on the second SPI Ethernet module.
|
|
||||||
Set to -1 to disable PHY chip hardware reset.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_PHY_ADDR0
|
|
||||||
int "PHY Address of SPI Ethernet Module #1"
|
|
||||||
range 0 31
|
|
||||||
default 1
|
|
||||||
help
|
|
||||||
Set the first SPI Ethernet module PHY address according your board schematic.
|
|
||||||
|
|
||||||
config EXAMPLE_ETH_SPI_PHY_ADDR1
|
|
||||||
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
|
|
||||||
int "PHY Address of SPI Ethernet Module #2"
|
|
||||||
range 0 31
|
|
||||||
default 1
|
|
||||||
help
|
|
||||||
Set the second SPI Ethernet module PHY address according your board schematic.
|
|
||||||
endif # EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
endmenu
|
|
@@ -1,340 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
|
||||||
*/
|
|
||||||
#include "ethernet_init.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_mac.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
#include "driver/spi_master.h"
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM
|
|
||||||
#define SPI_ETHERNETS_NUM CONFIG_EXAMPLE_SPI_ETHERNETS_NUM
|
|
||||||
#else
|
|
||||||
#define SPI_ETHERNETS_NUM 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
#define INTERNAL_ETHERNETS_NUM 1
|
|
||||||
#else
|
|
||||||
#define INTERNAL_ETHERNETS_NUM 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define INIT_SPI_ETH_MODULE_CONFIG(eth_module_config, num) \
|
|
||||||
do { \
|
|
||||||
eth_module_config[num].spi_cs_gpio = CONFIG_EXAMPLE_ETH_SPI_CS ##num## _GPIO; \
|
|
||||||
eth_module_config[num].int_gpio = CONFIG_EXAMPLE_ETH_SPI_INT ##num## _GPIO; \
|
|
||||||
eth_module_config[num].polling_ms = CONFIG_EXAMPLE_ETH_SPI_POLLING ##num## _MS; \
|
|
||||||
eth_module_config[num].phy_reset_gpio = CONFIG_EXAMPLE_ETH_SPI_PHY_RST ##num## _GPIO; \
|
|
||||||
eth_module_config[num].phy_addr = CONFIG_EXAMPLE_ETH_SPI_PHY_ADDR ##num; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t spi_cs_gpio;
|
|
||||||
int8_t int_gpio;
|
|
||||||
uint32_t polling_ms;
|
|
||||||
int8_t phy_reset_gpio;
|
|
||||||
uint8_t phy_addr;
|
|
||||||
uint8_t *mac_addr;
|
|
||||||
}spi_eth_module_config_t;
|
|
||||||
|
|
||||||
static const char *TAG = "example_eth_init";
|
|
||||||
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
static bool gpio_isr_svc_init_by_eth = false; // indicates that we initialized the GPIO ISR service
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
/**
|
|
||||||
* @brief Internal ESP32 Ethernet initialization
|
|
||||||
*
|
|
||||||
* @param[out] mac_out optionally returns Ethernet MAC object
|
|
||||||
* @param[out] phy_out optionally returns Ethernet PHY object
|
|
||||||
* @return
|
|
||||||
* - esp_eth_handle_t if init succeeded
|
|
||||||
* - NULL if init failed
|
|
||||||
*/
|
|
||||||
static esp_eth_handle_t eth_init_internal(esp_eth_mac_t **mac_out, esp_eth_phy_t **phy_out)
|
|
||||||
{
|
|
||||||
esp_eth_handle_t ret = NULL;
|
|
||||||
|
|
||||||
// Init common MAC and PHY configs to default
|
|
||||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
|
||||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
|
||||||
|
|
||||||
// Update PHY config based on board specific configuration
|
|
||||||
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
|
|
||||||
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
|
|
||||||
// Init vendor specific MAC config to default
|
|
||||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
|
||||||
// Update vendor specific MAC config based on board configuration
|
|
||||||
esp32_emac_config.smi_gpio.mdc_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
|
|
||||||
esp32_emac_config.smi_gpio.mdio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
|
|
||||||
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
// The DMA is shared resource between EMAC and the SPI. Therefore, adjust
|
|
||||||
// EMAC DMA burst length when SPI Ethernet is used along with EMAC.
|
|
||||||
esp32_emac_config.dma_burst_len = ETH_DMA_BURST_LEN_4;
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
// Create new ESP32 Ethernet MAC instance
|
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
|
||||||
// Create new PHY instance based on board configuration
|
|
||||||
#if CONFIG_EXAMPLE_ETH_PHY_GENERIC
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_IP101
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_ksz80xx(&phy_config);
|
|
||||||
#endif
|
|
||||||
// Init Ethernet driver to default and install it
|
|
||||||
esp_eth_handle_t eth_handle = NULL;
|
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_driver_install(&config, ð_handle) == ESP_OK, NULL,
|
|
||||||
err, TAG, "Ethernet driver install failed");
|
|
||||||
|
|
||||||
if (mac_out != NULL) {
|
|
||||||
*mac_out = mac;
|
|
||||||
}
|
|
||||||
if (phy_out != NULL) {
|
|
||||||
*phy_out = phy;
|
|
||||||
}
|
|
||||||
return eth_handle;
|
|
||||||
err:
|
|
||||||
if (eth_handle != NULL) {
|
|
||||||
esp_eth_driver_uninstall(eth_handle);
|
|
||||||
}
|
|
||||||
if (mac != NULL) {
|
|
||||||
mac->del(mac);
|
|
||||||
}
|
|
||||||
if (phy != NULL) {
|
|
||||||
phy->del(phy);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
/**
|
|
||||||
* @brief SPI bus initialization (to be used by Ethernet SPI modules)
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ESP_OK on success
|
|
||||||
*/
|
|
||||||
static esp_err_t spi_bus_init(void)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
|
|
||||||
#if (CONFIG_EXAMPLE_ETH_SPI_INT0_GPIO >= 0) || (CONFIG_EXAMPLE_ETH_SPI_INT1_GPIO > 0)
|
|
||||||
// Install GPIO ISR handler to be able to service SPI Eth modules interrupts
|
|
||||||
ret = gpio_install_isr_service(0);
|
|
||||||
if (ret == ESP_OK) {
|
|
||||||
gpio_isr_svc_init_by_eth = true;
|
|
||||||
} else if (ret == ESP_ERR_INVALID_STATE) {
|
|
||||||
ESP_LOGW(TAG, "GPIO ISR handler has been already installed");
|
|
||||||
ret = ESP_OK; // ISR handler has been already installed so no issues
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "GPIO ISR handler install failed");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Init SPI bus
|
|
||||||
spi_bus_config_t buscfg = {
|
|
||||||
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
|
|
||||||
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
|
|
||||||
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
|
|
||||||
.quadwp_io_num = -1,
|
|
||||||
.quadhd_io_num = -1,
|
|
||||||
};
|
|
||||||
ESP_GOTO_ON_ERROR(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO),
|
|
||||||
err, TAG, "SPI host #%d init failed", CONFIG_EXAMPLE_ETH_SPI_HOST);
|
|
||||||
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Ethernet SPI modules initialization
|
|
||||||
*
|
|
||||||
* @param[in] spi_eth_module_config specific SPI Ethernet module configuration
|
|
||||||
* @param[out] mac_out optionally returns Ethernet MAC object
|
|
||||||
* @param[out] phy_out optionally returns Ethernet PHY object
|
|
||||||
* @return
|
|
||||||
* - esp_eth_handle_t if init succeeded
|
|
||||||
* - NULL if init failed
|
|
||||||
*/
|
|
||||||
static esp_eth_handle_t eth_init_spi(spi_eth_module_config_t *spi_eth_module_config, esp_eth_mac_t **mac_out, esp_eth_phy_t **phy_out)
|
|
||||||
{
|
|
||||||
esp_eth_handle_t ret = NULL;
|
|
||||||
|
|
||||||
// Init common MAC and PHY configs to default
|
|
||||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
|
||||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
|
||||||
|
|
||||||
// Update PHY config based on board specific configuration
|
|
||||||
phy_config.phy_addr = spi_eth_module_config->phy_addr;
|
|
||||||
phy_config.reset_gpio_num = spi_eth_module_config->phy_reset_gpio;
|
|
||||||
|
|
||||||
// Configure SPI interface for specific SPI module
|
|
||||||
spi_device_interface_config_t spi_devcfg = {
|
|
||||||
.mode = 0,
|
|
||||||
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
|
||||||
.queue_size = 20,
|
|
||||||
.spics_io_num = spi_eth_module_config->spi_cs_gpio
|
|
||||||
};
|
|
||||||
// Init vendor specific MAC config to default, and create new SPI Ethernet MAC instance
|
|
||||||
// and new PHY instance based on board configuration
|
|
||||||
#if CONFIG_EXAMPLE_USE_KSZ8851SNL
|
|
||||||
eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
|
||||||
ksz8851snl_config.int_gpio_num = spi_eth_module_config->int_gpio;
|
|
||||||
ksz8851snl_config.poll_period_ms = spi_eth_module_config->polling_ms;
|
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config);
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_ksz8851snl(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_USE_DM9051
|
|
||||||
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
|
||||||
dm9051_config.int_gpio_num = spi_eth_module_config->int_gpio;
|
|
||||||
dm9051_config.poll_period_ms = spi_eth_module_config->polling_ms;
|
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_USE_W5500
|
|
||||||
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
|
||||||
w5500_config.int_gpio_num = spi_eth_module_config->int_gpio;
|
|
||||||
w5500_config.poll_period_ms = spi_eth_module_config->polling_ms;
|
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
|
|
||||||
#endif //CONFIG_EXAMPLE_USE_W5500
|
|
||||||
// Init Ethernet driver to default and install it
|
|
||||||
esp_eth_handle_t eth_handle = NULL;
|
|
||||||
esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac, phy);
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_driver_install(ð_config_spi, ð_handle) == ESP_OK, NULL, err, TAG, "SPI Ethernet driver install failed");
|
|
||||||
|
|
||||||
// The SPI Ethernet module might not have a burned factory MAC address, we can set it manually.
|
|
||||||
if (spi_eth_module_config->mac_addr != NULL) {
|
|
||||||
ESP_GOTO_ON_FALSE(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, spi_eth_module_config->mac_addr) == ESP_OK,
|
|
||||||
NULL, err, TAG, "SPI Ethernet MAC address config failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mac_out != NULL) {
|
|
||||||
*mac_out = mac;
|
|
||||||
}
|
|
||||||
if (phy_out != NULL) {
|
|
||||||
*phy_out = phy;
|
|
||||||
}
|
|
||||||
return eth_handle;
|
|
||||||
err:
|
|
||||||
if (eth_handle != NULL) {
|
|
||||||
esp_eth_driver_uninstall(eth_handle);
|
|
||||||
}
|
|
||||||
if (mac != NULL) {
|
|
||||||
mac->del(mac);
|
|
||||||
}
|
|
||||||
if (phy != NULL) {
|
|
||||||
phy->del(phy);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
|
|
||||||
esp_err_t example_eth_init(esp_eth_handle_t *eth_handles_out[], uint8_t *eth_cnt_out)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
esp_eth_handle_t *eth_handles = NULL;
|
|
||||||
uint8_t eth_cnt = 0;
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET || CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
ESP_GOTO_ON_FALSE(eth_handles_out != NULL && eth_cnt_out != NULL, ESP_ERR_INVALID_ARG,
|
|
||||||
err, TAG, "invalid arguments: initialized handles array or number of interfaces");
|
|
||||||
eth_handles = calloc(SPI_ETHERNETS_NUM + INTERNAL_ETHERNETS_NUM, sizeof(esp_eth_handle_t));
|
|
||||||
ESP_GOTO_ON_FALSE(eth_handles != NULL, ESP_ERR_NO_MEM, err, TAG, "no memory");
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
eth_handles[eth_cnt] = eth_init_internal(NULL, NULL);
|
|
||||||
ESP_GOTO_ON_FALSE(eth_handles[eth_cnt], ESP_FAIL, err, TAG, "internal Ethernet init failed");
|
|
||||||
eth_cnt++;
|
|
||||||
#endif //CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
ESP_GOTO_ON_ERROR(spi_bus_init(), err, TAG, "SPI bus init failed");
|
|
||||||
// Init specific SPI Ethernet module configuration from Kconfig (CS GPIO, Interrupt GPIO, etc.)
|
|
||||||
spi_eth_module_config_t spi_eth_module_config[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM] = { 0 };
|
|
||||||
INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 0);
|
|
||||||
// The SPI Ethernet module(s) might not have a burned factory MAC address, hence use manually configured address(es).
|
|
||||||
// In this example, Locally Administered MAC address derived from ESP32x base MAC address is used.
|
|
||||||
// Note that Locally Administered OUI range should be used only when testing on a LAN under your control!
|
|
||||||
uint8_t base_mac_addr[ETH_ADDR_LEN];
|
|
||||||
ESP_GOTO_ON_ERROR(esp_efuse_mac_get_default(base_mac_addr), err, TAG, "get EFUSE MAC failed");
|
|
||||||
uint8_t local_mac_1[ETH_ADDR_LEN];
|
|
||||||
esp_derive_local_mac(local_mac_1, base_mac_addr);
|
|
||||||
spi_eth_module_config[0].mac_addr = local_mac_1;
|
|
||||||
#if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM > 1
|
|
||||||
INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 1);
|
|
||||||
uint8_t local_mac_2[ETH_ADDR_LEN];
|
|
||||||
base_mac_addr[ETH_ADDR_LEN - 1] += 1;
|
|
||||||
esp_derive_local_mac(local_mac_2, base_mac_addr);
|
|
||||||
spi_eth_module_config[1].mac_addr = local_mac_2;
|
|
||||||
#endif
|
|
||||||
#if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM > 2
|
|
||||||
#error Maximum number of supported SPI Ethernet devices is currently limited to 2 by this example.
|
|
||||||
#endif
|
|
||||||
for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) {
|
|
||||||
eth_handles[eth_cnt] = eth_init_spi(&spi_eth_module_config[i], NULL, NULL);
|
|
||||||
ESP_GOTO_ON_FALSE(eth_handles[eth_cnt], ESP_FAIL, err, TAG, "SPI Ethernet init failed");
|
|
||||||
eth_cnt++;
|
|
||||||
}
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
#else
|
|
||||||
ESP_LOGD(TAG, "no Ethernet device selected to init");
|
|
||||||
#endif // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET || CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
*eth_handles_out = eth_handles;
|
|
||||||
*eth_cnt_out = eth_cnt;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET || CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
err:
|
|
||||||
free(eth_handles);
|
|
||||||
return ret;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t example_eth_deinit(esp_eth_handle_t *eth_handles, uint8_t eth_cnt)
|
|
||||||
{
|
|
||||||
ESP_RETURN_ON_FALSE(eth_handles != NULL, ESP_ERR_INVALID_ARG, TAG, "array of Ethernet handles cannot be NULL");
|
|
||||||
for (int i = 0; i < eth_cnt; i++) {
|
|
||||||
esp_eth_mac_t *mac = NULL;
|
|
||||||
esp_eth_phy_t *phy = NULL;
|
|
||||||
if (eth_handles[i] != NULL) {
|
|
||||||
esp_eth_get_mac_instance(eth_handles[i], &mac);
|
|
||||||
esp_eth_get_phy_instance(eth_handles[i], &phy);
|
|
||||||
ESP_RETURN_ON_ERROR(esp_eth_driver_uninstall(eth_handles[i]), TAG, "Ethernet %p uninstall failed", eth_handles[i]);
|
|
||||||
}
|
|
||||||
if (mac != NULL) {
|
|
||||||
mac->del(mac);
|
|
||||||
}
|
|
||||||
if (phy != NULL) {
|
|
||||||
phy->del(phy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
spi_bus_free(CONFIG_EXAMPLE_ETH_SPI_HOST);
|
|
||||||
#if (CONFIG_EXAMPLE_ETH_SPI_INT0_GPIO >= 0) || (CONFIG_EXAMPLE_ETH_SPI_INT1_GPIO > 0)
|
|
||||||
// We installed the GPIO ISR service so let's uninstall it too.
|
|
||||||
// BE CAREFUL HERE though since the service might be used by other functionality!
|
|
||||||
if (gpio_isr_svc_init_by_eth) {
|
|
||||||
ESP_LOGW(TAG, "uninstalling GPIO ISR service!");
|
|
||||||
gpio_uninstall_isr_service();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif //CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
free(eth_handles);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "esp_eth_driver.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize Ethernet driver based on Espressif IoT Development Framework Configuration
|
|
||||||
*
|
|
||||||
* @param[out] eth_handles_out array of initialized Ethernet driver handles
|
|
||||||
* @param[out] eth_cnt_out number of initialized Ethernets
|
|
||||||
* @return
|
|
||||||
* - ESP_OK on success
|
|
||||||
* - ESP_ERR_INVALID_ARG when passed invalid pointers
|
|
||||||
* - ESP_ERR_NO_MEM when there is no memory to allocate for Ethernet driver handles array
|
|
||||||
* - ESP_FAIL on any other failure
|
|
||||||
*/
|
|
||||||
esp_err_t example_eth_init(esp_eth_handle_t *eth_handles_out[], uint8_t *eth_cnt_out);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief De-initialize array of Ethernet drivers
|
|
||||||
* @note All Ethernet drivers in the array must be stopped prior calling this function.
|
|
||||||
*
|
|
||||||
* @param[in] eth_handles array of Ethernet drivers to be de-initialized
|
|
||||||
* @param[in] eth_cnt number of Ethernets drivers to be de-initialized
|
|
||||||
* @return
|
|
||||||
* - ESP_OK on success
|
|
||||||
* - ESP_ERR_INVALID_ARG when passed invalid pointers
|
|
||||||
*/
|
|
||||||
esp_err_t example_eth_deinit(esp_eth_handle_t *eth_handles, uint8_t eth_cnt);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@@ -1,3 +1,3 @@
|
|||||||
idf_component_register(SRCS "ethernet_example_main.c"
|
idf_component_register(SRCS "ethernet_example_main.c"
|
||||||
PRIV_REQUIRES esp_netif esp_eth ethernet_init
|
PRIV_REQUIRES esp_netif esp_eth
|
||||||
INCLUDE_DIRS ".")
|
INCLUDE_DIRS ".")
|
||||||
|
@@ -1,9 +1,194 @@
|
|||||||
menu "Example Configuration"
|
menu "Example Ethernet Configuration"
|
||||||
|
|
||||||
|
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
|
||||||
|
|
||||||
|
choice EXAMPLE_ETH_PHY_INTERFACE
|
||||||
|
prompt "PHY interface"
|
||||||
|
default EXAMPLE_ETH_PHY_INTERFACE_DEFAULT
|
||||||
|
help
|
||||||
|
Select the communication interface between MAC and PHY chip.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_PHY_INTERFACE_DEFAULT
|
||||||
|
bool "Default EMAC interface configuration"
|
||||||
|
help
|
||||||
|
Will use default hardcoded ESP Ethernet MAC driver configuration
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_PHY_INTERFACE_RMII
|
||||||
|
bool "Reduced Media Independent Interface (RMII)"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
if EXAMPLE_ETH_PHY_INTERFACE_RMII
|
||||||
|
choice EXAMPLE_ETH_RMII_CLK_MODE
|
||||||
|
prompt "RMII CLK mode"
|
||||||
|
default EXAMPLE_ETH_RMII_CLK_INPUT
|
||||||
|
help
|
||||||
|
Select external or internal RMII CLK.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_CLK_INPUT
|
||||||
|
bool "Input RMII CLK from external"
|
||||||
|
help
|
||||||
|
MAC will get RMII CLK from outside.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_CLK_OUTPUT
|
||||||
|
bool "Output RMII CLK from internal"
|
||||||
|
help
|
||||||
|
Generate RMII CLK by internal PLL.
|
||||||
|
This clock can be routed to the external PHY device.
|
||||||
|
!! WARNING !!
|
||||||
|
ESP32 Errata: If you want the Ethernet to work with WiFi or BT, don’t select ESP32
|
||||||
|
as RMII CLK output as it would result in clock instability! Applicable only to ESP32,
|
||||||
|
other ESP32 SoCs (like ESP32P4) are not affected.
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_CLK_GPIO
|
||||||
|
int "RMII CLK GPIO"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_RANGE_MAX
|
||||||
|
default 50 if IDF_TARGET_ESP32P4
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
RMII CLK input or output GPIO. See datasheet for available GPIOs.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_CLK_EXT_LOOPBACK_EN
|
||||||
|
depends on !SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK && EXAMPLE_ETH_RMII_CLK_OUTPUT
|
||||||
|
bool "Enable external RMII CLK loopback input"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
RMII CLK output signal must be looped back to the EMAC externally on certain chips.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_CLK_EXT_LOOPBACK_IN_GPIO
|
||||||
|
depends on EXAMPLE_ETH_RMII_CLK_EXT_LOOPBACK_EN
|
||||||
|
int "RMII CLK loopback input GPIO"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_RANGE_MAX
|
||||||
|
default 32 if IDF_TARGET_ESP32P4
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Set GPIO number used by RMII REF CLK input to loopback internally generated RMII CLK output.
|
||||||
|
See datasheet for available GPIOs.
|
||||||
|
|
||||||
|
if SOC_EMAC_USE_MULTI_IO_MUX
|
||||||
|
config EXAMPLE_ETH_RMII_TX_EN_GPIO
|
||||||
|
int "RMII TX_EN GPIO number"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||||
|
default 49 if IDF_TARGET_ESP32P4
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Set the GPIO number used by RMII TX_EN signal.
|
||||||
|
See datasheet for available GPIOs.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_TXD0_GPIO
|
||||||
|
int "RMII TXD0 GPIO number"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||||
|
default 34 if IDF_TARGET_ESP32P4
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Set the GPIO number used by RMII TXD0 signal.
|
||||||
|
See datasheet for available GPIOs.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_TXD1_GPIO
|
||||||
|
int "RMII TXD1 GPIO number"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||||
|
default 35 if IDF_TARGET_ESP32P4
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Set the GPIO number used by RMII TXD1 signal.
|
||||||
|
See datasheet for available GPIOs.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_CRS_DV_GPIO
|
||||||
|
int "RMII CRS_DV GPIO number"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
||||||
|
default 28 if IDF_TARGET_ESP32P4
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Set the GPIO number used by RMII CRS_DV signal.
|
||||||
|
See datasheet for available GPIOs.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_RXD0_GPIO
|
||||||
|
int "RMII RXD0 GPIO number"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
||||||
|
default 29 if IDF_TARGET_ESP32P4
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Set the GPIO number used by RMII RXD0 signal.
|
||||||
|
See datasheet for available GPIOs.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_RMII_RXD1_GPIO
|
||||||
|
int "RMII RXD1 GPIO number"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
||||||
|
default 30 if IDF_TARGET_ESP32P4
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Set the GPIO number used by RMII RXD1 signal.
|
||||||
|
See datasheet for available GPIOs.
|
||||||
|
|
||||||
|
endif # SOC_EMAC_USE_MULTI_IO_MUX
|
||||||
|
|
||||||
|
endif # EXAMPLE_ETH_PHY_INTERFACE_RMII
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_MDC_GPIO
|
||||||
|
int "SMI MDC GPIO number"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||||
|
default 23 if IDF_TARGET_ESP32
|
||||||
|
default 31 if IDF_TARGET_ESP32P4
|
||||||
|
help
|
||||||
|
Set the GPIO number used by SMI MDC.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_MDIO_GPIO
|
||||||
|
int "SMI MDIO GPIO number"
|
||||||
|
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||||
|
default 18 if IDF_TARGET_ESP32
|
||||||
|
default 52 if IDF_TARGET_ESP32P4
|
||||||
|
help
|
||||||
|
Set the GPIO number used by SMI MDIO.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_PHY_ADDR
|
||||||
|
int "PHY Address"
|
||||||
|
range -1 31
|
||||||
|
default 1
|
||||||
|
help
|
||||||
|
Set PHY address according your board schematic.
|
||||||
|
Set to -1 to driver find the PHY address automatically.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_PHY_RST_GPIO
|
||||||
|
int "PHY Reset GPIO number"
|
||||||
|
range -1 ENV_GPIO_OUT_RANGE_MAX
|
||||||
|
default 5 if IDF_TARGET_ESP32
|
||||||
|
default 51 if IDF_TARGET_ESP32P4
|
||||||
|
help
|
||||||
|
Set the GPIO number used to reset PHY chip.
|
||||||
|
Set to -1 to disable PHY chip hardware reset.
|
||||||
|
|
||||||
|
menuconfig EXAMPLE_ETH_PHY_RST_TIMING_EN
|
||||||
|
bool "PHY Reset Timing configuration"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Default reset timing configuration is set conservatively. If you need faster response and
|
||||||
|
your chip supports it, enable and configure it. See PHY datasheet "AC Specification" section.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_PHY_RST_ASSERT_TIME_US
|
||||||
|
int "PHY Reset Assert Time (microseconds)"
|
||||||
|
depends on EXAMPLE_ETH_PHY_RST_TIMING_EN
|
||||||
|
range 0 100000
|
||||||
|
default 10000
|
||||||
|
help
|
||||||
|
Time in microseconds to assert the PHY reset signal.
|
||||||
|
This should be long enough to ensure the PHY chip is properly reset.
|
||||||
|
|
||||||
|
config EXAMPLE_ETH_PHY_RST_DELAY_MS
|
||||||
|
int "PHY Post-Reset Delay (milliseconds)"
|
||||||
|
depends on EXAMPLE_ETH_PHY_RST_TIMING_EN
|
||||||
|
range -1 4000
|
||||||
|
default 10
|
||||||
|
help
|
||||||
|
Delay in milliseconds after releasing the PHY reset signal.
|
||||||
|
This allows the PHY chip to stabilize before communication begins.
|
||||||
|
When no delay required, set -1.
|
||||||
|
|
||||||
config EXAMPLE_ETH_DEINIT_AFTER_S
|
config EXAMPLE_ETH_DEINIT_AFTER_S
|
||||||
int "Stop and deinit Ethernet after elapsing number of secs"
|
int "Deinitialize Ethernet after (seconds)"
|
||||||
range -1 300
|
range -1 3600
|
||||||
default -1
|
default -1
|
||||||
help
|
help
|
||||||
This option is for demonstration purposes only to demonstrate deinitialization of the Ethernet driver.
|
This option is for demonstration purposes only to demonstrate deinitialization of the Ethernet driver.
|
||||||
Set to -1 to not deinitialize.
|
Set to -1 to not deinitialize.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@@ -1,23 +1,145 @@
|
|||||||
/* Ethernet Basic Example
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
Unless required by applicable law or agreed to in writing, this
|
*
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
*/
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
#include "esp_eth.h"
|
#include "esp_eth.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "ethernet_init.h"
|
#include "esp_check.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
static const char *TAG = "eth_example";
|
static const char *TAG = "eth_basic_example";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize Ethernet driver with generic PHY (all IEEE 802.3 compliant PHYs)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param[out] eth_handle_out initialized Ethernet driver handle
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG when passed invalid pointer
|
||||||
|
* - ESP_FAIL on any other failure
|
||||||
|
*/
|
||||||
|
static esp_err_t eth_init(esp_eth_handle_t *eth_handle_out)
|
||||||
|
{
|
||||||
|
if (eth_handle_out == NULL) {
|
||||||
|
ESP_LOGE(TAG, "invalid argument: eth_handle_out cannot be NULL");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init common MAC and PHY configs to default
|
||||||
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
|
|
||||||
|
// Update PHY config based on board specific configuration
|
||||||
|
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
|
||||||
|
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
|
||||||
|
#if CONFIG_EXAMPLE_ETH_PHY_RST_TIMING_EN
|
||||||
|
phy_config.hw_reset_assert_time_us = CONFIG_EXAMPLE_ETH_PHY_RST_ASSERT_TIME_US;
|
||||||
|
phy_config.post_hw_reset_delay_ms = CONFIG_EXAMPLE_ETH_PHY_RST_DELAY_MS;
|
||||||
|
#endif // CONFIG_EXAMPLE_ETH_PHY_RST_TIMING_EN
|
||||||
|
|
||||||
|
// Init vendor specific MAC config to default
|
||||||
|
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||||
|
// Update vendor specific MAC config based on board configuration
|
||||||
|
esp32_emac_config.smi_gpio.mdc_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
|
||||||
|
esp32_emac_config.smi_gpio.mdio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_ETH_PHY_INTERFACE_RMII
|
||||||
|
// Configure RMII based on Kconfig when non-default configuration selected
|
||||||
|
esp32_emac_config.interface = EMAC_DATA_INTERFACE_RMII;
|
||||||
|
|
||||||
|
// Configure RMII clock mode and GPIO
|
||||||
|
#if CONFIG_EXAMPLE_ETH_RMII_CLK_INPUT
|
||||||
|
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_EXT_IN;
|
||||||
|
#else // CONFIG_EXAMPLE_ETH_RMII_CLK_OUTPUT
|
||||||
|
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT;
|
||||||
|
#endif
|
||||||
|
esp32_emac_config.clock_config.rmii.clock_gpio = CONFIG_EXAMPLE_ETH_RMII_CLK_GPIO;
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_ETH_RMII_CLK_EXT_LOOPBACK_EN
|
||||||
|
esp32_emac_config.clock_config.rmii.clock_loopback_gpio = CONFIG_EXAMPLE_ETH_RMII_CLK_EXT_LOOPBACK_IN_GPIO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SOC_EMAC_USE_MULTI_IO_MUX
|
||||||
|
// Configure RMII datapane GPIOs
|
||||||
|
esp32_emac_config.emac_dataif_gpio.rmii.tx_en_num = CONFIG_EXAMPLE_ETH_RMII_TX_EN_GPIO;
|
||||||
|
esp32_emac_config.emac_dataif_gpio.rmii.txd0_num = CONFIG_EXAMPLE_ETH_RMII_TXD0_GPIO;
|
||||||
|
esp32_emac_config.emac_dataif_gpio.rmii.txd1_num = CONFIG_EXAMPLE_ETH_RMII_TXD1_GPIO;
|
||||||
|
esp32_emac_config.emac_dataif_gpio.rmii.crs_dv_num = CONFIG_EXAMPLE_ETH_RMII_CRS_DV_GPIO;
|
||||||
|
esp32_emac_config.emac_dataif_gpio.rmii.rxd0_num = CONFIG_EXAMPLE_ETH_RMII_RXD0_GPIO;
|
||||||
|
esp32_emac_config.emac_dataif_gpio.rmii.rxd1_num = CONFIG_EXAMPLE_ETH_RMII_RXD1_GPIO;
|
||||||
|
#endif // SOC_EMAC_USE_MULTI_IO_MUX
|
||||||
|
#endif // CONFIG_EXAMPLE_ETH_PHY_INTERFACE_RMII
|
||||||
|
|
||||||
|
// Create new ESP32 Ethernet MAC instance
|
||||||
|
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||||
|
if (mac == NULL) {
|
||||||
|
ESP_LOGE(TAG, "create MAC instance failed");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new generic PHY instance
|
||||||
|
esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config);
|
||||||
|
if (phy == NULL) {
|
||||||
|
ESP_LOGE(TAG, "create PHY instance failed");
|
||||||
|
mac->del(mac);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init Ethernet driver to default and install it
|
||||||
|
esp_eth_handle_t eth_handle = NULL;
|
||||||
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
|
if (esp_eth_driver_install(&config, ð_handle) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Ethernet driver install failed");
|
||||||
|
mac->del(mac);
|
||||||
|
phy->del(phy);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*eth_handle_out = eth_handle;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_ETH_DEINIT_AFTER_S >= 0
|
||||||
|
/**
|
||||||
|
* @brief De-initialize Ethernet driver
|
||||||
|
* @note Ethernet driver must be stopped prior calling this function.
|
||||||
|
*
|
||||||
|
* @param[in] eth_handle Ethernet driver to be de-initialized
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG when passed invalid pointer
|
||||||
|
*/
|
||||||
|
static esp_err_t eth_deinit(esp_eth_handle_t eth_handle)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE(eth_handle != NULL, ESP_ERR_INVALID_ARG, TAG, "Ethernet handle cannot be NULL");
|
||||||
|
|
||||||
|
esp_eth_mac_t *mac = NULL;
|
||||||
|
esp_eth_phy_t *phy = NULL;
|
||||||
|
esp_eth_get_mac_instance(eth_handle, &mac);
|
||||||
|
esp_eth_get_phy_instance(eth_handle, &phy);
|
||||||
|
ESP_RETURN_ON_ERROR(esp_eth_driver_uninstall(eth_handle), TAG, "Ethernet %p uninstall failed", eth_handle);
|
||||||
|
|
||||||
|
if (mac != NULL) {
|
||||||
|
mac->del(mac);
|
||||||
|
}
|
||||||
|
if (phy != NULL) {
|
||||||
|
phy->del(phy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#endif // CONFIG_EXAMPLE_ETH_DEINIT_AFTER_S >= 0
|
||||||
|
|
||||||
/** Event handler for Ethernet events */
|
/** Event handler for Ethernet events */
|
||||||
static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||||
@@ -66,73 +188,40 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
|
|||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
// Initialize Ethernet driver
|
// Initialize Ethernet driver
|
||||||
uint8_t eth_port_cnt = 0;
|
esp_eth_handle_t eth_handle;
|
||||||
esp_eth_handle_t *eth_handles;
|
ESP_ERROR_CHECK(eth_init(ð_handle));
|
||||||
ESP_ERROR_CHECK(example_eth_init(ð_handles, ð_port_cnt));
|
|
||||||
|
|
||||||
// Initialize TCP/IP network interface aka the esp-netif (should be called only once in application)
|
// Initialize TCP/IP network interface aka the esp-netif (should be called only once in application)
|
||||||
ESP_ERROR_CHECK(esp_netif_init());
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
// Create default event loop that running in background
|
// Create default event loop that running in background
|
||||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
|
||||||
esp_netif_t *eth_netifs[eth_port_cnt];
|
// Create instance of esp-netif for Ethernet
|
||||||
esp_eth_netif_glue_handle_t eth_netif_glues[eth_port_cnt];
|
|
||||||
|
|
||||||
// Create instance(s) of esp-netif for Ethernet(s)
|
|
||||||
if (eth_port_cnt == 1) {
|
|
||||||
// Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and you don't need to modify
|
// Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and you don't need to modify
|
||||||
// default esp-netif configuration parameters.
|
// default esp-netif configuration parameters.
|
||||||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
|
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
|
||||||
eth_netifs[0] = esp_netif_new(&cfg);
|
esp_netif_t *eth_netif = esp_netif_new(&cfg);
|
||||||
eth_netif_glues[0] = esp_eth_new_netif_glue(eth_handles[0]);
|
esp_eth_netif_glue_handle_t eth_netif_glue = esp_eth_new_netif_glue(eth_handle);
|
||||||
// Attach Ethernet driver to TCP/IP stack
|
// Attach Ethernet driver to TCP/IP stack
|
||||||
ESP_ERROR_CHECK(esp_netif_attach(eth_netifs[0], eth_netif_glues[0]));
|
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, eth_netif_glue));
|
||||||
} else {
|
|
||||||
// Use ESP_NETIF_INHERENT_DEFAULT_ETH when multiple Ethernet interfaces are used and so you need to modify
|
|
||||||
// esp-netif configuration parameters for each interface (name, priority, etc.).
|
|
||||||
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
|
|
||||||
esp_netif_config_t cfg_spi = {
|
|
||||||
.base = &esp_netif_config,
|
|
||||||
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
|
|
||||||
};
|
|
||||||
char if_key_str[10];
|
|
||||||
char if_desc_str[10];
|
|
||||||
char num_str[3];
|
|
||||||
for (int i = 0; i < eth_port_cnt; i++) {
|
|
||||||
itoa(i, num_str, 10);
|
|
||||||
strcat(strcpy(if_key_str, "ETH_"), num_str);
|
|
||||||
strcat(strcpy(if_desc_str, "eth"), num_str);
|
|
||||||
esp_netif_config.if_key = if_key_str;
|
|
||||||
esp_netif_config.if_desc = if_desc_str;
|
|
||||||
esp_netif_config.route_prio -= i*5;
|
|
||||||
eth_netifs[i] = esp_netif_new(&cfg_spi);
|
|
||||||
eth_netif_glues[i] = esp_eth_new_netif_glue(eth_handles[i]);
|
|
||||||
// Attach Ethernet driver to TCP/IP stack
|
|
||||||
ESP_ERROR_CHECK(esp_netif_attach(eth_netifs[i], eth_netif_glues[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register user defined event handlers
|
// Register user defined event handlers
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
|
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
|
||||||
|
|
||||||
// Start Ethernet driver state machine
|
// Start Ethernet driver state machine
|
||||||
for (int i = 0; i < eth_port_cnt; i++) {
|
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
|
||||||
ESP_ERROR_CHECK(esp_eth_start(eth_handles[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_ETH_DEINIT_AFTER_S >= 0
|
#if CONFIG_EXAMPLE_ETH_DEINIT_AFTER_S >= 0
|
||||||
// For demonstration purposes, wait and then deinit Ethernet network
|
// For demonstration purposes, wait and then deinit Ethernet network
|
||||||
vTaskDelay(pdMS_TO_TICKS(CONFIG_EXAMPLE_ETH_DEINIT_AFTER_S * 1000));
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_EXAMPLE_ETH_DEINIT_AFTER_S * 1000));
|
||||||
ESP_LOGI(TAG, "stop and deinitialize Ethernet network...");
|
ESP_LOGI(TAG, "stop and deinitialize Ethernet network...");
|
||||||
// Stop Ethernet driver state machine and destroy netif
|
// Stop Ethernet driver state machine and destroy netif
|
||||||
for (int i = 0; i < eth_port_cnt; i++) {
|
ESP_ERROR_CHECK(esp_eth_stop(eth_handle));
|
||||||
ESP_ERROR_CHECK(esp_eth_stop(eth_handles[i]));
|
ESP_ERROR_CHECK(esp_eth_del_netif_glue(eth_netif_glue));
|
||||||
ESP_ERROR_CHECK(esp_eth_del_netif_glue(eth_netif_glues[i]));
|
esp_netif_destroy(eth_netif);
|
||||||
esp_netif_destroy(eth_netifs[i]);
|
|
||||||
}
|
|
||||||
esp_netif_deinit();
|
esp_netif_deinit();
|
||||||
ESP_ERROR_CHECK(example_eth_deinit(eth_handles, eth_port_cnt));
|
ESP_ERROR_CHECK(eth_deinit(eth_handle));
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler));
|
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler));
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler));
|
ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler));
|
||||||
ESP_ERROR_CHECK(esp_event_loop_delete_default());
|
ESP_ERROR_CHECK(esp_event_loop_delete_default());
|
||||||
|
@@ -5,19 +5,17 @@ import subprocess
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
from pytest_embedded_idf.utils import idf_parametrize
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config, target',
|
||||||
[
|
[
|
||||||
pytest.param('default_ip101', marks=[pytest.mark.eth_ip101]),
|
pytest.param('defaults', 'esp32', marks=[pytest.mark.eth_ip101]),
|
||||||
pytest.param('default_generic', marks=[pytest.mark.eth_ip101]),
|
pytest.param('lan8720_esp32', 'esp32', marks=[pytest.mark.eth_lan8720]),
|
||||||
pytest.param('default_dm9051', marks=[pytest.mark.eth_dm9051]),
|
pytest.param('defaults', 'esp32p4', marks=[pytest.mark.eth_ip101]),
|
||||||
],
|
],
|
||||||
indirect=True,
|
indirect=['target'],
|
||||||
)
|
)
|
||||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
|
||||||
def test_esp_eth_basic(dut: Dut) -> None:
|
def test_esp_eth_basic(dut: Dut) -> None:
|
||||||
# wait for ip received
|
# wait for ip received
|
||||||
dut_ip = dut.expect(r'esp_netif_handlers: .+ ip: (\d+\.\d+\.\d+\.\d+),').group(1)
|
dut_ip = dut.expect(r'esp_netif_handlers: .+ ip: (\d+\.\d+\.\d+\.\d+),').group(1)
|
||||||
@@ -25,4 +23,5 @@ def test_esp_eth_basic(dut: Dut) -> None:
|
|||||||
param = '-n' if platform.system().lower() == 'windows' else '-c'
|
param = '-n' if platform.system().lower() == 'windows' else '-c'
|
||||||
command = ['ping', param, '1', dut_ip]
|
command = ['ping', param, '1', dut_ip]
|
||||||
output = subprocess.run(command, capture_output=True)
|
output = subprocess.run(command, capture_output=True)
|
||||||
assert 'unreachable' not in str(output.stdout)
|
if 'unreachable' in str(output.stdout):
|
||||||
|
raise RuntimeError('Host unreachable')
|
||||||
|
@@ -1,5 +0,0 @@
|
|||||||
CONFIG_EXAMPLE_USE_SPI_ETHERNET=y
|
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=n
|
|
||||||
CONFIG_EXAMPLE_SPI_ETHERNETS_NUM=1
|
|
||||||
CONFIG_EXAMPLE_USE_DM9051=y
|
|
||||||
CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ=20
|
|
@@ -1,9 +0,0 @@
|
|||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
|
||||||
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
|
||||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
|
||||||
|
|
||||||
CONFIG_ETH_ENABLED=y
|
|
||||||
CONFIG_ETH_USE_ESP32_EMAC=y
|
|
@@ -1,9 +0,0 @@
|
|||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
|
||||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
|
||||||
|
|
||||||
CONFIG_ETH_ENABLED=y
|
|
||||||
CONFIG_ETH_USE_ESP32_EMAC=y
|
|
2
examples/ethernet/basic/sdkconfig.ci.defaults
Normal file
2
examples/ethernet/basic/sdkconfig.ci.defaults
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_ETH_ENABLED=y
|
||||||
|
CONFIG_ETH_USE_ESP32_EMAC=y
|
8
examples/ethernet/basic/sdkconfig.ci.lan8720_esp32
Normal file
8
examples/ethernet/basic/sdkconfig.ci.lan8720_esp32
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# RMII GPIO Configuration to align with LAN8720 test board
|
||||||
|
CONFIG_IDF_TARGET="esp32"
|
||||||
|
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_INTERFACE_RMII=y
|
||||||
|
CONFIG_EXAMPLE_ETH_RMII_CLK_OUTPUT=y
|
||||||
|
CONFIG_EXAMPLE_ETH_RMII_CLK_GPIO=17
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=0
|
2
examples/ethernet/basic/sdkconfig.defaults
Normal file
2
examples/ethernet/basic/sdkconfig.defaults
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_ETH_ENABLED=y
|
||||||
|
CONFIG_ETH_USE_ESP32_EMAC=y
|
@@ -15,9 +15,12 @@ The cli environment in the example is based on the [console component](https://d
|
|||||||
|
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a supported Ethernet PHY chip. Up until now, ESP-IDF supports up to four Ethernet PHY: `LAN8720`, `IP101`, `DP83848` and `RTL8201`, additional PHY drivers should be implemented by users themselves.
|
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a supported Ethernet PHY chip. Espressif supports multiple Ethernet PHYs. The full list of supported PHYs is available at [esp-eth-drivers](https://github.com/espressif/esp-eth-drivers) repository. If your PHY is IEEE 802.3 compliant, you can use `Generic PHY` driver for most use cases.
|
||||||
|
|
||||||
Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). This example will take the **DM9051** as an example, illustrating how to install the Ethernet driver in the same manner.
|
Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). The full list of supported SPI Ethernet modules is also available at [esp-eth-drivers](https://github.com/espressif/esp-eth-drivers) repository.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> `Generic 802.3 PHY` basic functionality should always work for PHY compliant with IEEE 802.3. However, some specific features might be limited. A typical example is loopback functionality, where certain PHYs may require setting a specific speed mode to operate correctly. If this is a case, use driver tailored to that specific chip.
|
||||||
|
|
||||||
#### Pin Assignment
|
#### Pin Assignment
|
||||||
|
|
||||||
|
@@ -2,6 +2,6 @@ dependencies:
|
|||||||
cmd_system:
|
cmd_system:
|
||||||
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system
|
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system
|
||||||
espressif/ethernet_init:
|
espressif/ethernet_init:
|
||||||
version: "0.7.0"
|
version: "*"
|
||||||
espressif/iperf-cmd:
|
espressif/iperf-cmd:
|
||||||
version: "~0.1.1"
|
version: "~0.1.1"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
espressif/ethernet_init:
|
espressif/ethernet_init:
|
||||||
version: "0.7.0"
|
version: "*"
|
||||||
esp_eth_time:
|
esp_eth_time:
|
||||||
path: ${IDF_PATH}/examples/ethernet/ptp/components/esp_eth_time
|
path: ${IDF_PATH}/examples/ethernet/ptp/components/esp_eth_time
|
||||||
ptpd:
|
ptpd:
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
espressif/ethernet_init:
|
espressif/ethernet_init:
|
||||||
version: "0.7.0"
|
version: "*"
|
||||||
|
@@ -17,13 +17,12 @@ The similarities on MAC layer between Ethernet and Wi-Fi make it easy to forward
|
|||||||
|
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a supported Ethernet PHY chip. Up until now, ESP-IDF supports up to four Ethernet PHY: `LAN8720`, `IP101`, `DP83848` and `RTL8201`, additional PHY drivers should be implemented by users themselves.
|
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a supported Ethernet PHY chip. Espressif supports multiple Ethernet PHYs. The full list of supported PHYs is available at [esp-eth-drivers](https://github.com/espressif/esp-eth-drivers) repository. If your PHY is IEEE 802.3 compliant, you can use `Generic PHY` driver for most use cases.
|
||||||
|
|
||||||
Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). This example will take the **DM9051** as an example, illustrating how to install the Ethernet driver in the same manner.
|
Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). The full list of supported SPI Ethernet modules is also available at [esp-eth-drivers](https://github.com/espressif/esp-eth-drivers) repository.
|
||||||
|
|
||||||
#### Pin Assignment
|
> [!NOTE]
|
||||||
|
> `Generic 802.3 PHY` basic functionality should always work for PHY compliant with IEEE 802.3. However, some specific features might be limited. A typical example is loopback functionality, where certain PHYs may require setting a specific speed mode to operate correctly. If this is a case, use driver tailored to that specific chip.
|
||||||
See common pin assignments for Ethernet examples from [upper level](../README.md#common-pin-assignments).
|
|
||||||
|
|
||||||
### Configure the project
|
### Configure the project
|
||||||
|
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
espressif/ethernet_init:
|
espressif/ethernet_init:
|
||||||
version: "0.7.0"
|
version: "*"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
pcap: "^1.0.0"
|
pcap: "^1.0.0"
|
||||||
espressif/ethernet_init:
|
espressif/ethernet_init:
|
||||||
version: "0.7.0"
|
version: "*"
|
||||||
|
@@ -8,6 +8,6 @@ dependencies:
|
|||||||
dns_server:
|
dns_server:
|
||||||
path: ${IDF_PATH}/examples/protocols/http_server/captive_portal/components/dns_server
|
path: ${IDF_PATH}/examples/protocols/http_server/captive_portal/components/dns_server
|
||||||
espressif/ethernet_init:
|
espressif/ethernet_init:
|
||||||
version: "0.7.0"
|
version: "*"
|
||||||
espressif/network_provisioning:
|
espressif/network_provisioning:
|
||||||
version: "^1.0.5"
|
version: "^1.0.5"
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
espressif/ethernet_init:
|
espressif/ethernet_init:
|
||||||
version: "0.7.0"
|
version: "*"
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -3,7 +3,7 @@ CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -3,7 +3,7 @@ CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -3,7 +3,7 @@ CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -3,7 +3,7 @@ CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -3,7 +3,7 @@ CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -5,7 +5,7 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs"
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -7,7 +7,7 @@ CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -13,7 +13,7 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -3,7 +3,7 @@ CONFIG_BROKER_URL="FROM_STDIN"
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -2,7 +2,7 @@ CONFIG_BROKER_URI="ws://${EXAMPLE_MQTT_BROKER_WS}/ws"
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -3,7 +3,7 @@ CONFIG_BROKER_CERTIFICATE_OVERRIDE="${EXAMPLE_MQTT_BROKER_CERTIFICATE}"
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -7,7 +7,7 @@ CONFIG_EXAMPLE_CONNECT_IPV6=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
@@ -7,7 +7,7 @@ CONFIG_EXAMPLE_CONNECT_IPV6=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=31
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=31
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=52
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=52
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=51
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=51
|
@@ -1,3 +1,3 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
espressif/ethernet_init:
|
espressif/ethernet_init:
|
||||||
version: "0.7.0"
|
version: "*"
|
||||||
|
@@ -6,7 +6,7 @@ CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=3000
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -14,7 +14,7 @@ CONFIG_BOOTLOADER_APP_SECURE_VERSION=1
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -7,7 +7,7 @@ CONFIG_EXAMPLE_ENABLE_OTA_RESUMPTION=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -9,7 +9,7 @@ CONFIG_EXAMPLE_ENABLE_OTA_RESUMPTION=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -10,7 +10,7 @@ CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -6,7 +6,7 @@ CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=3000
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -14,7 +14,7 @@ CONFIG_SECURE_BOOT_SIGNING_KEY="test/secure_boot_signing_key_ecdsa.pem"
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -16,7 +16,7 @@ CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
@@ -5,7 +5,7 @@ CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
|
|||||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user