refactor(hal): graduate emac hal into a new component

- Separate emac from hal component to a new one: esp_hal_emac.
This commit is contained in:
glmfe
2025-11-12 06:46:38 -03:00
parent b1c7498580
commit 9fd020d9da
16 changed files with 85 additions and 25 deletions

View File

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

View File

@@ -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, dont 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

View File

@@ -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"

View File

@@ -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"

View File

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

View File

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

View File

@@ -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 */

View File

@@ -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 = {

View File

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

View File

@@ -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"

View File

@@ -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;

View File

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

View File

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

View File

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

View File

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