From 279e8dd6c23c2df78057cce8452ea33afa6c9799 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 9 Jan 2020 19:34:22 +0800 Subject: [PATCH] add Ethernet doc --- .../diagrams/ethernet/RMII Interface.drawio | 1 + .../diagrams/ethernet/data_frame_format.diag | 17 + docs/_static/rmii-interface.png | Bin 0 -> 56138 bytes docs/en/api-reference/network/esp_eth.rst | 393 ++++++++++++++++-- docs/en/api-reference/system/system.rst | 1 + 5 files changed, 366 insertions(+), 46 deletions(-) create mode 100644 docs/_static/diagrams/ethernet/RMII Interface.drawio create mode 100644 docs/_static/diagrams/ethernet/data_frame_format.diag create mode 100644 docs/_static/rmii-interface.png diff --git a/docs/_static/diagrams/ethernet/RMII Interface.drawio b/docs/_static/diagrams/ethernet/RMII Interface.drawio new file mode 100644 index 0000000000..7c6402ec0d --- /dev/null +++ b/docs/_static/diagrams/ethernet/RMII Interface.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/_static/diagrams/ethernet/data_frame_format.diag b/docs/_static/diagrams/ethernet/data_frame_format.diag new file mode 100644 index 0000000000..201a14efc8 --- /dev/null +++ b/docs/_static/diagrams/ethernet/data_frame_format.diag @@ -0,0 +1,17 @@ +#Ethernet Data Frame Format + +rackdiag ethernet_data_frame { + node_width = 500; + default_fontsize = 15; + ascending; + 8U; + description = "Ethernet Data Frame Format"; + 1: Preamble (7 Bytes) [color = lightgrey]; + 2: Start-of-Frame Delimiter (1 Byte) [color = lightgrey]; + 3: Destination Address (6 Bytes) [color = lightblue]; + 4: Source Address (6 Bytes) [color = lightblue]; + 5: Type / Length (2 Bytes) [color = lightyellow]; + 6: Payload (0 ~ 1500 Bytes) [2U]; + 6: Pad (if necessary) [2U]; + 8: Frame Check Sequence (4 Bytes) [color = lightgrey]; +} \ No newline at end of file diff --git a/docs/_static/rmii-interface.png b/docs/_static/rmii-interface.png new file mode 100644 index 0000000000000000000000000000000000000000..d27275ce4de21aa65703ccff45577c2a08faa674 GIT binary patch literal 56138 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

gxplVe3yO|zS8O>TF1uT+@8siZ|HB9GF&^y_ zbFauKS@u;r>>ryV%PiAxPiA^9vPqaSZ(;|!BDtrme`o3+La4D2qTwE!Pp>)9Ur z%Dp{s?Wx@xwr@VZ(RR7yWS7bV8iqd)^V=Udcg|0!Z@J&xCIP1Ob8{}{y}rBKd{_B< zJ+MEnA98*0_O^KHsn9DsL0znp51(8+gO-*ad&2PlqJUGv^NSo6<*%6)S-!QprE>)- zvef-b-F+^3&i;QaWo6$oZY?rRzI5V=+Y-0B{*$|}mmOZ5HdQA5NJaZT|MA zZb#hf&sJ*5%8v~5uBdP*ZYVk_b=0u(@gvzQ>mu33#Kbsm?s4B;d+J7}fK$So6P<3H zp2t)I)7&~wE?J^7MK@YZPEPK|mQ3Ng-*3%BR)_KON|`uhWvwckyL-3wG`(1@?D@yK zPEMWu&4HuQw|?G)JNthBP~}kEkn+`Ru3@F6o#axl>8nj`O>@#JpK{rr5-zEIVL2dT!}^-%^Lg+j63$ERXA{lb*)`aPEO#S z2u_#Q*vrS3H1A~wujBl-*6z9_D2+&%88A3;oS9=JZ5Ou>w7z{?siGSC4s^Eh2LbUp{@zo-Hjsr_bw3 z-s^km8Z81hc0D&)Bpg)m<&Q3h;)TukH`wrd9!q%#bza=rwKEUpwQelDnt$u-*VlWd zKUNn>5uJQ7Jvm@!QmTcu<>5PbWNd5y^hizW@mzG~lPh?XCGG4ii^@++z;kiebM1K) zS+4!7TWl0PM#3AV7@z2K7d)empy%-?c(@%s8((kJ5QKiyOE zoHZvWw=(UL%agy`7l_PJ{Q2oq*1N#N#}n#4D8*RRd2Wh(dHT+*n_H^1TLdEG?w*~Y zVzjPCaPs~?pSan0rIuW;?U9@e>L+|!YXn-7{-QgYt5dv)uK)t>*|V|Tkg zS6n;L>-Wux?{{54_i?k1b@^M~=}zk=ZJyKPsWeI1eowm5<0odIgbtd-edZe_VXGoJ z*=6R_?in@T-pqV*`1DhQG#@whB@50!5Y!0TVxf1pvhmdWJ>2>C_uaZ}bS&kw|LsGk zZbha4`C9k4Zhq+O?@CsRtjzm;ep~Hy)vmw%)8bI_{DWHy1Vh$Gwx_FgdgMbIbe~*( zv=ZOUxU)&yP1R`qYTf7I{3%T+YR|v0_LT>_B__KpF$cGRa(g^y8cNQc&{QOR}adN_h7ue)FC0(W$2np1jHWaN~K<02Xh(jO)cD)r8E+{oy`=q<){szx&fv0AuESdvZPX*p} z;G%X$!Z7ke8>|6M#Q3~#nU7lB&6X1a`FDDw7C(DDu@^Lkxo8e3J-cL0mYvL>RIX%n zMB4oDzTnRvPk^WO0?&aOxk_74_MKG!s4gJ+sQ1O+U$t)+MuCM-NkY7L({SdW_xC$^ zKDwoJmFldjHk-h9PBDgre$~+@m#fpa zrmN4t+aL1U@Z=#-QxInJOVP;;1;5wtTz}u%Qb1E*ZskWbv%mD64A(plTFC%f)cEP% zz8}x?W=QpGyMwG2d4&z(K~xjs+o*T&Rt$r7SdgJnaM=u}w+*Z?Lh2re4`A=QWpExv>0^pQknJo8Oxm=NK3m7(8A5T-G@yGywqG&^V9) literal 0 HcmV?d00001 diff --git a/docs/en/api-reference/network/esp_eth.rst b/docs/en/api-reference/network/esp_eth.rst index 9edb7c46a9..9908e3b81a 100644 --- a/docs/en/api-reference/network/esp_eth.rst +++ b/docs/en/api-reference/network/esp_eth.rst @@ -1,61 +1,362 @@ Ethernet ======== - :link_to_translation:`zh_CN:[中文]` +.. -------------------------------- Overview ----------------------------------- + +Overview +-------- + +ESP-IDF provides a set of consistent and flexible APIs to support both internal Ethernet MAC (EMAC) controller and external SPI-Ethernet modules. + +This programming guide is split into the following sections: + + 1. :ref:`basic-ethernet-concepts` + 2. :ref:`driver-configuration-and-installation` + 3. :ref:`connect-driver-to-stack` + 4. :ref:`misc-operation-of-driver` + +.. --------------------------- Basic Ethernet Concepts ------------------------------ + +.. _basic-ethernet-concepts: + +Basic Ethernet Concepts +----------------------- + +Ethernet is an asynchronous Carrier Sense Multiple Access with Collision Detect (CSMA/CD) protocol/interface. +It is generally not well suited for low power applications. However, with ubiquitous deployment, internet connectivity, high data rates and limitless rage expandability, Ethernet can accommodate nearly all wired communications. + +Normal IEEE 802.3 compliant Ethernet frames are between 64 and 1518 bytes in length. They are made up of five or six different fields: a destination MAC address (DA), a source MAC address (SA), a type/length field, data payload, an optional padding field and a Cyclic Redundancy Check (CRC). +Additionally, when transmitted on the Ethernet medium, a 7-byte preamble field and Start-of-Frame (SOF) delimiter byte are appended to the beginning of the Ethernet packet. + +Thus the traffic on the twist-pair cabling will appear as shown blow: + +.. rackdiag:: ../../../_static/diagrams/ethernet/data_frame_format.diag + :caption: Ethernet Data Frame Format + :align: center + +Preamble and Start-of-Frame Delimiter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The preamble contains seven bytes of ``55H``, it allows the receiver to lock onto the stream of data before the actual frame arrives. +The Start-of-Frame Delimiter (SFD) is a binary sequence ``10101011`` (as seen on the physical medium). It is sometimes considered to be part of the preamble. + +When transmitting and receiving data, the preamble and SFD bytes will automatically be generated or stripped from the packets. + +Destination Address +^^^^^^^^^^^^^^^^^^^ + +The destination address field contains a 6-byte length MAC address of the device that the packet is directed to. +If the Least Significant bit in the first byte of the MAC address is set, the address is a multi-cast destination. +For example, 01-00-00-00-F0-00 and 33-45-67-89-AB-CD are multi-cast addresses, while 00-00-00-00-F0-00 and 32-45-67-89-AB-CD are not. +Packets with multi-cast destination addresses are designed to arrive and be important to a selected group of Ethernet nodes. +If the destination address field is the reserved multi-cast address, i.e. FF-FF-FF-FF-FF-FF, the packet is a broadcast packet and it will be directed to everyone sharing the network. +If the Least Significant bit in the first byte of the MAC address is clear, the address is a uni-cast address and will be designed for usage by only the addressed node. + +Normally the EMAC controller incorporates receive filters which can be used to discard or accept packets with multi-cast, broadcast and/or uni-cast destination addresses. +When transmitting packets, the host controller is responsible for writing the desired destination address into the transmit buffer. + +Source Address +^^^^^^^^^^^^^^ + +The source address field contains a 6-byte length MAC address of the node which created the Ethernet packet. +Users of Ethernet must generate a unique MAC address for each controller used. +MAC addresses consist of two portions. The first three bytes are known as the Organizationally Unique Identifier (OUI). OUIs are distributed by the IEEE. +The last three bytes are address bytes at the discretion of the company that purchased the OUI. More information about MAC Address used in ESP-IDF, please see :ref:`MAC Address Allocation `. + +When transmitting packets, the assigned source MAC address must be written into the transmit buffer by the host controller. + +Type / Length +^^^^^^^^^^^^^ + +The type/length field is a 2-byte field, if the value in this field is <= 1500 (decimal), it is considered a length field and it specifies the amount of non-padding data which follows in the data field. +If the value is >= 1536, it represents the protocol the following packet data belongs to. The following are the most common type values: + + * IPv4 = 0800H + * IPv6 = 86DDH + * ARP = 0806H + +Users implementing proprietary networks may choose to treat this field as a length field, while applications implementing protocols such as the Internet Protocol (IP) or Address Resolution Protocol (ARP), should program this field with the appropriate type defined by the protocol’s specification when transmitting packets. + +Payload +^^^^^^^ + +The payload field is a variable length field, anywhere from 0 to 1500 bytes. Larger data packets will violate Ethernet standards and will be dropped by most Ethernet nodes. +This field contains the client data, such as an IP datagram. + +Padding and FCS +^^^^^^^^^^^^^^^ + +The padding field is a variable length field added to meet IEEE 802.3 specification requirements when small data payloads are used. +The DA, SA, type, payload and padding of an Ethernet packet must be no smaller than 60 bytes. +Adding the required 4-byte FCS field, packets must be no smaller than 64 bytes. +If the data field is less than 46 bytes long, a padding field is required. + +The FCS field is a 4-byte field which contains an industry standard 32-bit CRC calculated with the data from the DA, SA, type, payload and padding fields. +Given the complexity of calculating a CRC, the hardware normally will automatically generate a valid CRC and transmit it. Otherwise, the host controller must generate the CRC and place it in the transmit buffer. + +Normally, the host controller does not need to concern itself with padding and the CRC which the hardware EMAC will also be able to automatically generate when transmitting and verify when receiving. +However, the padding and CRC fields will be written into the receive buffer when packets arrive, so they may be evaluated by the host controller if needed. + +.. note:: + Besides the basic data frame described above, there're two other common frame types in 10/100 Mbps Ethernet: control frames and VLAN tagged frames. + They're not supported in ESP-IDF. + +.. ------------------------------ Driver Operation -------------------------------- + +.. _driver-configuration-and-installation: + +Configure MAC and PHY +--------------------- + +Ethernet driver is composed of two parts: MAC and PHY. The communication between MAC and PHY can have diverse choices: **MII** (Media Independent Interface), **RMII** (Reduced Media Independent Interface) and etc. + +.. figure:: ../../../_static/rmii-interface.png + :align: center + :scale: 80 % + :alt: Ethernet RMII Interface + :figclass: align-center + + Ethernet RMII Interface + +.. only:: esp32 + + One of the obvious difference between MII and RMII is the signal consumption. For MII, it usually costs up to 18 signals. Instead, RMII interface can reduce the consumption to 9. + + In RMII mode, both the receiver and transmitter signals are referenced to the ``REF_CLK``. **REF_CLK must be stable during any access to PHY and MAC**. + Generally there're three ways to generate the ``REF_CLK`` depending on the PHY device in your design: + + * Some PHY chip can derive the ``REF_CLK`` from its external connected 25MHz crystal oscillator (as seen the option *a* in the picture). In this case, you should select ``CONFIG_ETH_RMII_CLK_INPUT`` in :ref:`CONFIG_ETH_RMII_CLK_MODE`. + * Some PHY chip uses an external connected 50MHz crystal oscillator or other clock source, which can also be used as the ``REF_CLK`` for MAC side (as seen the option *b* in the picture). In this case, you still need to select ``CONFIG_ETH_RMII_CLK_INPUT`` in :ref:`CONFIG_ETH_RMII_CLK_MODE`. + * Some EMAC controller can generate the ``REF_CLK`` using its internal high precision PLL (as seen the option *c* in the picture). In this case, you should select ``CONFIG_ETH_RMII_CLK_OUTPUT`` in :ref:`CONFIG_ETH_RMII_CLK_MODE`. + + .. warning:: + If the RMII clock mode is selected to ``CONFIG_ETH_RMII_CLK_OUTPUT``, then ``GPIO0`` can be used to output the ``REF_CLK`` signal. See :ref:`CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0` for more information. + What's more, if you're not using PSRAM in your design, GPIO16 and GPIO17 are also available to output the reference clock. See :ref:`CONFIG_ETH_RMII_CLK_OUT_GPIO` for more information. + + If the RMII clock mode is selected to ``CONFIG_ETH_RMII_CLK_INPUT``, then ``GPIO0`` is the only choice to input the ``REF_CLK`` signal. + Please note that, ``GPIO0`` is also an important strapping GPIO on ESP32. + If GPIO0 samples a low level during power up, ESP32 will go into download mode. The system will get halted until a manually reset. + The workaround of this issue is disabling the ``REF_CLK`` in hardware by default, so that the strapping pin won't be interfered by other signals in boot stage. Then re-enable the ``REF_CLK`` in Ethernet driver installation stage. + The ways to disable the ``REF_CLK`` signal can be: + + * Disable or power down the crystal oscillator (as the case *b* in the picture). + * Force the PHY device in reset status (as the case *a* in the picture). **This could fail for some PHY device** (i.e. it still outputs signal to GPIO0 even in reset state). + + **No matter which RMII clock mode you select, you really need to take care of the signal integrity of REF_CLK in your hardware design!** + Keep the trace as short as possible. Keep it away from RF devices. Keep it away from inductor elements. + + .. note:: + ESP-IDF only supports the RMII interface (i.e. always select ``CONFIG_ETH_PHY_INTERFACE_RMII`` in Kconfig option :ref:`CONFIG_ETH_PHY_INTERFACE`). + + Signals used in data plane are fixed to specific GPIOs via MUX, they can't be modified to other GPIOs. + Signals used in control plane can be routed to any free GPIOs via Matrix. + Please refer to :doc:`ESP32-Ethernet-Kit <../../hw-reference/esp32/get-started-ethernet-kit>` for hardware design example. + +We need to setup necessary parameters for MAC and PHY respectively based on your Ethernet board design and then combine the two together, completing the driver installation. + +Configuration for MAC is described in :cpp:class:`eth_mac_config_t`, including: + +* :cpp:member:`sw_reset_timeout_ms`: software reset timeout value, in milliseconds, typically MAC reset should be finished within 100ms. +* :cpp:member:`rx_task_stack_size` and :cpp:member:`rx_task_prio`: the MAC driver creates a dedicated task to process incoming packets, these two parameters are used to set the stack size and priority of the task. +* :cpp:member:`smi_mdc_gpio_num` and :cpp:member:`smi_mdio_gpio_num`: the GPIO number used to connect the SMI signals. +* :cpp:member:`flags`: specifying extra features that the MAC driver should have, it could be useful in some special situations. The value of this field can be OR'd with macros prefixed with ``ETH_MAC_FLAG_``. For example, if the MAC driver should work when cache is disabled, then you should configure this field with :c:macro:`ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE`. + +Configuration for PHY is described in :cpp:class:`eth_phy_config_t`, including: + +* :cpp:member:`phy_addr`: multiple PHY device can share the same SMI bus, so each PHY needs a unique address. Usually this address is configured during hardware design by pulling up/down some PHY strapping pins. You can set the value from 0 to 15 based on your Ethernet board. Especially, if the SMI bus is shared by only one PHY device, setting this value to -1 can enable the driver to detect the PHY address automatically. +* :cpp:member:`reset_timeout_ms`: reset timeout value, in milliseconds, typically PHY reset should be finished within 100ms. +* :cpp:member:`autonego_timeout_ms`: auto-negotiation timeout value, in milliseconds. Ethernet driver will start negotiation with the peer Ethernet node automatically, to determine to duplex and speed mode. This value usually depends on the ability of the PHY device on your board. +* :cpp:member:`reset_gpio_num`: if your board also connect the PHY reset pin to one of the GPIO, then set it here. Otherwise, set this field to -1. + +ESP-IDF provides a default configuration for MAC and PHY in macro :c:macro:`ETH_MAC_DEFAULT_CONFIG` and :c:macro:`ETH_PHY_DEFAULT_CONFIG`. + + +Create MAC and PHY Instance +--------------------------- + +Ethernet driver is implemented in an Object-Oriented style. Any operation on MAC and PHY should be based on the instance of them two. + +.. highlight:: c + +:: + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration + mac_config.smi_mdc_gpio_num = 23; // alter the GPIO used for MDC signal + mac_config.smi_mdio_gpio_num = 18; // alter the GPIO used for MDIO signal + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); // create MAC instance + + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration + phy_config.phy_addr = 1; // alter the PHY address according to your board design + phy_config.reset_gpio_num = 5; // alter the GPIO used for PHY reset + esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance + // ESP-IDF officially supports several different Ethernet PHY + // esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config); + // esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); + // esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config); + +.. note:: + Care should be taken, when creating MAC and PHY instance for SPI-Ethernet modules (e.g. DM9051), the constructor function must have the same suffix (e.g. `esp_eth_mac_new_dm9051` and `esp_eth_phy_new_dm9051`). This is because we don't have other choices but the integrated PHY. + Besides that, we have to create an SPI device handle firstly and then pass it to the MAC constructor function. More instructions on creating SPI device handle, please refer to :doc:`SPI Master <../peripherals/spi_master>`. + +Install Driver +-------------- + +Ethernet driver also includes event-driven model, which will send useful and important event to user space. We need to initialize the event loop before installing the Ethernet driver. For more information about event-driven programming, please refer to :doc:`ESP Event <../system/esp_event>`. + +.. highlight:: c + +:: + + /** Event handler for Ethernet events */ + 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}; + /* we can get the ethernet driver handle from event data */ + 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(); // create a default event loop that running in background + esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL); // register Ethernet event handler (to deal with user specific stuffs when event like link up/down happened) + +To install the Ethernet driver, we need to combine the instance of MAC and PHY and set some additional high-level configurations (i.e. not specific to either MAC or PHY) in :cpp:class:`esp_eth_config_t`: + +* :cpp:member:`mac`: instance that created from MAC generator (e.g. :cpp:func:`esp_eth_mac_new_esp32`). +* :cpp:member:`phy`: instance that created from PHY generator (e.g. :cpp:func:`esp_eth_phy_new_ip101`). +* :cpp:member:`check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds. +* :cpp:member:`stack_input`: In most of Ethernet IoT applications, any Ethernet frame that received by driver should be passed to upper layer (e.g. TCP/IP stack). This field is set to a function which is responsible to deal with the incoming frames. You can even update this field at runtime via function :cpp:func:`esp_eth_update_input_path` after driver installation. +* :cpp:member:`on_lowlevel_init_done` and :cpp:member:`on_lowlevel_deinit_done`: These two fields are used to specify the hooks which get invoked when low level hardware has been initialized or de-initialized. + +ESP-IDF provides a default configuration for driver installation in macro :c:macro:`ETH_DEFAULT_CONFIG`. + +.. highlight:: c + +:: + + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration + esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver + esp_eth_driver_install(&config, ð_handle); // install driver + +Start Ethernet Driver +--------------------- + +After driver installation, we can start Ethernet immediately. + +.. highlight:: c + +:: + + esp_eth_start(eth_handle); // start Ethernet driver state machine + +.. _connect-driver-to-stack: + +Connect Driver to TCP/IP Stack +------------------------------ + +Up until now, we have installed the Ethernet driver. From the view of OSI (Open System Interconnection), we're still on level 2 (i.e. Data Link Layer). We can detect link up and down event, we can gain MAC address in user space, but we can't obtain IP address, let alone send HTTP request. +The TCP/IP stack used in ESP-IDF is called LwIP, for more information about it, please refer to :doc:`LwIP <../../api-guides/lwip>`. + +To connect Ethernet driver to TCP/IP stack, these three steps need to follow: + +1. Create network interface for Ethernet driver +2. Register IP event handlers +3. Attach the network interface to Ethernet driver + +More information about network interface, please refer to :doc:`Network Interface `. + +.. highlight:: c + +:: + + /** Event handler for 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()); // Initialize TCP/IP network interface (should be called only once in application) + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); // apply default network interface configuration for Ethernet + esp_netif_t *eth_netif = esp_netif_new(&cfg); // create network interface for Ethernet driver + esp_eth_set_default_handlers(eth_netif); // set default handlers to process TCP/IP stuffs + esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // register user defined IP event handlers + + esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)); // attach Ethernet driver to TCP/IP stack + esp_eth_start(eth_handle); // start Ethernet driver state machine + +.. _misc-operation-of-driver: + +Misc control of Ethernet driver +------------------------------- + +The following functions should only be invoked after the Ethernet driver has been installed. + +* Stop Ethernet driver: :cpp:func:`esp_eth_stop` +* Update Ethernet data input path: :cpp:func:`esp_eth_update_input_path` +* Misc get/set of Ethernet driver attributes: :cpp:func:`esp_eth_ioctl` + +.. highlight:: c + +:: + + /* get MAC address */ + 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]); + + /* get PHY address */ + 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); + +.. -------------------------------- Examples ----------------------------------- + Application Example ------------------- -- Ethernet basic example: :example:`ethernet/basic`. -- Ethernet iperf example: :example:`ethernet/iperf`. -- Ethernet to Wi-Fi AP "router": :example:`ethernet/eth2ap`. + * Ethernet basic example: :example:`ethernet/basic`. + * Ethernet iperf example: :example:`ethernet/iperf`. + * Ethernet to Wi-Fi AP "router": :example:`ethernet/eth2ap`. + * Most of protocol examples should also work for Ethernet: :example:`protocols`. -Ethernet Driver Model ---------------------- +.. ---------------------------- API Reference ---------------------------------- - * :component_file:`esp_eth/include/esp_eth.h` - -Ethernet Common Interface -------------------------- - - * :component_file:`esp_eth/include/esp_eth_com.h` - -Ethernet MAC Interface ----------------------- - - * :component_file:`esp_eth/include/esp_eth_mac.h` - -Ethernet PHY Interface ----------------------- - - * :component_file:`esp_eth/include/esp_eth_phy.h` - -Ethernet PHY Common Registers ------------------------------ - - * :component_file:`esp_eth/include/eth_phy_regs_struct.h` - -API Reference - Driver Model ----------------------------- +API Reference +------------- .. include-build-file:: inc/esp_eth.inc - -API Reference - Common Interface --------------------------------- - .. include-build-file:: inc/esp_eth_com.inc - -API Reference - MAC Interface ------------------------------ - .. include-build-file:: inc/esp_eth_mac.inc - -API Reference - PHY Interface ------------------------------ - .. include-build-file:: inc/esp_eth_phy.inc - -API Reference - Glue for esp_netif ----------------------------------- - .. include-build-file:: inc/esp_eth_netif_glue.inc diff --git a/docs/en/api-reference/system/system.rst b/docs/en/api-reference/system/system.rst index a34213ab56..eaee4bb992 100644 --- a/docs/en/api-reference/system/system.rst +++ b/docs/en/api-reference/system/system.rst @@ -30,6 +30,7 @@ Random number generation When Wi-Fi or Bluetooth are enabled, numbers returned by hardware random number generator (RNG) can be considered true random numbers. Without Wi-Fi or Bluetooth enabled, hardware RNG is a pseudo-random number generator. At startup, ESP-IDF bootloader seeds the hardware RNG with entropy, but care must be taken when reading random values between the start of ``app_main`` and initialization of Wi-Fi or Bluetooth drivers. +.. _MAC-Address-Allocation: MAC Address -----------