# 以太网

[English]

## 概述

ESP-IDF 提供一系列灵活度高且兼具一致性的 API，为内部以太网 MAC (EMAC) 控制器和外部 SPI-Ethernet 模块提供支持。

本编程指南分为以下几个部分：

> 1. 以太网基本概念

> 2. 配置 MAC 和 PHY

> 3. 连接驱动程序至 TCP/IP 协议栈

> 4. 以太网驱动程序的杂项控制

## 以太网基本概念

以太网是一种异步的带冲突检测的载波侦听多路访问 (CSMA/CD) 协议/接口。通常来说，以太网不太适用于低功耗应用。然而，得益于其广泛的部署、高效的网络连接、高数据率以及范围不限的可扩展性，几乎所有的有线通信都可以通过以太网进行。

符合 IEEE 802.3 标准的正常以太网帧的长度在 64 至 1518 字节之间，由五个或六个不同的字段组成：目的地 MAC 地址 (DA)、源 MAC 地址 (SA)、类型/长度字段、数据有效载荷字段、可选的填充字段和帧校验序列字段 (CRC)。此外，在以太网上传输时，以太网数据包的开头需附加 7 字节的前导码和 1 字节的帧起始符 (SOF)。

因此，双绞线上的通信如图所示：

以太网数据帧格式

### 前导码和帧起始符

前导码包含 7 字节的 `55H`，作用是使接收器在实际帧到达之前锁定数据流。

帧前界定符 (SFD) 为二进制序列 `10101011` （物理介质层可见）。有时它也被视作前导码的一部分。

在传输和接收数据时，协议将自动从数据包中生成/移除前导码和帧起始符。

### 目的地址 (DA)

目的地址字段包含一个 6 字节长的设备 MAC 地址，数据包将发送到该地址。如果 MAC 地址第一个字节中的最低有效位是 1，则该地址为组播地址。例如，01-00-00-F0-00 和 33-45-67-89-AB-CD 是组播地址，而 00-00-00-F0-00 和 32-45-67-89-AB-CD 不是。

带有组播地址的数据包将到达选定的一组以太网节点，并发挥重要作用。如果目的地址字段是保留的多播地址，即 FF-FF-FF-FF-FF-FF，则该数据包是一个广播数据包，指向共享网络中的每个对象。如果 MAC 地址的第一个字节中的最低有效位为 0，则该地址为单播地址，仅供寻址节点使用。

通常，EMAC 控制器会集成接收过滤器，用于丢弃或接收带有组播、广播和/或单播目的地址的数据包。传输数据包时，由主机控制器将所需的目标地址写入传输缓冲区。

### 源地址 (SA)

源地址字段包含一个 6 字节长的节点 MAC 地址，以太网数据包通过该节点创建。以太网的用户需为所使用的任意控制器生成唯一的 MAC 地址。MAC 地址由两部分组成：前三个字节称为组织唯一标识符 (OUI)，由 IEEE 分配；后三个字节是地址字节，由购买 OUI 的公司配置。有关 ESP-IDF 中使用的 MAC 地址的详细信息，请参见 MAC 地址分配。

传输数据包时，由主机控制器将分配的源 MAC 地址写入传输缓冲区。

### 类型/长度

类型/长度字段长度为 2 字节。如果其值 <= 1500（十进制），则该字段为长度字段，指定在数据字段后的非填充数据量；如果其值 >= 1536，则该字段值表示后续数据包所属的协议。以下为该字段的常见值：

> - IPv4 = 0800H

> - IPv6 = 86DDH

> - ARP = 0806H

使用专有网络的用户可以将此字段配置为长度字段。然而，对于使用互联网协议 (IP) 或地址解析协议 (ARP) 等协议的应用程序，在传输数据包时，应将此字段配置为协议规范定义的适当类型。

### 数据有效载荷

数据有效载荷字段是一个可变长度的字段，长度从 0 到 1500 字节不等。更大的数据包会因违反以太网标准而被大多数以太网节点丢弃。

数据有效载荷字段包含客户端数据，如 IP 数据报。

### 填充及帧校验序列 (FCS)

填充字段是一个可变长度的字段。数据有效载荷较小时，将添加填充字段以满足 IEEE 802.3 规范的要求。

以太网数据包的 DA、SA、类型、数据有效载荷和填充字段共计必须不小于 60 字节。加上所需的 4 字节 FCS 字段，数据包的长度必须不小于 64 字节。如果数据有效载荷字段小于 46 字节，则需要加上一个填充字段。

帧校验序列字段 (FCS) 长度为 4 字节，其中包含一个行业标准的 32 位 CRC，该 CRC 是根据 DA、SA、类型、数据有效载荷和填充字段的数据计算的。鉴于计算 CRC 的复杂性，硬件通常会自动生成一个有效的 CRC 进行传输。否则，需由主机控制器生成 CRC 并将其写入传输缓冲区。

通常情况下，主机控制器无需关注填充字段和 CRC 字段，因为这两部分可以在传输或接收时由硬件 EMAC 自动生成或验证。然而，当数据包到达时，填充字段和 CRC 字段将被写入接收缓冲区。因此，如果需要的话，主机控制器也可以对它们进行评估。

备注

除了上述的基本数据帧，在 10/100 Mbps 以太网中还有两种常见的帧类型：控制帧和 VLAN 标记帧。ESP-IDF 不支持这两种帧类型。

## 配置 MAC 和 PHY

以太网驱动器由两部分组成：MAC 和 PHY。

MAC 和 PHY 之间的通信可以通过多种方式进行，如： MII （媒体独立接口）、 RMII （简化媒体独立接口）等。

以太网 RMII 接口

MII 和 RMII 的一个明显区别在于其所需的信号数。MII 通常需要多达 18 个信号，RMII 接口则仅需要 9 个信号。

备注

ESP-IDF 只支持 RMII 接口，所以请将 `eth_esp32_emac_config_t::interface` 设置为 `eth_data_interface_t::EMAC_DATA_INTERFACE_RMII`。

在 RMII 模式下，接收器和发射器信号的参考时钟为 `REF_CLK`。 在访问 PHY 和 MAC 时，REF_CLK 必须保持稳定。一般来说，根据设计中 PHY 设备的特征，可通过以下三种方式生成 `REF_CLK`：

- 一些 PHY 芯片可以从其外部连接的 25 MHz 晶体振荡器中衍生出 `REF_CLK` （如图中的选项 a 所示）。对于此类芯片，请将 `eth_esp32_emac_config_t::clock_config` 中的 `eth_mac_clock_config_t::clock_mode` 设置为 `emac_rmii_clock_mode_t::EMAC_CLK_EXT_IN`。

- 一些 PHY 芯片使用外接的 50 MHz 晶体振荡器或其他时钟源作为 MAC 端的 `REF_CLK` （如图中的选项 b 所示）。对于此类芯片，请同样将 `eth_esp32_emac_config_t::clock_config` 中的 `eth_mac_clock_config_t::clock_mode` 设置为 `emac_rmii_clock_mode_t::EMAC_CLK_EXT_IN`。

- 一些 EMAC 控制器可以使用其内部的高精度 PLL 生成 `REF_CLK` （如图中的选项 c 所示）。此种情况下，请将 `eth_esp32_emac_config_t::clock_config` 中的 `eth_mac_clock_config_t::clock_mode` 设置为 `emac_rmii_clock_mode_t::EMAC_CLK_OUT`。

警告

如果将 RMII 时钟模式配置为 `emac_rmii_clock_mode_t::EMAC_CLK_OUT`，则会使用内部音频 PLL (APLL) 时钟作为 50 MHz 时钟源。因此，请确保该配置不会与 I2S 总线的配置发生冲突。

当选择内部时钟时，可以使用 `GPIO0` 输出 `REF_CLK` 信号。然而，在这种情况下时钟是直接输出到 GPIO 的，因此与 EMAC 外设并没有直接关联。有时这种配置可能无法很好地兼容所使用的 PHY 芯片。如果设计中未使用 PSRAM，则还可以使用 GPIO16 和 GPIO17 来输出参考时钟信号。其时钟源相同（均来自 APLL），但这些信号是通过 EMAC 外设引出的。

如果配置 RMII 时钟模式为 `emac_rmii_clock_mode_t::EMAC_CLK_EXT_IN`，那么只能选择 `GPIO0` 输入 `REF_CLK` 信号。请注意， `GPIO0` 同时也是 ESP32 上一个重要的 strapping GPIO 管脚。如果上电时 GPIO0 为低电平，则 ESP32 将进入下载模式，需进行手动复位重启系统。解决这个问题的方法是，在硬件中默认禁用 `REF_CLK`，从而避免 strapping 管脚在启动阶段受到其他信号的干扰。随后，再在以太网驱动安装阶段重新启用 `REF_CLK`。

可以通过以下方法禁用 `REF_CLK` 信号：

- 禁用或关闭晶体振荡器的电源（对应图中的选项 b）。

- 强制复位 PHY 设备（对应图中的选项 a）。此种方法并不适用于所有 PHY 设备 （即便处于复位状态，某些 PHY 设备仍会向 GPIO0 输出信号）。

警告

如希望 以太网与 Wi-Fi 一起工作，不要选择 ESP32 作为 `REF_CLK` 的源，因为这会导致 `REF_CLK` 不稳定。可以选择禁用 Wi-Fi，或使用 PHY 或外部振荡器作为 `REF_CLK` 的源。

无论选择哪种 RMII 时钟模式，都请确保硬件设计中 REF_CLK 的信号完整性！ 信号线越短越好，并远离 RF 设备和电感。

备注

数据平面中使用的信号通过 IO_MUX 连接至特定的 GPIO，这些信号无法配置到其他 GPIO 上。控制平面中使用的信号可以通过矩阵路由到任何空闲的 GPIO 上。相关硬件设计示例，请参阅 ESP32-Ethernet-Kit。

根据以太网板设计，需要分别为 MAC 和 PHY 配置必要的参数，通过两者完成驱动程序的安装。

MAC 的相关配置可以在 `eth_mac_config_t` 中找到，具体包括：

- `eth_mac_config_t::sw_reset_timeout_ms`：软件复位超时值，单位为毫秒。通常，MAC 复位应在 100 ms 内完成。

- `eth_mac_config_t::rx_task_stack_size` 和 `eth_mac_config_t::rx_task_prio`：MAC 驱动会创建一个专门的任务来处理传入的数据包，这两个参数用于设置该任务的堆栈大小和优先级。

- `eth_mac_config_t::flags`：指定 MAC 驱动应支持的额外功能，尤其适用于某些特殊情况。这个字段的值支持与以 `ETH_MAC_FLAG_` 为前缀的宏进行 OR 运算。例如，如果要求 MAC 驱动程序在 cache 禁用时仍能正常工作，那么则需要用 `ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE` 配置这个字段。

`eth_esp32_emac_config_t` 描述了 内部 MAC 模块 的特定配置，其中包括：

- `eth_esp32_emac_config_t::smi_mdc_gpio_num` 和 `eth_esp32_emac_config_t::smi_mdio_gpio_num`：连接 SMI 信号的 GPIO 编号。

- `eth_esp32_emac_config_t::interface`：配置到 PHY (MII/RMII) 的 MAC 数据接口。

- `eth_esp32_emac_config_t::clock_config`：配置 EMAC 接口时钟（RMII 模式下的 `REF_CLK` 模式以及 GPIO 编号）。

- `eth_esp32_emac_config_t::intr_priority`： 设置 MAC 中断的优先级。如果设置为 `0` 或负值，则驱动程序将分配一个具有默认优先级的中断。否则，驱动程序将使用给定的优先级。请注意，可以设置 低、 中 中断优先级（1 到 3），因为这可以在 C 中处理。

### 使用内部 MAC 时的内存注意事项

内部 MAC 子系统通过 DMA 使用描述符链表在 CPU 域之间传输数据。描述符有发送和接收两种类型，分别保存接收或已发送帧的状态信息，或提供传输控制。每个描述符还包含指向当前数据缓冲区和下一个描述符的指针。因此，在支持 DMA 的内存中，单个 EMAC DMA 描述符的大小为 32 字节。

默认配置应涵盖大多数用例。然而，某些情况可能需要对以太网 DMA 内存的使用进行配置，以满足特定需求。典型问题可能发生于下列情形：

- 网络流量由短且频繁的帧主导时：如果你的网络流量主要由短且频繁发送（或接收）的帧组成，可能会遇到吞吐量低于预期（尽管额定为 100 Mbps），以及接收过程中丢帧等问题。在发送时，套接字发送 API 可能会返回 `errno` 为 `ENOMEM`，并显示 TX 缓冲区大小不足`（如果启用了调试日志级别）。这些问题的主要原因是，默认的内存配置针对较大帧进行了优化。默认情况下 :ref:`CONFIG_ETH_DMA_BUFFER_SIZE 设置为 512 字节，以确保 数据缓冲区 与 描述符 大小的开销比。要解决此问题，可以增加缓冲区数量， CONFIG_ETH_DMA_RX_BUFFER_NUM 或 CONFIG_ETH_DMA_TX_BUFFER_NUM。此外，还可以减小 CONFIG_ETH_DMA_BUFFER_SIZE，使其与网络中典型帧的大小相匹配，从而合理控制以太网驱动的内存占用。

- 高吞吐量导致缓冲区耗尽时：如果套接字发送 API 间歇性返回 `errno` 为 `ENOMEM`，并显示 TX 缓冲区大小不足`（如果启用了调试日志级别），且吞吐量接近额定的 100 Mbps，这通常表明接近硬件限制。在这种情况下，硬件无法跟上传输请求。解决方案是，增加 :ref:`CONFIG_ETH_DMA_TX_BUFFER_NUM，以缓存更多的帧，并缓解传输请求的短时峰值。然而，如果请求的流量持续超过额定吞吐量，此方法将失效，需通过应用层通过软件限制带宽。

PHY 的相关配置可以在 `eth_phy_config_t` 中找到，具体包括：

- `eth_phy_config_t::phy_addr`：同一条 SMI 总线上可以存在多个 PHY 设备，所以有必要为各个 PHY 设备分配唯一地址。通常，这个地址是在硬件设计期间，通过拉高/拉低一些 PHY strapping 管脚来配置的。根据不同的以太网开发板，可配置值为 `0` 到 `15`。需注意，如果 SMI 总线上仅有一个 PHY 设备，将该值配置为 `-1`，即可使驱动程序自动检测 PHY 地址。

- `eth_phy_config_t::reset_timeout_ms`：复位超时值，单位为毫秒。通常，PHY 复位应在 100 ms 内完成。

- `eth_phy_config_t::autonego_timeout_ms`：自动协商超时值，单位为毫秒。以太网驱动程序会与链路另一端的设备进行自协商，以确定连接的最佳双工模式和速率。此值通常取决于电路板上 PHY 设备的性能。

- `eth_phy_config_t::reset_gpio_num`：如果开发板同时将 PHY 复位管脚连接至了任意 GPIO 管脚，请使用该字段进行配置。否则，配置为 `-1`。

- `eth_phy_config_t::hw_reset_assert_time_us`：PHY 复位引脚被置为有效状态的时间（以微秒为单位）。将该值配置为 `0`，即可使用芯片默认的复位时长。

- `eth_phy_config_t::post_hw_reset_delay_ms`：PHY 硬件复位完成后的等待时间（以毫秒为单位）。将该值配置为 `0`，即可使用芯片默认的等待时长，配置为 `-1`，表示执行 PHY 硬件复位后不等待。

ESP-IDF 在宏 `ETH_MAC_DEFAULT_CONFIG` 和 `ETH_PHY_DEFAULT_CONFIG` 中为 MAC 和 PHY 提供了默认配置。

## 创建 MAC 和 PHY 实例

以太网驱动是以面向对象的方式实现的。对 MAC 和 PHY 的任何操作都应基于实例。

### 内部 EMAC + 外部 PHY

    eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();                      // 应用默认的通用 MAC 配置
    eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); // 应用默认的供应商特定 MAC 配置
    esp32_emac_config.smi_gpio.mdc_num = CONFIG_ETHERNET_MDC_GPIO;               // 更改用于 MDC 信号的 GPIO
    esp32_emac_config.smi_gpio.mdio_num = CONFIG_ETHERNET_MDIO_GPIO;             // 更改用于 MDIO 信号的 GPIO
    esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // 创建 MAC 实例

    eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();      // 应用默认的 PHY 配置
    phy_config.phy_addr = CONFIG_ETHERNET_PHY_ADDR;              // 根据开发板设计更改 PHY 地址
    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_new_generic()` 创建新的 PHY 实例时，可以使用任何符合 IEEE 802.3 标准的以太网 PHY 芯片。然而，尽管 PHY 芯片符合 IEEE 802.3 标准，能提供基本功能，但某些特定的功能可能无法完全实现。例如，某些以太网 PHY 芯片可能需要配置特定的速度模式才能启用环回功能。遇到这种情况，需要配置 PHY 驱动程序以满足特定芯片需求，请使用 ESP-IDF 官方支持的 PHY 芯片驱动程序，或参阅 Custom PHY Driver 小节以创建新的自定义驱动程序。

小技巧

乐鑫为多种特定的以太网 PHY 芯片提供了驱动程序，这些驱动程序可在 esp-eth-drivers 仓库中获取。驱动以组件形式分发，并可在 ESP 组件库 上获取。

### 可选的运行时 MAC 时钟配置

可以通过用户应用程序代码，选择性配置 EMAC 中的 `REF_CLK`。

    eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); // 应用默认的供应商特定 MAC 配置

    // ...

    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_gpio = 17;                         // 配置用于输入/输出 EMAC REF_CLK 的 GPIO 编号
    esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // 创建 MAC 实例

### SPI-Ethernet 模块

    eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();      // 应用默认的通用 MAC 配置
    eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();      // 应用默认的 PHY 配置
    phy_config.phy_addr = CONFIG_ETHERNET_PHY_ADDR;              // 根据开发板设计更改 PHY 地址
    phy_config.reset_gpio_num = CONFIG_ETHERNET_PHY_RST_GPIO;    // 更改用于 PHY 复位的 GPIO
    // 安装 GPIO 中断服务（因为 SPI-Ethernet 模块为中断驱动）
    gpio_install_isr_service(0);
    // 配置 SPI 总线
    spi_device_handle_t spi_handle = NULL;
    spi_bus_config_t buscfg = {
        .miso_io_num = CONFIG_ETHERNET_SPI_MISO_GPIO,
        .mosi_io_num = CONFIG_ETHERNET_SPI_MOSI_GPIO,
        .sclk_io_num = CONFIG_ETHERNET_SPI_SCLK_GPIO,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
    };
    ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_ETHERNET_SPI_HOST, &buscfg, 1));
    // 配置 SPI 从机设备
    spi_device_interface_config_t spi_devcfg = {
        .mode = 0,
        .clock_speed_hz = CONFIG_ETHERNET_SPI_CLOCK_MHZ * 1000 * 1000,
        .spics_io_num = CONFIG_ETHERNET_SPI_CS_GPIO,
        .queue_size = 20
    };
    /* dm9051 ethernet driver is based on spi driver */
    eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_ETHERNET_SPI_HOST, &spi_devcfg);
    dm9051_config.int_gpio_num = CONFIG_ETHERNET_SPI_INT_GPIO;
    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);

备注

- 当为 SPI-Ethernet 模块（例如 DM9051）创建 MAC 和 PHY 实例时，由于 PHY 是集成在模块中的，因此调用的实例创建函数的后缀须保持一致（例如 esp_eth_mac_new_dm9051 和 esp_eth_phy_new_dm9051 搭配使用）。

- 针对不同的以太网模块，或是为了满足特定 PCB 上的 SPI 时序，SPI 从机设备配置（即 spi_device_interface_config_t）可能略有不同。具体配置请查看模块规格以及 ESP-IDF 中的示例。

小技巧

乐鑫为多种 SPI-Ethernet 模块提供了驱动程序，这些驱动程序可在 esp-eth-drivers 仓库中获取。驱动以组件形式分发，并可在 ESP 组件库 上获取。

## 安装驱动程序

安装以太网驱动程序需要结合 MAC 和 PHY 实例，并在 `esp_eth_config_t` 中配置一些额外的高级选项（即不仅限于 MAC 或 PHY 的选项）：

- `esp_eth_config_t::mac`：由 MAC 生成器创建的实例（例如 `esp_eth_mac_new_esp32()`）。

- `esp_eth_config_t::phy`：由 PHY 生成器创建的实例（例如 `esp_eth_phy_new_generic()`）。

- `esp_eth_config_t::check_link_period_ms`：以太网驱动程序会启用操作系统定时器来定期检查链接状态。该字段用于设置间隔时间，单位为毫秒。

- `esp_eth_config_t::stack_input` 或 `esp_eth_config_t::stack_input_info`：在大多数的以太网物联网应用中，驱动器接收的以太网帧会被传递到上层（如 TCP/IP 栈）。经配置，该字段为负责处理传入帧的函数。可以在安装驱动程序后，通过函数 `esp_eth_update_input_path()` 更新该字段。该字段支持在运行过程中进行更新。

- `esp_eth_config_t::on_lowlevel_init_done` 和 `esp_eth_config_t::on_lowlevel_deinit_done`：这两个字段用于指定钩子函数，当去初始化或初始化低级别硬件时，会调用钩子函数。

ESP-IDF 在宏 `ETH_DEFAULT_CONFIG` 中为安装驱动程序提供了一个默认配置。

    esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // 应用默认驱动程序配置
    esp_eth_handle_t eth_handle = NULL; // 驱动程序安装完毕后，将得到驱动程序的句柄
    esp_eth_driver_install(&config, &eth_handle); // 安装驱动程序

以太网驱动程序包含事件驱动模型，该模型会向用户空间发送有用及重要的事件。安装以太网驱动程序之前，需要首先初始化事件循环。有关事件驱动编程的更多信息，请参考 事件循环库。

    /** 以太网事件的事件处理程序 */
    static void eth_event_handler(void *arg, esp_event_base_t event_base,
                                  int32_t event_id, void *event_data)
    {
        uint8_t mac_addr[6] = {0};
        /* 可从事件数据中获得以太网驱动句柄 */
        esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;

        switch (event_id) {
        case ETHERNET_EVENT_CONNECTED:
            esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
            ESP_LOGI(TAG, "Ethernet Link Up");
            ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
                        mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
            break;
        case ETHERNET_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "Ethernet Link Down");
            break;
        case ETHERNET_EVENT_START:
            ESP_LOGI(TAG, "Ethernet Started");
            break;
        case ETHERNET_EVENT_STOP:
            ESP_LOGI(TAG, "Ethernet Stopped");
            break;
        default:
            break;
        }
    }

    esp_event_loop_create_default(); // 创建一个在后台运行的默认事件循环
    esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL); // 注册以太网事件处理程序（用于在发生 link up/down 等事件时，处理特定的用户相关内容）

## 启动以太网驱动程序

安装驱动程序后，可以立即启动以太网。

    esp_eth_start(eth_handle); // 启动以太网驱动程序状态机

## 连接驱动程序至 TCP/IP 协议栈

现在，以太网驱动程序已经完成安装。但对应 OSI（开放式系统互连模型）来看，目前阶段仍然属于第二层（即数据链路层）。这意味着可以检测到 link up/down 事件，获得用户空间的 MAC 地址，但无法获得 IP 地址，当然也无法发送 HTTP 请求。ESP-IDF 中使用的 TCP/IP 协议栈是 LwIP，关于 LwIP 的更多信息，请参考 LwIP。

要将以太网驱动程序连接至 TCP/IP 协议栈，需要以下三步：

1. 为以太网驱动程序创建网络接口

2. 将网络接口连接到以太网驱动程序

3. 注册 IP 事件处理程序

有关网络接口的更多信息，请参考 Network Interface。

    /** IP_EVENT_ETH_GOT_IP 的事件处理程序 */
    static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
                                     int32_t event_id, void *event_data)
    {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
        const esp_netif_ip_info_t *ip_info = &event->ip_info;

        ESP_LOGI(TAG, "Ethernet Got IP Address");
        ESP_LOGI(TAG, "~~~~~~~~~~~");
        ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
        ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
        ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
        ESP_LOGI(TAG, "~~~~~~~~~~~");
    }

    esp_netif_init()); // 初始化 TCP/IP 网络接口（在应用程序中应仅调用一次）
    esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); // 应用以太网的默认网络接口配置
    esp_netif_t *eth_netif = esp_netif_new(&cfg); // 为以太网驱动程序创建网络接口

    esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)); // 将以太网驱动程序连接至 TCP/IP 协议栈
    esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // 注册用户定义的 IP 事件处理程序
    esp_eth_start(eth_handle); // 启动以太网驱动程序状态机

警告

推荐在完成整个以太网驱动和网络接口的初始化后，再注册用户定义的以太网/IP 事件处理程序，也就是把注册事件处理程序作为启动以太网驱动程序的最后一步。这样可以确保以太网驱动程序或网络接口将首先执行以太网/IP 事件，从而保证在执行用户定义的处理程序时，系统处于预期状态。

## 以太网驱动程序的杂项控制

以下功能只支持在安装以太网驱动程序后调用。

- 关闭以太网驱动程序：`esp_eth_stop()`

- 更新以太网数据输入路径：`esp_eth_update_input_path()`

- 获取/设置以太网驱动程序杂项内容：`esp_eth_ioctl()`

    /* 获取 MAC 地址 */
    uint8_t mac_addr[6];
    memset(mac_addr, 0, sizeof(mac_addr));
    esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
    ESP_LOGI(TAG, "Ethernet MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
             mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);

    /* 获取 PHY 地址 */
    int phy_addr = -1;
    esp_eth_ioctl(eth_handle, ETH_CMD_G_PHY_ADDR, &phy_addr);
    ESP_LOGI(TAG, "Ethernet PHY Address: %d", phy_addr);

## 数据流量控制

受 RAM 大小限制，在网络拥堵时，MCU 上的以太网通常仅能处理有限数量的帧。发送站的数据传输速度可能快于对等端的接收能力。以太网数据流量控制机制允许接收节点向发送方发出信号，要求暂停传输，直到接收方跟上。这项功能是通过暂停帧实现的，该帧定义在 IEEE 802.3x 中。

暂停帧是一种特殊的以太网帧，用于携带暂停命令，其 EtherType 字段为 `0x8808`，控制操作码为 `0x0001`。只有配置为全双工操作的节点组可以发送暂停帧。当节点组希望暂停链路的另一端时，它会发送一个暂停帧到 48 位的保留组播地址 `01-80-C2-00-00-01`。暂停帧中也包括请求暂停的时间段，以两字节的整数形式发送，值的范围从 `0` 到 `65535`。

安装以太网驱动程序后，数据流量控制功能默认禁用，可以通过以下方式启用此功能：

    bool flow_ctrl_enable = true;
    esp_eth_ioctl(eth_handle, ETH_CMD_S_FLOW_CTRL, &flow_ctrl_enable);

需注意，暂停帧是在自动协商期间由 PHY 向对等端公布的。只有当链路两端都支持暂停帧时，以太网驱动程序才会发送暂停帧。

## 应用示例

> - ethernet/basic 演示了如何使用以太网驱动程序，包括驱动程序的安装、将其连接到 `esp_netif`、发送 DHCP 请求以及获取可 ping 的 IP 地址。

> - ethernet/iperf 演示了如何使用以太网功能，使用 iPerf 测量吞吐量/带宽。

> - ethernet/ptp 演示了如何在以太网上使用精确时间协议 (PTP) 同步时间。

> - network/vlan_support 演示了如何在以太网上创建虚拟网络接口，包括 VLAN 和非 VLAN 接口。

> - network/sta2eth 演示了如何使用 Wi-Fi station 和有线接口（如以太网或 USB）创建 1 对 1 的桥接。

> - network/simple_sniffer 演示了如何在嗅探模式下使用 Wi-Fi 和以太网来捕获数据包，并将其保存为 PCAP 格式。

> - network/eth2ap 演示了如何实现一个桥接器，在以太网端口和 Wi-Fi AP 接口之间转发数据包。该示例使用 ESP32 创建以太网和 Wi-Fi 之间的 1 对多连接，而无需初始化 TCP/IP 栈。

> - network/bridge 演示了如何使用 LwIP IEEE 802.1D 桥接器根据 MAC 地址在多个网络段之间转发以太网帧。

> - 大多数协议示例也适用于以太网：protocols

## 进阶操作

### 自定义 PHY 驱动程序

市面上有多家 PHY 芯片制造商提供各种类型的芯片。ESP-IDF 现已支持 `通用 PHY` 和数种特定的 PHY 芯片，但是由于价格、功能、库存等原因，有时用户还是无法找到一款能满足其实际需求的芯片。

好在 IEEE 802.3 在其 22.2.4 管理功能部分对 EMAC 和 PHY 之间的管理接口进行了标准化。该部分定义了所谓的 ”MII 管理接口”规范，用于控制 PHY 和收集 PHY 的状态，还定义了一组管理寄存器来控制芯片行为、链接属性、自动协商配置等。在 ESP-IDF 中，这项基本的管理功能是由 esp_eth/src/phy/esp_eth_phy_802_3.c 实现的，这也大大降低了创建新的自定义 PHY 芯片驱动的难度。

备注

由于一些 PHY 芯片可能不符合 IEEE 802.3 第 22.2.4 节的规定，所以请首先查看 PHY 数据手册。不过，就算芯片不符合规定，依旧可以创建自定义 PHY 驱动程序，只是由于需要自行定义所有的 PHY 管理功能，这个过程将变得较为复杂。

ESP-IDF 以太网驱动程序所需的大部分 PHY 管理功能都已涵盖在 esp_eth/src/phy/esp_eth_phy_802_3.c 中。不过对于以下几项，可能仍需针对不同芯片开发具体的管理功能：

> - 链接状态。此项总是由使用的具体芯片决定

> - 芯片初始化。即使不存在严格的限制，也应进行自定义，以确保使用的是符合预期的芯片

> - 芯片的具体功能配置

创建自定义 PHY 驱动程序的步骤：

1. 请根据 PHY 数据手册，定义厂家私有的寄存器。

2. 准备衍生的 PHY 管理对象信息结构，该结构：

   > - 必须至少包含 IEEE 802.3 `phy_802_3_t` 父对象

   > - 可选择包含额外的变量，以支持非 IEEE 802.3 或定制功能。

3. 定义针对芯片的特定管理回调功能。

4. 初始化 IEEE 802.3 父对象并重新分配针对芯片的特定管理回调功能。

实现新的自定义 PHY 驱动程序后，你可以通过 乐鑫组件注册表 将驱动分享给其他用户。

## API 参考

### Header File

- components/hal/include/hal/eth_types.h

- This header file can be included with:

  >     #include "hal/eth_types.h"

### Enumerations

enum eth_data_interface_t

  Ethernet interface.

  Values:

  enumerator EMAC_DATA_INTERFACE_RMII

    Reduced Media Independent Interface

  enumerator EMAC_DATA_INTERFACE_MII

    Media Independent Interface

enum eth_link_t

  Ethernet link status.

  Values:

  enumerator ETH_LINK_UP

    Ethernet link is up

  enumerator ETH_LINK_DOWN

    Ethernet link is down

enum eth_speed_t

  Ethernet speed.

  Values:

  enumerator ETH_SPEED_10M

    Ethernet speed is 10Mbps

  enumerator ETH_SPEED_100M

    Ethernet speed is 100Mbps

  enumerator ETH_SPEED_MAX

    Max speed mode (for checking purpose)

enum eth_duplex_t

  Ethernet duplex mode.

  Values:

  enumerator ETH_DUPLEX_HALF

    Ethernet is in half duplex

  enumerator ETH_DUPLEX_FULL

    Ethernet is in full duplex

enum eth_checksum_t

  Ethernet Checksum.

  Values:

  enumerator ETH_CHECKSUM_SW

    Ethernet checksum calculate by software

  enumerator ETH_CHECKSUM_HW

    Ethernet checksum calculate by hardware

enum eth_mac_dma_burst_len_t

  Internal ethernet EMAC's DMA available burst sizes.

  Values:

  enumerator ETH_DMA_BURST_LEN_32
  enumerator ETH_DMA_BURST_LEN_16
  enumerator ETH_DMA_BURST_LEN_8
  enumerator ETH_DMA_BURST_LEN_4
  enumerator ETH_DMA_BURST_LEN_2
  enumerator ETH_DMA_BURST_LEN_1

enum eth_mac_ptp_update_method_t

  EMAC System timestamp update update method.

  Values:

  enumerator ETH_PTP_UPDATE_METHOD_COARSE

    EMAC System timestamp update using the Coarse method

  enumerator ETH_PTP_UPDATE_METHOD_FINE

    EMAC System timestamp update using the Fine method

enum eth_mac_ptp_roll_type_t

  EMAC System Timestamp Rollover.

  Values:

  enumerator ETH_PTP_DIGITAL_ROLLOVER

    Digital - subseconds register rolls over after 999999999 value (1 nanosecond accuracy)

  enumerator ETH_PTP_BINARY_ROLLOVER

    Binary - subseconds register rolls over after 0x7FFFFFFF value

### Header File

- components/esp_eth/include/esp_eth.h

- This header file can be included with:

  >     #include "esp_eth.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Header File

- components/esp_eth/include/esp_eth_driver.h

- This header file can be included with:

  >     #include "esp_eth_driver.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Functions

esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_t *out_hdl)

  Install Ethernet driver.

  参数:

    - config -- [in] configuration of the Ethernet driver

    - out_hdl -- [out] handle of Ethernet driver

  返回:

    - ESP_OK: install esp_eth driver successfully

    - ESP_ERR_INVALID_ARG: install esp_eth driver failed because of some invalid argument

    - ESP_ERR_NO_MEM: install esp_eth driver failed because there's no memory for driver

    - ESP_FAIL: install esp_eth driver failed because some other error occurred

esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl)

  Uninstall Ethernet driver.

  备注

  It's not recommended to uninstall Ethernet driver unless it won't get used any more in application code. To uninstall Ethernet driver, you have to make sure, all references to the driver are released. Ethernet driver can only be uninstalled successfully when reference counter equals to one.

  参数:

    hdl -- [in] handle of Ethernet driver

  返回:

    - ESP_OK: uninstall esp_eth driver successfully

    - ESP_ERR_INVALID_ARG: uninstall esp_eth driver failed because of some invalid argument

    - ESP_ERR_INVALID_STATE: uninstall esp_eth driver failed because it has more than one reference

    - ESP_FAIL: uninstall esp_eth driver failed because some other error occurred

esp_err_t esp_eth_start(esp_eth_handle_t hdl)

  Start Ethernet driver ONLY in standalone mode (i.e. without TCP/IP stack)

  备注

  This API will start driver state machine and internal software timer (for checking link status).

  参数:

    hdl -- [in] handle of Ethernet driver

  返回:

    - ESP_OK: start esp_eth driver successfully

    - ESP_ERR_INVALID_ARG: start esp_eth driver failed because of some invalid argument

    - ESP_ERR_INVALID_STATE: start esp_eth driver failed because driver has started already

    - ESP_FAIL: start esp_eth driver failed because some other error occurred

esp_err_t esp_eth_stop(esp_eth_handle_t hdl)

  Stop Ethernet driver.

  备注

  This function does the opposite operation of `esp_eth_start`.

  参数:

    hdl -- [in] handle of Ethernet driver

  返回:

    - ESP_OK: stop esp_eth driver successfully

    - ESP_ERR_INVALID_ARG: stop esp_eth driver failed because of some invalid argument

    - ESP_ERR_INVALID_STATE: stop esp_eth driver failed because driver has not started yet

    - ESP_FAIL: stop esp_eth driver failed because some other error occurred

esp_err_t esp_eth_update_input_path(esp_eth_handle_t hdl, esp_err_t (*stack_input)(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv), void *priv)

  Update Ethernet data input path (i.e. specify where to pass the input buffer)

  备注

  After install driver, Ethernet still don't know where to deliver the input buffer. In fact, this API registers a callback function which get invoked when Ethernet received new packets.

  参数:

    - hdl -- [in] handle of Ethernet driver

    - stack_input -- [in] function pointer, which does the actual process on incoming packets

    - priv -- [in] private resource, which gets passed to `stack_input` callback without any modification

  返回:

    - ESP_OK: update input path successfully

    - ESP_ERR_INVALID_ARG: update input path failed because of some invalid argument

    - ESP_FAIL: update input path failed because some other error occurred

esp_err_t esp_eth_update_input_path_info(esp_eth_handle_t hdl, esp_err_t (*stack_input_info)(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv, void *info), void *priv)

  Update Ethernet data input path with input function which consumes extra info about received frame.

  备注

  Extra information may include but is not limited to such info like Time Stamp, CRC check offload result, etc. The MAC layer of the Ethernet driver of the particular device must provide extra information using `stack_input_info()` function. Otherwise, input path function registered by this API is not invoked. If this is the case, register `stack_input` function by `esp_eth_update_input_path()` instead.

  备注

  After install driver, Ethernet still don't know where to deliver the input buffer. In fact, this API registers a callback function which get invoked when Ethernet received new packets.

  参数:

    - hdl -- [in] handle of Ethernet driver

    - stack_input_info -- [in] function pointer, which does the actual process on incoming packets

    - priv -- [in] private resource, which gets passed to `stack_input_info` callback without any modification

  返回:

    - ESP_OK: update input path successfully

    - ESP_ERR_INVALID_ARG: update input path failed because of some invalid argument

    - ESP_FAIL: update input path failed because some other error occurred

esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length)

  General Transmit.

  参数:

    - hdl -- [in] handle of Ethernet driver

    - buf -- [in] buffer of the packet to transfer

    - length -- [in] length of the buffer to transfer

  返回:

    - ESP_OK: transmit frame buffer successfully

    - ESP_ERR_INVALID_ARG: transmit frame buffer failed because of some invalid argument

    - 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

esp_err_t esp_eth_transmit_ctrl_vargs(esp_eth_handle_t hdl, void *ctrl, uint32_t argc, ...)

  Extended Transmit with variable number of arguments.

  备注

  Typical intended use case of this function is to assemble Ethernet frame from multiple input buffers at lower layer of the driver (MAC layer) to avoid unnecessary buffer reallocation and copy.

  参数:

    - hdl -- handle of Ethernet driver

    - ctrl -- optional transmit control structure (MAC specific), set to NULL when not required

    - argc -- number variable arguments

    - ... -- variable arguments

  返回:

    - 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

esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data)

  Misc IO function of Ethernet driver.

  The following common IO control commands are supported:

  - `ETH_CMD_S_MAC_ADDR` sets Ethernet interface MAC address. `data` argument is pointer to MAC address buffer with expected size of 6 bytes.

  - `ETH_CMD_G_MAC_ADDR` gets Ethernet interface MAC address. `data` argument is pointer to a buffer to which MAC address is to be copied. The buffer size must be at least 6 bytes.

  - `ETH_CMD_S_PHY_ADDR` sets PHY address in range of <0-31>. `data` argument is pointer to memory of uint32_t datatype from where the configuration option is read.

  - `ETH_CMD_G_PHY_ADDR` gets PHY address. `data` argument is pointer to memory of uint32_t datatype to which the PHY address is to be stored.

  - `ETH_CMD_S_AUTONEGO` enables or disables Ethernet link speed and duplex mode autonegotiation. `data` argument is pointer to memory of bool datatype from which the configuration option is read. Preconditions: Ethernet driver needs to be stopped.

  - `ETH_CMD_G_AUTONEGO` gets current configuration of the Ethernet link speed and duplex mode autonegotiation. `data` argument is pointer to memory of bool datatype to which the current configuration is to be stored.

  - `ETH_CMD_S_SPEED` sets the Ethernet link speed. `data` argument is pointer to memory of eth_speed_t datatype from which the configuration option is read. Preconditions: Ethernet driver needs to be stopped and auto-negotiation disabled.

  - `ETH_CMD_G_SPEED` gets current Ethernet link speed. `data` argument is pointer to memory of eth_speed_t datatype to which the speed is to be stored.

  - `ETH_CMD_S_PROMISCUOUS` sets/resets Ethernet interface promiscuous mode. `data` argument is pointer to memory of bool datatype from which the configuration option is read.

  - `ETH_CMD_S_FLOW_CTRL` sets/resets Ethernet interface flow control. `data` argument is pointer to memory of bool datatype from which the configuration option is read.

  - `ETH_CMD_S_DUPLEX_MODE` sets the Ethernet duplex mode. `data` argument is pointer to memory of eth_duplex_t datatype from which the configuration option is read. Preconditions: Ethernet driver needs to be stopped and auto-negotiation disabled.

  - `ETH_CMD_G_DUPLEX_MODE` gets current Ethernet link duplex mode. `data` argument is pointer to memory of eth_duplex_t datatype to which the duplex mode is to be stored.

  - `ETH_CMD_S_PHY_LOOPBACK` sets/resets PHY to/from loopback mode. `data` argument is pointer to memory of bool datatype from which the configuration option is read.

  - `ETH_CMD_S_ALL_MULTICAST` sets/resets Ethernet interface to/from receive all multicast mode. `data` argument is pointer to memory of bool datatype from which the configuration option is read.

  - `ETH_CMD_ADD_MAC_FILTER` adds a MAC address to the MAC filter. `data` argument is pointer to MAC address buffer with expected size of 6 bytes.

  - `ETH_CMD_DEL_MAC_FILTER` deletes a MAC address from the MAC filter. `data` argument is pointer to MAC address buffer with expected size of 6 bytes.

  - Note that additional control commands may be available for specific MAC or PHY chips. Please consult specific MAC or PHY documentation or driver code.

  参数:

    - hdl -- [in] handle of Ethernet driver

    - cmd -- [in] IO control command

    - data -- [inout] address of data for `set` command or address where to store the data when used with `get` command

  返回:

    - ESP_OK: process io command successfully

    - ESP_ERR_INVALID_ARG: process io command failed because of some invalid argument

    - ESP_FAIL: process io command failed because some other error occurred

    - ESP_ERR_NOT_SUPPORTED: requested feature is not supported

esp_err_t esp_eth_get_phy_instance(esp_eth_handle_t hdl, esp_eth_phy_t **phy)

  Get PHY instance memory address.

  参数:

    - hdl -- [in] handle of Ethernet driver

    - phy -- [out] pointer to memory to store the instance

  返回:

    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)

  Get MAC instance memory address.

  参数:

    - hdl -- [in] handle of Ethernet driver

    - mac -- [out] pointer to memory to store the instance

  返回:

    esp_err_t

    - ESP_OK: success

    - ESP_ERR_INVALID_ARG: failed because of some invalid argument

esp_err_t esp_eth_increase_reference(esp_eth_handle_t hdl)

  Increase Ethernet driver reference.

  备注

  Ethernet driver handle can be obtained by os timer, netif, etc. It's dangerous when thread A is using Ethernet but thread B uninstall the driver. Using reference counter can prevent such risk, but care should be taken, when you obtain Ethernet driver, this API must be invoked so that the driver won't be uninstalled during your using time.

  参数:

    hdl -- [in] handle of Ethernet driver

  返回:

    - ESP_OK: increase reference successfully

    - ESP_ERR_INVALID_ARG: increase reference failed because of some invalid argument

esp_err_t esp_eth_decrease_reference(esp_eth_handle_t hdl)

  Decrease Ethernet driver reference.

  参数:

    hdl -- [in] handle of Ethernet driver

  返回:

    - ESP_OK: increase reference successfully

    - ESP_ERR_INVALID_ARG: increase reference failed because of some invalid argument

### Structures

struct esp_eth_config_t

  Configuration of Ethernet driver.

  Public Members

  esp_eth_mac_t *mac

    Ethernet MAC object.

  esp_eth_phy_t *phy

    Ethernet PHY object.

  uint32_t check_link_period_ms

    Period time of checking Ethernet link status.

  esp_err_t (*stack_input)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv)

    Input frame buffer to user's stack.

    Param eth_handle:

      [in] handle of Ethernet driver

    Param buffer:

      [in] frame buffer that will get input to upper stack

    Param length:

      [in] length of the frame buffer

    Param priv:

      [in] pointer to private resource, defined when registering the input function

    Return:

      - ESP_OK: input frame buffer to upper stack successfully

      - ESP_FAIL: error occurred when inputting buffer to upper stack

  esp_err_t (*stack_input_info)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv, void *info)

    Input frame buffer to user's stack with additional information about received frame.

    Param eth_handle:

      [in] handle of Ethernet driver

    Param buffer:

      [in] frame buffer that will get input to upper stack

    Param length:

      [in] length of the frame buffer

    Param priv:

      [in] pointer to private resource, defined when registering the input function

    Param info:

      [in] extra information about received Ethernet frame (may be timestamp, CRC offload check result, etc.)

    Return:

      - ESP_OK: input frame buffer to upper stack successfully

      - ESP_FAIL: error occurred when inputting buffer to upper stack

  esp_err_t (*on_lowlevel_init_done)(esp_eth_handle_t eth_handle)

    Callback function invoked when lowlevel initialization is finished.

    Param eth_handle:

      [in] handle of Ethernet driver

    Return:

      - ESP_OK: process extra lowlevel initialization successfully

      - ESP_FAIL: error occurred when processing extra lowlevel initialization

  esp_err_t (*on_lowlevel_deinit_done)(esp_eth_handle_t eth_handle)

    Callback function invoked when lowlevel deinitialization is finished.

    Param eth_handle:

      [in] handle of Ethernet driver

    Return:

      - ESP_OK: process extra lowlevel deinitialization successfully

      - ESP_FAIL: error occurred when processing extra lowlevel deinitialization

  esp_err_t (*read_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)

    Read PHY register.

    备注

    Usually the PHY register read/write function is provided by MAC (SMI interface), but if the PHY device is managed by other interface (e.g. I2C), then user needs to implement the corresponding read/write. Setting this to NULL means your PHY device is managed by MAC's SMI interface.

    Param eth_handle:

      [in] handle of Ethernet driver

    Param phy_addr:

      [in] PHY chip address (0~31)

    Param phy_reg:

      [in] PHY register index code

    Param reg_value:

      [out] PHY register value

    Return:

      - ESP_OK: read PHY register successfully

      - ESP_ERR_INVALID_ARG: read PHY register failed because of invalid argument

      - ESP_ERR_TIMEOUT: read PHY register failed because of timeout

      - ESP_FAIL: read PHY register failed because some other error occurred

  esp_err_t (*write_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)

    Write PHY register.

    备注

    Usually the PHY register read/write function is provided by MAC (SMI interface), but if the PHY device is managed by other interface (e.g. I2C), then user needs to implement the corresponding read/write. Setting this to NULL means your PHY device is managed by MAC's SMI interface.

    Param eth_handle:

      [in] handle of Ethernet driver

    Param phy_addr:

      [in] PHY chip address (0~31)

    Param phy_reg:

      [in] PHY register index code

    Param reg_value:

      [in] PHY register value

    Return:

      - ESP_OK: write PHY register successfully

      - ESP_ERR_INVALID_ARG: read PHY register failed because of invalid argument

      - ESP_ERR_TIMEOUT: write PHY register failed because of timeout

      - ESP_FAIL: write PHY register failed because some other error occurred

struct esp_eth_phy_reg_rw_data_t

  Data structure to Read/Write PHY register via ioctl API.

  Public Members

  uint32_t reg_addr

    PHY register address

  uint32_t *reg_value_p

    Pointer to a memory where the register value is read/written

### Macros

ETH_DEFAULT_CONFIG(emac, ephy)

  Default configuration for Ethernet driver.

esp_eth_transmit_vargs(eth_hdl, argc, ...)

  Wrapper over Extended Transmit function to ensure backward compatibility.

  备注

  For new implementations, it is recommended to use `esp_eth_transmit_ctrl_vargs()` directly.

  参数:

    - eth_hdl -- [in] handle of Ethernet driver

    - argc -- [in] number variable arguments

    - ... -- variable arguments

  返回:

    - 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

### Type Definitions

typedef void *esp_eth_handle_t

  Handle of Ethernet driver.

### Enumerations

enum esp_eth_io_cmd_t

  Command list for ioctl API.

  Values:

  enumerator ETH_CMD_G_MAC_ADDR

    Get MAC address

  enumerator ETH_CMD_S_MAC_ADDR

    Set MAC address

  enumerator ETH_CMD_G_PHY_ADDR

    Get PHY address

  enumerator ETH_CMD_S_PHY_ADDR

    Set PHY address

  enumerator ETH_CMD_G_AUTONEGO

    Get PHY Auto Negotiation

  enumerator ETH_CMD_S_AUTONEGO

    Set PHY Auto Negotiation

  enumerator ETH_CMD_G_SPEED

    Get Speed

  enumerator ETH_CMD_S_SPEED

    Set Speed

  enumerator ETH_CMD_S_PROMISCUOUS

    Set promiscuous mode

  enumerator ETH_CMD_S_FLOW_CTRL

    Set flow control

  enumerator ETH_CMD_G_DUPLEX_MODE

    Get Duplex mode

  enumerator ETH_CMD_S_DUPLEX_MODE

    Set Duplex mode

  enumerator ETH_CMD_S_PHY_LOOPBACK

    Set PHY loopback

  enumerator ETH_CMD_READ_PHY_REG

    Read PHY register

  enumerator ETH_CMD_WRITE_PHY_REG

    Write PHY register

  enumerator ETH_CMD_S_ALL_MULTICAST

    Set receive all multicast

  enumerator ETH_CMD_ADD_MAC_FILTER

    Add MAC filter

  enumerator ETH_CMD_DEL_MAC_FILTER

    Delete MAC filter

  enumerator ETH_CMD_CUSTOM_MAC_CMDS
  enumerator ETH_CMD_CUSTOM_PHY_CMDS

### Header File

- components/esp_eth/include/esp_eth_com.h

- This header file can be included with:

  >     #include "esp_eth_com.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Structures

struct esp_eth_mediator_s

  Ethernet mediator.

  Public Members

  esp_err_t (*phy_reg_read)(esp_eth_mediator_t *eth, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)

    Read PHY register.

    Param eth:

      [in] mediator of Ethernet driver

    Param phy_addr:

      [in] PHY Chip address (0~31)

    Param phy_reg:

      [in] PHY register index code

    Param reg_value:

      [out] PHY register value

    Return:

      - ESP_OK: read PHY register successfully

      - ESP_FAIL: read PHY register failed because some error occurred

  esp_err_t (*phy_reg_write)(esp_eth_mediator_t *eth, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)

    Write PHY register.

    Param eth:

      [in] mediator of Ethernet driver

    Param phy_addr:

      [in] PHY Chip address (0~31)

    Param phy_reg:

      [in] PHY register index code

    Param reg_value:

      [in] PHY register value

    Return:

      - ESP_OK: write PHY register successfully

      - ESP_FAIL: write PHY register failed because some error occurred

  esp_err_t (*stack_input)(esp_eth_mediator_t *eth, uint8_t *buffer, uint32_t length)

    Deliver packet to upper stack.

    Param eth:

      [in] mediator of Ethernet driver

    Param buffer:

      [in] packet buffer

    Param length:

      [in] length of the packet

    Return:

      - ESP_OK: deliver packet to upper stack successfully

      - ESP_FAIL: deliver packet failed because some error occurred

  esp_err_t (*stack_input_info)(esp_eth_mediator_t *eth, uint8_t *buffer, uint32_t length, void *info)

    Deliver packet to upper stack with additional information about reception.

    Param eth:

      [in] mediator of Ethernet driver

    Param buffer:

      [in] packet buffer

    Param length:

      [in] length of the packet

    Param info:

      [in] info associated with reception (e.g. time stamp)

    Return:

      - ESP_OK: deliver packet to upper stack successfully

      - ESP_FAIL: deliver packet failed because some error occurred

  esp_err_t (*on_state_changed)(esp_eth_mediator_t *eth, esp_eth_state_t state, void *args)

    Callback on Ethernet state changed.

    Param eth:

      [in] mediator of Ethernet driver

    Param state:

      [in] new state

    Param args:

      [in] optional argument for the new state

    Return:

      - ESP_OK: process the new state successfully

      - ESP_FAIL: process the new state failed because some error occurred

### Macros

ETH_CMD_CUSTOM_MAC_CMDS_OFFSET

  Offset for start of MAC custom ioctl commands.

ETH_CMD_CUSTOM_PHY_CMDS_OFFSET

  Offset for start of PHY custom ioctl commands.

### Type Definitions

typedef struct esp_eth_mediator_s esp_eth_mediator_t

  Ethernet mediator.

### Enumerations

enum esp_eth_state_t

  Ethernet driver state.

  Values:

  enumerator ETH_STATE_LLINIT

    Lowlevel init done

  enumerator ETH_STATE_DEINIT

    Deinit done

  enumerator ETH_STATE_LINK

    Link status changed

  enumerator ETH_STATE_SPEED

    Speed updated

  enumerator ETH_STATE_DUPLEX

    Duplex updated

  enumerator ETH_STATE_PAUSE

    Pause ability updated

enum eth_event_t

  Ethernet event declarations.

  Values:

  enumerator ETHERNET_EVENT_START

    Ethernet driver start

  enumerator ETHERNET_EVENT_STOP

    Ethernet driver stop

  enumerator ETHERNET_EVENT_CONNECTED

    Ethernet got a valid link

  enumerator ETHERNET_EVENT_DISCONNECTED

    Ethernet lost a valid link

### Header File

- components/esp_eth/include/esp_eth_mac.h

- This header file can be included with:

  >     #include "esp_eth_mac.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Structures

struct esp_eth_mac_s

  Ethernet MAC.

  Public Members

  esp_err_t (*set_mediator)(esp_eth_mac_t *mac, esp_eth_mediator_t *eth)

    Set mediator for Ethernet MAC.

    Param mac:

      [in] Ethernet MAC instance

    Param eth:

      [in] Ethernet mediator

    Return:

      - ESP_OK: set mediator for Ethernet MAC successfully

      - ESP_ERR_INVALID_ARG: set mediator for Ethernet MAC failed because of invalid argument

  esp_err_t (*init)(esp_eth_mac_t *mac)

    Initialize Ethernet MAC.

    Param mac:

      [in] Ethernet MAC instance

    Return:

      - ESP_OK: initialize Ethernet MAC successfully

      - ESP_ERR_TIMEOUT: initialize Ethernet MAC failed because of timeout

      - ESP_FAIL: initialize Ethernet MAC failed because some other error occurred

  esp_err_t (*deinit)(esp_eth_mac_t *mac)

    Deinitialize Ethernet MAC.

    Param mac:

      [in] Ethernet MAC instance

    Return:

      - ESP_OK: deinitialize Ethernet MAC successfully

      - ESP_FAIL: deinitialize Ethernet MAC failed because some error occurred

  esp_err_t (*start)(esp_eth_mac_t *mac)

    Start Ethernet MAC.

    Param mac:

      [in] Ethernet MAC instance

    Return:

      - ESP_OK: start Ethernet MAC successfully

      - ESP_FAIL: start Ethernet MAC failed because some other error occurred

  esp_err_t (*stop)(esp_eth_mac_t *mac)

    Stop Ethernet MAC.

    Param mac:

      [in] Ethernet MAC instance

    Return:

      - ESP_OK: stop Ethernet MAC successfully

      - ESP_FAIL: stop Ethernet MAC failed because some error occurred

  esp_err_t (*transmit)(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length)

    Transmit packet from Ethernet MAC.

    备注

    Returned error codes may differ for each specific MAC chip.

    Param mac:

      [in] Ethernet MAC instance

    Param buf:

      [in] packet buffer to transmit

    Param length:

      [in] length of packet

    Return:

      - ESP_OK: transmit packet successfully

      - ESP_ERR_INVALID_SIZE: number of actually sent bytes differs to expected

      - ESP_FAIL: transmit packet failed because some other error occurred

  esp_err_t (*transmit_ctrl_vargs)(esp_eth_mac_t *mac, void *ctrl, uint32_t argc, va_list args)

    Transmit packet with extended control from Ethernet MAC and constructed with special parameters at Layer2.

    备注

    Typical intended use case is to make possible to construct a frame from multiple higher layer buffers without a need of buffer reallocations. However, other use cases are not limited.

    备注

    Returned error codes may differ for each specific MAC chip.

    Param mac:

      [in] Ethernet MAC instance

    Param ctrl:

      [in] optional transmit control structure (chip specific), set to NULL when not required

    Param argc:

      [in] number variable arguments

    Param args:

      [in] variable arguments

    Return:

      - ESP_OK: transmit packet successfully

      - ESP_ERR_INVALID_SIZE: number of actually sent bytes differs to expected

      - ESP_FAIL: transmit packet failed because some other error occurred

  esp_err_t (*transmit_vargs)(esp_eth_mac_t *mac, uint32_t argc, va_list args)

    Transmit packet from Ethernet MAC constructed with special parameters at Layer2.

    备注

    Typical intended use case is to make possible to construct a frame from multiple higher layer buffers without a need of buffer reallocations. However, other use cases are not limited.

    备注

    Returned error codes may differ for each specific MAC chip.

    警告

    Deprecated, use `transmit_ctrl_vargs()` function instead.

    Param mac:

      [in] Ethernet MAC instance

    Param argc:

      [in] number variable arguments

    Param args:

      [in] variable arguments

    Return:

      - ESP_OK: transmit packet successfully

      - ESP_ERR_INVALID_SIZE: number of actually sent bytes differs to expected

      - ESP_FAIL: transmit packet failed because some other error occurred

  esp_err_t (*receive)(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length)

    Receive packet from Ethernet MAC.

    备注

    Memory of buf is allocated in the Layer2, make sure it get free after process.

    备注

    Before this function got invoked, the value of "length" should set by user, equals the size of buffer. After the function returned, the value of "length" means the real length of received data.

    Param mac:

      [in] Ethernet MAC instance

    Param buf:

      [out] packet buffer which will preserve the received frame

    Param length:

      [out] length of the received packet

    Return:

      - ESP_OK: receive packet successfully

      - ESP_ERR_INVALID_ARG: receive packet failed because of invalid argument

      - ESP_ERR_INVALID_SIZE: input buffer size is not enough to hold the incoming data. in this case, value of returned "length" indicates the real size of incoming data.

      - ESP_FAIL: receive packet failed because some other error occurred

  esp_err_t (*read_phy_reg)(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)

    Read PHY register.

    Param mac:

      [in] Ethernet MAC instance

    Param phy_addr:

      [in] PHY chip address (0~31)

    Param phy_reg:

      [in] PHY register index code

    Param reg_value:

      [out] PHY register value

    Return:

      - ESP_OK: read PHY register successfully

      - ESP_ERR_INVALID_ARG: read PHY register failed because of invalid argument

      - ESP_ERR_INVALID_STATE: read PHY register failed because of wrong state of MAC

      - ESP_ERR_TIMEOUT: read PHY register failed because of timeout

      - ESP_FAIL: read PHY register failed because some other error occurred

  esp_err_t (*write_phy_reg)(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)

    Write PHY register.

    Param mac:

      [in] Ethernet MAC instance

    Param phy_addr:

      [in] PHY chip address (0~31)

    Param phy_reg:

      [in] PHY register index code

    Param reg_value:

      [in] PHY register value

    Return:

      - ESP_OK: write PHY register successfully

      - ESP_ERR_INVALID_STATE: write PHY register failed because of wrong state of MAC

      - ESP_ERR_TIMEOUT: write PHY register failed because of timeout

      - ESP_FAIL: write PHY register failed because some other error occurred

  esp_err_t (*set_addr)(esp_eth_mac_t *mac, uint8_t *addr)

    Set MAC address.

    Param mac:

      [in] Ethernet MAC instance

    Param addr:

      [in] MAC address

    Return:

      - ESP_OK: set MAC address successfully

      - ESP_ERR_INVALID_ARG: set MAC address failed because of invalid argument

      - ESP_FAIL: set MAC address failed because some other error occurred

  esp_err_t (*get_addr)(esp_eth_mac_t *mac, uint8_t *addr)

    Get MAC address.

    Param mac:

      [in] Ethernet MAC instance

    Param addr:

      [out] MAC address

    Return:

      - ESP_OK: get MAC address successfully

      - ESP_ERR_INVALID_ARG: get MAC address failed because of invalid argument

      - ESP_FAIL: get MAC address failed because some other error occurred

  esp_err_t (*add_mac_filter)(esp_eth_mac_t *mac, uint8_t *addr)

    Add Destination address MAC filter.

    Param mac:

      [in] Ethernet MAC instance

    Param addr:

      [in] MAC address

    Return:

      - ESP_OK: add MAC filter successfully

      - ESP_FAIL: add MAC filter failed because some error occurred

  esp_err_t (*rm_mac_filter)(esp_eth_mac_t *mac, uint8_t *addr)

    Remove Destination address MAC filter.

    Param mac:

      [in] Ethernet MAC instance

    Param addr:

      [in] MAC address

    Return:

      - ESP_OK: remove MAC filter successfully

      - ESP_FAIL: remove MAC filter failed because some error occurred

  esp_err_t (*set_speed)(esp_eth_mac_t *mac, eth_speed_t speed)

    Set speed of MAC.

    Param ma:c:

      [in] Ethernet MAC instance

    Param speed:

      [in] MAC speed

    Return:

      - ESP_OK: set MAC speed successfully

      - ESP_ERR_INVALID_ARG: set MAC speed failed because of invalid argument

      - ESP_FAIL: set MAC speed failed because some other error occurred

  esp_err_t (*set_duplex)(esp_eth_mac_t *mac, eth_duplex_t duplex)

    Set duplex mode of MAC.

    Param mac:

      [in] Ethernet MAC instance

    Param duplex:

      [in] MAC duplex

    Return:

      - ESP_OK: set MAC duplex mode successfully

      - ESP_ERR_INVALID_ARG: set MAC duplex failed because of invalid argument

      - ESP_FAIL: set MAC duplex failed because some other error occurred

  esp_err_t (*set_link)(esp_eth_mac_t *mac, eth_link_t link)

    Set link status of MAC.

    Param mac:

      [in] Ethernet MAC instance

    Param link:

      [in] Link status

    Return:

      - ESP_OK: set link status successfully

      - ESP_ERR_INVALID_ARG: set link status failed because of invalid argument

      - ESP_FAIL: set link status failed because some other error occurred

  esp_err_t (*set_promiscuous)(esp_eth_mac_t *mac, bool enable)

    Set promiscuous of MAC.

    Param mac:

      [in] Ethernet MAC instance

    Param enable:

      [in] set true to enable promiscuous mode; set false to disable promiscuous mode

    Return:

      - ESP_OK: set promiscuous mode successfully

      - ESP_FAIL: set promiscuous mode failed because some error occurred

  esp_err_t (*set_all_multicast)(esp_eth_mac_t *mac, bool enable)

    Set receive all multicast.

    Param mac:

      [in] Ethernet MAC instance

    Param enable:

      [in] set true to enable receive all multicast; set false to disable receive all multicast

    Return:

      - ESP_OK: set receive all multicast successfully

      - ESP_FAIL: set receive all multicast failed because some error occurred

  esp_err_t (*enable_flow_ctrl)(esp_eth_mac_t *mac, bool enable)

    Enable flow control on MAC layer or not.

    Param mac:

      [in] Ethernet MAC instance

    Param enable:

      [in] set true to enable flow control; set false to disable flow control

    Return:

      - ESP_OK: set flow control successfully

      - ESP_FAIL: set flow control failed because some error occurred

  esp_err_t (*set_peer_pause_ability)(esp_eth_mac_t *mac, uint32_t ability)

    Set the PAUSE ability of peer node.

    Param mac:

      [in] Ethernet MAC instance

    Param ability:

      [in] zero indicates that pause function is supported by link partner; non-zero indicates that pause function is not supported by link partner

    Return:

      - ESP_OK: set peer pause ability successfully

      - ESP_FAIL: set peer pause ability failed because some error occurred

  esp_err_t (*custom_ioctl)(esp_eth_mac_t *mac, int cmd, void *data)

    Custom IO function of MAC driver. This function is intended to extend common options of esp_eth_ioctl to cover specifics of MAC chip.

    备注

    This function may not be assigned when the MAC chip supports only most common set of configuration options.

    Param mac:

      [in] Ethernet MAC instance

    Param cmd:

      [in] IO control command

    Param data:

      [inout] address of data for `set` command or address where to store the data when used with `get` command

    Return:

      - ESP_OK: process io command successfully

      - ESP_ERR_INVALID_ARG: process io command failed because of some invalid argument

      - ESP_FAIL: process io command failed because some other error occurred

      - ESP_ERR_NOT_SUPPORTED: requested feature is not supported

  esp_err_t (*del)(esp_eth_mac_t *mac)

    Free memory of Ethernet MAC.

    Param mac:

      [in] Ethernet MAC instance

    Return:

      - ESP_OK: free Ethernet MAC instance successfully

      - ESP_FAIL: free Ethernet MAC instance failed because some error occurred

struct eth_mac_time_t

  Ethernet MAC Time Stamp.

  Public Members

  uint32_t seconds

    Seconds

  uint32_t nanoseconds

    Nanoseconds

struct eth_mac_config_t

  Configuration of Ethernet MAC object.

  Public Members

  uint32_t sw_reset_timeout_ms

    Software reset timeout value (Unit: ms)

  uint32_t rx_task_stack_size

    Stack size of the receive task

  uint32_t rx_task_prio

    Priority of the receive task

  uint32_t flags

    Flags that specify extra capability for mac driver

### Macros

ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE

  MAC driver can work when cache is disabled

ETH_MAC_FLAG_PIN_TO_CORE

  Pin MAC task to the CPU core where driver installation happened

ETH_MAC_DEFAULT_CONFIG()

  Default configuration for Ethernet MAC object.

### Type Definitions

typedef struct esp_eth_mac_s esp_eth_mac_t

  Ethernet MAC.

### Header File

- components/esp_eth/include/esp_eth_mac_esp.h

- This header file can be included with:

  >     #include "esp_eth_mac_esp.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Functions

esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config, const eth_mac_config_t *config)

  Create ESP32 Ethernet MAC instance.

  参数:

    - esp32_config -- EMAC specific configuration

    - config -- Ethernet MAC configuration

  返回:

    - instance: create MAC instance successfully

    - NULL: create MAC instance failed because some error occurred

### Unions

union eth_mac_clock_config_t
  #include <esp_eth_mac_esp.h>

  Ethernet MAC Clock Configuration.

  Public Members

  struct eth_mac_clock_config_t mii

    EMAC MII Clock Configuration

  emac_rmii_clock_mode_t clock_mode

    RMII Clock Mode Configuration

  int clock_gpio

    RMII Clock GPIO Configuration

  struct eth_mac_clock_config_t rmii

    EMAC RMII Clock Configuration

### Structures

struct emac_esp_smi_gpio_config_t

  EMAC SMI GPIO configuration.

  Public Members

  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

struct eth_mac_mii_gpio_config_t

  EMAC MII data interface GPIO configuration.

  Public Members

  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

struct eth_mac_rmii_gpio_config_t

  EMAC RMII data interface GPIO configuration.

  Public Members

  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

struct eth_esp32_emac_config_t

  EMAC specific configuration.

  Public Members

  emac_esp_smi_gpio_config_t smi_gpio

    SMI GPIO numbers

  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

  int32_t mdc_freq_hz

    EMAC MDC frequency range limit, if set to 0 or a negative value, the driver will set the CSR clock range up to 2.5 MHz

### Macros

ETH_ESP32_EMAC_DEFAULT_CONFIG()

  Default ESP32's EMAC specific configuration.

### Enumerations

enum emac_rmii_clock_mode_t

  RMII Clock Mode Options.

  Values:

  enumerator EMAC_CLK_EXT_IN

    Input RMII Clock from external. EMAC Clock GPIO number needs to be configured when this option is selected.

    备注

    See components/soc/esp32(*)/emac_periph.c for available GPIO numbers.

  enumerator EMAC_CLK_OUT

    Output RMII Clock from internal (A/M)PLL Clock. EMAC Clock GPIO number needs to be configured when this option is selected.

    备注

    See components/soc/esp32(*)/emac_periph.c for available GPIO numbers.

    警告

    ESP32 Errata: If you want the Ethernet to work with Wi-Fi or BT, don’t select ESP32 as RMII CLK output as it would result in clock instability. Applicable only to ESP32, other ESP32 SoCs are not affected.

enum eth_mac_esp_io_cmd_t

  List of ESP EMAC specific commands for ioctl API.

  Values:

  enumerator ETH_MAC_ESP_CMD_SET_TDES0_CFG_BITS

    Set Transmit Descriptor Word 0 control bit mask (debug option)

  enumerator ETH_MAC_ESP_CMD_CLEAR_TDES0_CFG_BITS

    Clear Transmit Descriptor Word 0 control bit mask (debug option)

  enumerator ETH_MAC_ESP_CMD_DUMP_REGS

    Dump EMAC registers (debug option)

### Header File

- components/esp_eth/include/esp_eth_mac_spi.h

- This header file can be included with:

  >     #include "esp_eth_mac_spi.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Structures

struct eth_spi_custom_driver_config_t

  Custom SPI Driver Configuration. This structure declares configuration and callback functions to access Ethernet SPI module via user's custom SPI driver.

  Public Members

  void *config

    Custom driver specific configuration data used by `init()` function.

    备注

    Type and its content is fully under user's control

  void *(*init)(const void *spi_config)

    Custom driver SPI Initialization.

    备注

    return type and its content is fully under user's control

    Param spi_config:

      [in] 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

  esp_err_t (*deinit)(void *spi_ctx)

    Custom driver De-initialization.

    Param spi_ctx:

      [in] 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 (*read)(void *spi_ctx, uint32_t cmd, uint32_t addr, void *data, uint32_t data_len)

    Custom driver SPI read.

    备注

    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 spi_ctx:

      [in] a pointer to driver specific context structure

    Param cmd:

      [in] command

    Param addr:

      [in] register address

    Param data:

      [out] read data

    Param data_len:

      [in] 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 (*write)(void *spi_ctx, uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len)

    Custom driver SPI write.

    备注

    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 spi_ctx:

      [in] a pointer to driver specific context structure

    Param cmd:

      [in] command

    Param addr:

      [in] register address

    Param data:

      [in] data to write

    Param data_len:

      [in] 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

### Macros

ETH_DEFAULT_SPI

  Default configuration of the custom SPI driver. Internal ESP-IDF SPI Master driver is used by default.

### Header File

- components/esp_eth/include/esp_eth_phy.h

- This header file can be included with:

  >     #include "esp_eth_phy.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Functions

esp_eth_phy_t *esp_eth_phy_new_generic(const eth_phy_config_t *config)

  Create a PHY instance of generic chip which conforms with IEEE 802.3.

  备注

  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 `config` parameter.

  警告

  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 -- [in] configuration of PHY

  返回:

    - instance: create PHY instance successfully

    - NULL: create PHY instance failed because some error occurred

### Structures

struct esp_eth_phy_s

  Ethernet PHY.

  Public Members

  esp_err_t (*set_mediator)(esp_eth_phy_t *phy, esp_eth_mediator_t *mediator)

    Set mediator for PHY.

    Param phy:

      [in] Ethernet PHY instance

    Param mediator:

      [in] mediator of Ethernet driver

    Return:

      - ESP_OK: set mediator for Ethernet PHY instance successfully

      - ESP_ERR_INVALID_ARG: set mediator for Ethernet PHY instance failed because of some invalid arguments

  esp_err_t (*reset)(esp_eth_phy_t *phy)

    Software Reset Ethernet PHY.

    Param phy:

      [in] Ethernet PHY instance

    Return:

      - ESP_OK: reset Ethernet PHY successfully

      - ESP_FAIL: reset Ethernet PHY failed because some error occurred

  esp_err_t (*reset_hw)(esp_eth_phy_t *phy)

    Hardware Reset Ethernet PHY.

    备注

    Hardware reset is mostly done by pull down and up PHY's nRST pin

    Param phy:

      [in] Ethernet PHY instance

    Return:

      - ESP_OK: reset Ethernet PHY successfully

      - ESP_FAIL: reset Ethernet PHY failed because some error occurred

  esp_err_t (*init)(esp_eth_phy_t *phy)

    Initialize Ethernet PHY.

    Param phy:

      [in] Ethernet PHY instance

    Return:

      - ESP_OK: initialize Ethernet PHY successfully

      - ESP_FAIL: initialize Ethernet PHY failed because some error occurred

  esp_err_t (*deinit)(esp_eth_phy_t *phy)

    Deinitialize Ethernet PHY.

    Param phy:

      [in] Ethernet PHY instance

    Return:

      - ESP_OK: deinitialize Ethernet PHY successfully

      - ESP_FAIL: deinitialize Ethernet PHY failed because some error occurred

  esp_err_t (*autonego_ctrl)(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat)

    Configure auto negotiation.

    Param phy:

      [in] Ethernet PHY instance

    Param cmd:

      [in] Configuration command, it is possible to Enable (restart), Disable or get current status of PHY auto negotiation

    Param autonego_en_stat:

      [out] Address where to store current status of auto negotiation configuration

    Return:

      - ESP_OK: restart auto negotiation successfully

      - ESP_FAIL: restart auto negotiation failed because some error occurred

      - ESP_ERR_INVALID_ARG: invalid command

  esp_err_t (*get_link)(esp_eth_phy_t *phy)

    Get Ethernet PHY link status.

    Param phy:

      [in] Ethernet PHY instance

    Return:

      - ESP_OK: get Ethernet PHY link status successfully

      - ESP_FAIL: get Ethernet PHY link status failed because some error occurred

  esp_err_t (*set_link)(esp_eth_phy_t *phy, eth_link_t link)

    Set Ethernet PHY link status.

    Param phy:

      [in] Ethernet PHY instance

    Param link:

      [in] new link status

    Return:

      - ESP_OK: set Ethernet PHY link status successfully

      - ESP_FAIL: set Ethernet PHY link status failed because some error occurred

  esp_err_t (*pwrctl)(esp_eth_phy_t *phy, bool enable)

    Power control of Ethernet PHY.

    Param phy:

      [in] Ethernet PHY instance

    Param enable:

      [in] set true to power on Ethernet PHY; ser false to power off Ethernet PHY

    Return:

      - ESP_OK: control Ethernet PHY power successfully

      - ESP_FAIL: control Ethernet PHY power failed because some error occurred

  esp_err_t (*set_addr)(esp_eth_phy_t *phy, uint32_t addr)

    Set PHY chip address.

    Param phy:

      [in] Ethernet PHY instance

    Param addr:

      [in] PHY chip address

    Return:

      - ESP_OK: set Ethernet PHY address successfully

      - ESP_FAIL: set Ethernet PHY address failed because some error occurred

  esp_err_t (*get_addr)(esp_eth_phy_t *phy, uint32_t *addr)

    Get PHY chip address.

    Param phy:

      [in] Ethernet PHY instance

    Param addr:

      [out] PHY chip address

    Return:

      - ESP_OK: get Ethernet PHY address successfully

      - ESP_ERR_INVALID_ARG: get Ethernet PHY address failed because of invalid argument

  esp_err_t (*advertise_pause_ability)(esp_eth_phy_t *phy, uint32_t ability)

    Advertise pause function supported by MAC layer.

    Param phy:

      [in] Ethernet PHY instance

    Param addr:

      [out] Pause ability

    Return:

      - ESP_OK: Advertise pause ability successfully

      - ESP_ERR_INVALID_ARG: Advertise pause ability failed because of invalid argument

  esp_err_t (*loopback)(esp_eth_phy_t *phy, bool enable)

    Sets the PHY to loopback mode.

    Param phy:

      [in] Ethernet PHY instance

    Param enable:

      [in] enables or disables PHY loopback

    Return:

      - ESP_OK: PHY instance loopback mode has been configured successfully

      - ESP_FAIL: PHY instance loopback configuration failed because some error occurred

  esp_err_t (*set_speed)(esp_eth_phy_t *phy, eth_speed_t speed)

    Sets PHY speed mode.

    备注

    Autonegotiation feature needs to be disabled prior to calling this function for the new setting to be applied

    Param phy:

      [in] Ethernet PHY instance

    Param speed:

      [in] Speed mode to be set

    Return:

      - ESP_OK: PHY instance speed mode has been configured successfully

      - ESP_FAIL: PHY instance speed mode configuration failed because some error occurred

  esp_err_t (*set_duplex)(esp_eth_phy_t *phy, eth_duplex_t duplex)

    Sets PHY duplex mode.

    备注

    Autonegotiation feature needs to be disabled prior to calling this function for the new setting to be applied

    Param phy:

      [in] Ethernet PHY instance

    Param duplex:

      [in] Duplex mode to be set

    Return:

      - ESP_OK: PHY instance duplex mode has been configured successfully

      - ESP_FAIL: PHY instance duplex mode configuration failed because some error occurred

  esp_err_t (*custom_ioctl)(esp_eth_phy_t *phy, int cmd, void *data)

    Custom IO function of PHY driver. This function is intended to extend common options of esp_eth_ioctl to cover specifics of PHY chip.

    备注

    This function may not be assigned when the PHY chip supports only most common set of configuration options.

    Param phy:

      [in] Ethernet PHY instance

    Param cmd:

      [in] IO control command

    Param data:

      [inout] address of data for `set` command or address where to store the data when used with `get` command

    Return:

      - ESP_OK: process io command successfully

      - ESP_ERR_INVALID_ARG: process io command failed because of some invalid argument

      - ESP_FAIL: process io command failed because some other error occurred

      - ESP_ERR_NOT_SUPPORTED: requested feature is not supported

  esp_err_t (*del)(esp_eth_phy_t *phy)

    Free memory of Ethernet PHY instance.

    Param phy:

      [in] Ethernet PHY instance

    Return:

      - ESP_OK: free PHY instance successfully

      - ESP_FAIL: free PHY instance failed because some error occurred

struct eth_phy_config_t

  Ethernet PHY configuration.

  Public Members

  int32_t phy_addr

    PHY address, set -1 to enable PHY address detection at initialization stage

  uint32_t reset_timeout_ms

    Reset timeout value (Unit: ms)

  uint32_t autonego_timeout_ms

    Auto-negotiation timeout value (Unit: ms)

  int reset_gpio_num

    Reset GPIO number, -1 means no hardware reset

  int32_t hw_reset_assert_time_us

    Time the reset pin is asserted (Unit: us), 0 to use chip specific default

  int32_t post_hw_reset_delay_ms

    Time to wait after the HW reset (Unit: ms), 0 to use chip specific default, -1 means no wait

### Macros

ESP_ETH_PHY_ADDR_AUTO

ESP_ETH_NO_POST_HW_RESET_DELAY

ETH_PHY_DEFAULT_CONFIG()

  Default configuration for Ethernet PHY object.

### Type Definitions

typedef struct esp_eth_phy_s esp_eth_phy_t

  Ethernet PHY.

### Enumerations

enum eth_phy_autoneg_cmd_t

  Auto-negotiation control commands.

  Values:

  enumerator ESP_ETH_PHY_AUTONEGO_RESTART
  enumerator ESP_ETH_PHY_AUTONEGO_EN
  enumerator ESP_ETH_PHY_AUTONEGO_DIS
  enumerator ESP_ETH_PHY_AUTONEGO_G_STAT

### Header File

- components/esp_eth/include/esp_eth_phy_802_3.h

- This header file can be included with:

  >     #include "esp_eth_phy_802_3.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Functions

esp_err_t esp_eth_phy_802_3_set_mediator(phy_802_3_t *phy_802_3, esp_eth_mediator_t *eth)

  Set Ethernet mediator.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - eth -- Ethernet mediator pointer

  返回:

    - ESP_OK: Ethermet mediator set successfully

    - ESP_ERR_INVALID_ARG: if `eth` is `NULL`

esp_err_t esp_eth_phy_802_3_reset(phy_802_3_t *phy_802_3)

  Reset PHY.

  参数:

    phy_802_3 -- IEEE 802.3 PHY object infostructure

  返回:

    - ESP_OK: Ethernet PHY reset successfully

    - ESP_FAIL: reset Ethernet PHY failed because some error occurred

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)

  Control autonegotiation mode of Ethernet PHY.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - cmd -- autonegotiation command enumeration

    - autonego_en_stat -- [out] autonegotiation enabled flag

  返回:

    - 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 `cmd`

esp_err_t esp_eth_phy_802_3_updt_link_dup_spd(phy_802_3_t *phy_802_3)

  Retrieve link status and propagate the status to higher layers if the status changed.

  参数:

    phy_802_3 -- IEEE 802.3 PHY object infostructure

  返回:

    - ESP_OK: Ethernet PHY link status retrieved successfully

    - ESP_FAIL: Error occurred during reading registry

esp_err_t esp_eth_phy_802_3_pwrctl(phy_802_3_t *phy_802_3, bool enable)

  Power control of Ethernet PHY.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - enable -- set true to power ON Ethernet PHY; set false to power OFF Ethernet PHY

  返回:

    - 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_set_addr(phy_802_3_t *phy_802_3, uint32_t addr)

  Set Ethernet PHY address.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - addr -- new PHY address

  返回:

    - ESP_OK: Ethernet PHY address set

esp_err_t esp_eth_phy_802_3_get_addr(phy_802_3_t *phy_802_3, uint32_t *addr)

  Get Ethernet PHY address.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - addr -- [out] Ethernet PHY address

  返回:

    - ESP_OK: Ethernet PHY address read successfully

    - ESP_ERR_INVALID_ARG: `addr` pointer is `NULL`

esp_err_t esp_eth_phy_802_3_advertise_pause_ability(phy_802_3_t *phy_802_3, uint32_t ability)

  Advertise pause function ability.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - ability -- enable or disable pause ability

  返回:

    - 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_loopback(phy_802_3_t *phy_802_3, bool enable)

  Set Ethernet PHY loopback mode.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - enable -- set true to enable loopback; set false to disable loopback

  返回:

    - 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_set_speed(phy_802_3_t *phy_802_3, eth_speed_t speed)

  Set Ethernet PHY speed.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - speed -- new speed of Ethernet PHY link

  返回:

    - 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_duplex(phy_802_3_t *phy_802_3, eth_duplex_t duplex)

  Set Ethernet PHY duplex mode.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - duplex -- new duplex mode for Ethernet PHY link

  返回:

    - 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 occurred

esp_err_t esp_eth_phy_802_3_set_link(phy_802_3_t *phy_802_3, eth_link_t link)

  Set Ethernet PHY link status.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - link -- new link status

  返回:

    - ESP_OK: Ethernet PHY link set successfully

esp_err_t esp_eth_phy_802_3_init(phy_802_3_t *phy_802_3)

  Initialize Ethernet PHY.

  参数:

    phy_802_3 -- IEEE 802.3 PHY object infostructure

  返回:

    - ESP_OK: Ethernet PHY initialized successfully

esp_err_t esp_eth_phy_802_3_deinit(phy_802_3_t *phy_802_3)

  Power off Eternet PHY.

  参数:

    phy_802_3 -- IEEE 802.3 PHY object infostructure

  返回:

    - ESP_OK: Ethernet PHY powered off successfully

esp_err_t esp_eth_phy_802_3_del(phy_802_3_t *phy_802_3)

  Delete Ethernet PHY infostructure.

  参数:

    phy_802_3 -- IEEE 802.3 PHY object infostructure

  返回:

    - ESP_OK: Ethernet PHY infostructure deleted

esp_err_t esp_eth_phy_802_3_reset_hw(phy_802_3_t *phy_802_3)

  Performs hardware reset with internal timing configuration defined during initialization.

  参数:

    phy_802_3 -- IEEE 802.3 PHY object infostructure

  返回:

    - ESP_OK: reset Ethernet PHY successfully

    - ESP_ERR_NOT_ALLOWED: reset GPIO not defined

esp_err_t esp_eth_phy_802_3_detect_phy_addr(esp_eth_mediator_t *eth, int *detected_addr)

  Detect PHY address.

  参数:

    - eth -- Mediator of Ethernet driver

    - detected_addr -- [out] a valid address after detection

  返回:

    - ESP_OK: detect phy address successfully

    - ESP_ERR_INVALID_ARG: invalid parameter

    - ESP_ERR_NOT_FOUND: can't detect any PHY device

    - ESP_FAIL: detect phy address failed because some error occurred

esp_err_t esp_eth_phy_802_3_basic_phy_init(phy_802_3_t *phy_802_3)

  Performs basic PHY chip initialization.

  备注

  It should be called as the first function in PHY specific driver instance

  参数:

    phy_802_3 -- IEEE 802.3 PHY object infostructure

  返回:

    - ESP_OK: initialized Ethernet PHY successfully

    - ESP_FAIL: initialization of Ethernet PHY failed because some error occurred

    - ESP_ERR_INVALID_ARG: invalid argument

    - ESP_ERR_NOT_FOUND: PHY device not detected

    - ESP_ERR_TIMEOUT: MII Management read/write operation timeout

    - ESP_ERR_INVALID_STATE: PHY is in invalid state to perform requested operation

esp_err_t esp_eth_phy_802_3_basic_phy_deinit(phy_802_3_t *phy_802_3)

  Performs basic PHY chip de-initialization.

  备注

  It should be called as the last function in PHY specific driver instance

  参数:

    phy_802_3 -- IEEE 802.3 PHY object infostructure

  返回:

    - ESP_OK: de-initialized Ethernet PHY successfully

    - ESP_FAIL: de-initialization of Ethernet PHY failed because some error occurred

    - ESP_ERR_TIMEOUT: MII Management read/write operation timeout

    - ESP_ERR_INVALID_STATE: PHY is in invalid state to perform requested operation

esp_err_t esp_eth_phy_802_3_read_oui(phy_802_3_t *phy_802_3, uint32_t *oui)

  Reads raw content of OUI field.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - oui -- [out] OUI value

  返回:

    - ESP_OK: OUI field read successfully

    - ESP_FAIL: OUI field read failed because some error occurred

    - ESP_ERR_INVALID_ARG: invalid `oui` argument

    - ESP_ERR_TIMEOUT: MII Management read/write operation timeout

    - ESP_ERR_INVALID_STATE: PHY is in invalid state to perform requested operation

esp_err_t esp_eth_phy_802_3_read_manufac_info(phy_802_3_t *phy_802_3, uint8_t *model, uint8_t *rev)

  Reads manufacturer’s model and revision number.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - model -- [out] Manufacturer’s model number (can be NULL when not required)

    - rev -- [out] Manufacturer’s revision number (can be NULL when not required)

  返回:

    - ESP_OK: Manufacturer’s info read successfully

    - ESP_FAIL: Manufacturer’s info read failed because some error occurred

    - ESP_ERR_TIMEOUT: MII Management read/write operation timeout

    - ESP_ERR_INVALID_STATE: PHY is in invalid state to perform requested operation

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)

  Reads MDIO device's internal address register.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - devaddr -- Address of MDIO device

    - mmd_addr -- [out] Current address stored in device's register

  返回:

    - 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_set_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr)

  Write to DIO device's internal address register.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - devaddr -- Address of MDIO device

    - mmd_addr -- [out] New value of MDIO device's address register value

  返回:

    - 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_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)

  Read data of MDIO device's memory at address register.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - devaddr -- Address of MDIO device

    - function -- MMD function

    - data -- [out] Data read from the device's memory

  返回:

    - 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_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)

  Write data to MDIO device's memory at address register.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - devaddr -- Address of MDIO device

    - function -- MMD function

    - data -- [out] Data to write to the device's memory

  返回:

    - 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_read_mmd_register(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr, uint32_t *data)

  Set MMD address to mmd_addr with function MMD_FUNC_NOINCR and read contents to *data.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - devaddr -- Address of MDIO device

    - mmd_addr -- Address of MDIO device register

    - data -- [out] Data read from the device's memory

  返回:

    - 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_write_mmd_register(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr, uint32_t data)

  Set MMD address to mmd_addr with function MMD_FUNC_NOINCR and write data.

  参数:

    - phy_802_3 -- IEEE 802.3 PHY object infostructure

    - devaddr -- Address of MDIO device

    - mmd_addr -- Address of MDIO device register

    - data -- [out] Data to write to the device's memory

  返回:

    - 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)

inline phy_802_3_t *esp_eth_phy_into_phy_802_3(esp_eth_phy_t *phy)

  Returns address to parent IEEE 802.3 PHY object infostructure.

  参数:

    phy -- Ethernet PHY instance

  返回:

    phy_802_3_t*

    - address to parent IEEE 802.3 PHY object infostructure

esp_err_t esp_eth_phy_802_3_obj_config_init(phy_802_3_t *phy_802_3, const eth_phy_config_t *config)

  Initializes configuration of parent IEEE 802.3 PHY object infostructure.

  参数:

    - phy_802_3 -- Address to IEEE 802.3 PHY object infostructure

    - config -- Configuration of the IEEE 802.3 PHY object

  返回:

    - ESP_OK: configuration initialized successfully

    - ESP_ERR_INVALID_ARG: invalid `config` argument

### Structures

struct phy_802_3_t

  IEEE 802.3 PHY object infostructure.

  Public Members

  esp_eth_phy_t parent

    Parent Ethernet PHY instance

  esp_eth_mediator_t *eth

    Mediator of Ethernet driver

  int addr

    PHY address

  uint32_t reset_timeout_ms

    Reset timeout value (Unit: ms)

  uint32_t autonego_timeout_ms

    Auto-negotiation timeout value (Unit: ms)

  eth_link_t link_status

    Current Link status

  int reset_gpio_num

    Reset GPIO number, -1 means no hardware reset

  int32_t hw_reset_assert_time_us

    Time the reset pin is asserted (Unit: us)

  int32_t post_hw_reset_delay_ms

    Time to wait after the HW reset (Unit: ms)

### Enumerations

enum esp_eth_phy_802_3_mmd_func_t

  IEEE 802.3 MMD modes enumeration.

  Values:

  enumerator MMD_FUNC_ADDRESS
  enumerator MMD_FUNC_DATA_NOINCR
  enumerator MMD_FUNC_DATA_RWINCR
  enumerator MMD_FUNC_DATA_WINCR

### Header File

- components/esp_eth/include/esp_eth_netif_glue.h

- This header file can be included with:

  >     #include "esp_eth_netif_glue.h"

- This header file is a part of the API provided by the `esp_eth` component. To declare that your component depends on `esp_eth`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_eth

  > or

  >     PRIV_REQUIRES esp_eth

### Functions

esp_eth_netif_glue_handle_t esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl)

  Create a netif glue for Ethernet driver.

  备注

  netif glue is used to attach io driver to TCP/IP netif

  参数:

    eth_hdl -- Ethernet driver handle

  返回:

    glue object, which inherits esp_netif_driver_base_t

esp_err_t esp_eth_del_netif_glue(esp_eth_netif_glue_handle_t eth_netif_glue)

  Delete netif glue of Ethernet driver.

  参数:

    eth_netif_glue -- netif glue

  返回:

    -ESP_OK: delete netif glue successfully

### Type Definitions

typedef struct esp_eth_netif_glue_t *esp_eth_netif_glue_handle_t

  Handle of netif glue - an intermediate layer between netif and Ethernet driver.

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。