From 9fd020d9daa397c2cab5518e381db5408a34db76 Mon Sep 17 00:00:00 2001 From: glmfe Date: Wed, 12 Nov 2025 06:46:38 -0300 Subject: [PATCH] refactor(hal): graduate emac hal into a new component - Separate emac from hal component to a new one: esp_hal_emac. --- components/esp_eth/CMakeLists.txt | 1 + components/esp_eth/include/esp_eth_mac_esp.h | 4 +- components/esp_eth/src/mac/esp_eth_mac_esp.c | 2 +- .../esp_eth/src/mac/esp_eth_mac_esp_gpio.c | 2 +- components/esp_hal_emac/CMakeLists.txt | 20 +++++++ components/esp_hal_emac/README.md | 52 +++++++++++++++++++ components/{hal => esp_hal_emac}/emac_hal.c | 5 +- .../{soc => esp_hal_emac}/esp32/emac_periph.c | 2 +- .../esp32/include/hal/emac_ll.h | 1 - .../esp32p4/emac_periph.c | 2 +- .../esp32p4/include/hal/emac_ll.h | 9 ++-- .../include/hal/emac_hal.h | 2 - .../include/hal}/emac_periph.h | 0 components/esp_system/CMakeLists.txt | 1 + components/hal/CMakeLists.txt | 4 -- components/soc/CMakeLists.txt | 3 -- 16 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 components/esp_hal_emac/CMakeLists.txt create mode 100644 components/esp_hal_emac/README.md rename components/{hal => esp_hal_emac}/emac_hal.c (99%) rename components/{soc => esp_hal_emac}/esp32/emac_periph.c (99%) rename components/{hal => esp_hal_emac}/esp32/include/hal/emac_ll.h (99%) rename components/{soc => esp_hal_emac}/esp32p4/emac_periph.c (99%) rename components/{hal => esp_hal_emac}/esp32p4/include/hal/emac_ll.h (99%) rename components/{hal => esp_hal_emac}/include/hal/emac_hal.h (99%) rename components/{soc/include/soc => esp_hal_emac/include/hal}/emac_periph.h (100%) diff --git a/components/esp_eth/CMakeLists.txt b/components/esp_eth/CMakeLists.txt index c31497d42e4..e530874db77 100644 --- a/components/esp_eth/CMakeLists.txt +++ b/components/esp_eth/CMakeLists.txt @@ -42,6 +42,7 @@ idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${include} LDFRAGMENTS ${ld_fragments} REQUIRES esp_event # For using "ESP_EVENT_DECLARE_BASE" in header file + esp_hal_emac PRIV_REQUIRES ${priv_requires}) if(CONFIG_ETH_ENABLED) diff --git a/components/esp_eth/include/esp_eth_mac_esp.h b/components/esp_eth/include/esp_eth_mac_esp.h index 0a858b7d94d..2fa45815ed9 100644 --- a/components/esp_eth/include/esp_eth_mac_esp.h +++ b/components/esp_eth/include/esp_eth_mac_esp.h @@ -25,7 +25,7 @@ typedef enum { /** * @brief Input RMII Clock from external. EMAC Clock GPIO number needs to be configured when this option is selected. * - * @note See components/soc/esp32(*)/emac_periph.c for available GPIO numbers. + * @note See components/esp_hal_emac/esp32(*)/emac_periph.c for available GPIO numbers. * */ EMAC_CLK_EXT_IN, @@ -36,7 +36,7 @@ typedef enum { * @warning ESP32 Errata: If you want the Ethernet to work with Wi-Fi or BT, don’t select ESP32 as RMII CLK output as it would result in clock instability. * Applicable only to ESP32, other ESP32 SoCs are not affected. * - * @note See components/soc/esp32(*)/emac_periph.c for available GPIO numbers. + * @note See components/esp_hal_emac/esp32(*)/emac_periph.c for available GPIO numbers. * */ EMAC_CLK_OUT diff --git a/components/esp_eth/src/mac/esp_eth_mac_esp.c b/components/esp_eth/src/mac/esp_eth_mac_esp.c index a326fa3d693..ae23482be4f 100644 --- a/components/esp_eth/src/mac/esp_eth_mac_esp.c +++ b/components/esp_eth/src/mac/esp_eth_mac_esp.c @@ -30,7 +30,7 @@ #include "freertos/semphr.h" #include "hal/emac_hal.h" #include "soc/soc.h" -#include "soc/emac_periph.h" +#include "hal/emac_periph.h" #include "clk_ctrl_os.h" #include "sdkconfig.h" #include "esp_rom_sys.h" diff --git a/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c b/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c index ee2eced1ab6..be0a1c2dc49 100644 --- a/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c +++ b/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c @@ -13,7 +13,7 @@ #include "soc/gpio_sig_map.h" #include "soc/io_mux_reg.h" #include "soc/gpio_periph.h" -#include "soc/emac_periph.h" +#include "hal/emac_periph.h" #include "esp_private/gpio.h" #include "esp_private/eth_mac_esp_gpio.h" #include "esp_private/esp_gpio_reserve.h" diff --git a/components/esp_hal_emac/CMakeLists.txt b/components/esp_hal_emac/CMakeLists.txt new file mode 100644 index 00000000000..02dfc13edbd --- /dev/null +++ b/components/esp_hal_emac/CMakeLists.txt @@ -0,0 +1,20 @@ +idf_build_get_property(target IDF_TARGET) +if(${target} STREQUAL "linux") + return() # This component is not supported by the POSIX/Linux simulator +endif() + +# target specific include must be added before the generic one +set(includes) +list(APPEND includes "include") + +set(srcs) + +if(CONFIG_SOC_EMAC_SUPPORTED) + list(APPEND srcs "emac_hal.c") + list(APPEND srcs "${target}/emac_periph.c") + list(APPEND includes "${target}/include") +endif() + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${includes} + REQUIRES soc hal) diff --git a/components/esp_hal_emac/README.md b/components/esp_hal_emac/README.md new file mode 100644 index 00000000000..9bb679ae78d --- /dev/null +++ b/components/esp_hal_emac/README.md @@ -0,0 +1,52 @@ +# ESP Hardware Abstraction Layer for Ethernet MAC Peripheral + +> [!NOTE] +> This component is currently in beta. Its API, behavior, and compatibility may change at any time and without notice; backward compatibility is not guaranteed. Use caution when integrating into production systems. + +## Overview + +The `esp_hal_emac` component provides a **Hardware Abstraction Layer** for the Ethernet MAC (EMAC) peripherals across all ESP-IDF supported targets. It serves as a foundation for the higher-level Ethernet drivers, offering a consistent interface to interact with Ethernet MAC hardware while hiding the complexities of chip-specific implementations. + +## Architecture + +The HAL architecture consists of two primary layers: + +1. **HAL Layer (Upper)**: Defines the operational sequences and data structures required to interact with EMAC peripherals, including: + - Initialization and de-initialization + - MAC configuration (speed, duplex, promiscuous mode) + - DMA descriptor management + - PHY interface management (MII/RMII) + - Address filtering and frame reception/transmission + - Flow control and interrupt handling + +2. **Low-Level Layer (Bottom)**: Acts as a translation layer between the HAL and the register definitions in the `soc` component, handling: + - Register access abstractions + - Chip-specific register configurations + - Hardware feature compatibility + +## Features + +- Unified Ethernet MAC interface across all ESP chip families +- Support for MII and RMII PHY interfaces +- DMA-based frame transmission and reception +- MAC address filtering with multiple address support +- Flow control (pause frame) support +- Promiscuous mode and multicast filtering +- Hardware checksum offloading +- IEEE 1588 PTP (Precision Time Protocol) support on compatible chips +- Sleep retention support on compatible chips +- Configurable DMA burst length +- VLAN tag insertion/removal/replacement +- IP checksum insertion for TCP/UDP/ICMP headers + +## Usage + +This component is primarily used by ESP-IDF peripheral drivers such as `esp_eth`. It is also utilized by system components that require Ethernet functionality. + +For advanced developers implementing custom Ethernet solutions, the HAL functions can be used directly. However, please note that the interfaces provided by this component are internal to ESP-IDF and are subject to change. + +## Dependencies + +- `soc`: Provides chip-specific register definitions and peripheral information +- `hal`: Core hardware abstraction utilities and macros + diff --git a/components/hal/emac_hal.c b/components/esp_hal_emac/emac_hal.c similarity index 99% rename from components/hal/emac_hal.c rename to components/esp_hal_emac/emac_hal.c index 58ee6837bca..1d6c36f897e 100644 --- a/components/hal/emac_hal.c +++ b/components/esp_hal_emac/emac_hal.c @@ -416,7 +416,7 @@ esp_err_t emac_hal_ptp_stop(emac_hal_context_t *hal) esp_err_t emac_hal_ptp_adj_inc(emac_hal_context_t *hal, int32_t adj_ppb) { if (emac_ll_get_ts_update_method(hal->ptp_regs) != ETH_PTP_UPDATE_METHOD_FINE || - !emac_ll_is_ts_addend_update_done(hal->ptp_regs)) { + !emac_ll_is_ts_addend_update_done(hal->ptp_regs)) { return ESP_ERR_INVALID_STATE; } /** @@ -464,7 +464,7 @@ esp_err_t emac_hal_ptp_adj_inc(emac_hal_context_t *hal, int32_t adj_ppb) esp_err_t emac_hal_adj_freq_factor(emac_hal_context_t *hal, double scale_factor) { if (emac_ll_get_ts_update_method(hal->ptp_regs) != ETH_PTP_UPDATE_METHOD_FINE || - !emac_ll_is_ts_addend_update_done(hal->ptp_regs)) { + !emac_ll_is_ts_addend_update_done(hal->ptp_regs)) { return ESP_ERR_INVALID_STATE; } @@ -529,7 +529,6 @@ esp_err_t emac_hal_ptp_enable_ts4all(emac_hal_context_t *hal, bool enable) } #endif // SOC_EMAC_IEEE1588V2_SUPPORTED - void emac_hal_start(emac_hal_context_t *hal) { /* Enable Ethernet MAC and DMA Interrupt */ diff --git a/components/soc/esp32/emac_periph.c b/components/esp_hal_emac/esp32/emac_periph.c similarity index 99% rename from components/soc/esp32/emac_periph.c rename to components/esp_hal_emac/esp32/emac_periph.c index 389ee539214..6b9e1650ae5 100644 --- a/components/soc/esp32/emac_periph.c +++ b/components/esp_hal_emac/esp32/emac_periph.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include "soc/emac_periph.h" +#include "hal/emac_periph.h" #include "soc/io_mux_reg.h" const emac_io_info_t emac_io_idx = { diff --git a/components/hal/esp32/include/hal/emac_ll.h b/components/esp_hal_emac/esp32/include/hal/emac_ll.h similarity index 99% rename from components/hal/esp32/include/hal/emac_ll.h rename to components/esp_hal_emac/esp32/include/hal/emac_ll.h index eea392fc003..c20fb1ca7ad 100644 --- a/components/hal/esp32/include/hal/emac_ll.h +++ b/components/esp_hal_emac/esp32/include/hal/emac_ll.h @@ -134,7 +134,6 @@ extern "C" { /* Enable needed DMA interrupts (recv/recv_buf_unavailabal/normal must be enabled to make eth work) */ #define EMAC_LL_CONFIG_ENABLE_INTR_MASK (EMAC_LL_INTR_RECEIVE_ENABLE | EMAC_LL_INTR_NORMAL_SUMMARY_ENABLE) - /* Maximum number of MAC address to be filtered */ #define EMAC_LL_MAX_MAC_ADDR_NUM 8 diff --git a/components/soc/esp32p4/emac_periph.c b/components/esp_hal_emac/esp32p4/emac_periph.c similarity index 99% rename from components/soc/esp32p4/emac_periph.c rename to components/esp_hal_emac/esp32p4/emac_periph.c index 19096f6f132..3f6dd545e33 100644 --- a/components/soc/esp32p4/emac_periph.c +++ b/components/esp_hal_emac/esp32p4/emac_periph.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include "soc/emac_periph.h" +#include "hal/emac_periph.h" #include "soc/io_mux_reg.h" #if __has_include("soc/emac_reg.h") #include "soc/emac_reg.h" diff --git a/components/hal/esp32p4/include/hal/emac_ll.h b/components/esp_hal_emac/esp32p4/include/hal/emac_ll.h similarity index 99% rename from components/hal/esp32p4/include/hal/emac_ll.h rename to components/esp_hal_emac/esp32p4/include/hal/emac_ll.h index 073f0aab8e7..63b4bb03436 100644 --- a/components/hal/esp32p4/include/hal/emac_ll.h +++ b/components/esp_hal_emac/esp32p4/include/hal/emac_ll.h @@ -465,8 +465,6 @@ static inline void emac_ll_disable_corresponding_emac_intr(emac_mac_dev_t *mac_r /*************** End of mac regs operation *********************/ - - /************** Start of dma regs operation ********************/ /* dmabusmode */ static inline void emac_ll_reset(emac_dma_dev_t *dma_regs) @@ -659,7 +657,6 @@ __attribute__((always_inline)) static inline void emac_ll_clear_all_pending_intr dma_regs->dmastatus.val = 0xFFFFFFFF; } - /* dmatxpolldemand / dmarxpolldemand */ static inline void emac_ll_transmit_poll_demand(emac_dma_dev_t *dma_regs, uint32_t val) { @@ -714,7 +711,8 @@ static inline void emac_ll_ts_all_enable(emac_ptp_dev_t *ptp_regs, bool enable) ptp_regs->timestamp_ctrl.en_ts4all = enable; } -static inline void emac_ll_ptp_v2_proc_enable(emac_ptp_dev_t *ptp_regs, bool enable) { +static inline void emac_ll_ptp_v2_proc_enable(emac_ptp_dev_t *ptp_regs, bool enable) +{ ptp_regs->timestamp_ctrl.en_ptp_pkg_proc_ver2_fmt = enable; } @@ -987,8 +985,7 @@ static inline void emac_ll_clock_enable_ptp(void *ext_regs, soc_periph_emac_ptp_ { uint8_t clk_src_val; - switch (clk_src) - { + switch (clk_src) { case EMAC_PTP_CLK_SRC_XTAL: clk_src_val = 0; break; diff --git a/components/hal/include/hal/emac_hal.h b/components/esp_hal_emac/include/hal/emac_hal.h similarity index 99% rename from components/hal/include/hal/emac_hal.h rename to components/esp_hal_emac/include/hal/emac_hal.h index 0d6ca3b0cd4..a262c26fc78 100644 --- a/components/hal/include/hal/emac_hal.h +++ b/components/esp_hal_emac/include/hal/emac_hal.h @@ -33,7 +33,6 @@ extern "C" { #define EMAC_HAL_DMA_DESC_SIZE (32) #endif - /* DMA descriptor control bits */ #define EMAC_HAL_TDES0_INTR_ON_COMPLET (1 << 30) #define EMAC_HAL_TDES0_CRC_APPEND_DISABLE (1 << 27) @@ -189,7 +188,6 @@ typedef struct { ASSERT_TYPE_SIZE(eth_dma_rx_descriptor_t, EMAC_HAL_DMA_DESC_SIZE); - typedef struct emac_mac_dev_s *emac_mac_soc_regs_t; typedef struct emac_dma_dev_s *emac_dma_soc_regs_t; #if SOC_IS(ESP32) diff --git a/components/soc/include/soc/emac_periph.h b/components/esp_hal_emac/include/hal/emac_periph.h similarity index 100% rename from components/soc/include/soc/emac_periph.h rename to components/esp_hal_emac/include/hal/emac_periph.h diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index 5d38d8bffea..db6baa27528 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -83,6 +83,7 @@ else() esp_hal_lcd esp_hal_mcpwm esp_hal_jpeg + esp_hal_emac LDFRAGMENTS "linker.lf" "app.lf") add_subdirectory(port) diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index c7e7537a597..0241bd3bb23 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -139,10 +139,6 @@ elseif(NOT BOOTLOADER_BUILD) list(APPEND srcs "sdmmc_hal.c") endif() - if(CONFIG_ETH_USE_ESP32_EMAC) - list(APPEND srcs "emac_hal.c") - endif() - if(CONFIG_SOC_ETM_SUPPORTED) list(APPEND srcs "etm_hal.c") endif() diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index 9e79e69f8c2..f4c470f4a1b 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -80,9 +80,6 @@ if(CONFIG_SOC_DEBUG_PROBE_SUPPORTED) list(APPEND srcs "${target_folder}/debug_probe_periph.c") endif() -if(CONFIG_SOC_EMAC_SUPPORTED) - list(APPEND srcs "${target_folder}/emac_periph.c") -endif() if(CONFIG_SOC_ETM_SUPPORTED) list(APPEND srcs "${target_folder}/etm_periph.c")