feat(esp_eth): a new folder structure of the driver and other improvements

Fixed memory leak in emac_esp_new_dma function.

Polished ESP EMAC cache management.

Added emac_periph definitions based on SoC features and improved(generalized) ESP EMAC GPIO
initialization.

Added ESP EMAC GPIO reservation.

Added check for frame error condition indicated by EMAC DMA and created a target test.
This commit is contained in:
Ondrej Kosta
2024-04-26 12:27:54 +02:00
parent ee8a9e8410
commit d15a9c2c48
63 changed files with 2068 additions and 1442 deletions
+12 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,6 +14,17 @@
extern "C" {
#endif
/**
* @brief Offset for start of MAC custom ioctl commands
*
*/
#define ETH_CMD_CUSTOM_MAC_CMDS_OFFSET 0x0FFF
/**
* @brief Offset for start of PHY custom ioctl commands
*
*/
#define ETH_CMD_CUSTOM_PHY_CMDS_OFFSET 0x1FFF
/**
* @brief Ethernet driver state
*
+36 -6
View File
@@ -1,12 +1,20 @@
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_eth_com.h"
#include "esp_eth_mac.h"
#if CONFIG_ETH_USE_SPI_ETHERNET
#include "esp_eth_mac_spi.h"
#endif // CONFIG_ETH_USE_SPI_ETHERNET
#if CONFIG_ETH_USE_ESP32_EMAC
#include "esp_eth_mac_esp.h"
#endif // CONFIG_ETH_USE_ESP32_EMAC
#if CONFIG_ETH_USE_OPENETH
#include "esp_eth_mac_openeth.h"
#endif // CONFIG_ETH_USE_OPENETH
#include "esp_eth_phy.h"
#ifdef __cplusplus
@@ -151,8 +159,8 @@ typedef enum {
ETH_CMD_READ_PHY_REG, /*!< Read PHY register */
ETH_CMD_WRITE_PHY_REG, /*!< Write PHY register */
ETH_CMD_CUSTOM_MAC_CMDS = 0x0FFF, // Offset for start of MAC custom commands
ETH_CMD_CUSTOM_PHY_CMDS = 0x1FFF, // Offset for start of PHY custom commands
ETH_CMD_CUSTOM_MAC_CMDS = ETH_CMD_CUSTOM_MAC_CMDS_OFFSET, // Offset for start of MAC custom commands
ETH_CMD_CUSTOM_PHY_CMDS = ETH_CMD_CUSTOM_PHY_CMDS_OFFSET, // Offset for start of PHY custom commands
} esp_eth_io_cmd_t;
/**
@@ -272,7 +280,7 @@ esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length);
* @param[in] argc number variable arguments
* @param ... variable arguments
* @return
* - ESP_OK: transmit successfull
* - ESP_OK: transmit successful
* - ESP_ERR_INVALID_STATE: invalid driver state (e.i. driver is not started)
* - ESP_ERR_TIMEOUT: transmit frame buffer failed because HW was not get available in predefined period
* - ESP_FAIL: transmit frame buffer failed because some other error occurred
@@ -280,7 +288,7 @@ esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length);
esp_err_t esp_eth_transmit_vargs(esp_eth_handle_t hdl, uint32_t argc, ...);
/**
* @brief Misc IO function of Etherent driver
* @brief Misc IO function of Ethernet driver
*
* @param[in] hdl: handle of Ethernet driver
* @param[in] cmd: IO control command
@@ -314,6 +322,28 @@ esp_err_t esp_eth_transmit_vargs(esp_eth_handle_t hdl, uint32_t argc, ...);
*/
esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data);
/**
* @brief Get PHY instance memory address
*
* @param[in] hdl handle of Ethernet driver
* @param[out] phy pointer to memory to store the instance
* @return esp_err_t
* - ESP_OK: success
* - ESP_ERR_INVALID_ARG: failed because of some invalid argument
*/
esp_err_t esp_eth_get_phy_instance(esp_eth_handle_t hdl, esp_eth_phy_t **phy);
/**
* @brief Get MAC instance memory address
*
* @param[in] hdl handle of Ethernet driver
* @param[out] mac pointer to memory to store the instance
* @return esp_err_t
* - ESP_OK: success
* - ESP_ERR_INVALID_ARG: failed because of some invalid argument
*/
esp_err_t esp_eth_get_mac_instance(esp_eth_handle_t hdl, esp_eth_mac_t **mac);
/**
* @brief Increase Ethernet driver reference
* @note Ethernet driver handle can be obtained by os timer, netif, etc.
+1 -434
View File
@@ -9,9 +9,6 @@
#include "soc/soc_caps.h"
#include "esp_eth_com.h"
#include "sdkconfig.h"
#if CONFIG_ETH_USE_SPI_ETHERNET
#include "driver/spi_master.h"
#endif
#ifdef __cplusplus
extern "C" {
@@ -306,7 +303,7 @@ struct esp_eth_mac_s {
* - ESP_FAIL: process io command failed because some other error occurred
* - ESP_ERR_NOT_SUPPORTED: requested feature is not supported
*/
esp_err_t (*custom_ioctl)(esp_eth_mac_t *mac, uint32_t cmd, void *data);
esp_err_t (*custom_ioctl)(esp_eth_mac_t *mac, int cmd, void *data);
/**
* @brief Free memory of Ethernet MAC
@@ -321,115 +318,6 @@ struct esp_eth_mac_s {
esp_err_t (*del)(esp_eth_mac_t *mac);
};
/**
* @brief RMII Clock Mode Options
*
*/
typedef enum {
/**
* @brief Default values configured using Kconfig are going to be used when "Default" selected.
*
* @note May not be supported on all targets.
*
*/
EMAC_CLK_DEFAULT,
/**
* @brief Input RMII Clock from external. EMAC Clock GPIO number needs to be configured when this option is selected.
*
* @note MAC will get RMII clock from outside. Note that ESP32 only supports GPIO0 to input the RMII clock.
*
*/
EMAC_CLK_EXT_IN,
/**
* @brief Output RMII Clock from internal (A/M)PLL Clock. EMAC Clock GPIO number needs to be configured when this option is selected.
*
*/
EMAC_CLK_OUT
} emac_rmii_clock_mode_t;
#if CONFIG_IDF_TARGET_ESP32
/**
* @brief RMII Clock GPIO number Options for ESP32
*
*/
typedef enum {
/**
* @brief MAC will get RMII clock from outside at this GPIO.
*
* @note ESP32 only supports GPIO0 to input the RMII clock.
*
*/
EMAC_CLK_IN_GPIO = 0,
/**
* @brief Output RMII Clock from internal APLL Clock available at GPIO0
*
* @note GPIO0 can be set to output a pre-divided PLL clock (test only!). Enabling this option will configure GPIO0 to output a 50MHz clock.
* In fact this clock doesnt have directly relationship with EMAC peripheral. Sometimes this clock wont work well with your PHY chip.
* You might need to add some extra devices after GPIO0 (e.g. inverter). Note that outputting RMII clock on GPIO0 is an experimental practice.
* If you want the Ethernet to work with WiFi, dont select GPIO0 output mode for stability.
*
*/
EMAC_APPL_CLK_OUT_GPIO = 0,
/**
* @brief Output RMII Clock from internal APLL Clock available at GPIO16
*
*/
EMAC_CLK_OUT_GPIO = 16,
/**
* @brief Inverted Output RMII Clock from internal APLL Clock available at GPIO17
*
*/
EMAC_CLK_OUT_180_GPIO = 17
} emac_rmii_clock_gpio_t;
#else
/**
* @brief RMII Clock GPIO number
*
*/
typedef int emac_rmii_clock_gpio_t;
#endif // CONFIG_IDF_TARGET_ESP32
/**
* @brief Ethernet MAC Clock Configuration
*
*/
typedef union {
struct {
// MII interface is not fully implemented...
// Reserved for GPIO number, clock source, etc. in MII mode
} mii; /*!< EMAC MII Clock Configuration */
struct {
emac_rmii_clock_mode_t clock_mode; /*!< RMII Clock Mode Configuration */
emac_rmii_clock_gpio_t clock_gpio; /*!< RMII Clock GPIO Configuration */
} rmii; /*!< EMAC RMII Clock Configuration */
} eth_mac_clock_config_t;
#if SOC_EMAC_USE_IO_MUX
/**
* @brief Ethernet MAC MII/RMII data plane GPIO configuration
*
*/
typedef union {
struct {
// MII interface is not fully implemented...
// Reserved for data interface GPIO numbers in MII mode
} mii; /*!< EMAC MII Data GPIO Configuration */
struct {
int32_t tx_en_num; /*!< TX_EN GPIO number */
int32_t txd0_num; /*!< TXD0 GPIO number */
int32_t txd1_num; /*!< TXD1 GPIO number */
int32_t crs_dv_num; /*!< CRS_DV GPIO number */
int32_t rxd0_num; /*!< RXD0 GPIO number */
int32_t rxd1_num; /*!< RXD1 GPIO number */
} rmii; /*!< EMAC RMII Data GPIO Configuration */
} eth_mac_dataif_gpio_config_t;
#endif // SOC_EMAC_USE_IO_MUX
/**
* @brief Configuration of Ethernet MAC object
*
@@ -456,327 +344,6 @@ typedef struct {
.flags = 0, \
}
#if CONFIG_ETH_USE_ESP32_EMAC
/**
* @brief EMAC specific configuration
*
*/
typedef struct {
int smi_mdc_gpio_num; /*!< SMI MDC GPIO number, set to -1 could bypass the SMI GPIO configuration */
int smi_mdio_gpio_num; /*!< SMI MDIO GPIO number, set to -1 could bypass the SMI GPIO configuration */
eth_data_interface_t interface; /*!< EMAC Data interface to PHY (MII/RMII) */
eth_mac_clock_config_t clock_config; /*!< EMAC Interface clock configuration */
eth_mac_dma_burst_len_t dma_burst_len; /*!< EMAC DMA burst length for both Tx and Rx */
int intr_priority; /*!< EMAC interrupt priority, if set to 0 or a negative value, the driver will try to allocate an interrupt with a default priority */
#if SOC_EMAC_USE_IO_MUX
eth_mac_dataif_gpio_config_t emac_dataif_gpio; /*!< EMAC MII/RMII data plane GPIO configuration */
#endif // SOC_EMAC_USE_IO_MUX
#if !SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK
eth_mac_clock_config_t clock_config_out_in; /*!< EMAC input clock configuration for internally generated output clock (when output clock is looped back externally) */
#endif //SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK
} eth_esp32_emac_config_t;
/**
* @brief Default ESP32's EMAC specific configuration
*
*/
#if CONFIG_IDF_TARGET_ESP32
#define ETH_ESP32_EMAC_DEFAULT_CONFIG() \
{ \
.smi_mdc_gpio_num = 23, \
.smi_mdio_gpio_num = 18, \
.interface = EMAC_DATA_INTERFACE_RMII, \
.clock_config = \
{ \
.rmii = \
{ \
.clock_mode = EMAC_CLK_DEFAULT, \
.clock_gpio = EMAC_CLK_IN_GPIO \
} \
}, \
.dma_burst_len = ETH_DMA_BURST_LEN_32, \
.intr_priority = 0, \
}
#elif CONFIG_IDF_TARGET_ESP32P4
#define ETH_ESP32_EMAC_DEFAULT_CONFIG() \
{ \
.smi_mdc_gpio_num = 31, \
.smi_mdio_gpio_num = 27, \
.interface = EMAC_DATA_INTERFACE_RMII, \
.clock_config = \
{ \
.rmii = \
{ \
.clock_mode = EMAC_CLK_EXT_IN, \
.clock_gpio = 50 \
} \
}, \
.clock_config_out_in = \
{ \
.rmii = \
{ \
.clock_mode = EMAC_CLK_DEFAULT, \
.clock_gpio = -1 \
} \
}, \
.dma_burst_len = ETH_DMA_BURST_LEN_32, \
.intr_priority = 0, \
.emac_dataif_gpio = \
{ \
.rmii = \
{ \
.tx_en_num = 49, \
.txd0_num = 34, \
.txd1_num = 35, \
.crs_dv_num = 28, \
.rxd0_num = 29, \
.rxd1_num = 30 \
} \
}, \
}
#endif // CONFIG_IDF_TARGET_ESP32P4
/**
* @brief Create ESP32 Ethernet MAC instance
*
* @param esp32_config: EMAC specific configuration
* @param 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_esp32(const eth_esp32_emac_config_t *esp32_config, const eth_mac_config_t *config);
#endif // CONFIG_ETH_USE_ESP32_EMAC
#if CONFIG_ETH_USE_SPI_ETHERNET
/**
* @brief Custom SPI Driver Configuration.
* This structure declares configuration and callback functions to access Ethernet SPI module via
* user's custom SPI driver.
*
*/
typedef struct
{
/**
* @brief Custom driver specific configuration data used by `init()` function.
*
* @note Type and its content is fully under user's control
*
*/
void *config;
/**
* @brief Custom driver SPI Initialization
*
* @param[in] spi_config: Custom driver specific configuration
*
* @return
* - spi_ctx: when initialization is successful, a pointer to context structure holding all variables
* needed for subsequent SPI access operations (e.g. SPI bus identification, mutexes, etc.)
* - NULL: driver initialization failed
*
* @note return type and its content is fully under user's control
*/
void *(*init)(const void *spi_config);
/**
* @brief Custom driver De-initialization
*
* @param[in] spi_ctx: a pointer to driver specific context structure
*
* @return
* - ESP_OK: driver de-initialization was successful
* - ESP_FAIL: driver de-initialization failed
* - any other failure codes are allowed to be used to provide failure isolation
*/
esp_err_t (*deinit)(void *spi_ctx);
/**
* @brief Custom driver SPI read
*
* @note The read function is responsible to construct command, address and data fields
* of the SPI frame in format expected by particular SPI Ethernet module
*
* @param[in] spi_ctx: a pointer to driver specific context structure
* @param[in] cmd: command
* @param[in] addr: register address
* @param[out] data: read data
* @param[in] data_len: read data length in bytes
*
* @return
* - ESP_OK: read was successful
* - ESP_FAIL: read failed
* - any other failure codes are allowed to be used to provide failure isolation
*/
esp_err_t (*read)(void *spi_ctx, uint32_t cmd, uint32_t addr, void *data, uint32_t data_len);
/**
* @brief Custom driver SPI write
*
* @note The write function is responsible to construct command, address and data fields
* of the SPI frame in format expected by particular SPI Ethernet module
*
* @param[in] spi_ctx: a pointer to driver specific context structure
* @param[in] cmd: command
* @param[in] addr: register address
* @param[in] data: data to write
* @param[in] data_len: length of data to write in bytes
*
* @return
* - ESP_OK: write was successful
* - ESP_FAIL: write failed
* - any other failure codes are allowed to be used to provide failure isolation
*/
esp_err_t (*write)(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len);
} eth_spi_custom_driver_config_t;
/**
* @brief Default configuration of the custom SPI driver.
* Internal ESP-IDF SPI Master driver is used by default.
*
*/
#define ETH_DEFAULT_SPI \
{ \
.config = NULL, \
.init = NULL, \
.deinit = NULL, \
.read = NULL, \
.write = NULL \
}
#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
#if CONFIG_ETH_USE_OPENETH
/**
* @brief Create OpenCores Ethernet MAC instance
*
* @param 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_openeth(const eth_mac_config_t *config);
#endif // CONFIG_ETH_USE_OPENETH
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,296 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "esp_eth_com.h"
#include "esp_eth_mac.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_ETH_USE_ESP32_EMAC
/**
* @brief RMII Clock Mode Options
*
*/
typedef enum {
/**
* @brief Default values configured using Kconfig are going to be used when "Default" selected.
*
* @warning Deprecated option. Clock configuration using Kconfig is limitedly supported only for ESP32 SoC via @c ETH_ESP32_EMAC_DEFAULT_CONFIG
* and is going to be reevaluated in the next major release.
* Clock mode and clock GPIO number is supposed to be defined in `EMAC specific configuration` structure from user's code.
*
*/
EMAC_CLK_DEFAULT __attribute__((deprecated)), // IDF-9724
/**
* @brief Input RMII Clock from external. EMAC Clock GPIO number needs to be configured when this option is selected.
*
* @note MAC will get RMII clock from outside. Note that ESP32 only supports GPIO0 to input the RMII clock.
*
*/
EMAC_CLK_EXT_IN,
/**
* @brief Output RMII Clock from internal (A/M)PLL Clock. EMAC Clock GPIO number needs to be configured when this option is selected.
*
*/
EMAC_CLK_OUT
} emac_rmii_clock_mode_t;
#if CONFIG_IDF_TARGET_ESP32
/**
* @brief RMII Clock GPIO number Options for ESP32
*
*/
typedef enum {
/**
* @brief MAC will get RMII clock from outside at this GPIO.
*
* @note ESP32 only supports GPIO0 to input the RMII clock.
*
*/
EMAC_CLK_IN_GPIO = 0,
/**
* @brief Output RMII Clock from internal APLL Clock available at GPIO0
*
* @note GPIO0 can be set to output a pre-divided PLL clock (test only!). Enabling this option will configure GPIO0 to output a 50MHz clock.
* In fact this clock doesnt have directly relationship with EMAC peripheral. Sometimes this clock wont work well with your PHY chip.
* You might need to add some extra devices after GPIO0 (e.g. inverter). Note that outputting RMII clock on GPIO0 is an experimental practice.
* If you want the Ethernet to work with WiFi, dont select GPIO0 output mode for stability.
*
*/
EMAC_APPL_CLK_OUT_GPIO = 0,
/**
* @brief Output RMII Clock from internal APLL Clock available at GPIO16
*
*/
EMAC_CLK_OUT_GPIO = 16,
/**
* @brief Inverted Output RMII Clock from internal APLL Clock available at GPIO17
*
*/
EMAC_CLK_OUT_180_GPIO = 17
} emac_rmii_clock_gpio_t;
#else
/**
* @brief RMII Clock GPIO number
*
*/
typedef int emac_rmii_clock_gpio_t;
#endif // CONFIG_IDF_TARGET_ESP32
/**
* @brief Ethernet MAC Clock Configuration
*
*/
typedef union {
struct {
// MII interface is not fully implemented...
// Reserved for GPIO number, clock source, etc. in MII mode
} mii; /*!< EMAC MII Clock Configuration */
struct {
emac_rmii_clock_mode_t clock_mode; /*!< RMII Clock Mode Configuration */
emac_rmii_clock_gpio_t clock_gpio; /*!< RMII Clock GPIO Configuration */
} rmii; /*!< EMAC RMII Clock Configuration */
} eth_mac_clock_config_t;
/**
* @brief EMAC SMI GPIO configuration
*/
typedef struct {
int mdc_num; /*!< SMI MDC GPIO number, set to -1 could bypass the SMI GPIO configuration */
int mdio_num; /*!< SMI MDIO GPIO number, set to -1 could bypass the SMI GPIO configuration */
} emac_esp_smi_gpio_config_t;
/**
* @brief EMAC MII data interface GPIO configuration
*/
typedef struct {
int tx_clk_num; /*!< TX_CLK GPIO number */
int tx_en_num; /*!< TX_EN GPIO number */
int txd0_num; /*!< TXD0 GPIO number */
int txd1_num; /*!< TXD1 GPIO number */
int txd2_num; /*!< TXD2 GPIO number */
int txd3_num; /*!< TXD3 GPIO number */
int rx_clk_num; /*!< RX_CLK GPIO number */
int rx_dv_num; /*!< RX_DV GPIO number */
int rxd0_num; /*!< RXD0 GPIO number */
int rxd1_num; /*!< RXD1 GPIO number */
int rxd2_num; /*!< RXD2 GPIO number */
int rxd3_num; /*!< RXD3 GPIO number */
int col_in_num; /*!< COL_IN GPIO number */
int crs_in_num; /*!< CRS_IN GPIO number */
int tx_er_num; /*!< TX_ER GPIO number */
int rx_er_num; /*!< RX_ER GPIO number */
} eth_mac_mii_gpio_config_t;
/**
* @brief EMAC RMII data interface GPIO configuration
*/
typedef struct {
int tx_en_num; /*!< TX_EN GPIO number */
int txd0_num; /*!< TXD0 GPIO number */
int txd1_num; /*!< TXD1 GPIO number */
int crs_dv_num; /*!< CRS_DV GPIO number */
int rxd0_num; /*!< RXD0 GPIO number */
int rxd1_num; /*!< RXD1 GPIO number */
} eth_mac_rmii_gpio_config_t;
#if SOC_EMAC_USE_MULTI_IO_MUX || SOC_EMAC_MII_USE_GPIO_MATRIX
/**
* @brief Ethernet MAC MII/RMII data plane GPIO configuration
*
*/
typedef union {
eth_mac_mii_gpio_config_t mii; /*!< EMAC MII Data GPIO Configuration */
eth_mac_rmii_gpio_config_t rmii; /*!< EMAC RMII Data GPIO Configuration */
} eth_mac_dataif_gpio_config_t;
#endif // SOC_EMAC_USE_MULTI_IO_MUX
/**
* @brief EMAC specific configuration
*
*/
typedef struct {
union {
emac_esp_smi_gpio_config_t smi_gpio; /*!< SMI GPIO numbers */
struct {
int smi_mdc_gpio_num __attribute__((deprecated("Please use smi_gpio instead"))); /*!< SMI MDC GPIO number, set to -1 could bypass the SMI GPIO configuration */
int smi_mdio_gpio_num __attribute__((deprecated("Please use smi_gpio instead"))); /*!< SMI MDIO GPIO number, set to -1 could bypass the SMI GPIO configuration */
};
};
eth_data_interface_t interface; /*!< EMAC Data interface to PHY (MII/RMII) */
eth_mac_clock_config_t clock_config; /*!< EMAC Interface clock configuration */
eth_mac_dma_burst_len_t dma_burst_len; /*!< EMAC DMA burst length for both Tx and Rx */
int intr_priority; /*!< EMAC interrupt priority, if set to 0 or a negative value, the driver will try to allocate an interrupt with a default priority */
#if SOC_EMAC_USE_MULTI_IO_MUX || SOC_EMAC_MII_USE_GPIO_MATRIX
eth_mac_dataif_gpio_config_t emac_dataif_gpio; /*!< EMAC MII/RMII data plane GPIO configuration */
#endif // SOC_EMAC_USE_MULTI_IO_MUX
#if !SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK
eth_mac_clock_config_t clock_config_out_in; /*!< EMAC input clock configuration for internally generated output clock (when output clock is looped back externally) */
#endif //SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK
} eth_esp32_emac_config_t;
/**
* @brief List of ESP EMAC specific commands for ioctl API
*
*/
typedef enum {
ETH_MAC_ESP_CMD_SET_TDES0_CFG_BITS = ETH_CMD_CUSTOM_MAC_CMDS_OFFSET, /*!< Set Transmit Descriptor Word 0 control bit mask (debug option)*/
ETH_MAC_ESP_CMD_CLEAR_TDES0_CFG_BITS, /*!< Clear Transmit Descriptor Word 0 control bit mask (debug option)*/
ETH_MAC_ESP_CMD_PTP_ENABLE, /*!< Enable IEEE1588 Time stamping */
} eth_mac_esp_io_cmd_t;
/**
* @brief Default ESP32's EMAC specific configuration
*
*/
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_ETH_RMII_CLK_INPUT // IDF-9724
#define DEFAULT_RMII_CLK_MODE EMAC_CLK_EXT_IN
#if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
#define DEFAULT_RMII_CLK_GPIO CONFIG_ETH_RMII_CLK_IN_GPIO
#else
#error "ESP32 EMAC only support input RMII clock to GPIO0"
#endif // CONFIG_ETH_RMII_CLK_IN_GPIO == 0
#elif CONFIG_ETH_RMII_CLK_OUTPUT
#define DEFAULT_RMII_CLK_MODE EMAC_CLK_OUT
#if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
#define DEFAULT_RMII_CLK_GPIO EMAC_APPL_CLK_OUT_GPIO
#else
#define DEFAULT_RMII_CLK_GPIO CONFIG_ETH_RMII_CLK_OUT_GPIO
#endif // CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
#else
#error "Unsupported RMII clock mode"
#endif // CONFIG_ETH_RMII_CLK_INPUT
#define ETH_ESP32_EMAC_DEFAULT_CONFIG() \
{ \
.smi_gpio = \
{ \
.mdc_num = 23, \
.mdio_num = 18 \
}, \
.interface = EMAC_DATA_INTERFACE_RMII, \
.clock_config = \
{ \
.rmii = \
{ \
.clock_mode = DEFAULT_RMII_CLK_MODE, \
.clock_gpio = DEFAULT_RMII_CLK_GPIO \
} \
}, \
.dma_burst_len = ETH_DMA_BURST_LEN_32, \
.intr_priority = 0, \
}
#elif CONFIG_IDF_TARGET_ESP32P4
#define ETH_ESP32_EMAC_DEFAULT_CONFIG() \
{ \
.smi_gpio = \
{ \
.mdc_num = 31, \
.mdio_num = 27 \
}, \
.interface = EMAC_DATA_INTERFACE_RMII, \
.clock_config = \
{ \
.rmii = \
{ \
.clock_mode = EMAC_CLK_EXT_IN, \
.clock_gpio = 50 \
} \
}, \
.clock_config_out_in = \
{ \
.rmii = \
{ \
.clock_mode = EMAC_CLK_EXT_IN, \
.clock_gpio = -1 \
} \
}, \
.dma_burst_len = ETH_DMA_BURST_LEN_32, \
.intr_priority = 0, \
.emac_dataif_gpio = \
{ \
.rmii = \
{ \
.tx_en_num = 49, \
.txd0_num = 34, \
.txd1_num = 35, \
.crs_dv_num = 28, \
.rxd0_num = 29, \
.rxd1_num = 30 \
} \
}, \
}
#endif // CONFIG_IDF_TARGET_ESP32P4
/**
* @brief Create ESP32 Ethernet MAC instance
*
* @param esp32_config: EMAC specific configuration
* @param 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_esp32(const eth_esp32_emac_config_t *esp32_config, const eth_mac_config_t *config);
#endif // CONFIG_ETH_USE_ESP32_EMAC
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_eth_com.h"
#include "esp_eth_mac.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_ETH_USE_OPENETH
/**
* @brief Create OpenCores Ethernet MAC instance
*
* @param 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_openeth(const eth_mac_config_t *config);
#endif // CONFIG_ETH_USE_OPENETH
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,236 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "esp_eth_com.h"
#include "esp_eth_mac.h"
#include "sdkconfig.h"
#include "driver/spi_master.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_ETH_USE_SPI_ETHERNET
/**
* @brief Custom SPI Driver Configuration.
* This structure declares configuration and callback functions to access Ethernet SPI module via
* user's custom SPI driver.
*
*/
typedef struct
{
/**
* @brief Custom driver specific configuration data used by `init()` function.
*
* @note Type and its content is fully under user's control
*
*/
void *config;
/**
* @brief Custom driver SPI Initialization
*
* @param[in] spi_config: Custom driver specific configuration
*
* @return
* - spi_ctx: when initialization is successful, a pointer to context structure holding all variables
* needed for subsequent SPI access operations (e.g. SPI bus identification, mutexes, etc.)
* - NULL: driver initialization failed
*
* @note return type and its content is fully under user's control
*/
void *(*init)(const void *spi_config);
/**
* @brief Custom driver De-initialization
*
* @param[in] spi_ctx: a pointer to driver specific context structure
*
* @return
* - ESP_OK: driver de-initialization was successful
* - ESP_FAIL: driver de-initialization failed
* - any other failure codes are allowed to be used to provide failure isolation
*/
esp_err_t (*deinit)(void *spi_ctx);
/**
* @brief Custom driver SPI read
*
* @note The read function is responsible to construct command, address and data fields
* of the SPI frame in format expected by particular SPI Ethernet module
*
* @param[in] spi_ctx: a pointer to driver specific context structure
* @param[in] cmd: command
* @param[in] addr: register address
* @param[out] data: read data
* @param[in] data_len: read data length in bytes
*
* @return
* - ESP_OK: read was successful
* - ESP_FAIL: read failed
* - any other failure codes are allowed to be used to provide failure isolation
*/
esp_err_t (*read)(void *spi_ctx, uint32_t cmd, uint32_t addr, void *data, uint32_t data_len);
/**
* @brief Custom driver SPI write
*
* @note The write function is responsible to construct command, address and data fields
* of the SPI frame in format expected by particular SPI Ethernet module
*
* @param[in] spi_ctx: a pointer to driver specific context structure
* @param[in] cmd: command
* @param[in] addr: register address
* @param[in] data: data to write
* @param[in] data_len: length of data to write in bytes
*
* @return
* - ESP_OK: write was successful
* - ESP_FAIL: write failed
* - any other failure codes are allowed to be used to provide failure isolation
*/
esp_err_t (*write)(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len);
} eth_spi_custom_driver_config_t;
/**
* @brief Default configuration of the custom SPI driver.
* Internal ESP-IDF SPI Master driver is used by default.
*
*/
#define ETH_DEFAULT_SPI \
{ \
.config = NULL, \
.init = NULL, \
.deinit = NULL, \
.read = NULL, \
.write = NULL \
}
#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
}
#endif
+2 -2
View File
@@ -16,7 +16,7 @@ extern "C" {
#define ESP_ETH_PHY_ADDR_AUTO (-1)
/**
* @brief Auto-negotiation controll commands
* @brief Auto-negotiation control commands
*
*/
typedef enum {
@@ -253,7 +253,7 @@ struct esp_eth_phy_s {
* - ESP_FAIL: process io command failed because some other error occurred
* - ESP_ERR_NOT_SUPPORTED: requested feature is not supported
*/
esp_err_t (*custom_ioctl)(esp_eth_phy_t *phy, uint32_t cmd, void *data);
esp_err_t (*custom_ioctl)(esp_eth_phy_t *phy, int cmd, void *data);
/**
* @brief Free memory of Ethernet PHY instance
+32 -32
View File
@@ -6,7 +6,7 @@
#pragma once
#include <stdbool.h>
#include "esp_eth.h"
#include "esp_eth_phy.h"
#include "sdkconfig.h"
#include "eth_phy_802_3_regs.h"
@@ -45,7 +45,7 @@ typedef enum {
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param eth Ethernet mediator pointer
* @return
* - ESP_OK: Ethermet mediator set successfuly
* - ESP_OK: Ethermet mediator set successfully
* - ESP_ERR_INVALID_ARG: if @c eth is @c NULL
*/
esp_err_t esp_eth_phy_802_3_set_mediator(phy_802_3_t *phy_802_3, esp_eth_mediator_t *eth);
@@ -55,8 +55,8 @@ esp_err_t esp_eth_phy_802_3_set_mediator(phy_802_3_t *phy_802_3, esp_eth_mediato
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @return
* - ESP_OK: Ethernet PHY reset successfuly
* - ESP_FAIL: reset Ethernet PHY failed because some error occured
* - ESP_OK: Ethernet PHY reset successfully
* - ESP_FAIL: reset Ethernet PHY failed because some error occurred
*/
esp_err_t esp_eth_phy_802_3_reset(phy_802_3_t *phy_802_3);
@@ -67,8 +67,8 @@ esp_err_t esp_eth_phy_802_3_reset(phy_802_3_t *phy_802_3);
* @param cmd autonegotiation command enumeration
* @param[out] autonego_en_stat autonegotiation enabled flag
* @return
* - ESP_OK: Ethernet PHY autonegotiation configured successfuly
* - ESP_FAIL: Ethernet PHY autonegotiation configuration fail because some error occured
* - ESP_OK: Ethernet PHY autonegotiation configured successfully
* - ESP_FAIL: Ethernet PHY autonegotiation configuration fail because some error occurred
* - ESP_ERR_INVALID_ARG: invalid value of @c cmd
*/
esp_err_t esp_eth_phy_802_3_autonego_ctrl(phy_802_3_t *phy_802_3, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat);
@@ -79,8 +79,8 @@ esp_err_t esp_eth_phy_802_3_autonego_ctrl(phy_802_3_t *phy_802_3, eth_phy_autone
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param enable set true to power ON Ethernet PHY; set false to power OFF Ethernet PHY
* @return
* - ESP_OK: Ethernet PHY power down mode set successfuly
* - ESP_FAIL: Ethernet PHY power up or power down failed because some error occured
* - ESP_OK: Ethernet PHY power down mode set successfully
* - ESP_FAIL: Ethernet PHY power up or power down failed because some error occurred
*/
esp_err_t esp_eth_phy_802_3_pwrctl(phy_802_3_t *phy_802_3, bool enable);
@@ -100,7 +100,7 @@ esp_err_t esp_eth_phy_802_3_set_addr(phy_802_3_t *phy_802_3, uint32_t addr);
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param[out] addr Ethernet PHY address
* @return
* - ESP_OK: Ethernet PHY address read successfuly
* - ESP_OK: Ethernet PHY address read successfully
* - ESP_ERR_INVALID_ARG: @c addr pointer is @c NULL
*/
esp_err_t esp_eth_phy_802_3_get_addr(phy_802_3_t *phy_802_3, uint32_t *addr);
@@ -111,8 +111,8 @@ esp_err_t esp_eth_phy_802_3_get_addr(phy_802_3_t *phy_802_3, uint32_t *addr);
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param ability enable or disable pause ability
* @return
* - ESP_OK: pause ability set successfuly
* - ESP_FAIL: Advertise pause function ability failed because some error occured
* - ESP_OK: pause ability set successfully
* - ESP_FAIL: Advertise pause function ability failed because some error occurred
*/
esp_err_t esp_eth_phy_802_3_advertise_pause_ability(phy_802_3_t *phy_802_3, uint32_t ability);
@@ -122,8 +122,8 @@ esp_err_t esp_eth_phy_802_3_advertise_pause_ability(phy_802_3_t *phy_802_3, uint
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param enable set true to enable loopback; set false to disable loopback
* @return
* - ESP_OK: Ethernet PHY loopback mode set successfuly
* - ESP_FAIL: Ethernet PHY loopback configuration failed because some error occured
* - ESP_OK: Ethernet PHY loopback mode set successfully
* - ESP_FAIL: Ethernet PHY loopback configuration failed because some error occurred
*/
esp_err_t esp_eth_phy_802_3_loopback(phy_802_3_t *phy_802_3, bool enable);
@@ -133,8 +133,8 @@ esp_err_t esp_eth_phy_802_3_loopback(phy_802_3_t *phy_802_3, bool enable);
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param speed new speed of Ethernet PHY link
* @return
* - ESP_OK: Ethernet PHY speed set successfuly
* - ESP_FAIL: Set Ethernet PHY speed failed because some error occured
* - ESP_OK: Ethernet PHY speed set successfully
* - ESP_FAIL: Set Ethernet PHY speed failed because some error occurred
*/
esp_err_t esp_eth_phy_802_3_set_speed(phy_802_3_t *phy_802_3, eth_speed_t speed);
@@ -144,9 +144,9 @@ esp_err_t esp_eth_phy_802_3_set_speed(phy_802_3_t *phy_802_3, eth_speed_t speed)
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param duplex new duplex mode for Ethernet PHY link
* @return
* - ESP_OK: Ethernet PHY duplex mode set successfuly
* - ESP_OK: Ethernet PHY duplex mode set successfully
* - ESP_ERR_INVALID_STATE: unable to set duplex mode to Half if loopback is enabled
* - ESP_FAIL: Set Ethernet PHY duplex mode failed because some error occured
* - ESP_FAIL: Set Ethernet PHY duplex mode failed because some error occurred
*/
esp_err_t esp_eth_phy_802_3_set_duplex(phy_802_3_t *phy_802_3, eth_duplex_t duplex);
@@ -156,7 +156,7 @@ esp_err_t esp_eth_phy_802_3_set_duplex(phy_802_3_t *phy_802_3, eth_duplex_t dupl
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param link new link status
* @return
* - ESP_OK: Ethernet PHY link set successfuly
* - ESP_OK: Ethernet PHY link set successfully
*/
esp_err_t esp_eth_phy_802_3_set_link(phy_802_3_t *phy_802_3, eth_link_t link);
@@ -165,7 +165,7 @@ esp_err_t esp_eth_phy_802_3_set_link(phy_802_3_t *phy_802_3, eth_link_t link);
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @return
* - ESP_OK: Ethernet PHY initialized successfuly
* - ESP_OK: Ethernet PHY initialized successfully
*/
esp_err_t esp_eth_phy_802_3_init(phy_802_3_t *phy_802_3);
@@ -174,7 +174,7 @@ esp_err_t esp_eth_phy_802_3_init(phy_802_3_t *phy_802_3);
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @return
* - ESP_OK: Ethernet PHY powered off successfuly
* - ESP_OK: Ethernet PHY powered off successfully
*/
esp_err_t esp_eth_phy_802_3_deinit(phy_802_3_t *phy_802_3);
@@ -275,8 +275,8 @@ esp_err_t esp_eth_phy_802_3_read_manufac_info(phy_802_3_t *phy_802_3, uint8_t *m
* @param devaddr Address of MDIO device
* @param[out] mmd_addr Current address stored in device's register
* @return
* - ESP_OK: Address register read successfuly
* - ESP_FAIL: Address register read failed because of some error occured
* - ESP_OK: Address register read successfully
* - ESP_FAIL: Address register read failed because of some error occurred
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits)
*/
esp_err_t esp_eth_phy_802_3_get_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t *mmd_addr);
@@ -288,8 +288,8 @@ esp_err_t esp_eth_phy_802_3_get_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr
* @param devaddr Address of MDIO device
* @param[out] mmd_addr New value of MDIO device's address register value
* @return
* - ESP_OK: Address register written to successfuly
* - ESP_FAIL: Address register write failed because of some error occured
* - ESP_OK: Address register written to successfully
* - ESP_FAIL: Address register write failed because of some error occurred
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits)
*/
esp_err_t esp_eth_phy_802_3_set_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr);
@@ -302,8 +302,8 @@ esp_err_t esp_eth_phy_802_3_set_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr
* @param function MMD function
* @param[out] data Data read from the device's memory
* @return
* - ESP_OK: Memory read successfuly
* - ESP_FAIL: Memory read failed because of some error occured
* - ESP_OK: Memory read successfully
* - ESP_FAIL: Memory read failed because of some error occurred
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits) or MMD access function is invalid
*/
esp_err_t esp_eth_phy_802_3_read_mmd_data(phy_802_3_t *phy_802_3, uint8_t devaddr, esp_eth_phy_802_3_mmd_func_t function, uint32_t *data);
@@ -316,8 +316,8 @@ esp_err_t esp_eth_phy_802_3_read_mmd_data(phy_802_3_t *phy_802_3, uint8_t devadd
* @param function MMD function
* @param[out] data Data to write to the device's memory
* @return
* - ESP_OK: Memory written successfuly
* - ESP_FAIL: Memory write failed because of some error occured
* - ESP_OK: Memory written successfully
* - ESP_FAIL: Memory write failed because of some error occurred
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits) or MMD access function is invalid
*/
esp_err_t esp_eth_phy_802_3_write_mmd_data(phy_802_3_t *phy_802_3, uint8_t devaddr, esp_eth_phy_802_3_mmd_func_t function, uint32_t data);
@@ -330,8 +330,8 @@ esp_err_t esp_eth_phy_802_3_write_mmd_data(phy_802_3_t *phy_802_3, uint8_t devad
* @param mmd_addr Address of MDIO device register
* @param[out] data Data read from the device's memory
* @return
* - ESP_OK: Memory read successfuly
* - ESP_FAIL: Memory read failed because of some error occured
* - ESP_OK: Memory read successfully
* - ESP_FAIL: Memory read failed because of some error occurred
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits)
*/
esp_err_t esp_eth_phy_802_3_read_mmd_register(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr, uint32_t *data);
@@ -344,8 +344,8 @@ esp_err_t esp_eth_phy_802_3_read_mmd_register(phy_802_3_t *phy_802_3, uint8_t de
* @param mmd_addr Address of MDIO device register
* @param[out] data Data to write to the device's memory
* @return
* - ESP_OK: Memory written to successfuly
* - ESP_FAIL: Memory write failed because of some error occured
* - ESP_OK: Memory written to successfully
* - ESP_FAIL: Memory write failed because of some error occurred
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits)
*/
esp_err_t esp_eth_phy_802_3_write_mmd_register(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr, uint32_t data);
@@ -15,20 +15,144 @@ extern "C" {
* @brief Indicate to ::emac_esp_dma_receive_frame that receive frame buffer was allocated by ::emac_esp_dma_alloc_recv_buf
*
*/
#define EMAC_HAL_BUF_SIZE_AUTO 0
#define EMAC_DMA_BUF_SIZE_AUTO 0
/**
* @brief EMAC DMA handle
*
*/
typedef struct emac_esp_dma_t *emac_esp_dma_handle_t;
typedef void *emac_esp_dma_config_t;
void emac_esp_dma_reset_desc_chain(emac_esp_dma_handle_t emac_esp_dma);
/**
* @brief EMAC DMA configuration
* @note Currently just a placeholder
*
*/
typedef struct emac_esp_dma_config_t emac_esp_dma_config_t;
/**
* @brief Reset DMA
* @note This function should be called prior each EMAC start
*
* @param[in] emac_esp_dma EMAC DMA handle
*/
void emac_esp_dma_reset(emac_esp_dma_handle_t emac_esp_dma);
/**
* @brief Transmit data from buffer over EMAC
*
* @param[in] emac_esp_dma EMAC DMA handle
* @param[in] buf buffer to be transmitted
* @param[in] length length of the buffer
* @return number of transmitted bytes on success
* zero on fail
*/
uint32_t emac_esp_dma_transmit_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t *buf, uint32_t length);
uint32_t emac_esp_dma_transmit_multiple_buf_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t **buffs, uint32_t *lengths, uint32_t buffs_cnt);
uint8_t *emac_esp_dma_alloc_recv_buf(emac_esp_dma_handle_t emac_esp_dma, uint32_t *size);
uint32_t emac_esp_dma_receive_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t *buf, uint32_t size, uint32_t *frames_remain, uint32_t *free_desc);
void emac_esp_dma_flush_recv_frame(emac_esp_dma_handle_t emac_esp_dma, uint32_t *frames_remain, uint32_t *free_desc);
/**
* @brief Transmit data from multiple buffers over EMAC in single Ethernet frame. Data will be joint into
* single frame in order in which the buffers are stored in input array.
*
* @param[in] emac_esp_dma EMAC DMA handle
* @param[in] buffs array of pointers to buffers to be transmitted
* @param[in] lengths array of lengths of the buffers
* @param[in] inbuffs_cnt number of buffers (i.e. input arrays size)
* @return number of transmitted bytes on success
* zero on fail
*
* @pre @p lengths array must have the same size as @p buffs array and their elements need to be stored in the same
* order, i.e. lengths[1] is a length associated with data buffer referenced at buffs[1] position.
*/
uint32_t emac_esp_dma_transmit_multiple_buf_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t **buffs, uint32_t *lengths, uint32_t buffs_cnt);
/**
* @brief Allocate buffer with size equal to actually received Ethernet frame size.
*
* @param[in] emac_esp_dma EMAC DMA handle
* @param[in, out] size as an input defines maximum size of buffer to be allocated. As an output, indicates actual size of received
* Ethernet frame which is waiting to be processed. Returned size may be 0 when there is no waiting valid frame.
*
* @note If maximum allowed size of buffer to be allocated is less than actual size of received Ethernet frame, the buffer
* is allocated with that limit and the frame will be truncated by emac_hal_receive_frame.
*
* @return Pointer to allocated buffer
* NULL when allocation fails (returned @p size is non-zero)
* NULL when there is no waiting Ethernet frame (returned @p size is zero)
*/
uint8_t *emac_esp_dma_alloc_recv_buf(emac_esp_dma_handle_t emac_esp_dma, uint32_t *size);
/**
* @brief Copy received Ethernet frame from EMAC DMA memory space to application.
*
* @param[in] emac_esp_dma EMAC DMA handle
* @param[in] buf buffer into which the Ethernet frame is to be copied
* @param[in] size buffer size. When buffer was allocated by ::emac_esp_dma_alloc_recv_buf, this parameter needs to be set
* to @c EMAC_DMA_BUF_SIZE_AUTO
*
* @return - number of copied bytes when success
* - number of bytes of received Ethernet frame when maximum allowed buffer @p size is less than actual size of
* received Ethernet frame and @p size is NOT set to @c EMAC_DMA_BUF_SIZE_AUTO
* - 0 when there is no waiting Ethernet frame or on frame error when @p size is NOT set to @c EMAC_DMA_BUF_SIZE_AUTO
*
* @note When this function is called with @c EMAC_DMA_BUF_SIZE_AUTO size option (preferred), buffer needs to be
* successfully allocated by ::emac_esp_dma_alloc_recv_buf function at first.
* @note When this function is NOT called with @c EMAC_DMA_BUF_SIZE_AUTO size option and maximum allowed buffer @p size
* is less than actual size of received Ethernet frame, the frame will be truncated.
* @note FCS field is never copied
*/
uint32_t emac_esp_dma_receive_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t *buf, uint32_t size);
/**
* @brief Flush frame stored in Rx DMA
*
* @param[in] emac_esp_dma EMAC DMA handle
*/
void emac_esp_dma_flush_recv_frame(emac_esp_dma_handle_t emac_esp_dma);
/**
* @brief Get number of frames remaining in Rx DMA
*
* @param[in] emac_esp_dma EMAC DMA handle
* @param[out] frames_remain number of frames remaining to be processed
* @param[out] free_desc number of free DMA Rx descriptors
*/
void emac_esp_dma_get_remain_frames(emac_esp_dma_handle_t emac_esp_dma, uint32_t *remain_frames, uint32_t *used_descs);
/**
* @brief Set the Transmit Descriptor Word 0 (TDES0) control bits
*
* @param[in] emac_esp_dma EMAC DMA handle
* @param[in] bit_mask mask of control bits to be set
*/
void emac_esp_dma_set_tdes0_ctrl_bits(emac_esp_dma_handle_t emac_esp_dma, uint32_t bit_mask);
/**
* @brief Clear the Transmit Descriptor Word 0 (TDES0) control bits
*
* @param[in] emac_esp_dma EMAC DMA handle
* @param[in] bit_mask mask of control bits to be cleared
*/
void emac_esp_dma_clear_tdes0_ctrl_bits(emac_esp_dma_handle_t emac_esp_dma, uint32_t bit_mask);
/**
* @brief Creates a new instance of the ESP EMAC DMA
*
* @param config ESP EMAC DMA configuration
* @param[out] ret_handle EMAC DMA handle
* @return esp_err_t
* ESP_OK on success
* ESP_ERR_NO_MEM when there is not enough memory to allocate instance
*/
esp_err_t emac_esp_new_dma(const emac_esp_dma_config_t* config, emac_esp_dma_handle_t *ret_handle);
/**
* @brief Deletes the ESP EMAC DMA instance
*
* @param[in] emac_esp_dma EMAC DMA handle
* @return esp_err_t
* ESP_OK on success
*/
esp_err_t emac_esp_del_dma(emac_esp_dma_handle_t emac_esp_dma);
#ifdef __cplusplus
@@ -10,53 +10,23 @@ extern "C" {
#endif
#include "esp_err.h"
#include "esp_eth_mac.h"
#include "esp_eth_mac_esp.h"
/**
* @brief EMAC SMI GPIO configuration
*/
typedef struct {
int mdc_num;
int mdio_num;
} emac_esp_smi_gpio_config_t;
#if CONFIG_ETH_USE_ESP32_EMAC
/**
* @brief EMAC MII data interface GPIO configuration
*/
typedef struct {
uint8_t tx_clk_num;
uint8_t tx_en_num;
uint8_t txd0_num;
uint8_t txd1_num;
uint8_t txd2_num;
uint8_t txd3_num;
uint8_t rx_clk_num;
uint8_t rx_dv_num;
uint8_t rxd0_num;
uint8_t rxd1_num;
uint8_t rxd2_num;
uint8_t rxd3_num;
} emac_esp_mii_gpio_config_t;
/**
* @brief EMAC RMII data interface GPIO configuration
*/
typedef struct {
uint8_t tx_en_num;
uint8_t txd0_num;
uint8_t txd1_num;
uint8_t crs_dv_num;
uint8_t rxd0_num;
uint8_t rxd1_num;
} emac_esp_rmii_gpio_config_t;
esp_err_t emac_esp_iomux_init_mii(emac_esp_mii_gpio_config_t *mii_gpio);
esp_err_t emac_esp_iomux_init_rmii(emac_esp_rmii_gpio_config_t *rmii_gpio);
esp_err_t emac_esp_gpio_matrix_init_mii(const eth_mac_mii_gpio_config_t *mii_gpio);
esp_err_t emac_esp_iomux_init_mii(const eth_mac_mii_gpio_config_t *mii_gpio);
esp_err_t emac_esp_iomux_init_rmii(const eth_mac_rmii_gpio_config_t *rmii_gpio);
esp_err_t emac_esp_iomux_rmii_clk_input(int num);
esp_err_t emac_esp_iomux_rmii_clk_ouput(int num);
esp_err_t emac_esp_iomux_init_tx_er(int num);
esp_err_t emac_esp_iomux_init_rx_er(int num);
void emac_esp32_gpio_init_smi(emac_esp_smi_gpio_config_t *smi_gpio);
esp_err_t emac_esp_iomux_rmii_init_tx_er(int num);
esp_err_t emac_esp_iomux_rmii_init_rx_er(int num);
esp_err_t emac_esp_iomux_mii_init_tx_er(int num);
esp_err_t emac_esp_iomux_mii_init_rx_er(int num);
esp_err_t emac_esp_gpio_init_smi(const emac_esp_smi_gpio_config_t *smi_gpio);
esp_err_t emac_esp_gpio_deinit_all(void);
#endif // CONFIG_ETH_USE_ESP32_EMAC
#ifdef __cplusplus
}