This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 5c4c60f9d265fe48b47d2c86a9acdb20da441163
Author: Tiago Medicci Serrano <[email protected]>
AuthorDate: Fri Apr 24 14:16:19 2026 -0300

    arch/risc-v: Support the ethernet driver on ESP32-P4
    
    This commit enables the ethernet driver support on ESP32-P4 based
    on a common-source implementation. This required a set of changes
    regargind the event handler for the Wi-Fi driver (which is now
    shared with the ethernet driver).
    
    Signed-off-by: Tiago Medicci Serrano <[email protected]>
---
 arch/risc-v/src/common/espressif/CMakeLists.txt    |   6 +-
 arch/risc-v/src/common/espressif/Kconfig           | 162 +++++
 arch/risc-v/src/common/espressif/Make.defs         |   6 +-
 arch/risc-v/src/common/espressif/esp_emac.c        | 791 +++++++++++++++++++++
 arch/risc-v/src/common/espressif/esp_emac.h        |  62 ++
 arch/risc-v/src/common/espressif/esp_wifi_api.c    |   1 +
 .../src/common/espressif/esp_wifi_event_handler.c  | 309 ++++----
 arch/risc-v/src/common/espressif/esp_wifi_utils.h  |  51 +-
 arch/risc-v/src/esp32c3/hal_esp32c3.cmake          |   4 +
 arch/risc-v/src/esp32c3/hal_esp32c3.mk             |   4 +
 arch/risc-v/src/esp32c6/hal_esp32c6.cmake          |   4 +
 arch/risc-v/src/esp32c6/hal_esp32c6.mk             |   4 +
 arch/risc-v/src/esp32h2/hal_esp32h2.cmake          |   5 +
 arch/risc-v/src/esp32h2/hal_esp32h2.mk             |   5 +
 arch/risc-v/src/esp32p4/hal_esp32p4.cmake          |  26 +
 arch/risc-v/src/esp32p4/hal_esp32p4.mk             |  20 +
 16 files changed, 1245 insertions(+), 215 deletions(-)

diff --git a/arch/risc-v/src/common/espressif/CMakeLists.txt 
b/arch/risc-v/src/common/espressif/CMakeLists.txt
index ccb926cedb8..47b1bbeffbc 100644
--- a/arch/risc-v/src/common/espressif/CMakeLists.txt
+++ b/arch/risc-v/src/common/espressif/CMakeLists.txt
@@ -164,6 +164,10 @@ if(CONFIG_ESP_MCPWM)
   list(APPEND SRCS esp_mcpwm.c)
 endif()
 
+if(CONFIG_ESPRESSIF_EMAC)
+  list(APPEND SRCS esp_emac.c)
+endif()
+
 if(CONFIG_SYSTEM_NXDIAG_ESPRESSIF_CHIP_WO_TOOL)
   list(APPEND SRCS esp_nxdiag.c)
 endif()
@@ -209,7 +213,7 @@ if(DEFINED ENV{ESP_HAL_3RDPARTY_VERSION})
       CACHE STRING "ESP HAL 3rdparty version")
 else()
   set(ESP_HAL_3RDPARTY_VERSION
-      8630b6b82cb84838f86332e00f39ab72a64cf186
+      c32f1ad13f4ce8312de494e8b79c88fda10fe9ed
       CACHE STRING "ESP HAL 3rdparty version")
 endif()
 
diff --git a/arch/risc-v/src/common/espressif/Kconfig 
b/arch/risc-v/src/common/espressif/Kconfig
index 7e73d90e6d1..3c16ea9c4a2 100644
--- a/arch/risc-v/src/common/espressif/Kconfig
+++ b/arch/risc-v/src/common/espressif/Kconfig
@@ -1995,6 +1995,17 @@ config ESPRESSIF_BLE
        ---help---
                Enable BLE support
 
+config ESPRESSIF_EMAC
+       bool "Ethernet MAC"
+       depends on ARCH_CHIP_ESP32P4
+       default n
+       select NET
+       select ARCH_PHY_INTERRUPT
+       select ESPRESSIF_HR_TIMER
+       select SCHED_LPWORK
+       ---help---
+               Enable Ethernet MAC support.
+
 config ESP_COEX_SW_COEXIST_ENABLE
        bool "Software WiFi/Bluetooth/IEEE 802.15.4 coexistence"
        depends on (ESPRESSIF_WIFI && ESPRESSIF_BLE) || \
@@ -2462,6 +2473,157 @@ endif  # ESPRESSIF_ADC_2
 
 endmenu # ADC Configuration
 
+menu "Ethernet Configuration"
+       depends on ESPRESSIF_EMAC
+
+config ESPRESSIF_ETH_NRXDESC
+       int "RX descriptor number"
+       default 20
+       ---help---
+               Number of DMA receive descriptors/buffers used by the EMAC.
+               Each buffer is CONFIG_ESPRESSIF_ETH_DMA_BUFFER_SIZE bytes.
+               The default of 20 provides headroom for TCP-style ACK bursts
+               that arrive while the upper layer is busy submitting a TX burst
+               (otherwise the EMAC asserts RX_BUFF_UNAVAILABLE and silently
+               drops incoming frames, forcing TCP retransmissions).
+
+config ESPRESSIF_ETH_NTXDESC
+       int "TX descriptor number"
+       default 20
+       ---help---
+               Number of DMA transmit descriptors/buffers used by the EMAC.
+               With CONFIG_ESPRESSIF_ETH_DMA_BUFFER_SIZE=1600, each descriptor
+               holds one Ethernet frame.  TCP send() bursts up to ~12 segments
+               back-to-back; 20 descriptors gives ample headroom so that
+               esp_eth_transmit() never returns ESP_ERR_NO_MEM mid-burst.
+               If the ring is exhausted, frames are silently dropped and
+               retransmissions happen via fast-retransmit/RTO, drastically
+               degrading throughput.
+
+config ESPRESSIF_ETH_DMA_BUFFER_SIZE
+       int "DMA buffer size (bytes)"
+       default 1600
+       range 256 1600
+       ---help---
+               Size of each DMA buffer used by the EMAC (must match esp_eth's
+               CONFIG_ETH_DMA_BUFFER_SIZE).  At the maximum 1600 bytes one
+               buffer holds an entire 1518-byte Ethernet frame, so a typical
+               TX uses exactly one descriptor.  Lower values cause the MAC DMA
+               to chain multiple descriptors per frame, reducing the effective
+               number of frames the ring can hold.
+
+config ESPRESSIF_ETH_TX_MAX_RETRIES
+       int "TX submit retry budget"
+       default 32
+       range 1 256
+       ---help---
+               Number of times emac_transmit() retries esp_eth_transmit() when
+               the DMA TX descriptor ring is fully owned by hardware
+               (ESP_ERR_NO_MEM).  Between attempts the driver yields the CPU
+               via sched_yield() so that the RX worker (and any other peer at
+               the same priority) can run while the EMAC DMA drains its TX
+               descriptors in the background.  The default of 32 covers a
+               full ring rotation under sustained TCP bursts while remaining
+               bounded; increase if the network has very high latency between
+               TX submissions and DMA descriptor recycling.
+
+config ESPRESSIF_ETH_PHY_ADDR
+       int "PHY address"
+       default 1
+       range 0 31
+       ---help---
+               Address of the external Ethernet PHY on the SMI (MDC/MDIO) bus.
+
+config ESPRESSIF_ETH_MDC_GPIO
+       int "MDC GPIO"
+       default 31 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number connected to the PHY MDC pin.  The shipped default
+               corresponds to the ESP32-P4 Function EV Board V1.5.2; override
+               for other boards/SoCs.
+
+config ESPRESSIF_ETH_MDIO_GPIO
+       int "MDIO GPIO"
+       default 52 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number connected to the PHY MDIO pin.  The shipped default
+               corresponds to the ESP32-P4 Function EV Board V1.5.2; override
+               for other boards/SoCs.
+
+config ESPRESSIF_ETH_RMII_CLK_GPIO
+       int "RMII REF_CLK GPIO"
+       default 50 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number for the RMII 50MHz reference clock (input).  The
+               shipped default corresponds to the ESP32-P4 Function EV Board
+               V1.5.2; override for other boards/SoCs.
+
+config ESPRESSIF_ETH_RMII_TX_EN_GPIO
+       int "RMII TX_EN GPIO"
+       default 49 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number connected to the RMII TX_EN pin.  Default is for the
+               ESP32-P4 Function EV Board V1.5.2.
+
+config ESPRESSIF_ETH_RMII_TXD0_GPIO
+       int "RMII TXD0 GPIO"
+       default 34 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number connected to the RMII TXD0 pin.  Default is for the
+               ESP32-P4 Function EV Board V1.5.2.
+
+config ESPRESSIF_ETH_RMII_TXD1_GPIO
+       int "RMII TXD1 GPIO"
+       default 35 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number connected to the RMII TXD1 pin.  Default is for the
+               ESP32-P4 Function EV Board V1.5.2.
+
+config ESPRESSIF_ETH_RMII_CRS_DV_GPIO
+       int "RMII CRS_DV GPIO"
+       default 28 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number connected to the RMII CRS_DV pin.  Default is for
+               the ESP32-P4 Function EV Board V1.5.2.
+
+config ESPRESSIF_ETH_RMII_RXD0_GPIO
+       int "RMII RXD0 GPIO"
+       default 29 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number connected to the RMII RXD0 pin.  Default is for the
+               ESP32-P4 Function EV Board V1.5.2.
+
+config ESPRESSIF_ETH_RMII_RXD1_GPIO
+       int "RMII RXD1 GPIO"
+       default 30 if ARCH_CHIP_ESP32P4
+       default -1
+       ---help---
+               GPIO number connected to the RMII RXD1 pin.  Default is for the
+               ESP32-P4 Function EV Board V1.5.2.
+
+config ESPRESSIF_ETH_ENABLE_PHY_RSTPIN
+       bool "Enable PHY reset pin"
+       default y
+
+config ESPRESSIF_ETH_PHY_RST_GPIO
+       int "PHY reset GPIO"
+       default 51 if ARCH_CHIP_ESP32P4
+       default -1
+       depends on ESPRESSIF_ETH_ENABLE_PHY_RSTPIN
+       ---help---
+               GPIO number connected to the PHY reset pin.  Default is for the
+               ESP32-P4 Function EV Board V1.5.2.
+
+endmenu # Ethernet Configuration
+
 menu "Wi-Fi Configuration"
        depends on ESPRESSIF_WIFI
 
diff --git a/arch/risc-v/src/common/espressif/Make.defs 
b/arch/risc-v/src/common/espressif/Make.defs
index 8e27bde0839..43b7090d208 100644
--- a/arch/risc-v/src/common/espressif/Make.defs
+++ b/arch/risc-v/src/common/espressif/Make.defs
@@ -169,6 +169,10 @@ ifeq ($(CONFIG_ESP_MCPWM),y)
        CHIP_CSRCS += esp_mcpwm.c
 endif
 
+ifeq ($(CONFIG_ESPRESSIF_EMAC),y)
+       CHIP_CSRCS += esp_emac.c
+endif
+
 ifeq ($(CONFIG_SYSTEM_NXDIAG_ESPRESSIF_CHIP_WO_TOOL),y)
        CHIP_CSRCS += esp_nxdiag.c
 endif
@@ -217,7 +221,7 @@ endif
 
 ESP_HAL_3RDPARTY_REPO   = esp-hal-3rdparty
 ifndef ESP_HAL_3RDPARTY_VERSION
-       ESP_HAL_3RDPARTY_VERSION = 8630b6b82cb84838f86332e00f39ab72a64cf186
+       ESP_HAL_3RDPARTY_VERSION = c32f1ad13f4ce8312de494e8b79c88fda10fe9ed
 endif
 
 ifndef ESP_HAL_3RDPARTY_URL
diff --git a/arch/risc-v/src/common/espressif/esp_emac.c 
b/arch/risc-v/src/common/espressif/esp_emac.c
new file mode 100644
index 00000000000..c97bad3812a
--- /dev/null
+++ b/arch/risc-v/src/common/espressif/esp_emac.c
@@ -0,0 +1,791 @@
+/****************************************************************************
+ * arch/risc-v/src/common/espressif/esp_emac.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_ESPRESSIF_EMAC
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <sched.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/queue.h>
+#include <nuttx/spinlock.h>
+#include <nuttx/net/ioctl.h>
+#include <nuttx/net/mii.h>
+#include <nuttx/net/netdev_lowerhalf.h>
+
+#include "esp_eth.h"
+#include "esp_eth_driver.h"
+#include "esp_eth_mac.h"
+#include "esp_eth_mac_esp.h"
+#include "esp_eth_phy.h"
+#include "esp_event.h"
+#include "esp_mac.h"
+
+#include "esp_emac.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ETH_HEADER_LEN          (14)
+#define ETH_VLANTAG_LEN         (4)
+#define ETH_MAXPAYLOAD_LEN      (1500)
+#define ETH_CRC_LEN             (4)
+
+#define ETH_MAXPKT_LEN          (ETH_HEADER_LEN + ETH_VLANTAG_LEN + \
+                                 ETH_MAXPAYLOAD_LEN + ETH_CRC_LEN)
+
+#define EMAC_PHY_ADDR           (CONFIG_ESPRESSIF_ETH_PHY_ADDR)
+#define NET2PRIV(_dev)          ((struct esp_emac_s *)(_dev))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct esp_emac_s
+{
+  struct netdev_lowerhalf_s dev;
+
+  esp_eth_handle_t    handle;
+
+  bool                installed;
+  bool                ifup;
+  bool                link_up;
+
+  spinlock_t          lock;
+  netpkt_queue_t      rxq;
+  uint8_t             txbuf[ETH_MAXPKT_LEN];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct esp_emac_s g_esp_emac;
+static mutex_t g_lock = NXMUTEX_INITIALIZER;
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int  emac_transmit(struct netdev_lowerhalf_s *dev, netpkt_t *pkt);
+static netpkt_t *emac_receive(struct netdev_lowerhalf_s *dev);
+static esp_err_t emac_stack_input(esp_eth_handle_t hdl,
+                                  uint8_t *buffer, uint32_t length,
+                                  void *priv_arg);
+static void emac_eth_event_handler(void *arg, esp_event_base_t base,
+                                   int32_t id, void *data);
+static int  emac_ifup(struct netdev_lowerhalf_s *dev);
+static int  emac_ifdown(struct netdev_lowerhalf_s *dev);
+#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6)
+static int  emac_addmac(struct netdev_lowerhalf_s *dev, const uint8_t *mac);
+#endif
+#ifdef CONFIG_NET_MCASTGROUP
+static int  emac_rmmac(struct netdev_lowerhalf_s *dev, const uint8_t *mac);
+#endif
+#ifdef CONFIG_NETDEV_IOCTL
+static int  emac_ioctl(struct netdev_lowerhalf_s *dev, int cmd,
+                       unsigned long arg);
+#endif
+
+static const struct netdev_ops_s g_emac_ops =
+{
+  .ifup     = emac_ifup,
+  .ifdown   = emac_ifdown,
+  .transmit = emac_transmit,
+  .receive  = emac_receive,
+#ifdef CONFIG_NET_MCASTGROUP
+  .addmac   = emac_addmac,
+  .rmmac    = emac_rmmac,
+#endif
+#ifdef CONFIG_NETDEV_IOCTL
+  .ioctl    = emac_ioctl,
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: emac_transmit
+ *
+ * Description:
+ *   Push one outbound packet from the netdev lower-half TX path to esp_eth.
+ *
+ *   Backpressure handling:
+ *
+ *   When a TCP burst is in flight the EMAC DMA TX descriptor ring may be
+ *   fully owned by the DMA engine.  In that case esp_eth_transmit() returns
+ *   ESP_ERR_NO_MEM and we must wait until the hardware releases at least
+ *   one descriptor before submitting the frame, otherwise the upper layer
+ *   would treat the frame as lost and only recover via TCP retransmission,
+ *   which collapses throughput.
+ *
+ *   The wait is implemented with sched_yield() rather than a fixed-time
+ *   delay: it relinquishes the CPU to any runnable peer (most importantly
+ *   the RX worker that consumes inbound TCP ACKs) without imposing an
+ *   arbitrary sleep, while the EMAC DMA hardware drains its TX descriptors
+ *   in parallel with no CPU involvement.
+ *
+ * Input Parameters:
+ *   dev - Lower-half network device state.
+ *   pkt - Packet to transmit.
+ *
+ * Returned Value:
+ *   OK on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int emac_transmit(struct netdev_lowerhalf_s *dev, netpkt_t *pkt)
+{
+  struct esp_emac_s *priv = NET2PRIV(dev);
+  unsigned int len;
+  esp_err_t err;
+  unsigned int retries = 0;
+  int ret;
+
+  len = netpkt_getdatalen(dev, pkt);
+
+  if (!priv->installed || !priv->ifup)
+    {
+      return -ENETDOWN;
+    }
+
+  if (len == 0 || len > ETH_MAXPKT_LEN)
+    {
+      return -EMSGSIZE;
+    }
+
+  ret = netpkt_copyout(dev, priv->txbuf, pkt, len, 0);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  do
+    {
+      err = esp_eth_transmit(priv->handle, priv->txbuf, len);
+      if (err != ESP_ERR_NO_MEM)
+        {
+          break;
+        }
+
+      sched_yield();
+    }
+  while (++retries < CONFIG_ESPRESSIF_ETH_TX_MAX_RETRIES);
+
+  if (err != ESP_OK)
+    {
+      nerr("ERROR: esp_eth_transmit failed: %d\n", (int)err);
+      return -EIO;
+    }
+
+  netpkt_free(dev, pkt, NETPKT_TX);
+  netdev_lower_txdone(dev);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: emac_receive
+ *
+ * Description:
+ *   Pop one received packet from the RX queue and hand it to upper-half.
+ *
+ * Input Parameters:
+ *   dev - Lower-half network device state.
+ *
+ * Returned Value:
+ *   Received packet pointer on success; NULL when no packet is queued.
+ *
+ ****************************************************************************/
+
+static netpkt_t *emac_receive(struct netdev_lowerhalf_s *dev)
+{
+  struct esp_emac_s *priv = NET2PRIV(dev);
+  irqstate_t flags;
+  netpkt_t *pkt;
+
+  flags = spin_lock_irqsave(&priv->lock);
+  pkt = netpkt_remove_queue(&priv->rxq);
+  spin_unlock_irqrestore(&priv->lock, flags);
+  return pkt;
+}
+
+/****************************************************************************
+ * Name: emac_stack_input
+ *
+ * Description:
+ *   esp_eth input-path callback. Convert the received frame to netpkt and
+ *   queue it to be consumed by netdev upper-half.
+ *
+ * Input Parameters:
+ *   hdl      - esp_eth driver handle.
+ *   buffer   - Frame buffer allocated by esp_eth (ownership transferred).
+ *   length   - Frame length in bytes.
+ *   priv_arg - Opaque pointer to struct esp_emac_s.
+ *
+ * Returned Value:
+ *   ESP_OK on success; ESP_ERR_NO_MEM on allocation or queue failures.
+ *
+ ****************************************************************************/
+
+static esp_err_t emac_stack_input(esp_eth_handle_t hdl,
+                                  uint8_t *buffer, uint32_t length,
+                                  void *priv_arg)
+{
+  struct esp_emac_s *priv = (struct esp_emac_s *)priv_arg;
+  netpkt_t *pkt;
+  irqstate_t flags;
+  int ret;
+
+  UNUSED(hdl);
+
+  pkt = netpkt_alloc(&priv->dev, NETPKT_RX);
+  if (pkt == NULL)
+    {
+      nerr("ERROR: emac RX netpkt_alloc failed\n");
+      free(buffer);
+      return ESP_ERR_NO_MEM;
+    }
+
+  ret = netpkt_copyin(&priv->dev, pkt, buffer, length, 0);
+  free(buffer);
+  if (ret < 0)
+    {
+      netpkt_free(&priv->dev, pkt, NETPKT_RX);
+      return ESP_ERR_NO_MEM;
+    }
+
+  flags = spin_lock_irqsave(&priv->lock);
+  ret = netpkt_tryadd_queue(pkt, &priv->rxq);
+  spin_unlock_irqrestore(&priv->lock, flags);
+
+  if (ret < 0)
+    {
+      nerr("ERROR: emac RX queue full\n");
+      netpkt_free(&priv->dev, pkt, NETPKT_RX);
+      return ESP_ERR_NO_MEM;
+    }
+
+  netdev_lower_rxready(&priv->dev);
+  return ESP_OK;
+}
+
+/****************************************************************************
+ * Name: emac_eth_event_handler
+ *
+ * Description:
+ *   Receive ETH_EVENT notifications posted by esp_eth (link up/down,
+ *   start/stop) and update NuttX carrier state accordingly.
+ *
+ * Input Parameters:
+ *   arg  - Opaque pointer to struct esp_emac_s.
+ *   base - Event base (unused; expected ETH_EVENT).
+ *   id   - Event identifier (ETHERNET_EVENT_*).
+ *   data - Event payload.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void emac_eth_event_handler(void *arg, esp_event_base_t base,
+                                   int32_t id, void *data)
+{
+  struct esp_emac_s *priv = (struct esp_emac_s *)arg;
+
+  UNUSED(base);
+  UNUSED(data);
+
+  switch (id)
+    {
+      case ETHERNET_EVENT_CONNECTED:
+        ninfo("Ethernet link up\n");
+        priv->link_up = true;
+        netdev_lower_carrier_on(&priv->dev);
+        break;
+
+      case ETHERNET_EVENT_DISCONNECTED:
+        ninfo("Ethernet link down\n");
+        priv->link_up = false;
+        netdev_lower_carrier_off(&priv->dev);
+        break;
+
+      case ETHERNET_EVENT_START:
+        ninfo("Ethernet started\n");
+        break;
+
+      case ETHERNET_EVENT_STOP:
+        ninfo("Ethernet stopped\n");
+        break;
+
+      default:
+        break;
+    }
+}
+
+/****************************************************************************
+ * Name: emac_ifup
+ *
+ * Description:
+ *   Bring the network interface up and start the esp_eth state machine.
+ *
+ * Input Parameters:
+ *   dev - NuttX network interface state.
+ *
+ * Returned Value:
+ *   OK on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int emac_ifup(struct netdev_lowerhalf_s *dev)
+{
+  struct esp_emac_s *priv = NET2PRIV(dev);
+  esp_err_t err;
+
+#ifdef CONFIG_NET_IPv4
+  ninfo("Bringing up: %d.%d.%d.%d\n",
+        (int)(dev->netdev.d_ipaddr & 0xff),
+        (int)((dev->netdev.d_ipaddr >> 8) & 0xff),
+        (int)((dev->netdev.d_ipaddr >> 16) & 0xff),
+        (int)((dev->netdev.d_ipaddr >> 24) & 0xff));
+#endif
+
+  if (!priv->installed)
+    {
+      nerr("ERROR: esp_eth driver not installed\n");
+      return -ENODEV;
+    }
+
+  if (priv->ifup)
+    {
+      return OK;
+    }
+
+  err = esp_eth_start(priv->handle);
+  if (err != ESP_OK)
+    {
+      nerr("ERROR: esp_eth_start failed: %d\n", (int)err);
+      return -EIO;
+    }
+
+  priv->ifup = true;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: emac_ifdown
+ *
+ * Description:
+ *   Bring the network interface down and stop the esp_eth state machine.
+ *
+ * Input Parameters:
+ *   dev - NuttX network interface state.
+ *
+ * Returned Value:
+ *   OK.
+ *
+ ****************************************************************************/
+
+static int emac_ifdown(struct netdev_lowerhalf_s *dev)
+{
+  struct esp_emac_s *priv = NET2PRIV(dev);
+  esp_err_t err;
+
+  ninfo("Taking the network down\n");
+
+  if (!priv->ifup)
+    {
+      return OK;
+    }
+
+  err = esp_eth_stop(priv->handle);
+  if (err != ESP_OK)
+    {
+      nerr("ERROR: esp_eth_stop failed: %d\n", (int)err);
+    }
+
+  priv->ifup = false;
+  priv->link_up = false;
+  netdev_lower_carrier_off(dev);
+
+  return OK;
+}
+
+#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6)
+/****************************************************************************
+ * Name: emac_addmac
+ *
+ * Description:
+ *   Add a multicast MAC address filter entry to the underlying ESP Ethernet
+ *   driver.
+ *
+ * Input Parameters:
+ *   dev - NuttX network interface state.
+ *   mac - MAC address to add to the multicast filter list.
+ *
+ * Returned Value:
+ *   OK.
+ *
+ ****************************************************************************/
+
+static int emac_addmac(struct netdev_lowerhalf_s *dev, const uint8_t *mac)
+{
+  struct esp_emac_s *priv = NET2PRIV(dev);
+
+  ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+  esp_eth_ioctl(priv->handle, ETH_CMD_ADD_MAC_FILTER, (void *)mac);
+  return OK;
+}
+#endif
+
+#ifdef CONFIG_NET_MCASTGROUP
+/****************************************************************************
+ * Name: emac_rmmac
+ *
+ * Description:
+ *   Remove a multicast MAC address filter entry from the underlying ESP
+ *   Ethernet driver.
+ *
+ * Input Parameters:
+ *   dev - NuttX network interface state.
+ *   mac - MAC address to remove from the multicast filter list.
+ *
+ * Returned Value:
+ *   OK.
+ *
+ ****************************************************************************/
+
+static int emac_rmmac(struct netdev_lowerhalf_s *dev, const uint8_t *mac)
+{
+  struct esp_emac_s *priv = NET2PRIV(dev);
+
+  ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+  esp_eth_ioctl(priv->handle, ETH_CMD_DEL_MAC_FILTER, (void *)mac);
+  return OK;
+}
+#endif
+
+#ifdef CONFIG_NETDEV_IOCTL
+/****************************************************************************
+ * Name: emac_ioctl
+ *
+ * Description:
+ *   Handle network device ioctl requests supported by the ESP EMAC driver.
+ *
+ * Input Parameters:
+ *   dev - NuttX network interface state.
+ *   cmd - Ioctl command code.
+ *   arg - Command-specific argument.
+ *
+ * Returned Value:
+ *   OK on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int emac_ioctl(struct netdev_lowerhalf_s *dev, int cmd,
+                      unsigned long arg)
+{
+  struct esp_emac_s *priv = NET2PRIV(dev);
+  int ret;
+
+  ret = nxmutex_lock(&g_lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  switch (cmd)
+    {
+#ifdef CONFIG_NETDEV_PHY_IOCTL
+      case SIOCGMIIPHY:
+        {
+          struct mii_ioctl_data_s *req =
+              (struct mii_ioctl_data_s *)((uintptr_t)arg);
+          uint32_t phy_addr = 0;
+
+          if (esp_eth_ioctl(priv->handle, ETH_CMD_G_PHY_ADDR, &phy_addr)
+              == ESP_OK)
+            {
+              req->phy_id = (uint16_t)phy_addr;
+              ret = OK;
+            }
+          else
+            {
+              ret = -EIO;
+            }
+        }
+        break;
+
+      case SIOCGMIIREG:
+        {
+          struct mii_ioctl_data_s *req =
+              (struct mii_ioctl_data_s *)((uintptr_t)arg);
+          esp_eth_phy_reg_rw_data_t rw;
+          uint32_t val = 0;
+
+          rw.reg_addr = req->reg_num;
+          rw.reg_value_p = &val;
+          if (esp_eth_ioctl(priv->handle, ETH_CMD_READ_PHY_REG, &rw)
+              == ESP_OK)
+            {
+              req->val_out = (uint16_t)val;
+              ret = OK;
+            }
+          else
+            {
+              ret = -EIO;
+            }
+        }
+        break;
+
+      case SIOCSMIIREG:
+        {
+          struct mii_ioctl_data_s *req =
+              (struct mii_ioctl_data_s *)((uintptr_t)arg);
+          esp_eth_phy_reg_rw_data_t rw;
+          uint32_t val = req->val_in;
+
+          rw.reg_addr = req->reg_num;
+          rw.reg_value_p = &val;
+          if (esp_eth_ioctl(priv->handle, ETH_CMD_WRITE_PHY_REG, &rw)
+              == ESP_OK)
+            {
+              ret = OK;
+            }
+          else
+            {
+              ret = -EIO;
+            }
+        }
+        break;
+#endif /* CONFIG_NETDEV_PHY_IOCTL */
+
+      default:
+        ret = -ENOTTY;
+        break;
+    }
+
+  nxmutex_unlock(&g_lock);
+  return ret;
+}
+#endif /* CONFIG_NETDEV_IOCTL */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_emac_init
+ *
+ * Description:
+ *   Create the esp_eth MAC+PHY+driver stack, register our RX callback and
+ *   ETH_EVENT handler, pull the factory-programmed MAC address from eFuse
+ *   and register the interface with the NuttX network stack.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   OK on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int esp_emac_init(void)
+{
+  struct esp_emac_s *priv = &g_esp_emac;
+  esp_eth_mac_t *mac = NULL;
+  esp_eth_phy_t *phy = NULL;
+  unsigned int quota;
+  uint8_t mac_addr[6];
+  esp_err_t err;
+  int ret;
+
+  eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
+  eth_esp32_emac_config_t esp32_cfg = ETH_ESP32_EMAC_DEFAULT_CONFIG();
+  eth_phy_config_t phy_cfg = ETH_PHY_DEFAULT_CONFIG();
+
+  memset(priv, 0, sizeof(*priv));
+  IOB_QINIT(&priv->rxq);
+  spin_lock_init(&priv->lock);
+
+  /* Override default RMII/SMI pin configuration from Kconfig. */
+
+  esp32_cfg.smi_gpio.mdc_num  = CONFIG_ESPRESSIF_ETH_MDC_GPIO;
+  esp32_cfg.smi_gpio.mdio_num = CONFIG_ESPRESSIF_ETH_MDIO_GPIO;
+
+#if defined(SOC_EMAC_USE_MULTI_IO_MUX) || defined(SOC_EMAC_MII_USE_GPIO_MATRIX)
+  esp32_cfg.emac_dataif_gpio.rmii.tx_en_num  =
+      CONFIG_ESPRESSIF_ETH_RMII_TX_EN_GPIO;
+  esp32_cfg.emac_dataif_gpio.rmii.txd0_num   =
+      CONFIG_ESPRESSIF_ETH_RMII_TXD0_GPIO;
+  esp32_cfg.emac_dataif_gpio.rmii.txd1_num   =
+      CONFIG_ESPRESSIF_ETH_RMII_TXD1_GPIO;
+  esp32_cfg.emac_dataif_gpio.rmii.crs_dv_num =
+      CONFIG_ESPRESSIF_ETH_RMII_CRS_DV_GPIO;
+  esp32_cfg.emac_dataif_gpio.rmii.rxd0_num   =
+      CONFIG_ESPRESSIF_ETH_RMII_RXD0_GPIO;
+  esp32_cfg.emac_dataif_gpio.rmii.rxd1_num   =
+      CONFIG_ESPRESSIF_ETH_RMII_RXD1_GPIO;
+#endif
+
+  esp32_cfg.clock_config.rmii.clock_gpio =
+      CONFIG_ESPRESSIF_ETH_RMII_CLK_GPIO;
+
+  phy_cfg.phy_addr = EMAC_PHY_ADDR;
+#ifdef CONFIG_ESPRESSIF_ETH_ENABLE_PHY_RSTPIN
+  phy_cfg.reset_gpio_num = CONFIG_ESPRESSIF_ETH_PHY_RST_GPIO;
+#else
+  phy_cfg.reset_gpio_num = -1;
+#endif
+
+  mac = esp_eth_mac_new_esp32(&esp32_cfg, &mac_config);
+  if (mac == NULL)
+    {
+      nerr("ERROR: esp_eth_mac_new_esp32 failed\n");
+      return -EIO;
+    }
+
+  phy = esp_eth_phy_new_generic(&phy_cfg);
+  if (phy == NULL)
+    {
+      nerr("ERROR: esp_eth_phy_new_generic failed\n");
+      mac->del(mac);
+      return -EIO;
+    }
+
+    {
+      esp_eth_config_t eth_cfg = ETH_DEFAULT_CONFIG(mac, phy);
+
+      err = esp_eth_driver_install(&eth_cfg, &priv->handle);
+      if (err != ESP_OK)
+        {
+          nerr("ERROR: esp_eth_driver_install failed: %d\n", (int)err);
+          phy->del(phy);
+          mac->del(mac);
+          return -EIO;
+        }
+    }
+
+  priv->installed = true;
+
+  err = esp_eth_update_input_path(priv->handle, emac_stack_input, priv);
+  if (err != ESP_OK)
+    {
+      nerr("ERROR: esp_eth_update_input_path failed: %d\n", (int)err);
+      ret = -EIO;
+      goto errout;
+    }
+
+  err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID,
+                                   emac_eth_event_handler, priv);
+  if (err != ESP_OK)
+    {
+      nerr("ERROR: esp_event_handler_register(ETH_EVENT) failed: %d\n",
+           (int)err);
+      ret = -EIO;
+      goto errout;
+    }
+
+  /* Apply the factory-programmed MAC address (eFuse) to the MAC. */
+
+  err = esp_read_mac(mac_addr, ESP_MAC_ETH);
+  if (err != ESP_OK)
+    {
+      nwarn("WARNING: esp_read_mac(ESP_MAC_ETH) failed: %d\n", (int)err);
+      mac_addr[0] = 0x02;
+      mac_addr[1] = 0x00;
+      mac_addr[2] = 0x00;
+      mac_addr[3] = 0x00;
+      mac_addr[4] = 0x00;
+      mac_addr[5] = 0x01;
+    }
+
+  esp_eth_ioctl(priv->handle, ETH_CMD_S_MAC_ADDR, mac_addr);
+  memcpy(priv->dev.netdev.d_mac.ether.ether_addr_octet, mac_addr, 6);
+  priv->dev.ops = &g_emac_ops;
+
+  /* Keep quotas well below the global netpkt pool size so lower-half
+   * registration remains valid across different board configurations.
+   */
+
+  quota = NETPKT_BUFNUM / 4;
+  if (quota == 0)
+    {
+      quota = 1;
+    }
+
+  priv->dev.quota[NETPKT_RX] = quota;
+  priv->dev.quota[NETPKT_TX] = quota;
+  priv->dev.rxtype = NETDEV_RX_WORK;
+  priv->dev.priority = LPWORK;
+
+  ret = netdev_lower_register(&priv->dev, NET_LL_ETHERNET);
+  if (ret != 0)
+    {
+      nerr("ERROR: netdev_lower_register failed: %d\n", ret);
+      goto errout_event;
+    }
+
+  ninfo("esp_emac: MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+        mac_addr[0], mac_addr[1], mac_addr[2],
+        mac_addr[3], mac_addr[4], mac_addr[5]);
+
+  return OK;
+
+errout_event:
+  esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID,
+                               emac_eth_event_handler);
+
+errout:
+  if (priv->installed)
+    {
+      esp_eth_driver_uninstall(priv->handle);
+      priv->installed = false;
+    }
+
+  return ret;
+}
+
+#endif /* CONFIG_ESPRESSIF_EMAC */
diff --git a/arch/risc-v/src/common/espressif/esp_emac.h 
b/arch/risc-v/src/common/espressif/esp_emac.h
new file mode 100644
index 00000000000..9f6524a3495
--- /dev/null
+++ b/arch/risc-v/src/common/espressif/esp_emac.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+ * arch/risc-v/src/common/espressif/esp_emac.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_EMAC_H
+#define __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_EMAC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_emac_init
+ *
+ * Description:
+ *   Initialize the Ethernet driver and register it with the NuttX network
+ *   stack.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int esp_emac_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_EMAC_H */
diff --git a/arch/risc-v/src/common/espressif/esp_wifi_api.c 
b/arch/risc-v/src/common/espressif/esp_wifi_api.c
index 3c90eb7eada..5c2f6e611cc 100644
--- a/arch/risc-v/src/common/espressif/esp_wifi_api.c
+++ b/arch/risc-v/src/common/espressif/esp_wifi_api.c
@@ -115,6 +115,7 @@ int esp_wifi_api_adapter_init(void)
   esp_wifi_lock(true);
 
   esp_evt_work_init();
+  esp_wifi_evt_work_init();
 
   wifi_cfg.nvs_enable = 0;
 
diff --git a/arch/risc-v/src/common/espressif/esp_wifi_event_handler.c 
b/arch/risc-v/src/common/espressif/esp_wifi_event_handler.c
index 19e3a02f98b..67273a9c220 100644
--- a/arch/risc-v/src/common/espressif/esp_wifi_event_handler.c
+++ b/arch/risc-v/src/common/espressif/esp_wifi_event_handler.c
@@ -27,9 +27,10 @@
 #include <nuttx/config.h>
 
 #include <nuttx/debug.h>
-#include <nuttx/spinlock.h>
 #include <nuttx/signal.h>
+#include <nuttx/wqueue.h>
 
+#include "esp_event.h"
 #include "esp_wifi.h"
 
 #include "esp_wifi_utils.h"
@@ -69,23 +70,13 @@ struct wifi_notify
   struct sigwork_s work;    /* Signal work private data */
 };
 
-/* Wi-Fi event private data */
-
-struct evt_adpt
-{
-  sq_entry_t entry;         /* Sequence entry */
-  wifi_event_t id;          /* Event ID */
-  uint8_t buf[0];           /* Event private data */
-};
-
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
 static struct wifi_notify g_wifi_notify[WIFI_EVENT_MAX];
-static struct work_s g_wifi_evt_work;
-static sq_queue_t g_wifi_evt_queue;
-static spinlock_t g_lock;
+static struct work_s g_wifi_reconnect_work;
+static bool g_wifi_handler_registered;
 
 /****************************************************************************
  * Private Functions
@@ -102,7 +93,7 @@ static spinlock_t g_lock;
  *   asked to disconnect from the AP.
  *
  * Input Parameters:
- *   None.
+ *   arg - Unused work queue argument.
  *
  * Returned Value:
  *   None.
@@ -130,146 +121,157 @@ static void esp_reconnect_work_cb(void *arg)
 }
 
 /****************************************************************************
- * Name: esp_evt_work_cb
+ * Name: esp_wifi_event_handler
  *
  * Description:
- *   Process Wi-Fi events.
+ *   Handler registered against WIFI_EVENT / ESP_EVENT_ANY_ID with the
+ *   generic esp_event dispatcher (see esp_event.c). Translates Wi-Fi
+ *   driver events into NuttX-visible actions (link-layer hooks and the
+ *   optional sigevent notification subsystem).
  *
  * Input Parameters:
- *   arg - Not used.
+ *   arg        - Handler-specific argument registered with the event
+ *                dispatcher (unused).
+ *   event_base - Event base identifier; always WIFI_EVENT here (unused).
+ *   event_id   - Wi-Fi event ID as defined by the ESP-IDF wifi_event_t
+ *                enumeration.
+ *   event_data - Pointer to the event-specific payload, whose concrete
+ *                type depends on event_id.
  *
  * Returned Value:
  *   None.
  *
  ****************************************************************************/
 
-static void esp_evt_work_cb(void *arg)
+static void esp_wifi_event_handler(void *arg, esp_event_base_t event_base,
+                                   int32_t event_id, void *event_data)
 {
   int ret;
-  irqstate_t flags;
-  struct evt_adpt *evt_adpt;
   struct wifi_notify *notify;
   wifi_ps_type_t ps_type = DEFAULT_PS_MODE;
 
-  while (1)
+  UNUSED(arg);
+  UNUSED(event_base);
+
+  /* Some of the following logic (eg. esp_wlan_sta_set_linkstatus)
+   * can take net_lock(). To maintain the consistent locking order,
+   * we take net_lock() here before taking esp_wifi_lock. Note that
+   * net_lock() is a recursive lock.
+   */
+
+  net_lock();
+  esp_wifi_lock(true);
+
+  switch (event_id)
     {
-      flags = spin_lock_irqsave(&g_lock);
-      evt_adpt = (struct evt_adpt *)sq_remfirst(&g_wifi_evt_queue);
-      spin_unlock_irqrestore(&g_lock, flags);
-      if (!evt_adpt)
+#ifdef ESP_WLAN_DEVS
+      case WIFI_EVENT_SCAN_DONE:
+        esp_wifi_scan_event_parse();
+        break;
+#endif
+      case WIFI_EVENT_HOME_CHANNEL_CHANGE:
+        wlinfo("Wi-Fi home channel change\n");
+        break;
+
+#ifdef ESP_WLAN_HAS_STA
+      case WIFI_EVENT_STA_START:
         {
-          break;
+          wlinfo("Wi-Fi sta start\n");
+
+          ret = esp_wifi_set_ps(ps_type);
+          if (ret)
+            {
+              wlerr("Failed to set power save type\n");
+              break;
+            }
         }
+        break;
 
-      /* Some of the following logic (eg. esp_wlan_sta_set_linkstatus)
-       * can take net_lock(). To maintain the consistent locking order,
-       * we take net_lock() here before taking esp_wifi_lock. Note that
-       * net_lock() is a recursive lock.
-       */
+      case WIFI_EVENT_STA_STOP:
+        wlinfo("Wi-Fi station stopped\n");
+        break;
 
-      net_lock();
-      esp_wifi_lock(true);
+      case WIFI_EVENT_STA_CONNECTED:
+        {
+          wlinfo("Wi-Fi station connected\n");
+          esp_wlan_sta_connect_success_hook();
+        }
+        break;
 
-      switch (evt_adpt->id)
+      case WIFI_EVENT_STA_DISCONNECTED:
         {
-#ifdef ESP_WLAN_DEVS
-          case WIFI_EVENT_SCAN_DONE:
-            esp_wifi_scan_event_parse();
-            break;
-#endif
-          case WIFI_EVENT_HOME_CHANNEL_CHANGE:
-            wlinfo("Wi-Fi home channel change\n");
-            break;
+          wifi_event_sta_disconnected_t *event =
+              (wifi_event_sta_disconnected_t *)event_data;
+          wifi_err_reason_t reason = event->reason;
 
-#ifdef ESP_WLAN_HAS_STA
-          case WIFI_EVENT_STA_START:
-            wlinfo("Wi-Fi sta start\n");
-
-            ret = esp_wifi_set_ps(ps_type);
-            if (ret)
-              {
-                wlerr("Failed to set power save type\n");
-                break;
-              }
-            break;
-
-          case WIFI_EVENT_STA_STOP:
-            wlinfo("Wi-Fi station stopped\n");
-            break;
-
-          case WIFI_EVENT_STA_CONNECTED:
-            wlinfo("Wi-Fi station connected\n");
-            esp_wlan_sta_connect_success_hook();
-            break;
-
-          case WIFI_EVENT_STA_DISCONNECTED:
-            wifi_event_sta_disconnected_t *event =
-            (wifi_event_sta_disconnected_t *)evt_adpt->buf;
-            wifi_err_reason_t reason = event->reason;
-
-            wlinfo("Wi-Fi station disconnected, reason: %u\n", reason);
-            esp_wlan_sta_disconnect_hook();
-            if (reason == WIFI_REASON_ASSOC_LEAVE)
-              {
-                work_queue(LPWORK, &g_wifi_evt_work, esp_reconnect_work_cb,
-                           NULL, 0);
-              }
-
-            break;
-
-          case WIFI_EVENT_STA_AUTHMODE_CHANGE:
-            wlinfo("Wi-Fi station auth mode change\n");
-            break;
+          wlinfo("Wi-Fi station disconnected, reason: %u\n", reason);
+          esp_wlan_sta_disconnect_hook();
+          if (reason == WIFI_REASON_ASSOC_LEAVE)
+            {
+              work_queue(LPWORK, &g_wifi_reconnect_work,
+                         esp_reconnect_work_cb, NULL, 0);
+            }
+        }
+        break;
+
+      case WIFI_EVENT_STA_AUTHMODE_CHANGE:
+        wlinfo("Wi-Fi station auth mode change\n");
+        break;
 #endif /* ESP_WLAN_HAS_STA */
 
 #ifdef ESP_WLAN_HAS_SOFTAP
-          case WIFI_EVENT_AP_START:
-            wlinfo("INFO: Wi-Fi softap start\n");
-            esp_wlan_softap_connect_success_hook();
-            ret = esp_wifi_set_ps(ps_type);
-            if (ret)
-              {
-                wlerr("Failed to set power save type\n");
-                break;
-              }
-            break;
-
-          case WIFI_EVENT_AP_STOP:
-            wlinfo("Wi-Fi softap stop\n");
-            esp_wlan_softap_disconnect_hook();
-            break;
-
-          case WIFI_EVENT_AP_STACONNECTED:
-            wlinfo("Wi-Fi station joined AP\n");
-            break;
-
-          case WIFI_EVENT_AP_STADISCONNECTED:
-            wlinfo("Wi-Fi station left AP\n");
-            break;
-#endif /* ESP_WLAN_HAS_SOFTAP */
-          default:
-            break;
+      case WIFI_EVENT_AP_START:
+        {
+          wlinfo("INFO: Wi-Fi softap start\n");
+          esp_wlan_softap_connect_success_hook();
+          ret = esp_wifi_set_ps(ps_type);
+          if (ret)
+            {
+              wlerr("Failed to set power save type\n");
+              break;
+            }
         }
+        break;
+
+      case WIFI_EVENT_AP_STOP:
+        {
+          wlinfo("Wi-Fi softap stop\n");
+          esp_wlan_softap_disconnect_hook();
+        }
+        break;
+
+      case WIFI_EVENT_AP_STACONNECTED:
+        wlinfo("Wi-Fi station joined AP\n");
+        break;
 
-      notify = &g_wifi_notify[evt_adpt->id];
+      case WIFI_EVENT_AP_STADISCONNECTED:
+        wlinfo("Wi-Fi station left AP\n");
+        break;
+#endif /* ESP_WLAN_HAS_SOFTAP */
+
+      default:
+        break;
+    }
+
+  if (event_id >= 0 && event_id < WIFI_EVENT_MAX)
+    {
+      notify = &g_wifi_notify[event_id];
       if (notify->assigned)
         {
-          notify->event.sigev_value.sival_ptr = evt_adpt->buf;
+          notify->event.sigev_value.sival_ptr = event_data;
 
           ret = nxsig_notification(notify->pid, &notify->event,
                                    SI_QUEUE, &notify->work);
           if (ret < 0)
             {
               wlwarn("nxsig_notification event ID=%d failed: %d\n",
-                     evt_adpt->id, ret);
+                     (int)event_id, ret);
             }
         }
-
-      esp_wifi_lock(false);
-      net_unlock();
-
-      kmm_free(evt_adpt);
     }
+
+  esp_wifi_lock(false);
+  net_unlock();
 }
 
 /****************************************************************************
@@ -277,81 +279,30 @@ static void esp_evt_work_cb(void *arg)
  ****************************************************************************/
 
 /****************************************************************************
- * Name: esp_event_post
+ * Name: esp_wifi_evt_work_init
  *
  * Description:
- *   Posts an event to the event loop system. The event is queued in a FIFO
- *   and processed asynchronously in the low-priority work queue.
+ *   Register the Wi-Fi event handler against the generic esp_event loop.
+ *   Kept under the original name so existing callers (esp_wifi_api.c)
+ *   continue to compile unchanged. Idempotent: subsequent calls after the
+ *   first successful registration are silently ignored.
  *
  * Input Parameters:
- *   event_base      - Identifier for the event category (e.g. WIFI_EVENT)
- *   event_id        - Event ID within the event base category
- *   event_data      - Pointer to event data structure
- *   event_data_size - Size of event data structure
- *   ticks           - Number of ticks to wait (currently unused)
+ *   None.
  *
  * Returned Value:
- *   0 on success
- *   -1 on failure with following error conditions:
- *      - Invalid event ID
- *      - Memory allocation failure
- *
- * Assumptions/Limitations:
- *   - Event data is copied into a new buffer, so the original can be freed
- *   - Events are processed in FIFO order in the low priority work queue
- *   - The function is thread-safe and can be called from interrupt context
+ *   None.
  *
  ****************************************************************************/
 
-int esp_event_post(const char *event_base,
-                         int32_t event_id,
-                         void *event_data,
-                         size_t event_data_size,
-                         uint32_t ticks)
+void esp_wifi_evt_work_init(void)
 {
-  size_t size;
-  int32_t id;
-  irqstate_t flags;
-  struct evt_adpt *evt_adpt;
-
-  wlinfo("Event: base=%s id=%ld data=%p data_size=%u ticks=%lu\n",
-         event_base, event_id, event_data, event_data_size, ticks);
-
-  size = event_data_size + sizeof(struct evt_adpt);
-  evt_adpt = kmm_malloc(size);
-  if (!evt_adpt)
+  if (g_wifi_handler_registered)
     {
-      wlerr("ERROR: Failed to alloc %d memory\n", size);
-      return -1;
+      return;
     }
 
-  evt_adpt->id = event_id;
-  memcpy(evt_adpt->buf, event_data, event_data_size);
-
-  flags = enter_critical_section();
-  sq_addlast(&evt_adpt->entry, &g_wifi_evt_queue);
-  leave_critical_section(flags);
-
-  work_queue(LPWORK, &g_wifi_evt_work, esp_evt_work_cb, NULL, 0);
-
-  return 0;
-}
-
-/****************************************************************************
- * Name: esp_evt_work_init
- *
- * Description:
- *   Initialize the event work queue
- *
- * Input Parameters:
- *   None.
- *
- * Returned Value:
- *   None.
- *
- ****************************************************************************/
-
-void esp_evt_work_init(void)
-{
-  sq_init(&g_wifi_evt_queue);
+  esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
+                             esp_wifi_event_handler, NULL);
+  g_wifi_handler_registered = true;
 }
diff --git a/arch/risc-v/src/common/espressif/esp_wifi_utils.h 
b/arch/risc-v/src/common/espressif/esp_wifi_utils.h
index 9363f492dac..28025c30705 100644
--- a/arch/risc-v/src/common/espressif/esp_wifi_utils.h
+++ b/arch/risc-v/src/common/espressif/esp_wifi_utils.h
@@ -99,7 +99,7 @@ int esp_freq_to_channel(uint16_t freq);
  * Name: esp_evt_work_init
  *
  * Description:
- *   Initialize the event work queue
+ *   Initialize the generic esp_event backend queue.
  *
  * Input Parameters:
  *   None
@@ -111,6 +111,22 @@ int esp_freq_to_channel(uint16_t freq);
 
 void esp_evt_work_init(void);
 
+/****************************************************************************
+ * Name: esp_wifi_evt_work_init
+ *
+ * Description:
+ *   Initialize the event work queue
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_wifi_evt_work_init(void);
+
 /****************************************************************************
  * Name: esp_wifi_start_scan
  *
@@ -212,39 +228,6 @@ wifi_mode_t esp_wifi_mode_translate(uint32_t 
wireless_mode);
 
 int esp_wifi_lock(bool lock);
 
-/****************************************************************************
- * Name: esp_event_post
- *
- * Description:
- *   Posts an event to the event loop system. The event is queued in a FIFO
- *   and processed asynchronously in the low-priority work queue.
- *
- * Input Parameters:
- *   event_base      - Identifier for the event category (e.g. WIFI_EVENT)
- *   event_id        - Event ID within the event base category
- *   event_data      - Pointer to event data structure
- *   event_data_size - Size of event data structure
- *   ticks           - Number of ticks to wait (currently unused)
- *
- * Returned Value:
- *   0 on success
- *   -1 on failure with following error conditions:
- *      - Invalid event ID
- *      - Memory allocation failure
- *
- * Assumptions/Limitations:
- *   - Event data is copied into a new buffer, so the original can be freed
- *   - Events are processed in FIFO order in the low priority work queue
- *   - The function is thread-safe and can be called from interrupt context
- *
- ****************************************************************************/
-
-int esp_event_post(const char *event_base,
-                         int32_t event_id,
-                         void *event_data,
-                         size_t event_data_size,
-                         uint32_t ticks);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/arch/risc-v/src/esp32c3/hal_esp32c3.cmake 
b/arch/risc-v/src/esp32c3/hal_esp32c3.cmake
index 4c76692e83c..4ceb670ad4f 100644
--- a/arch/risc-v/src/esp32c3/hal_esp32c3.cmake
+++ b/arch/risc-v/src/esp32c3/hal_esp32c3.cmake
@@ -507,6 +507,10 @@ list(
   ${ESP_HAL_3RDPARTY_REPO}/components/upper_hal_rmt/src/rmt_tx.c
   ${ESP_HAL_3RDPARTY_REPO}/components/upper_hal_uart/src/uart_wakeup.c)
 
+if(CONFIG_ESPRESSIF_WIFI OR CONFIG_ESPRESSIF_EMAC)
+  list(APPEND HAL_SRCS ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/esp_event.c)
+endif()
+
 # Bootloader flash encrypt source
 list(APPEND HAL_SRCS
      
${ESP_HAL_3RDPARTY_REPO}/components/bootloader_support/src/flash_encrypt.c)
diff --git a/arch/risc-v/src/esp32c3/hal_esp32c3.mk 
b/arch/risc-v/src/esp32c3/hal_esp32c3.mk
index 088761c60f0..a40e98de871 100644
--- a/arch/risc-v/src/esp32c3/hal_esp32c3.mk
+++ b/arch/risc-v/src/esp32c3/hal_esp32c3.mk
@@ -338,6 +338,10 @@ CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)platform$(DELIM)os.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)heap_caps.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)components$(DELIM)newlib$(DELIM)newlib$(DELIM)libc$(DELIM)misc$(DELIM)init.c
+
+ifneq ($(CONFIG_ESPRESSIF_WIFI)$(CONFIG_ESPRESSIF_EMAC),)
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)esp_event.c
+endif
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)upper_hal_gpio$(DELIM)src$(DELIM)gpio.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)upper_hal_gpio$(DELIM)src$(DELIM)rtc_io.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)upper_hal_rmt$(DELIM)src$(DELIM)rmt_common.c
diff --git a/arch/risc-v/src/esp32c6/hal_esp32c6.cmake 
b/arch/risc-v/src/esp32c6/hal_esp32c6.cmake
index 643e4199780..76e8a64e592 100644
--- a/arch/risc-v/src/esp32c6/hal_esp32c6.cmake
+++ b/arch/risc-v/src/esp32c6/hal_esp32c6.cmake
@@ -533,6 +533,10 @@ list(
   ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/heap_caps.c
   ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/components/newlib/newlib/libc/misc/init.c)
 
+if(CONFIG_ESPRESSIF_WIFI OR CONFIG_ESPRESSIF_EMAC)
+  list(APPEND HAL_SRCS ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/esp_event.c)
+endif()
+
 # Bootloader flash encrypt
 list(APPEND HAL_SRCS
      
${ESP_HAL_3RDPARTY_REPO}/components/bootloader_support/src/flash_encrypt.c)
diff --git a/arch/risc-v/src/esp32c6/hal_esp32c6.mk 
b/arch/risc-v/src/esp32c6/hal_esp32c6.mk
index b7af0247826..6da49a12d2a 100644
--- a/arch/risc-v/src/esp32c6/hal_esp32c6.mk
+++ b/arch/risc-v/src/esp32c6/hal_esp32c6.mk
@@ -382,6 +382,10 @@ CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELI
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)heap_caps.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)components$(DELIM)newlib$(DELIM)newlib$(DELIM)libc$(DELIM)misc$(DELIM)init.c
 
+ifneq ($(CONFIG_ESPRESSIF_WIFI)$(CONFIG_ESPRESSIF_EMAC),)
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)esp_event.c
+endif
+
 # Bootloader files
 
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)flash_encrypt.c
diff --git a/arch/risc-v/src/esp32h2/hal_esp32h2.cmake 
b/arch/risc-v/src/esp32h2/hal_esp32h2.cmake
index dde8f481fe8..039eb4b5989 100644
--- a/arch/risc-v/src/esp32h2/hal_esp32h2.cmake
+++ b/arch/risc-v/src/esp32h2/hal_esp32h2.cmake
@@ -51,6 +51,7 @@ target_include_directories(
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_adc/${CHIP_SERIES}/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_blockdev/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_common/include
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_event/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_hal_ana_conv/${CHIP_SERIES}/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_hal_ana_conv/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_hal_clock/${CHIP_SERIES}/include
@@ -492,6 +493,10 @@ list(
   ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/heap_caps.c
   ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/components/newlib/newlib/libc/misc/init.c)
 
+if(CONFIG_ESPRESSIF_WIFI OR CONFIG_ESPRESSIF_EMAC)
+  list(APPEND HAL_SRCS ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/esp_event.c)
+endif()
+
 # Bootloader flash encrypt
 list(APPEND HAL_SRCS
      
${ESP_HAL_3RDPARTY_REPO}/components/bootloader_support/src/flash_encrypt.c)
diff --git a/arch/risc-v/src/esp32h2/hal_esp32h2.mk 
b/arch/risc-v/src/esp32h2/hal_esp32h2.mk
index 60f12a61968..74f8fecb518 100644
--- a/arch/risc-v/src/esp32h2/hal_esp32h2.mk
+++ b/arch/risc-v/src/esp32h2/hal_esp32h2.mk
@@ -38,6 +38,7 @@ INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_adc$(DELIM)$(CHIP_SERIES)$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_blockdev$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_common$(DELIM)include
+INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_event$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hal_ana_conv$(DELIM)$(CHIP_SERIES)$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hal_ana_conv$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hal_dma$(DELIM)$(CHIP_SERIES)$(DELIM)include
@@ -358,6 +359,10 @@ CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)uppe
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)upper_hal_gpio$(DELIM)src$(DELIM)rtc_io.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)components$(DELIM)newlib$(DELIM)newlib$(DELIM)libc$(DELIM)misc$(DELIM)init.c
 
+ifneq ($(CONFIG_ESPRESSIF_WIFI)$(CONFIG_ESPRESSIF_EMAC),)
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)esp_event.c
+endif
+
 CHIP_ASRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)lowpower$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)sleep_cpu_asm.S
 
 # Bootloader files
diff --git a/arch/risc-v/src/esp32p4/hal_esp32p4.cmake 
b/arch/risc-v/src/esp32p4/hal_esp32p4.cmake
index 375a34cff74..8a994cbad33 100644
--- a/arch/risc-v/src/esp32p4/hal_esp32p4.cmake
+++ b/arch/risc-v/src/esp32p4/hal_esp32p4.cmake
@@ -49,6 +49,7 @@ set(ESP32P4_INCLUDES
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_app_format/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_blockdev/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_common/include
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_event/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_hal_ana_conv/${CHIP_SERIES}/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_hal_ana_conv/include
     ${ESP_HAL_3RDPARTY_REPO}/components/esp_hal_cam/${CHIP_SERIES}/include
@@ -436,6 +437,31 @@ list(
   ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/heap_caps.c
   ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/platform/os.c)
 
+if(CONFIG_ESPRESSIF_WIFI OR CONFIG_ESPRESSIF_EMAC)
+  list(APPEND HAL_SRCS ${ESP_HAL_3RDPARTY_REPO}/nuttx/src/esp_event.c)
+endif()
+
+if(CONFIG_ESPRESSIF_EMAC)
+  list(
+    APPEND
+    HAL_SRCS
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_hal_emac/emac_hal.c
+    
${ESP_HAL_3RDPARTY_REPO}/components/esp_hal_emac/${CHIP_SERIES}/emac_periph.c
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_eth/src/esp_eth.c
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_eth/src/mac/esp_eth_mac_esp.c
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_eth/src/mac/esp_eth_mac_esp_dma.c
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_eth/src/phy/esp_eth_phy_802_3.c
+    ${ESP_HAL_3RDPARTY_REPO}/components/esp_eth/src/phy/esp_eth_phy_generic.c
+    # log_buffers.c provides ESP_LOG_BUFFER_HEXDUMP used by esp_eth_mac_esp.c
+    # for its dump_hal_registers diagnostic helper; util.c supplies the hex
+    # conversion helper consumed by log_buffers.c.
+    ${ESP_HAL_3RDPARTY_REPO}/components/log/src/util.c
+    ${ESP_HAL_3RDPARTY_REPO}/components/log/src/buffer/log_buffers.c)
+  target_include_directories(
+    arch PRIVATE ${ESP_HAL_3RDPARTY_REPO}/components/esp_eth/include)
+endif()
+
 # Bootloader common
 list(
   APPEND HAL_SRCS
diff --git a/arch/risc-v/src/esp32p4/hal_esp32p4.mk 
b/arch/risc-v/src/esp32p4/hal_esp32p4.mk
index 31bfede5c08..39a47c3553d 100644
--- a/arch/risc-v/src/esp32p4/hal_esp32p4.mk
+++ b/arch/risc-v/src/esp32p4/hal_esp32p4.mk
@@ -39,6 +39,7 @@ INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_app_format$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_blockdev$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_common$(DELIM)include
+INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_event$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hal_ana_conv$(DELIM)$(CHIP_SERIES)$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hal_ana_conv$(DELIM)include
 INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hal_cam$(DELIM)$(CHIP_SERIES)$(DELIM)include
@@ -359,6 +360,8 @@ CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)efuse_hal.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)hal_utils.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mmu_hal.c
+CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)log$(DELIM)src$(DELIM)util.c
+CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)log$(DELIM)src$(DELIM)buffer$(DELIM)log_buffers.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)log$(DELIM)src$(DELIM)log_level$(DELIM)log_level.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)log$(DELIM)src$(DELIM)log_level$(DELIM)tag_log_level$(DELIM)linked_list$(DELIM)log_linked_list.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)log$(DELIM)src$(DELIM)log_level$(DELIM)tag_log_level$(DELIM)tag_log_level.c
@@ -410,6 +413,23 @@ CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELI
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)heap_caps.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)platform$(DELIM)os.c
 
+ifneq ($(CONFIG_ESPRESSIF_WIFI)$(CONFIG_ESPRESSIF_EMAC),)
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)esp_event.c
+endif
+
+ifeq ($(CONFIG_ESPRESSIF_EMAC),y)
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hal_emac$(DELIM)emac_hal.c
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hal_emac$(DELIM)$(CHIP_SERIES)$(DELIM)emac_periph.c
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_eth$(DELIM)src$(DELIM)esp_eth.c
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_eth$(DELIM)src$(DELIM)mac$(DELIM)esp_eth_mac_esp.c
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_eth$(DELIM)src$(DELIM)mac$(DELIM)esp_eth_mac_esp_dma.c
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_eth$(DELIM)src$(DELIM)mac$(DELIM)esp_eth_mac_esp_gpio.c
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_eth$(DELIM)src$(DELIM)phy$(DELIM)esp_eth_phy_802_3.c
+  CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_eth$(DELIM)src$(DELIM)phy$(DELIM)esp_eth_phy_generic.c
+
+  INCLUDES += 
$(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_eth$(DELIM)include
+endif
+
 # Bootloader files
 
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)bootloader_mem.c

Reply via email to