Merge branch 'docs/eth_memory_consideration' into 'master'

Non-functional Ethernet updates

Closes IDFGH-13346 and IDF-11736

See merge request espressif/esp-idf!36219
This commit is contained in:
Ondrej Kosta 2025-01-27 19:24:34 +08:00
commit e188afdacf
3 changed files with 36 additions and 9 deletions

View File

@ -446,7 +446,6 @@ static void emac_esp32_rx_task(void *arg)
#endif
} while (emac->frames_remain);
}
vTaskDelete(NULL);
}
static esp_err_t emac_config_pll_clock(emac_esp32_t *emac)

View File

@ -1,6 +1,7 @@
Ethernet
========
{IDF_TARGET_SOC_DMA_DESC_SIZE:default="", esp32="32 bytes", esp32p4=" 32 bytes (64 bytes in fact due to the need for proper memory alignment)"}
{IDF_TARGET_SOC_REF_CLK_IN_GPIO:default="", esp32="GPIO0", esp32p4="GPIO32, GPIO44 and GPIO50"}
{IDF_TARGET_SOC_REF_CLK_OUT_GPIO:default="", esp32="GPIO0, GPIO16 and GPIO17", esp32p4="GPIO23 and GPIO39"}
{IDF_TARGET_SOC_RMII_TX_EN:default="", esp32="GPIO21", esp32p4="GPIO33, GPIO40 and GPIO49"}
@ -257,6 +258,19 @@ Basic common configuration for MAC layer is described in :cpp:class:`eth_mac_con
:not SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK: * :cpp:member:`eth_esp32_emac_config_t::clock_config_out_in`: configuration of EMAC input interface clock when ``REF_CLK`` signal is generated internally and is looped back to the EMAC externally. The mode must be always configured to :cpp:enumerator:`emac_rmii_clock_mode_t::EMAC_CLK_EXT_IN`. This option is valid only when configuration of :cpp:member:`eth_esp32_emac_config_t::clock_config` is set to :cpp:enumerator:`emac_rmii_clock_mode_t::EMAC_CLK_OUT`.
Memory Considerations when Using Internal MAC
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The internal MAC subsystem transfers data to and from the CPU domain via DMA using a linked list of descriptors. There are two types of descriptors: Transmit and Receive. Based on its type, a descriptor holds status information about the received or transmitted frame or provides controls for transmission. Each descriptor also contains pointers to the current data buffer and the next descriptor. As such, a single EMAC DMA descriptor has size of {IDF_TARGET_SOC_DMA_DESC_SIZE} in DMA-capable memory.
The default configuration should cover most use cases. However, certain scenarios may require configuring the Ethernet DMA memory utilization to suit specific needs. Typical problems may arise in the following situations:
.. list::
* **Short and frequent frames dominate network traffic**: If your network traffic primarily consists of very short and frequently transmitted/received frames, you may observe issues such as lower-than-expected throughput (despite the rated 100 Mbps) and missed frames during reception. On transmission, the socket send API may return ``errno`` equal to ``ENOMEM``, accompanied by the `insufficient TX buffer size` message (if debug log level is enabled). This is because the default memory configuration is optimized for larger frames; :ref:`CONFIG_ETH_DMA_BUFFER_SIZE` is set to 512 bytes by default to ensure a better *data buffer* to *descriptor* size overhead ratio. The solution is to increase :ref:`CONFIG_ETH_DMA_RX_BUFFER_NUM` or :ref:`CONFIG_ETH_DMA_TX_BUFFER_NUM`. Additionally, consider decreasing :ref:`CONFIG_ETH_DMA_BUFFER_SIZE` to match the typical frame size in your network to maintain a reasonable memory footprint of the Ethernet driver.
* **High throughput leads to buffer exhaustion**: If the socket send API intermittently returns ``errno`` equal to ``ENOMEM``, accompanied by the `insufficient TX buffer size` message (if debug log level is enabled), and the throughput is close to the rated 100 Mbps, this likely indicates nearing hardware limitations. In such case, the hardware cannot keep up with the transmission requests. The solution is to increase :ref:`CONFIG_ETH_DMA_TX_BUFFER_NUM` to buffer more frames and mitigate temporary peaks in transmission requests. However, this will not help if the requested traffic consistently exceeds the rated throughput. In such situations, the only solution is to limit the bandwidth by software means at the application level.
Configuration for PHY is described in :cpp:class:`eth_phy_config_t`, including:
.. list::

View File

@ -1,14 +1,15 @@
以太网
=========
{IDF_TARGET_SOC_REF_CLK_IN_GPIO:default="", esp32="GPIO0", esp32p4="GPIO32, GPIO44 and GPIO50"}
{IDF_TARGET_SOC_REF_CLK_OUT_GPIO:default="", esp32="GPIO0, GPIO16 and GPIO17", esp32p4="GPIO23 and GPIO39"}
{IDF_TARGET_SOC_RMII_TX_EN:default="", esp32="GPIO21", esp32p4="GPIO33, GPIO40 and GPIO49"}
{IDF_TARGET_SOC_RMII_TXD0:default="", esp32="GPIO19", esp32p4="GPIO34 and GPIO41"}
{IDF_TARGET_SOC_RMII_TXD1:default="", esp32="GPIO22", esp32p4="GPIO35 and GPIO42"}
{IDF_TARGET_SOC_RMII_CRS_DV:default="", esp32="GPIO27", esp32p4="GPIO28, GPIO45 and GPIO51"}
{IDF_TARGET_SOC_RMII_RXD0:default="", esp32="GPIO25", esp32p4="GPIO29, GPIO46 and GPIO52"}
{IDF_TARGET_SOC_RMII_RXD1:default="", esp32="GPIO26", esp32p4="GPIO30, GPIO47 and GPIO53"}
{IDF_TARGET_SOC_DMA_DESC_SIZE:default="", esp32="32 字节", esp32p4=" 32 字节(由于需要适当的内存对齐,实际占用 64 字节)"}
{IDF_TARGET_SOC_REF_CLK_IN_GPIO:default="", esp32="GPIO0", esp32p4="GPIO32GPIO44 和 GPIO50"}
{IDF_TARGET_SOC_REF_CLK_OUT_GPIO:default="", esp32="GPIO0GPIO16 和 GPIO17", esp32p4="GPIO23 和 GPIO39"}
{IDF_TARGET_SOC_RMII_TX_EN:default="", esp32="GPIO21", esp32p4="GPIO33GPIO40 和 GPIO49"}
{IDF_TARGET_SOC_RMII_TXD0:default="", esp32="GPIO19", esp32p4="GPIO34 和 GPIO41"}
{IDF_TARGET_SOC_RMII_TXD1:default="", esp32="GPIO22", esp32p4="GPIO35 和 GPIO42"}
{IDF_TARGET_SOC_RMII_CRS_DV:default="", esp32="GPIO27", esp32p4="GPIO28GPIO45 和 GPIO51"}
{IDF_TARGET_SOC_RMII_RXD0:default="", esp32="GPIO25", esp32p4="GPIO29GPIO46 和 GPIO52"}
{IDF_TARGET_SOC_RMII_RXD1:default="", esp32="GPIO26", esp32p4="GPIO30GPIO47 和 GPIO53"}
:link_to_translation:`en:[English]`
@ -257,6 +258,19 @@ MAC 的相关配置可以在 :cpp:class:`eth_mac_config_t` 中找到,具体包
:not SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK: * :cpp:member:`eth_esp32_emac_config_t::clock_config_out_in`:当 ``REF_CLK`` 信号在内部生成并从外部回环到 EMAC 时,配置 EMAC 输入接口时钟。必须始终将 EMAC 的模式配置为 :cpp:enumerator:`emac_rmii_clock_mode_t::EMAC_CLK_EXT_IN`。此选项仅在 :cpp:member:`eth_esp32_emac_config_t::clock_config` 的配置设置为 :cpp:enumerator:`emac_rmii_clock_mode_t::EMAC_CLK_OUT` 时有效。
使用内部 MAC 时的内存注意事项
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
内部 MAC 子系统通过 DMA 使用描述符链表在 CPU 域之间传输数据。描述符有发送和接收两种类型,分别保存接收或已发送帧的状态信息,或提供传输控制。每个描述符还包含指向当前数据缓冲区和下一个描述符的指针。因此,在支持 DMA 的内存中,单个 EMAC DMA 描述符的大小为 {IDF_TARGET_SOC_DMA_DESC_SIZE}。
默认配置应涵盖大多数用例。然而,某些情况可能需要对以太网 DMA 内存的使用进行配置,以满足特定需求。典型问题可能发生于下列情形:
.. list::
* **网络流量由短且频繁的帧主导时**:如果你的网络流量主要由短且频繁发送(或接收)的帧组成,可能会遇到吞吐量低于预期(尽管额定为 100 Mbps以及接收过程中丢帧等问题。在发送时套接字发送 API 可能会返回 ``errno`` 为 ``ENOMEM``,并显示 `TX 缓冲区大小不足`(如果启用了调试日志级别)。这些问题的主要原因是,默认的内存配置针对较大帧进行了优化。默认情况下 :ref:`CONFIG_ETH_DMA_BUFFER_SIZE` 设置为 512 字节,以确保 *数据缓冲区* 与 *描述符* 大小的开销比。要解决此问题,可以增加缓冲区数量, :ref:`CONFIG_ETH_DMA_RX_BUFFER_NUM`:ref:`CONFIG_ETH_DMA_TX_BUFFER_NUM`。此外,还可以减小 :ref:`CONFIG_ETH_DMA_BUFFER_SIZE`,使其与网络中典型帧的大小相匹配,从而合理控制以太网驱动的内存占用。
* **高吞吐量导致缓冲区耗尽时**:如果套接字发送 API 间歇性返回 ``errno````ENOMEM``,并显示 `TX 缓冲区大小不足`(如果启用了调试日志级别),且吞吐量接近额定的 100 Mbps这通常表明接近硬件限制。在这种情况下硬件无法跟上传输请求。解决方案是增加 :ref:`CONFIG_ETH_DMA_TX_BUFFER_NUM`,以缓存更多的帧,并缓解传输请求的短时峰值。然而,如果请求的流量持续超过额定吞吐量,此方法将失效,需通过应用层通过软件限制带宽。
PHY 的相关配置可以在 :cpp:class:`eth_phy_config_t` 中找到,具体包括:
.. list::