hal/emac_hal: refactord emac_hal

This commit is contained in:
laokaiyao 2021-05-07 17:38:36 +08:00
parent e7f3099541
commit fe354f1c50
10 changed files with 1307 additions and 997 deletions

View File

@ -15,6 +15,7 @@
#include "esp_err.h"
#include "esp_event_base.h"
#include "hal/eth_types.h"
#ifdef __cplusplus
extern "C" {
@ -38,12 +39,6 @@ extern "C" {
*/
#define ETH_HEADER_LEN (14)
/**
* @brief Ethernet frame CRC length
*
*/
#define ETH_CRC_LEN (4)
/**
* @brief Optional 802.1q VLAN Tag length
*
@ -96,33 +91,6 @@ typedef enum {
ETH_CMD_G_DUPLEX_MODE, /*!< Get Duplex mode */
} esp_eth_io_cmd_t;
/**
* @brief Ethernet link status
*
*/
typedef enum {
ETH_LINK_UP, /*!< Ethernet link is up */
ETH_LINK_DOWN /*!< Ethernet link is down */
} eth_link_t;
/**
* @brief Ethernet speed
*
*/
typedef enum {
ETH_SPEED_10M, /*!< Ethernet speed is 10Mbps */
ETH_SPEED_100M /*!< Ethernet speed is 100Mbps */
} eth_speed_t;
/**
* @brief Ethernet duplex mode
*
*/
typedef enum {
ETH_DUPLEX_HALF, /*!< Ethernet is in half duplex */
ETH_DUPLEX_FULL /*!< Ethernet is in full duplex */
} eth_duplex_t;
/**
* @brief Ethernet mediator
*

View File

@ -24,16 +24,19 @@
#include "esp_system.h"
#include "esp_heap_caps.h"
#include "esp_intr_alloc.h"
#include "esp_private/esp_clk.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "hal/cpu_hal.h"
#include "hal/emac.h"
#include "hal/emac_hal.h"
#include "hal/gpio_hal.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "sdkconfig.h"
#include "esp_rom_gpio.h"
#include "esp_rom_sys.h"
#include "hal/emac_ll.h"
static const char *TAG = "esp.emac";
@ -80,15 +83,15 @@ static esp_err_t emac_esp32_write_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr,
{
esp_err_t ret = ESP_OK;
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
ESP_GOTO_ON_FALSE(!emac_hal_is_mii_busy(&emac->hal), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
emac_hal_set_phy_data(&emac->hal, reg_value);
ESP_GOTO_ON_FALSE(!emac_ll_is_mii_busy(emac->hal.mac_regs), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
emac_ll_set_phy_data(emac->hal.mac_regs, reg_value);
emac_hal_set_phy_cmd(&emac->hal, phy_addr, phy_reg, true);
/* polling the busy flag */
uint32_t to = 0;
bool busy = true;
do {
esp_rom_delay_us(100);
busy = emac_hal_is_mii_busy(&emac->hal);
busy = emac_ll_is_mii_busy(emac->hal.mac_regs);
to += 100;
} while (busy && to < PHY_OPERATION_TIMEOUT_US);
ESP_GOTO_ON_FALSE(!busy, ESP_ERR_TIMEOUT, err, TAG, "phy is busy");
@ -102,19 +105,19 @@ static esp_err_t emac_esp32_read_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr,
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_FALSE(reg_value, ESP_ERR_INVALID_ARG, err, TAG, "can't set reg_value to null");
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
ESP_GOTO_ON_FALSE(!emac_hal_is_mii_busy(&emac->hal), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
ESP_GOTO_ON_FALSE(!emac_ll_is_mii_busy(emac->hal.mac_regs), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
emac_hal_set_phy_cmd(&emac->hal, phy_addr, phy_reg, false);
/* polling the busy flag */
uint32_t to = 0;
bool busy = true;
do {
esp_rom_delay_us(100);
busy = emac_hal_is_mii_busy(&emac->hal);
busy = emac_ll_is_mii_busy(emac->hal.mac_regs);
to += 100;
} while (busy && to < PHY_OPERATION_TIMEOUT_US);
ESP_GOTO_ON_FALSE(!busy, ESP_ERR_TIMEOUT, err, TAG, "phy is busy");
/* Store value */
*reg_value = emac_hal_get_phy_data(&emac->hal);
*reg_value = emac_ll_get_phy_data(emac->hal.mac_regs);
return ESP_OK;
err:
return ret;
@ -167,52 +170,32 @@ err:
static esp_err_t emac_esp32_set_speed(esp_eth_mac_t *mac, eth_speed_t speed)
{
esp_err_t ret = ESP_OK;
esp_err_t ret = ESP_ERR_INVALID_ARG;
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
switch (speed) {
case ETH_SPEED_10M:
emac_hal_set_speed(&emac->hal, EMAC_SPEED_10M);
ESP_LOGD(TAG, "working in 10Mbps");
break;
case ETH_SPEED_100M:
emac_hal_set_speed(&emac->hal, EMAC_SPEED_100M);
ESP_LOGD(TAG, "working in 100Mbps");
break;
default:
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown speed");
break;
if (speed >= ETH_SPEED_10M && speed < ETH_SPEED_MAX) {
emac_ll_set_port_speed(emac->hal.mac_regs, speed);
ESP_LOGD(TAG, "working in %dMbps", speed == ETH_SPEED_10M ? 10 : 100);
return ESP_OK;
}
return ESP_OK;
err:
return ret;
}
static esp_err_t emac_esp32_set_duplex(esp_eth_mac_t *mac, eth_duplex_t duplex)
{
esp_err_t ret = ESP_OK;
esp_err_t ret = ESP_ERR_INVALID_ARG;
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
switch (duplex) {
case ETH_DUPLEX_HALF:
emac_hal_set_duplex(&emac->hal, EMAC_DUPLEX_HALF);
ESP_LOGD(TAG, "working in half duplex");
break;
case ETH_DUPLEX_FULL:
emac_hal_set_duplex(&emac->hal, EMAC_DUPLEX_FULL);
ESP_LOGD(TAG, "working in full duplex");
break;
default:
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown duplex");
break;
if (duplex == ETH_DUPLEX_HALF || duplex == ETH_DUPLEX_FULL) {
emac_ll_set_duplex(emac->hal.mac_regs, duplex);
ESP_LOGD(TAG, "working in %s duplex", duplex == ETH_DUPLEX_HALF ? "half" : "full");
return ESP_OK;
}
return ESP_OK;
err:
return ret;
}
static esp_err_t emac_esp32_set_promiscuous(esp_eth_mac_t *mac, bool enable)
{
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
emac_hal_set_promiscuous(&emac->hal, enable);
emac_ll_promiscuous_mode_enable(emac->hal.mac_regs, enable);
return ESP_OK;
}
@ -293,9 +276,9 @@ static void emac_esp32_rx_task(void *arg)
#if CONFIG_ETH_SOFT_FLOW_CONTROL
// we need to do extra checking of remained frames in case there are no unhandled frames left, but pause frame is still undergoing
if ((emac->free_rx_descriptor < emac->flow_control_low_water_mark) && emac->do_flow_ctrl && emac->frames_remain) {
emac_hal_send_pause_frame(&emac->hal, true);
emac_ll_pause_frame_enable(emac->hal.ext_regs, true);
} else if ((emac->free_rx_descriptor > emac->flow_control_high_water_mark) || !emac->frames_remain) {
emac_hal_send_pause_frame(&emac->hal, false);
emac_ll_pause_frame_enable(emac->hal.ext_regs, false);
}
#endif
} while (emac->frames_remain);
@ -320,30 +303,93 @@ static void emac_esp32_init_smi_gpio(emac_esp32_t *emac)
}
}
#if CONFIG_ETH_RMII_CLK_OUTPUT
static void emac_config_apll_clock(void)
{
/* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) */
rtc_xtal_freq_t rtc_xtal_freq = rtc_clk_xtal_freq_get();
switch (rtc_xtal_freq) {
case RTC_XTAL_FREQ_40M: // Recommended
/* 50 MHz = 40MHz * (4 + 6) / (2 * (2 + 2) = 50.000 */
/* sdm0 = 0, sdm1 = 0, sdm2 = 6, o_div = 2 */
rtc_clk_apll_enable(true, 0, 0, 6, 2);
break;
case RTC_XTAL_FREQ_26M:
/* 50 MHz = 26MHz * (4 + 15 + 118 / 256 + 39/65536) / ((3 + 2) * 2) = 49.999992 */
/* sdm0 = 39, sdm1 = 118, sdm2 = 15, o_div = 3 */
rtc_clk_apll_enable(true, 39, 118, 15, 3);
break;
case RTC_XTAL_FREQ_24M:
/* 50 MHz = 24MHz * (4 + 12 + 255 / 256 + 255/65536) / ((2 + 2) * 2) = 49.499977 */
/* sdm0 = 255, sdm1 = 255, sdm2 = 12, o_div = 2 */
rtc_clk_apll_enable(true, 255, 255, 12, 2);
break;
default: // Assume we have a 40M xtal
rtc_clk_apll_enable(true, 0, 0, 6, 2);
break;
}
}
#endif
static esp_err_t emac_esp32_init(esp_eth_mac_t *mac)
{
esp_err_t ret = ESP_OK;
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
esp_eth_mediator_t *eth = emac->eth;
/* enable peripheral clock */
/* enable APB to access Ethernet peripheral registers */
periph_module_enable(PERIPH_EMAC_MODULE);
/* init clock, config gpio, etc */
emac_hal_lowlevel_init(&emac->hal);
#if CONFIG_ETH_PHY_INTERFACE_MII
/* MII interface GPIO initialization */
emac_hal_iomux_init_mii();
/* Enable MII clock */
emac_ll_clock_enable_mii(emac->hal.ext_regs);
#elif CONFIG_ETH_PHY_INTERFACE_RMII
/* RMII interface GPIO initialization */
emac_hal_iomux_init_rmii();
/* If ref_clk is configured as input */
#if CONFIG_ETH_RMII_CLK_INPUT
#if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
emac_hal_iomux_rmii_clk_input();
#else
#error "ESP32 EMAC only support input RMII clock to GPIO0"
#endif // CONFIG_ETH_RMII_CLK_IN_GPIO == 0
emac_ll_clock_enable_rmii_input(emac->hal.ext_regs);
#endif // CONFIG_ETH_RMII_CLK_INPUT
/* If ref_clk is configured as output */
#if CONFIG_ETH_RMII_CLK_OUTPUT
#if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
emac_hal_iomux_rmii_clk_ouput(0);
/* Choose the APLL clock1 to output on specific GPIO */
REG_SET_FIELD(PIN_CTRL, CLK_OUT1, 6);
#elif CONFIG_ETH_RMII_CLK_OUT_GPIO == 16
emac_hal_iomux_rmii_clk_ouput(16);
#elif CONFIG_ETH_RMII_CLK_OUT_GPIO == 17
emac_hal_iomux_rmii_clk_ouput(17);
#endif // CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
/* Enable RMII clock */
emac_ll_clock_enable_rmii_output(emac->hal.ext_regs);
emac_config_apll_clock();
#endif // CONFIG_ETH_RMII_CLK_OUTPUT
#endif // CONFIG_ETH_PHY_INTERFACE_MII
/* init gpio used by smi interface */
emac_esp32_init_smi_gpio(emac);
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL), err, TAG, "lowlevel init failed");
/* software reset */
emac_hal_reset(&emac->hal);
emac_ll_reset(emac->hal.dma_regs);
uint32_t to = 0;
for (to = 0; to < emac->sw_reset_timeout_ms / 10; to++) {
if (emac_hal_is_reset_done(&emac->hal)) {
if (emac_ll_is_reset_done(emac->hal.dma_regs)) {
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
ESP_GOTO_ON_FALSE(to < emac->sw_reset_timeout_ms / 10, ESP_ERR_TIMEOUT, err, TAG, "reset timeout");
/* set smi clock */
emac_hal_set_csr_clock_range(&emac->hal);
emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq());
/* reset descriptor chain */
emac_hal_reset_desc_chain(&emac->hal);
/* init mac registers by default */
@ -414,15 +460,23 @@ static esp_err_t emac_esp32_del(esp_eth_mac_t *mac)
}
// To achieve a better performance, we put the ISR always in IRAM
IRAM_ATTR void emac_esp32_isr_handler(void *args)
IRAM_ATTR void emac_isr_default_handler(void *args)
{
emac_hal_context_t *hal = (emac_hal_context_t *)args;
emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal);
emac_hal_isr(args);
if (emac->isr_need_yield) {
emac->isr_need_yield = false;
portYIELD_FROM_ISR();
BaseType_t high_task_wakeup = pdFALSE;
uint32_t intr_stat = emac_ll_get_intr_status(hal->dma_regs);
emac_ll_clear_corresponding_intr(hal->dma_regs, intr_stat);
#if EMAC_LL_CONFIG_ENABLE_INTR_MASK & EMAC_LL_INTR_RECEIVE_ENABLE
if (intr_stat & EMAC_LL_DMA_RECEIVE_FINISH_INTR) {
/* notify receive task */
vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
if (high_task_wakeup == pdTRUE) {
portYIELD_FROM_ISR();
}
}
#endif
}
esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config)
@ -485,10 +539,10 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config)
/* Interrupt configuration */
if (config->flags & ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE) {
ret_code = esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, ESP_INTR_FLAG_IRAM,
emac_esp32_isr_handler, &emac->hal, &(emac->intr_hdl));
emac_isr_default_handler, &emac->hal, &(emac->intr_hdl));
} else {
ret_code = esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0,
emac_esp32_isr_handler, &emac->hal, &(emac->intr_hdl));
emac_isr_default_handler, &emac->hal, &(emac->intr_hdl));
}
ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "alloc emac interrupt failed");
#ifdef CONFIG_PM_ENABLE
@ -530,39 +584,3 @@ err:
}
return ret;
}
IRAM_ATTR void emac_hal_rx_complete_cb(void *arg)
{
emac_hal_context_t *hal = (emac_hal_context_t *)arg;
emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal);
BaseType_t high_task_wakeup;
/* notify receive task */
vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
if (high_task_wakeup == pdTRUE) {
emac->isr_need_yield = true;
}
}
IRAM_ATTR void emac_hal_rx_unavail_cb(void *arg)
{
emac_hal_context_t *hal = (emac_hal_context_t *)arg;
emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal);
BaseType_t high_task_wakeup;
/* notify receive task */
vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
if (high_task_wakeup == pdTRUE) {
emac->isr_need_yield = true;
}
}
IRAM_ATTR void emac_hal_rx_early_cb(void *arg)
{
emac_hal_context_t *hal = (emac_hal_context_t *)arg;
emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal);
BaseType_t high_task_wakeup;
/* notify receive task */
vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
if (high_task_wakeup == pdTRUE) {
emac->isr_need_yield = true;
}
}

View File

@ -47,7 +47,7 @@ if(NOT BOOTLOADER_BUILD)
"esp32/touch_sensor_hal.c"
"esp32/gpio_hal_workaround.c")
if(NOT BOOTLOADER_BUILD AND CONFIG_ETH_USE_ESP32_EMAC)
list(APPEND srcs "esp32/emac_hal.c")
list(APPEND srcs "emac_hal.c")
endif()
endif()

View File

@ -5,9 +5,9 @@ COMPONENT_ADD_LDFRAGMENTS += linker.lf
COMPONENT_OBJEXCLUDE += ./spi_slave_hd_hal.o ./spi_flash_hal_gpspi.o ./spi_slave_hd_hal.o ./ds_hal.o ./gdma_hal.o ./lcd_hal.o ./systimer_hal.o ./usb_hal.o ./usbh_hal.o
ifndef CONFIG_ETH_USE_ESP32_EMAC
COMPONENT_OBJEXCLUDE += esp32/emac_hal.o
COMPONENT_OBJEXCLUDE += ./emac_hal.o
endif
ifdef IS_BOOTLOADER_BUILD
COMPONENT_OBJEXCLUDE += esp32/emac_hal.o
COMPONENT_OBJEXCLUDE += ./emac_hal.o
endif

514
components/hal/emac_hal.c Normal file
View File

@ -0,0 +1,514 @@
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#include <string.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "hal/emac_hal.h"
#include "hal/emac_ll.h"
#include "hal/gpio_ll.h"
#define ETH_CRC_LENGTH (4)
void emac_hal_iomux_init_mii(void)
{
/* TX_CLK to GPIO0 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
/* TX_EN to GPIO21 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
/* TXD0 to GPIO19 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
/* TXD1 to GPIO22 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
/* TXD2 to MTMS */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTMS_U, FUNC_MTMS_EMAC_TXD2);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[14]);
/* TXD3 to MTDI */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTDI_U, FUNC_MTDI_EMAC_TXD3);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[12]);
/* RX_CLK to GPIO5 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5_EMAC_RX_CLK);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[5]);
/* RX_DV to GPIO27 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
/* RXD0 to GPIO25 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
/* RXD1 to GPIO26 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
/* RXD2 to U0TXD */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_EMAC_RXD2);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[1]);
/* RXD3 to MTDO */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTDO_U, FUNC_MTDO_EMAC_RXD3);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[15]);
}
void emac_hal_iomux_rmii_clk_input(void)
{
/* REF_CLK(RMII mode) to GPIO0 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
}
void emac_hal_iomux_rmii_clk_ouput(int num)
{
switch (num) {
case 0:
/* APLL clock output to GPIO0 (must be configured to 50MHz!) */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[0]);
break;
case 16:
/* RMII CLK (50MHz) output to GPIO16 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[16]);
break;
case 17:
/* RMII CLK (50MHz) output to GPIO17 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[17]);
break;
default:
break;
}
}
void emac_hal_iomux_init_rmii(void)
{
/* TX_EN to GPIO21 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
/* TXD0 to GPIO19 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
/* TXD1 to GPIO22 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
/* CRS_DV to GPIO27 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
/* RXD0 to GPIO25 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
/* RXD1 to GPIO26 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
}
void emac_hal_iomux_init_tx_er(void)
{
/* TX_ER to GPIO4 */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4_EMAC_TX_ER);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[4]);
}
void emac_hal_iomux_init_rx_er(void)
{
/* RX_ER to MTCK */
gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTCK_U, FUNC_MTCK_EMAC_RX_ER);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[13]);
}
void emac_hal_init(emac_hal_context_t *hal, void *descriptors,
uint8_t **rx_buf, uint8_t **tx_buf)
{
hal->dma_regs = &EMAC_DMA;
hal->mac_regs = &EMAC_MAC;
hal->ext_regs = &EMAC_EXT;
hal->descriptors = descriptors;
hal->rx_buf = rx_buf;
hal->tx_buf = tx_buf;
}
void emac_hal_set_csr_clock_range(emac_hal_context_t *hal, int freq)
{
/* Tell MAC system clock Frequency, which will determine the frequency range of MDC(1MHz~2.5MHz) */
if (freq >= 20 && freq < 35) {
emac_ll_set_csr_clock_division(hal->mac_regs, 2); // CSR clock/16
} else if (freq >= 35 && freq < 60) {
emac_ll_set_csr_clock_division(hal->mac_regs, 3); // CSR clock/26
} else if (freq >= 60 && freq < 100) {
emac_ll_set_csr_clock_division(hal->mac_regs, 0); // CSR clock/42
} else if (freq >= 100 && freq < 150) {
emac_ll_set_csr_clock_division(hal->mac_regs, 1); // CSR clock/62
} else if (freq > 150 && freq < 250) {
emac_ll_set_csr_clock_division(hal->mac_regs, 4); // CSR clock/102
} else {
emac_ll_set_csr_clock_division(hal->mac_regs, 5); // CSR clock/124
}
}
void emac_hal_reset_desc_chain(emac_hal_context_t *hal)
{
/* reset DMA descriptors */
hal->rx_desc = (eth_dma_rx_descriptor_t *)(hal->descriptors);
hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->descriptors +
sizeof(eth_dma_rx_descriptor_t) * CONFIG_ETH_DMA_RX_BUFFER_NUM);
/* init rx chain */
for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
/* Set Own bit of the Rx descriptor Status: DMA */
hal->rx_desc[i].RDES0.Own = 1;
/* Set Buffer1 size and Second Address Chained bit */
hal->rx_desc[i].RDES1.SecondAddressChained = 1;
hal->rx_desc[i].RDES1.ReceiveBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
/* Enable Ethernet DMA Rx Descriptor interrupt */
hal->rx_desc[i].RDES1.DisableInterruptOnComplete = 0;
/* point to the buffer */
hal->rx_desc[i].Buffer1Addr = (uint32_t)(hal->rx_buf[i]);
/* point to next descriptor */
hal->rx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc + i + 1);
}
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
hal->rx_desc[CONFIG_ETH_DMA_RX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc);
/* init tx chain */
for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
/* Set Second Address Chained bit */
hal->tx_desc[i].TDES0.SecondAddressChained = 1;
hal->tx_desc[i].TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
/* Enable Ethernet DMA Tx Descriptor interrupt */
hal->tx_desc[1].TDES0.InterruptOnComplete = 1;
/* Enable Transmit Timestamp */
hal->tx_desc[i].TDES0.TransmitTimestampEnable = 1;
/* point to the buffer */
hal->tx_desc[i].Buffer1Addr = (uint32_t)(hal->tx_buf[i]);
/* point to next descriptor */
hal->tx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc + i + 1);
}
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
hal->tx_desc[CONFIG_ETH_DMA_TX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc);
/* set base address of the first descriptor */
emac_ll_set_rx_desc_addr(hal->dma_regs, (uint32_t)hal->rx_desc);
emac_ll_set_tx_desc_addr(hal->dma_regs, (uint32_t)hal->tx_desc);
}
void emac_hal_init_mac_default(emac_hal_context_t *hal)
{
/* MACCR Configuration */
/* Enable the watchdog on the receiver, frame longer than 2048 Bytes is not allowed */
emac_ll_watchdog_enable(hal->mac_regs, true);
/* Enable the jabber timer on the transmitter, frame longer than 2048 Bytes is not allowed */
emac_ll_jabber_enable(hal->mac_regs, true);
/* minimum IFG between frames during transmission is 96 bit times */
emac_ll_set_inter_frame_gap(hal->mac_regs, EMAC_LL_INTERFRAME_GAP_96BIT);
/* Enable Carrier Sense During Transmission */
emac_ll_carrier_sense_enable(hal->mac_regs, true);
/* Select speed: port: 10/100 Mbps, here set default 100M, afterwards, will reset by auto-negotiation */
emac_ll_set_port_speed(hal->mac_regs, ETH_SPEED_100M);;
/* Allow the reception of frames when the TX_EN signal is asserted in Half-Duplex mode */
emac_ll_recv_own_enable(hal->mac_regs, true);
/* Disable internal loopback mode */
emac_ll_loopback_enable(hal->mac_regs, false);
/* Select duplex mode: here set default full duplex, afterwards, will reset by auto-negotiation */
emac_ll_set_duplex(hal->mac_regs, ETH_DUPLEX_FULL);
/* Select the checksum mode for received frame payload's TCP/UDP/ICMP headers */
emac_ll_checksum_offload_mode(hal->mac_regs, ETH_CHECKSUM_HW);
/* Enable MAC retry transmission when a colision occurs in half duplex mode */
emac_ll_retry_enable(hal->mac_regs, true);
/* MAC passes all incoming frames to host, without modifying them */
emac_ll_auto_pad_crc_strip_enable(hal->mac_regs, false);
/* Set Back-Off limit time before retry a transmittion after a collision */
emac_ll_set_back_off_limit(hal->mac_regs, EMAC_LL_BACKOFF_LIMIT_10);
/* Disable deferral check, MAC defers until the CRS signal goes inactive */
emac_ll_deferral_check_enable(hal->mac_regs, false);
/* Set preamble length 7 Bytes */
emac_ll_set_preamble_length(hal->mac_regs, EMAC_LL_PREAMBLE_LENGTH_7);
/* MACFFR Configuration */
/* Receiver module passes only those frames to the Application that pass the SA or DA address filter */
emac_ll_receive_all_enable(hal->mac_regs, false);
/* Disable source address filter */
emac_ll_set_src_addr_filter(hal->mac_regs, EMAC_LL_SOURCE_ADDR_FILTER_DISABLE);
emac_ll_sa_inverse_filter_enable(hal->mac_regs, false);
/* MAC blocks all control frames */
emac_ll_set_pass_ctrl_frame_mode(hal->mac_regs, EMAC_LL_CONTROL_FRAME_BLOCKALL);
/* AFM module passes all received broadcast frames and multicast frames */
emac_ll_broadcast_frame_enable(hal->mac_regs, true);
emac_ll_pass_all_multicast_enable(hal->mac_regs, true);
/* Address Check block operates in normal filtering mode for the DA address */
emac_ll_da_inverse_filter_enable(hal->mac_regs, false);
/* Disable Promiscuous Mode */
emac_ll_promiscuous_mode_enable(hal->mac_regs, false);
}
void emac_hal_enable_flow_ctrl(emac_hal_context_t *hal, bool enable)
{
/* MACFCR Configuration */
if (enable) {
/* Pause time */
emac_ll_set_pause_time(hal->mac_regs, EMAC_LL_PAUSE_TIME);
/* Enable generation of Zero-Quanta Pause Control frames */
emac_ll_zero_quanta_pause_enable(hal->mac_regs, true);
/* Threshold of the PAUSE to be checked for automatic retransmission of PAUSE Frame */
emac_ll_set_pause_low_threshold(hal->mac_regs, EMAC_LL_PAUSE_LOW_THRESHOLD_MINUS_28);
/* Don't allow MAC detect Pause frames with MAC address0 unicast address and unique multicast address */
emac_ll_unicast_pause_frame_detect_enable(hal->mac_regs, false);
/* Enable MAC to decode the received Pause frame and disable its transmitter for a specific time */
emac_ll_receive_flow_ctrl_enable(hal->mac_regs, true);
/* Enable MAC to transmit Pause frames in full duplex mode or the MAC back-pressure operation in half duplex mode */
emac_ll_transmit_flow_ctrl_enable(hal->mac_regs, true);
} else {
emac_ll_clear(hal->mac_regs);
}
}
void emac_hal_init_dma_default(emac_hal_context_t *hal)
{
/* DMAOMR Configuration */
/* Enable Dropping of TCP/IP Checksum Error Frames */
emac_ll_drop_tcp_err_frame_enable(hal->dma_regs, true);
/* Enable Receive Store Forward */
emac_ll_recv_store_forward_enable(hal->dma_regs, true);
/* Enable Flushing of Received Frames because of the unavailability of receive descriptors or buffers */
emac_ll_flush_recv_frame_enable(hal->dma_regs, true);
/* Enable Transmit Store Forward */
emac_ll_trans_store_forward_enable(hal->dma_regs, true);
/* Flush Transmit FIFO */
emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
/* Transmit Threshold Control */
emac_ll_set_transmit_threshold(hal->dma_regs, EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_64);
/* Disable Forward Error Frame */
emac_ll_forward_err_frame_enable(hal->dma_regs, false);
/* Disable forward undersized good frame */
emac_ll_forward_undersized_good_frame_enable(hal->dma_regs, false);
/* Receive Threshold Control */
emac_ll_set_recv_threshold(hal->dma_regs, EMAC_LL_RECEIVE_THRESHOLD_CONTROL_64);
/* Allow the DMA to process a second frame of Transmit data even before obtaining the status for the first frame */
emac_ll_opt_second_frame_enable(hal->dma_regs, true);;
/* DMABMR Configuration */
/* Enable Mixed Burst */
emac_ll_mixed_burst_enable(hal->dma_regs, true);
/* Enable Address Aligned Beates */
emac_ll_addr_align_enable(hal->dma_regs, true);
/* Use Separate PBL */
emac_ll_use_separate_pbl_enable(hal->dma_regs, true);
/* Set Rx/Tx DMA Burst Length */
emac_ll_set_rx_dma_pbl(hal->dma_regs, EMAC_LL_DMA_BURST_LENGTH_32BEAT);
emac_ll_set_prog_burst_len(hal->dma_regs, EMAC_LL_DMA_BURST_LENGTH_32BEAT);
/* Enable Enhanced Descriptor,8 Words(32 Bytes) */
emac_ll_enhance_desc_enable(hal->dma_regs, true);
/* Specifies the number of word to skip between two unchained descriptors (Ring mode) */
emac_ll_set_desc_skip_len(hal->dma_regs, 0);
/* DMA Arbitration Scheme */
emac_ll_fixed_arbitration_enable(hal->dma_regs, false);
/* Set priority ratio in the weighted round-robin arbitration between Rx DMA and Tx DMA */
emac_ll_set_priority_ratio(hal->dma_regs, EMAC_LL_DMA_ARBITRATION_ROUNDROBIN_RXTX_1_1);
}
void emac_hal_set_phy_cmd(emac_hal_context_t *hal, uint32_t phy_addr, uint32_t phy_reg, bool write)
{
/* Write the result value into the MII Address register */
emac_ll_set_phy_addr(hal->mac_regs, phy_addr);
/* Set the PHY register address */
emac_ll_set_phy_reg(hal->mac_regs, phy_reg);
/* Set as write mode */
emac_ll_write_enable(hal->mac_regs, write);
/* Set MII busy bit */
emac_ll_set_busy(hal->mac_regs, true);
}
void emac_hal_set_address(emac_hal_context_t *hal, uint8_t *mac_addr)
{
/* Make sure mac address is unicast type */
if (!(mac_addr[0] & 0x01)) {
emac_ll_set_addr(hal->mac_regs, mac_addr);
}
}
void emac_hal_start(emac_hal_context_t *hal)
{
/* Enable Ethernet MAC and DMA Interrupt */
emac_ll_enable_corresponding_intr(hal->dma_regs, EMAC_LL_CONFIG_ENABLE_INTR_MASK);
/* Enable transmit state machine of the MAC for transmission on the MII */
emac_ll_transmit_enable(hal->mac_regs, true);
/* Enable receive state machine of the MAC for reception from the MII */
emac_ll_receive_enable(hal->mac_regs, true);
/* Flush Transmit FIFO */
emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
/* Start DMA transmission */
emac_ll_start_stop_dma_transmit(hal->dma_regs, true);
/* Start DMA reception */
emac_ll_start_stop_dma_receive(hal->dma_regs, true);
/* Clear all pending interrupts */
emac_ll_clear_all_pending_intr(hal->dma_regs);
}
void emac_hal_stop(emac_hal_context_t *hal)
{
/* Flush Transmit FIFO */
emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
/* Stop DMA transmission */
emac_ll_start_stop_dma_transmit(hal->dma_regs, false);
/* Stop DMA reception */
emac_ll_start_stop_dma_receive(hal->dma_regs, false);
/* Disable receive state machine of the MAC for reception from the MII */
emac_ll_transmit_enable(hal->mac_regs, false);
/* Disable transmit state machine of the MAC for transmission on the MII */
emac_ll_receive_enable(hal->mac_regs, false);
/* Disable Ethernet MAC and DMA Interrupt */
emac_ll_disable_all_intr(hal->dma_regs);
}
uint32_t emac_hal_get_tx_desc_owner(emac_hal_context_t *hal)
{
return hal->tx_desc->TDES0.Own;
}
uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length)
{
/* Get the number of Tx buffers to use for the frame */
uint32_t bufcount = 0;
uint32_t lastlen = length;
uint32_t sentout = 0;
while (lastlen > CONFIG_ETH_DMA_BUFFER_SIZE) {
lastlen -= CONFIG_ETH_DMA_BUFFER_SIZE;
bufcount++;
}
if (lastlen) {
bufcount++;
}
if (bufcount > CONFIG_ETH_DMA_TX_BUFFER_NUM) {
goto err;
}
eth_dma_tx_descriptor_t *desc_iter = hal->tx_desc;
/* A frame is transmitted in multiple descriptor */
for (size_t i = 0; i < bufcount; i++) {
/* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
if (desc_iter->TDES0.Own != EMAC_LL_DMADESC_OWNER_CPU) {
goto err;
}
/* Clear FIRST and LAST segment bits */
desc_iter->TDES0.FirstSegment = 0;
desc_iter->TDES0.LastSegment = 0;
desc_iter->TDES0.InterruptOnComplete = 0;
if (i == 0) {
/* Setting the first segment bit */
desc_iter->TDES0.FirstSegment = 1;
}
if (i == (bufcount - 1)) {
/* Setting the last segment bit */
desc_iter->TDES0.LastSegment = 1;
/* Enable transmit interrupt */
desc_iter->TDES0.InterruptOnComplete = 1;
/* Program size */
desc_iter->TDES1.TransmitBuffer1Size = lastlen;
/* copy data from uplayer stack buffer */
memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen);
sentout += lastlen;
} else {
/* Program size */
desc_iter->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
/* copy data from uplayer stack buffer */
memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE);
sentout += CONFIG_ETH_DMA_BUFFER_SIZE;
}
/* Point to next descriptor */
desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
for (size_t i = 0; i < bufcount; i++) {
hal->tx_desc->TDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
}
emac_ll_transmit_poll_demand(hal->dma_regs, 0);
return sentout;
err:
return 0;
}
uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain, uint32_t *free_desc)
{
eth_dma_rx_descriptor_t *desc_iter = NULL;
eth_dma_rx_descriptor_t *first_desc = NULL;
uint32_t used_descs = 0;
uint32_t seg_count = 0;
uint32_t ret_len = 0;
uint32_t copy_len = 0;
uint32_t write_len = 0;
uint32_t frame_count = 0;
first_desc = hal->rx_desc;
desc_iter = hal->rx_desc;
/* Traverse descriptors owned by CPU */
while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM) && !frame_count) {
used_descs++;
seg_count++;
/* Last segment in frame */
if (desc_iter->RDES0.LastDescriptor) {
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
/* packets larger than expected will be truncated */
copy_len = ret_len > size ? size : ret_len;
/* update unhandled frame count */
frame_count++;
}
/* First segment in frame */
if (desc_iter->RDES0.FirstDescriptor) {
first_desc = desc_iter;
}
/* point to next descriptor */
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
/* there's at least one frame to process */
if (frame_count) {
/* check how many frames left to handle */
while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
used_descs++;
if (desc_iter->RDES0.LastDescriptor) {
frame_count++;
}
/* point to next descriptor */
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
desc_iter = first_desc;
for (size_t i = 0; i < seg_count - 1; i++) {
used_descs--;
write_len = copy_len < CONFIG_ETH_DMA_BUFFER_SIZE ? copy_len : CONFIG_ETH_DMA_BUFFER_SIZE;
/* copy data to buffer */
memcpy(buf, (void *)(desc_iter->Buffer1Addr), write_len);
buf += write_len;
copy_len -= write_len;
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
memcpy(buf, (void *)(desc_iter->Buffer1Addr), copy_len);
desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
/* update rxdesc */
hal->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
/* poll rx demand */
emac_ll_receive_poll_demand(hal->dma_regs, 0);
frame_count--;
used_descs--;
}
*frames_remain = frame_count;
*free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
return ret_len;
}

View File

@ -1,687 +0,0 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#include <string.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "soc/gpio_periph.h"
#include "soc/rtc.h"
#include "hal/emac.h"
#include "hal/gpio_hal.h"
#define ETH_CRC_LENGTH (4)
#if CONFIG_ETH_RMII_CLK_OUTPUT
static void emac_config_apll_clock(void)
{
/* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) */
rtc_xtal_freq_t rtc_xtal_freq = rtc_clk_xtal_freq_get();
switch (rtc_xtal_freq) {
case RTC_XTAL_FREQ_40M: // Recommended
/* 50 MHz = 40MHz * (4 + 6) / (2 * (2 + 2) = 50.000 */
/* sdm0 = 0, sdm1 = 0, sdm2 = 6, o_div = 2 */
rtc_clk_apll_enable(true, 0, 0, 6, 2);
break;
case RTC_XTAL_FREQ_26M:
/* 50 MHz = 26MHz * (4 + 15 + 118 / 256 + 39/65536) / ((3 + 2) * 2) = 49.999992 */
/* sdm0 = 39, sdm1 = 118, sdm2 = 15, o_div = 3 */
rtc_clk_apll_enable(true, 39, 118, 15, 3);
break;
case RTC_XTAL_FREQ_24M:
/* 50 MHz = 24MHz * (4 + 12 + 255 / 256 + 255/65536) / ((2 + 2) * 2) = 49.499977 */
/* sdm0 = 255, sdm1 = 255, sdm2 = 12, o_div = 2 */
rtc_clk_apll_enable(true, 255, 255, 12, 2);
break;
default: // Assume we have a 40M xtal
rtc_clk_apll_enable(true, 0, 0, 6, 2);
break;
}
}
#endif
void emac_hal_init(emac_hal_context_t *hal, void *descriptors,
uint8_t **rx_buf, uint8_t **tx_buf)
{
hal->dma_regs = &EMAC_DMA;
hal->mac_regs = &EMAC_MAC;
hal->ext_regs = &EMAC_EXT;
hal->descriptors = descriptors;
hal->rx_buf = rx_buf;
hal->tx_buf = tx_buf;
}
void emac_hal_lowlevel_init(emac_hal_context_t *hal)
{
/* GPIO configuration */
/* TX_EN to GPIO21 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
/* TXD0 to GPIO19 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
/* TXD1 to GPIO22 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
/* RXD0 to GPIO25 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
/* RXD1 to GPIO26 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
/* CRS_DV to GPIO27 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
#if CONFIG_ETH_RMII_CLK_INPUT
#if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
/* RMII clock (50MHz) input to GPIO0 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
#else
#error "ESP32 EMAC only support input RMII clock to GPIO0"
#endif
#endif
#if CONFIG_ETH_RMII_CLK_OUTPUT
#if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
/* APLL clock output to GPIO0 (must be configured to 50MHz!) */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[0]);
#elif CONFIG_ETH_RMII_CLK_OUT_GPIO == 16
/* RMII CLK (50MHz) output to GPIO16 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[16]);
#elif CONFIG_ETH_RMII_CLK_OUT_GPIO == 17
/* RMII CLK (50MHz) output to GPIO17 */
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[17]);
#endif
#endif // CONFIG_ETH_RMII_CLK_OUTPUT
/* Clock configuration */
#if CONFIG_ETH_PHY_INTERFACE_MII
hal->ext_regs->ex_phyinf_conf.phy_intf_sel = 0;
hal->ext_regs->ex_clk_ctrl.mii_clk_rx_en = 1;
hal->ext_regs->ex_clk_ctrl.mii_clk_tx_en = 1;
#elif CONFIG_ETH_PHY_INTERFACE_RMII
hal->ext_regs->ex_phyinf_conf.phy_intf_sel = 4;
#if CONFIG_ETH_RMII_CLK_INPUT
hal->ext_regs->ex_clk_ctrl.ext_en = 1;
hal->ext_regs->ex_clk_ctrl.int_en = 0;
hal->ext_regs->ex_oscclk_conf.clk_sel = 1;
#elif CONFIG_ETH_RMII_CLK_OUTPUT
hal->ext_regs->ex_clk_ctrl.ext_en = 0;
hal->ext_regs->ex_clk_ctrl.int_en = 1;
hal->ext_regs->ex_oscclk_conf.clk_sel = 0;
emac_config_apll_clock();
hal->ext_regs->ex_clkout_conf.div_num = 0;
hal->ext_regs->ex_clkout_conf.h_div_num = 0;
#if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
/* Choose the APLL clock to output on GPIO */
REG_WRITE(PIN_CTRL, 6);
#endif // CONFIG_RMII_CLK_OUTPUT_GPIO0
#endif // CONFIG_ETH_RMII_CLK_INPUT
#endif // CONFIG_ETH_PHY_INTERFACE_MII
}
void emac_hal_reset(emac_hal_context_t *hal)
{
hal->dma_regs->dmabusmode.sw_rst = 1;
}
bool emac_hal_is_reset_done(emac_hal_context_t *hal)
{
return hal->dma_regs->dmabusmode.sw_rst ? false : true;
}
void emac_hal_set_csr_clock_range(emac_hal_context_t *hal)
{
/* Tell MAC system clock Frequency, which will determin the frequency range of MDC(1MHz~2.5MHz) */
if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 20 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 35) {
hal->mac_regs->emacgmiiaddr.miicsrclk = 2;
} else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 35 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 60) {
hal->mac_regs->emacgmiiaddr.miicsrclk = 3;
} else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 60 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 100) {
hal->mac_regs->emacgmiiaddr.miicsrclk = 0;
} else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 100 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 150) {
hal->mac_regs->emacgmiiaddr.miicsrclk = 1;
} else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ > 150 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 250) {
hal->mac_regs->emacgmiiaddr.miicsrclk = 4;
} else {
hal->mac_regs->emacgmiiaddr.miicsrclk = 5;
}
}
void emac_hal_reset_desc_chain(emac_hal_context_t *hal)
{
/* reset DMA descriptors */
hal->rx_desc = (eth_dma_rx_descriptor_t *)(hal->descriptors);
hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->descriptors +
sizeof(eth_dma_rx_descriptor_t) * CONFIG_ETH_DMA_RX_BUFFER_NUM);
/* init rx chain */
for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
/* Set Own bit of the Rx descriptor Status: DMA */
hal->rx_desc[i].RDES0.Own = 1;
/* Set Buffer1 size and Second Address Chained bit */
hal->rx_desc[i].RDES1.SecondAddressChained = 1;
hal->rx_desc[i].RDES1.ReceiveBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
/* Enable Ethernet DMA Rx Descriptor interrupt */
hal->rx_desc[i].RDES1.DisableInterruptOnComplete = 0;
/* point to the buffer */
hal->rx_desc[i].Buffer1Addr = (uint32_t)(hal->rx_buf[i]);
/* point to next descriptor */
hal->rx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc + i + 1);
}
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
hal->rx_desc[CONFIG_ETH_DMA_RX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc);
/* init tx chain */
for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
/* Set Second Address Chained bit */
hal->tx_desc[i].TDES0.SecondAddressChained = 1;
hal->tx_desc[i].TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
/* Enable Ethernet DMA Tx Descriptor interrupt */
hal->tx_desc[1].TDES0.InterruptOnComplete = 1;
/* Enable Transmit Timestamp */
hal->tx_desc[i].TDES0.TransmitTimestampEnable = 1;
/* point to the buffer */
hal->tx_desc[i].Buffer1Addr = (uint32_t)(hal->tx_buf[i]);
/* point to next descriptor */
hal->tx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc + i + 1);
}
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
hal->tx_desc[CONFIG_ETH_DMA_TX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc);
/* set base address of the first descriptor */
hal->dma_regs->dmarxbaseaddr = (uint32_t)hal->rx_desc;
hal->dma_regs->dmatxbaseaddr = (uint32_t)hal->tx_desc;
}
void emac_hal_init_mac_default(emac_hal_context_t *hal)
{
/* MACCR Configuration */
typeof(hal->mac_regs->gmacconfig) maccr = hal->mac_regs->gmacconfig;
/* Enable the watchdog on the receiver, frame longer than 2048 Bytes is not allowed */
maccr.watchdog = EMAC_WATCHDOG_ENABLE;
/* Enable the jabber timer on the transmitter, frame longer than 2048 Bytes is not allowed */
maccr.jabber = EMAC_JABBER_ENABLE;
/* minimum IFG between frames during transmission is 96 bit times */
maccr.interframegap = EMAC_INTERFRAME_GAP_96BIT;
/* Enable Carrier Sense During Transmission */
maccr.disablecrs = EMAC_CARRIERSENSE_ENABLE;
/* Select port: 10/100 Mbps */
maccr.mii = EMAC_PORT_10_100MBPS;
/* Select speed: here set default 100M, afterwards, will reset by auto-negotiation */
maccr.fespeed = EMAC_SPEED_100M;
/* Allow the reception of frames when the TX_EN signal is asserted in Half-Duplex mode */
maccr.rxown = EMAC_RECEIVE_OWN_ENABLE;
/* Disable internal loopback mode */
maccr.loopback = EMAC_LOOPBACK_DISABLE;
/* Select duplex mode: here set default full duplex, afterwards, will reset by auto-negotiation */
maccr.duplex = EMAC_DUPLEX_FULL;
/* Select the checksum mode for received frame payload's TCP/UDP/ICMP headers */
maccr.rxipcoffload = EMAC_CHECKSUM_HW;
/* Enable MAC retry transmission when a colision occurs in half duplex mode */
maccr.retry = EMAC_RETRY_TRANSMISSION_ENABLE;
/* MAC passes all incoming frames to host, without modifying them */
maccr.padcrcstrip = EMAC_AUTO_PAD_CRC_STRIP_DISABLE;
/* Set Back-Off limit time before retry a transmittion after a collision */
maccr.backofflimit = EMAC_BACKOFF_LIMIT_10;
/* Disable deferral check, MAC defers until the CRS signal goes inactive */
maccr.deferralcheck = EMAC_DEFERRAL_CHECK_DISABLE;
/* Set preamble length 7 Bytes */
maccr.pltf = EMAC_PREAMBLE_LENGTH_7;
hal->mac_regs->gmacconfig = maccr;
/* MACFFR Configuration */
typeof(hal->mac_regs->gmacff) macffr = hal->mac_regs->gmacff;
/* Receiver module passes only those frames to the Application that pass the SA or DA address filter */
macffr.receive_all = EMAC_RECEIVE_ALL_DISABLE;
/* Disable source address filter */
macffr.safe = EMAC_SOURCE_ADDR_FILTER_DISABLE;
macffr.saif = 0;
/* MAC blocks all control frames */
macffr.pcf = EMAC_CONTROL_FRAME_BLOCKALL;
/* AFM module passes all received broadcast frames and multicast frames */
macffr.dbf = EMAC_RECEPT_BROADCAST_ENABLE;
macffr.pam = 1;
/* Address Check block operates in normal filtering mode for the DA address */
macffr.daif = EMAC_DEST_ADDR_FILTER_NORMAL;
/* Disable Promiscuous Mode */
macffr.pmode = EMAC_PROMISCUOUS_DISABLE;
hal->mac_regs->gmacff = macffr;
}
void emac_hal_enable_flow_ctrl(emac_hal_context_t *hal, bool enable)
{
/* MACFCR Configuration */
typeof(hal->mac_regs->gmacfc) macfcr = hal->mac_regs->gmacfc;
if (enable) {
/* Pause time */
macfcr.pause_time = EMAC_PAUSE_TIME;
/* Enable generation of Zero-Quanta Pause Control frames */
macfcr.dzpq = EMAC_ZERO_QUANTA_PAUSE_ENABLE;
/* Threshold of the PAUSE to be checked for automatic retransmission of PAUSE Frame */
macfcr.plt = EMAC_PAUSE_LOW_THRESHOLD_MINUS_28;
/* Don't allow MAC detect Pause frames with MAC address0 unicast address and unique multicast address */
macfcr.upfd = EMAC_UNICAST_PAUSE_DETECT_DISABLE;
/* Enable MAC to decode the received Pause frame and disable its transmitter for a specific time */
macfcr.rfce = EMAC_RECEIVE_FLOW_CONTROL_ENABLE;
/* Enable MAC to transmit Pause frames in full duplex mode or the MAC back-pressure operation in half duplex mode */
macfcr.tfce = EMAC_TRANSMIT_FLOW_CONTROL_ENABLE;
} else {
macfcr.val = 0;
}
hal->mac_regs->gmacfc = macfcr;
}
void emac_hal_init_dma_default(emac_hal_context_t *hal)
{
/* DMAOMR Configuration */
typeof(hal->dma_regs->dmaoperation_mode) dmaomr = hal->dma_regs->dmaoperation_mode;
/* Enable Dropping of TCP/IP Checksum Error Frames */
dmaomr.dis_drop_tcpip_err_fram = EMAC_DROP_TCPIP_CHECKSUM_ERROR_ENABLE;
/* Enable Receive Store Forward */
dmaomr.rx_store_forward = EMAC_RECEIVE_STORE_FORWARD_ENABLE;
/* Enable Flushing of Received Frames because of the unavailability of receive descriptors or buffers */
dmaomr.dis_flush_recv_frames = EMAC_FLUSH_RECEIVED_FRAME_ENABLE;
/* Enable Transmit Store Forward */
dmaomr.tx_str_fwd = EMAC_TRANSMIT_STORE_FORWARD_ENABLE;
/* Flush Transmit FIFO */
dmaomr.flush_tx_fifo = 1;
/* Transmit Threshold Control */
dmaomr.tx_thresh_ctrl = EMAC_TRANSMIT_THRESHOLD_CONTROL_64;
/* Disable Forward Error Frame */
dmaomr.fwd_err_frame = EMAC_FORWARD_ERROR_FRAME_DISABLE;
/* Disable forward undersized good frame */
dmaomr.fwd_under_gf = EMAC_FORWARD_UNDERSIZED_GOOD_FRAME_DISABLE;
/* Receive Threshold Control */
dmaomr.rx_thresh_ctrl = EMAC_RECEIVE_THRESHOLD_CONTROL_64;
/* Allow the DMA to process a second frame of Transmit data even before obtaining the status for the first frame */
dmaomr.opt_second_frame = EMAC_OPERATE_SECOND_FRAME_ENABLE;
hal->dma_regs->dmaoperation_mode = dmaomr;
/* DMABMR Configuration */
typeof(hal->dma_regs->dmabusmode) dmabmr = hal->dma_regs->dmabusmode;
/* Enable Mixed Burst */
dmabmr.dmamixedburst = EMAC_MIXED_BURST_ENABLE;
/* Enable Address Aligned Beates */
dmabmr.dmaaddralibea = EMAC_ADDR_ALIGN_BEATS_ENABLE;
/* Use Separate PBL */
dmabmr.use_sep_pbl = EMAC_USE_SEPARATE_PBL;
/* Set Rx/Tx DMA Burst Length */
dmabmr.rx_dma_pbl = EMAC_DMA_BURST_LENGTH_32BEAT;
dmabmr.prog_burst_len = EMAC_DMA_BURST_LENGTH_32BEAT;
/* Enable Enhanced Descriptor,8 Words(32 Bytes) */
dmabmr.alt_desc_size = EMAC_ENHANCED_DESCRIPTOR_ENABLE;
/* Specifies the number of word to skip between two unchained descriptors (Ring mode) */
dmabmr.desc_skip_len = 0;
/* DMA Arbitration Scheme */
dmabmr.dma_arb_sch = EMAC_DMA_ARBITRATION_SCHEME_ROUNDROBIN;
/* Set priority ratio in the weighted round-robin arbitration between Rx DMA and Tx DMA */
dmabmr.pri_ratio = EMAC_DMA_ARBITRATION_ROUNDROBIN_RXTX_1_1;
hal->dma_regs->dmabusmode = dmabmr;
}
void emac_hal_set_speed(emac_hal_context_t *hal, uint32_t speed)
{
hal->mac_regs->gmacconfig.fespeed = speed;
}
void emac_hal_set_duplex(emac_hal_context_t *hal, uint32_t duplex)
{
hal->mac_regs->gmacconfig.duplex = duplex;
}
void emac_hal_set_promiscuous(emac_hal_context_t *hal, bool enable)
{
if (enable) {
hal->mac_regs->gmacff.pmode = 1;
} else {
hal->mac_regs->gmacff.pmode = 0;
}
}
void emac_hal_send_pause_frame(emac_hal_context_t *hal, bool enable)
{
if (enable) {
hal->ext_regs->ex_phyinf_conf.sbd_flowctrl = 1;
} else {
hal->ext_regs->ex_phyinf_conf.sbd_flowctrl = 0;
}
}
bool emac_hal_is_mii_busy(emac_hal_context_t *hal)
{
return hal->mac_regs->emacgmiiaddr.miibusy ? true : false;
}
void emac_hal_set_phy_cmd(emac_hal_context_t *hal, uint32_t phy_addr, uint32_t phy_reg, bool write)
{
typeof(hal->mac_regs->emacgmiiaddr) macmiiar = hal->mac_regs->emacgmiiaddr;
macmiiar.miidev = phy_addr;
/* Set the PHY register address */
macmiiar.miireg = phy_reg;
if (write) {
/* Set write mode */
macmiiar.miiwrite = 1;
} else {
/* Set read mode */
macmiiar.miiwrite = 0;
}
/* Set MII busy bit */
macmiiar.miibusy = 1;
/* Write the result value into the MII Address register */
hal->mac_regs->emacgmiiaddr = macmiiar;
}
void emac_hal_set_phy_data(emac_hal_context_t *hal, uint32_t reg_value)
{
hal->mac_regs->emacmiidata.mii_data = reg_value;
}
uint32_t emac_hal_get_phy_data(emac_hal_context_t *hal)
{
return hal->mac_regs->emacmiidata.mii_data;
}
void emac_hal_set_address(emac_hal_context_t *hal, uint8_t *mac_addr)
{
/* Make sure mac address is unicast type */
if (!(mac_addr[0] & 0x01)) {
hal->mac_regs->emacaddr0high.address0_hi = (mac_addr[5] << 8) | mac_addr[4];
hal->mac_regs->emacaddr0low = (mac_addr[3] << 24) | (mac_addr[2] << 16) | (mac_addr[1] << 8) | (mac_addr[0]);
}
}
void emac_hal_start(emac_hal_context_t *hal)
{
typeof(hal->dma_regs->dmaoperation_mode) opm = hal->dma_regs->dmaoperation_mode;
typeof(hal->mac_regs->gmacconfig) cfg = hal->mac_regs->gmacconfig;
/* Enable Ethernet MAC and DMA Interrupt */
hal->dma_regs->dmain_en.val = 0xFFFFFFFF;
/* Flush Transmit FIFO */
opm.flush_tx_fifo = 1;
/* Start DMA transmission */
opm.start_stop_transmission_command = 1;
/* Start DMA reception */
opm.start_stop_rx = 1;
/* Enable transmit state machine of the MAC for transmission on the MII */
cfg.tx = 1;
/* Enable receive state machine of the MAC for reception from the MII */
cfg.rx = 1;
hal->dma_regs->dmaoperation_mode = opm;
hal->mac_regs->gmacconfig = cfg;
/* Clear all pending interrupts */
hal->dma_regs->dmastatus.val = 0xFFFFFFFF;
}
void emac_hal_stop(emac_hal_context_t *hal)
{
typeof(hal->dma_regs->dmaoperation_mode) opm = hal->dma_regs->dmaoperation_mode;
typeof(hal->mac_regs->gmacconfig) cfg = hal->mac_regs->gmacconfig;
/* Flush Transmit FIFO */
opm.flush_tx_fifo = 1;
/* Stop DMA transmission */
opm.start_stop_transmission_command = 0;
/* Stop DMA reception */
opm.start_stop_rx = 0;
/* Disable receive state machine of the MAC for reception from the MII */
cfg.rx = 0;
/* Disable transmit state machine of the MAC for transmission on the MII */
cfg.tx = 0;
hal->dma_regs->dmaoperation_mode = opm;
hal->mac_regs->gmacconfig = cfg;
/* Disable Ethernet MAC and DMA Interrupt */
hal->dma_regs->dmain_en.val = 0x0;
}
uint32_t emac_hal_get_tx_desc_owner(emac_hal_context_t *hal)
{
return hal->tx_desc->TDES0.Own;
}
uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length)
{
/* Get the number of Tx buffers to use for the frame */
uint32_t bufcount = 0;
uint32_t lastlen = length;
uint32_t sentout = 0;
while (lastlen > CONFIG_ETH_DMA_BUFFER_SIZE) {
lastlen -= CONFIG_ETH_DMA_BUFFER_SIZE;
bufcount++;
}
if (lastlen) {
bufcount++;
}
if (bufcount > CONFIG_ETH_DMA_TX_BUFFER_NUM) {
goto err;
}
eth_dma_tx_descriptor_t *desc_iter = hal->tx_desc;
/* A frame is transmitted in multiple descriptor */
for (size_t i = 0; i < bufcount; i++) {
/* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
if (desc_iter->TDES0.Own != EMAC_DMADESC_OWNER_CPU) {
goto err;
}
/* Clear FIRST and LAST segment bits */
desc_iter->TDES0.FirstSegment = 0;
desc_iter->TDES0.LastSegment = 0;
desc_iter->TDES0.InterruptOnComplete = 0;
if (i == 0) {
/* Setting the first segment bit */
desc_iter->TDES0.FirstSegment = 1;
}
if (i == (bufcount - 1)) {
/* Setting the last segment bit */
desc_iter->TDES0.LastSegment = 1;
/* Enable transmit interrupt */
desc_iter->TDES0.InterruptOnComplete = 1;
/* Program size */
desc_iter->TDES1.TransmitBuffer1Size = lastlen;
/* copy data from uplayer stack buffer */
memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen);
sentout += lastlen;
} else {
/* Program size */
desc_iter->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
/* copy data from uplayer stack buffer */
memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE);
sentout += CONFIG_ETH_DMA_BUFFER_SIZE;
}
/* Point to next descriptor */
desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
for (size_t i = 0; i < bufcount; i++) {
hal->tx_desc->TDES0.Own = EMAC_DMADESC_OWNER_DMA;
hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
}
hal->dma_regs->dmatxpolldemand = 0;
return sentout;
err:
return 0;
}
uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain, uint32_t *free_desc)
{
eth_dma_rx_descriptor_t *desc_iter = NULL;
eth_dma_rx_descriptor_t *first_desc = NULL;
uint32_t used_descs = 0;
uint32_t seg_count = 0;
uint32_t ret_len = 0;
uint32_t copy_len = 0;
uint32_t write_len = 0;
uint32_t frame_count = 0;
first_desc = hal->rx_desc;
desc_iter = hal->rx_desc;
/* Traverse descriptors owned by CPU */
while ((desc_iter->RDES0.Own != EMAC_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM) && !frame_count) {
used_descs++;
seg_count++;
/* Last segment in frame */
if (desc_iter->RDES0.LastDescriptor) {
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
/* packets larger than expected will be truncated */
copy_len = ret_len > size ? size : ret_len;
/* update unhandled frame count */
frame_count++;
}
/* First segment in frame */
if (desc_iter->RDES0.FirstDescriptor) {
first_desc = desc_iter;
}
/* point to next descriptor */
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
/* there's at least one frame to process */
if (frame_count) {
/* check how many frames left to handle */
while ((desc_iter->RDES0.Own != EMAC_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
used_descs++;
if (desc_iter->RDES0.LastDescriptor) {
frame_count++;
}
/* point to next descriptor */
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
desc_iter = first_desc;
for (size_t i = 0; i < seg_count - 1; i++) {
used_descs--;
write_len = copy_len < CONFIG_ETH_DMA_BUFFER_SIZE ? copy_len : CONFIG_ETH_DMA_BUFFER_SIZE;
/* copy data to buffer */
memcpy(buf, (void *)(desc_iter->Buffer1Addr), write_len);
buf += write_len;
copy_len -= write_len;
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
desc_iter->RDES0.Own = EMAC_DMADESC_OWNER_DMA;
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
memcpy(buf, (void *)(desc_iter->Buffer1Addr), copy_len);
desc_iter->RDES0.Own = EMAC_DMADESC_OWNER_DMA;
/* update rxdesc */
hal->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
/* poll rx demand */
hal->dma_regs->dmarxpolldemand = 0;
frame_count--;
used_descs--;
}
*frames_remain = frame_count;
*free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
return ret_len;
}
IRAM_ATTR void emac_hal_isr(void *arg)
{
emac_hal_context_t *hal = (emac_hal_context_t *)arg;
typeof(hal->dma_regs->dmastatus) dma_status = hal->dma_regs->dmastatus;
hal->dma_regs->dmastatus.val = dma_status.val;
/* DMA Normal Interrupt */
if (dma_status.norm_int_summ) {
/* Transmit Interrupt */
if (dma_status.trans_int) {
emac_hal_tx_complete_cb(arg);
}
/* Transmit Buffer Unavailable */
if (dma_status.trans_buf_unavail) {
emac_hal_tx_unavail_cb(arg);
}
/* Receive Interrupt */
if (dma_status.recv_int) {
emac_hal_rx_complete_cb(arg);
}
/* Early Receive Interrupt */
if (dma_status.early_recv_int) {
emac_hal_rx_early_cb(arg);
}
}
/* DMA Abnormal Interrupt */
if (dma_status.abn_int_summ) {
/* Transmit Process Stopped */
if (dma_status.trans_proc_stop) {
}
/* Transmit Jabber Timeout */
if (dma_status.trans_jabber_to) {
}
/* Receive FIFO Overflow */
if (dma_status.recv_ovflow) {
}
/* Transmit Underflow */
if (dma_status.trans_undflow) {
}
/* Receive Buffer Unavailable */
if (dma_status.recv_buf_unavail) {
emac_hal_rx_unavail_cb(arg);
}
/* Receive Process Stopped */
if (dma_status.recv_proc_stop) {
}
/* Receive Watchdog Timeout */
if (dma_status.recv_wdt_to) {
}
/* Early Transmit Interrupt */
if (dma_status.early_trans_int) {
}
/* Fatal Bus Error */
if (dma_status.fatal_bus_err_int) {
}
}
}
IRAM_ATTR __attribute__((weak)) void emac_hal_tx_complete_cb(void *arg)
{
// This is a weak function, do nothing by default
// Upper code can rewrite this function
// Note: you're in the interrupt context
return;
}
IRAM_ATTR __attribute__((weak)) void emac_hal_tx_unavail_cb(void *arg)
{
// This is a weak function, do nothing by default
// Upper code can rewrite this function
// Note: you're in the interrupt context
return;
}
IRAM_ATTR __attribute__((weak)) void emac_hal_rx_complete_cb(void *arg)
{
// This is a weak function, do nothing by default
// Upper code can rewrite this function
// Note: you're in the interrupt context
return;
}
IRAM_ATTR __attribute__((weak)) void emac_hal_rx_early_cb(void *arg)
{
// This is a weak function, do nothing by default
// Upper code can rewrite this function
// Note: you're in the interrupt context
return;
}
IRAM_ATTR __attribute__((weak)) void emac_hal_rx_unavail_cb(void *arg)
{
// This is a weak function, do nothing by default
// Upper code can rewrite this function
// Note: you're in the interrupt context
return;
}

View File

@ -0,0 +1,596 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32 eMAC register operations
#pragma once
#include <stdint.h>
#include "hal/eth_types.h"
#include "soc/emac_dma_struct.h"
#include "soc/emac_mac_struct.h"
#include "soc/emac_ext_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Register configuration */
#define EMAC_LL_INTERFRAME_GAP_96BIT (0)
#define EMAC_LL_INTERFRAME_GAP_88BIT (1)
#define EMAC_LL_INTERFRAME_GAP_80BIT (2)
#define EMAC_LL_INTERFRAME_GAP_72BIT (3)
#define EMAC_LL_INTERFRAME_GAP_64BIT (4)
#define EMAC_LL_INTERFRAME_GAP_56BIT (5)
#define EMAC_LL_INTERFRAME_GAP_48BIT (6)
#define EMAC_LL_INTERFRAME_GAP_40BIT (7)
#define EMAC_LL_BACKOFF_LIMIT_10 (0)
#define EMAC_LL_BACKOFF_LIMIT_8 (1)
#define EMAC_LL_BACKOFF_LIMIT_4 (2)
#define EMAC_LL_BACKOFF_LIMIT_1 (3)
#define EMAC_LL_PREAMBLE_LENGTH_7 (0)
#define EMAC_LL_PREAMBLE_LENGTH_5 (1)
#define EMAC_LL_PREAMBLE_LENGTH_3 (2)
#define EMAC_LL_SOURCE_ADDR_FILTER_DISABLE (0)
#define EMAC_LL_SOURCE_ADDR_FILTER_NORMAL (2)
#define EMAC_LL_SOURCE_ADDR_FILTER_INVERSE (3)
#define EMAC_LL_CONTROL_FRAME_BLOCKALL (0)
#define EMAC_LL_CONTROL_FRAME_FORWARDALL_PAUSE (1)
#define EMAC_LL_CONTROL_FRAME_FORWARDALL (2)
#define EMAC_LL_CONTROL_FRAME_FORWARDFILT (3)
#define EMAC_LL_PAUSE_TIME 0x1648
#define EMAC_LL_PAUSE_LOW_THRESHOLD_MINUS_4 (0)
#define EMAC_LL_PAUSE_LOW_THRESHOLD_MINUS_28 (1)
#define EMAC_LL_PAUSE_LOW_THRESHOLD_MINUS_144 (2)
#define EMAC_LL_PAUSE_LOW_THRESHOLD_MINUS_256 (3)
#define EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_64 (0)
#define EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_128 (1)
#define EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_192 (2)
#define EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_256 (3)
#define EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_40 (4)
#define EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_32 (5)
#define EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_24 (6)
#define EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_16 (7)
#define EMAC_LL_RECEIVE_THRESHOLD_CONTROL_64 (0)
#define EMAC_LL_RECEIVE_THRESHOLD_CONTROL_32 (1)
#define EMAC_LL_RECEIVE_THRESHOLD_CONTROL_96 (2)
#define EMAC_LL_RECEIVE_THRESHOLD_CONTROL_128 (3)
#define EMAC_LL_DMA_BURST_LENGTH_1BEAT (1)
#define EMAC_LL_DMA_BURST_LENGTH_2BEAT (2)
#define EMAC_LL_DMA_BURST_LENGTH_4BEAT (4)
#define EMAC_LL_DMA_BURST_LENGTH_8BEAT (8)
#define EMAC_LL_DMA_BURST_LENGTH_16BEAT (16)
#define EMAC_LL_DMA_BURST_LENGTH_32BEAT (32)
#define EMAC_LL_DMA_ARBITRATION_ROUNDROBIN_RXTX_1_1 (0)
#define EMAC_LL_DMA_ARBITRATION_ROUNDROBIN_RXTX_2_1 (1)
#define EMAC_LL_DMA_ARBITRATION_ROUNDROBIN_RXTX_3_1 (2)
#define EMAC_LL_DMA_ARBITRATION_ROUNDROBIN_RXTX_4_1 (3)
/* PTP register bits */
#define EMAC_LL_DMAPTPRXDESC_PTPMT_SYNC 0x00000100U /* SYNC message (all clock types) */
#define EMAC_LL_DMAPTPRXDESC_PTPMT_FOLLOWUP 0x00000200U /* FollowUp message (all clock types) */
#define EMAC_LL_DMAPTPRXDESC_PTPMT_DELAYREQ 0x00000300U /* DelayReq message (all clock types) */
#define EMAC_LL_DMAPTPRXDESC_PTPMT_DELAYRESP 0x00000400U /* DelayResp message (all clock types) */
#define EMAC_LL_DMAPTPRXDESC_PTPMT_PDELAYREQ_ANNOUNCE 0x00000500U /* PdelayReq message (peer-to-peer transparent clock) or Announce message (Ordinary or Boundary clock) */
#define EMAC_LL_DMAPTPRXDESC_PTPMT_PDELAYRESP_MANAG 0x00000600U /* PdelayResp message (peer-to-peer transparent clock) or Management message (Ordinary or Boundary clock) */
#define EMAC_LL_DMAPTPRXDESC_PTPMT_PDELAYRESPFOLLOWUP_SIGNAL 0x00000700U /* PdelayRespFollowUp message (peer-to-peer transparent clock) or Signaling message (Ordinary or Boundary clock) */
#define EMAC_LL_DMAPTPRXDESC_IPPT_UDP 0x00000001U /* UDP payload encapsulated in the IP datagram */
#define EMAC_LL_DMAPTPRXDESC_IPPT_TCP 0x00000002U /* TCP payload encapsulated in the IP datagram */
#define EMAC_LL_DMAPTPRXDESC_IPPT_ICMP 0x00000003U /* ICMP payload encapsulated in the IP datagram */
#define EMAC_LL_DMADESC_OWNER_CPU (0)
#define EMAC_LL_DMADESC_OWNER_DMA (1)
/* Interrupt flags (referring to dmastatus register in emac_dma_struct.h) */
#define EMAC_LL_DMA_TRANSMIT_FINISH_INTR 0x00000001U
#define EMAC_LL_DMA_TRANSMIT_STOP_INTR 0x00000002U
#define EMAC_LL_DMA_TRANSMIT_BUFF_UNAVAILABLE_INTR 0x00000004U
#define EMAC_LL_DMA_TRANSMIT_TIMEOUT_INTR 0x00000008U
#define EMAC_LL_DMA_RECEIVE_OVERFLOW_INTR 0x00000010U
#define EMAC_LL_DMA_TRANSMIT_UNDERFLOW_INTR 0x00000020U
#define EMAC_LL_DMA_RECEIVE_FINISH_INTR 0x00000040U
#define EMAC_LL_DMA_RECEIVE_BUFF_UNAVAILABLE_INTR 0x00000080U
#define EMAC_LL_DMA_RECEIVE_STOP_INTR 0x00000100U
#define EMAC_LL_DMA_RECEIVE_TIMEOUT_INTR 0x00000200U
#define EMAC_LL_DMA_TRANSMIT_FIRST_BYTE_INTR 0x00000400U
#define EMAC_LL_DMA_FATAL_BUS_ERROR_INRT 0x00001000U
#define EMAC_LL_DMA_RECEIVE_FIRST_BYTE_INTR 0x00002000U
#define EMAC_LL_DMA_ABNORMAL_INTR_SUMMARY 0x00004000U
#define EMAC_LL_DMA_NORMAL_INTR_SUMMARY 0x00008000U
#define EMAC_LL_DMA_POWER_MANAGE_INTR 0x10000000U
#define EMAC_LL_DMA_TIMESTAMP_TRIGGER_INTR 0x20000000U
/* Interrupt enable (referring to dmain_en register in emac_dma_struct.h) */
#define EMAC_LL_INTR_TRANSMIT_ENABLE 0x00000001U
#define EMAC_LL_INTR_TRANSMIT_STOP_ENABLE 0x00000002U
#define EMAC_LL_INTR_TRANSMIT_BUFF_UNAVAILABLE_ENABLE 0x00000004U
#define EMAC_LL_INTR_TRANSMIT_TIMEOUT_ENABLE 0x00000008U
#define EMAC_LL_INTR_OVERFLOW_ENABLE 0x00000010U
#define EMAC_LL_INTR_UNDERFLOW_ENABLE 0x00000020U
#define EMAC_LL_INTR_RECEIVE_ENABLE 0x00000040U
#define EMAC_LL_INTR_REVEIVE_BUFF_UNAVAILABLE_ENABLE 0x00000080U
#define EMAC_LL_INTR_RECEIVE_STOP_ENABLE 0x00000100U
#define EMAC_LL_INTR_RECEIVE_TIMEOUT_ENABLE 0x00000200U
#define EMAC_LL_INTR_TRANSMIT_FIRST_BYTE_ENABLE 0x00000400U
#define EMAC_LL_INTR_FATAL_BUS_ERR_ENABLE 0x00002000U
#define EMAC_LL_INTR_RECEIVE_FIRST_BYTE_ENABLE 0x00004000U
#define EMAC_LL_INTR_ABNORMAL_SUMMARY_ENABLE 0x00008000U
#define EMAC_LL_INTR_NORMAL_SUMMARY_ENABLE 0x00010000U
/* Enable needed 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)
/************** Start of mac regs operation ********************/
/* emacgmiiaddr */
static inline void emac_ll_set_csr_clock_division(emac_mac_dev_t *mac_regs, uint32_t div_mode)
{
mac_regs->emacgmiiaddr.miicsrclk = div_mode;
}
static inline bool emac_ll_is_mii_busy(emac_mac_dev_t *mac_regs)
{
return mac_regs->emacgmiiaddr.miibusy ? true : false;
}
static inline void emac_ll_set_phy_addr(emac_mac_dev_t *mac_regs, uint32_t addr)
{
mac_regs->emacgmiiaddr.miidev = addr;
}
static inline void emac_ll_set_phy_reg(emac_mac_dev_t *mac_regs, uint32_t reg)
{
mac_regs->emacgmiiaddr.miireg = reg;
}
static inline void emac_ll_write_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->emacgmiiaddr.miiwrite = enable;
}
static inline void emac_ll_set_busy(emac_mac_dev_t *mac_regs, bool busy)
{
mac_regs->emacgmiiaddr.miibusy = busy ? 1 : 0;
}
/* gmacconfig */
static inline void emac_ll_watchdog_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.watchdog = !enable;
}
static inline void emac_ll_jabber_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.jabber = !enable;
}
static inline void emac_ll_set_inter_frame_gap(emac_mac_dev_t *mac_regs, uint32_t gap)
{
mac_regs->gmacconfig.interframegap = gap;
}
static inline void emac_ll_carrier_sense_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.disablecrs = !enable;
}
static inline void emac_ll_set_port_speed(emac_mac_dev_t *mac_regs, eth_speed_t speed)
{
if (speed == ETH_SPEED_10M || speed == ETH_SPEED_100M) {
mac_regs->gmacconfig.mii = 1; // 10_100MBPS
mac_regs->gmacconfig.fespeed = speed;
} else {
mac_regs->gmacconfig.mii = 0; // 1000MBPS
}
}
static inline void emac_ll_recv_own_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.rxown = !enable;
}
static inline void emac_ll_loopback_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.loopback = enable;
}
static inline void emac_ll_set_duplex(emac_mac_dev_t *mac_regs, eth_duplex_t duplex)
{
mac_regs->gmacconfig.duplex = duplex;
}
static inline void emac_ll_checksum_offload_mode(emac_mac_dev_t *mac_regs, eth_checksum_t mode)
{
mac_regs->gmacconfig.rxipcoffload = mode;
}
static inline void emac_ll_retry_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.retry = !enable;
}
static inline void emac_ll_auto_pad_crc_strip_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.padcrcstrip = enable;
}
static inline void emac_ll_set_back_off_limit(emac_mac_dev_t *mac_regs, uint32_t limit)
{
mac_regs->gmacconfig.backofflimit = limit;
}
static inline void emac_ll_deferral_check_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.padcrcstrip = enable;
}
static inline void emac_ll_set_preamble_length(emac_mac_dev_t *mac_regs, uint32_t len)
{
mac_regs->gmacconfig.pltf = len;
}
static inline void emac_ll_transmit_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.tx = enable;
}
static inline void emac_ll_receive_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacconfig.rx = enable;
}
/* gmacff */
static inline void emac_ll_receive_all_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacff.receive_all = enable;
}
static inline void emac_ll_set_src_addr_filter(emac_mac_dev_t *mac_regs, uint32_t filter)
{
mac_regs->gmacff.safe = filter;
}
static inline void emac_ll_sa_inverse_filter_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacff.saif = enable;
}
static inline void emac_ll_set_pass_ctrl_frame_mode(emac_mac_dev_t *mac_regs, uint32_t mode)
{
mac_regs->gmacff.pcf = mode;
}
static inline void emac_ll_broadcast_frame_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacff.dbf = !enable;
}
static inline void emac_ll_pass_all_multicast_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacff.pam = enable;
}
static inline void emac_ll_da_inverse_filter_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacff.daif = enable;
}
static inline void emac_ll_promiscuous_mode_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacff.pmode = enable;
}
/* gmacfc */
static inline void emac_ll_set_pause_time(emac_mac_dev_t *mac_regs, uint32_t time)
{
mac_regs->gmacfc.pause_time = time;
}
static inline void emac_ll_zero_quanta_pause_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacfc.dzpq = !enable;
}
static inline void emac_ll_set_pause_low_threshold(emac_mac_dev_t *mac_regs, uint32_t threshold)
{
mac_regs->gmacfc.plt = threshold;
}
static inline void emac_ll_unicast_pause_frame_detect_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacfc.upfd = enable;
}
static inline void emac_ll_receive_flow_ctrl_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacfc.rfce = enable;
}
static inline void emac_ll_transmit_flow_ctrl_enable(emac_mac_dev_t *mac_regs, bool enable)
{
mac_regs->gmacfc.tfce = enable;
}
static inline void emac_ll_clear(emac_mac_dev_t *mac_regs)
{
mac_regs->gmacfc.val = 0;
}
/* emacmiidata */
static inline void emac_ll_set_phy_data(emac_mac_dev_t *mac_regs, uint32_t data)
{
mac_regs->emacmiidata.mii_data = data;
}
static inline uint32_t emac_ll_get_phy_data(emac_mac_dev_t *mac_regs)
{
return mac_regs->emacmiidata.mii_data;
}
/* emacaddr0 */
static inline void emac_ll_set_addr(emac_mac_dev_t *mac_regs, const uint8_t *addr)
{
mac_regs->emacaddr0high.address0_hi = (addr[5] << 8) | addr[4];
mac_regs->emacaddr0low = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | (addr[0]);
}
/*************** End of mac regs operation *********************/
/************** Start of dma regs operation ********************/
/* dmabusmode */
static inline void emac_ll_reset(emac_dma_dev_t *dma_regs)
{
dma_regs->dmabusmode.sw_rst = 1;
}
static inline bool emac_ll_is_reset_done(emac_dma_dev_t *dma_regs)
{
return dma_regs->dmabusmode.sw_rst ? false : true;
}
/* dmarxbaseaddr / dmatxbaseaddr */
static inline void emac_ll_set_rx_desc_addr(emac_dma_dev_t *dma_regs, uint32_t addr)
{
dma_regs->dmarxbaseaddr = addr;
}
static inline void emac_ll_set_tx_desc_addr(emac_dma_dev_t *dma_regs, uint32_t addr)
{
dma_regs->dmatxbaseaddr = addr;
}
/* dmaoperation_mode */
static inline void emac_ll_drop_tcp_err_frame_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.dis_drop_tcpip_err_fram = !enable;
}
static inline void emac_ll_recv_store_forward_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.rx_store_forward = enable;
}
static inline void emac_ll_flush_recv_frame_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.dis_flush_recv_frames = !enable;
}
static inline void emac_ll_trans_store_forward_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.tx_str_fwd = !enable;
}
static inline void emac_ll_flush_trans_fifo_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.flush_tx_fifo = enable;
}
static inline void emac_ll_set_transmit_threshold(emac_dma_dev_t *dma_regs, uint32_t threshold)
{
dma_regs->dmaoperation_mode.tx_thresh_ctrl = threshold;
}
static inline void emac_ll_start_stop_dma_transmit(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.start_stop_transmission_command = enable;
}
static inline void emac_ll_forward_err_frame_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.fwd_err_frame = enable;
}
static inline void emac_ll_forward_undersized_good_frame_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.fwd_under_gf = enable;
}
static inline void emac_ll_set_recv_threshold(emac_dma_dev_t *dma_regs, uint32_t threshold)
{
dma_regs->dmaoperation_mode.rx_thresh_ctrl = threshold;
}
static inline void emac_ll_opt_second_frame_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.opt_second_frame = enable;
}
static inline void emac_ll_start_stop_dma_receive(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmaoperation_mode.start_stop_rx = enable;
}
/* dmabusmode */
static inline void emac_ll_mixed_burst_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmabusmode.dmamixedburst = enable;
}
static inline void emac_ll_addr_align_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmabusmode.dmaaddralibea = enable;
}
static inline void emac_ll_use_separate_pbl_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmabusmode.use_sep_pbl = enable;
}
static inline void emac_ll_set_rx_dma_pbl(emac_dma_dev_t *dma_regs, uint32_t pbl)
{
dma_regs->dmabusmode.rx_dma_pbl = pbl;
}
static inline void emac_ll_set_prog_burst_len(emac_dma_dev_t *dma_regs, uint32_t len)
{
dma_regs->dmabusmode.prog_burst_len = len;
}
static inline void emac_ll_enhance_desc_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmabusmode.alt_desc_size = enable;
}
static inline void emac_ll_set_desc_skip_len(emac_dma_dev_t *dma_regs, uint32_t len)
{
dma_regs->dmabusmode.desc_skip_len = len;
}
static inline void emac_ll_fixed_arbitration_enable(emac_dma_dev_t *dma_regs, bool enable)
{
dma_regs->dmabusmode.dma_arb_sch = enable;
}
static inline void emac_ll_set_priority_ratio(emac_dma_dev_t *dma_regs, uint32_t ratio)
{
dma_regs->dmabusmode.pri_ratio = ratio;
}
/* dmain_en */
static inline void emac_ll_enable_all_intr(emac_dma_dev_t *dma_regs)
{
dma_regs->dmain_en.val = 0xFFFFFFFF;
}
static inline void emac_ll_disable_all_intr(emac_dma_dev_t *dma_regs)
{
dma_regs->dmain_en.val = 0x00000000;
}
static inline void emac_ll_enable_corresponding_intr(emac_dma_dev_t *dma_regs, uint32_t mask)
{
dma_regs->dmain_en.val |= mask;
}
static inline void emac_ll_disable_corresponding_intr(emac_dma_dev_t *dma_regs, uint32_t mask)
{
dma_regs->dmain_en.val &= ~mask;
}
static inline uint32_t emac_ll_get_intr_enable_status(emac_dma_dev_t *dma_regs)
{
return dma_regs->dmain_en.val;
}
/* dmastatus */
__attribute__((always_inline)) static inline uint32_t emac_ll_get_intr_status(emac_dma_dev_t *dma_regs)
{
return dma_regs->dmastatus.val;
}
__attribute__((always_inline)) static inline void emac_ll_clear_corresponding_intr(emac_dma_dev_t *dma_regs, uint32_t bits)
{
dma_regs->dmastatus.val = bits;
}
__attribute__((always_inline)) static inline void emac_ll_clear_all_pending_intr(emac_dma_dev_t *dma_regs)
{
dma_regs->dmastatus.val = 0xFFFFFFFF;
}
/* dmatxpolldemand / dmarxpolldemand */
static inline void emac_ll_transmit_poll_demand(emac_dma_dev_t *dma_regs, uint32_t val)
{
dma_regs->dmatxpolldemand = val;
}
static inline void emac_ll_receive_poll_demand(emac_dma_dev_t *dma_regs, uint32_t val)
{
dma_regs->dmarxpolldemand = val;
}
/*************** End of dma regs operation *********************/
/************** Start of ext regs operation ********************/
static inline void emac_ll_clock_enable_mii(emac_ext_dev_t *ext_regs)
{
/* 0 for mii mode */
ext_regs->ex_phyinf_conf.phy_intf_sel = 0;
ext_regs->ex_clk_ctrl.mii_clk_rx_en = 1;
ext_regs->ex_clk_ctrl.mii_clk_tx_en = 1;
}
static inline void emac_ll_clock_enable_rmii_input(emac_ext_dev_t *ext_regs)
{
/* 4 for rmii mode */
ext_regs->ex_phyinf_conf.phy_intf_sel = 4;
/* ref clk for phy is input in rmii mode, the clk can be offered by mac layer or external crystal.
config pin as output to generate ref clk by esp32 mac layer or input to obtain the clock from external crystal */
ext_regs->ex_clk_ctrl.ext_en = 1;
ext_regs->ex_clk_ctrl.int_en = 0;
ext_regs->ex_oscclk_conf.clk_sel = 1;
}
static inline void emac_ll_clock_enable_rmii_output(emac_ext_dev_t *ext_regs)
{
/* 4 for rmii mode */
ext_regs->ex_phyinf_conf.phy_intf_sel = 4;
/* ref clk for phy is input in rmii mode, the clk can be offered by mac layer or external crystal.
config pin as output to generate ref clk by esp32 mac layer or input to obtain the clock from external crystal */
ext_regs->ex_clk_ctrl.ext_en = 0;
ext_regs->ex_clk_ctrl.int_en = 1;
ext_regs->ex_oscclk_conf.clk_sel = 0;
ext_regs->ex_clkout_conf.div_num = 0;
ext_regs->ex_clkout_conf.h_div_num = 0;
}
static inline void emac_ll_pause_frame_enable(emac_ext_dev_t *ext_regs, bool enable)
{
ext_regs->ex_phyinf_conf.sbd_flowctrl = enable;
}
/*************** End of ext regs operation *********************/
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,4 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -21,169 +21,11 @@ extern "C" {
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "hal/eth_types.h"
#include "soc/emac_dma_struct.h"
#include "soc/emac_mac_struct.h"
#include "soc/emac_ext_struct.h"
#define EMAC_MEDIA_INTERFACE_MII (0)
#define EMAC_MEDIA_INTERFACE_RMII (1)
#define EMAC_WATCHDOG_ENABLE (0)
#define EMAC_WATCHDOG_DISABLE (1)
#define EMAC_JABBER_ENABLE (0)
#define EMAC_JABBER_DISABLE (1)
#define EMAC_INTERFRAME_GAP_96BIT (0)
#define EMAC_INTERFRAME_GAP_88BIT (1)
#define EMAC_INTERFRAME_GAP_80BIT (2)
#define EMAC_INTERFRAME_GAP_72BIT (3)
#define EMAC_INTERFRAME_GAP_64BIT (4)
#define EMAC_INTERFRAME_GAP_56BIT (5)
#define EMAC_INTERFRAME_GAP_48BIT (6)
#define EMAC_INTERFRAME_GAP_40BIT (7)
#define EMAC_CARRIERSENSE_ENABLE (0)
#define EMAC_CARRIERSENSE_DISABLE (1)
#define EMAC_PORT_1000MBPS (0)
#define EMAC_PORT_10_100MBPS (1)
#define EMAC_SPEED_10M (0)
#define EMAC_SPEED_100M (1)
#define EMAC_RECEIVE_OWN_ENABLE (0)
#define EMAC_RECEIVE_OWN_DISABLE (1)
#define EMAC_LOOPBACK_DISABLE (0)
#define EMAC_LOOPBACK_ENABLE (1)
#define EMAC_DUPLEX_HALF (0)
#define EMAC_DUPLEX_FULL (1)
#define EMAC_CHECKSUM_SW (0)
#define EMAC_CHECKSUM_HW (1)
#define EMAC_RETRY_TRANSMISSION_ENABLE (0)
#define EMAC_RETRY_TRANSMISSION_DISABLE (1)
#define EMAC_AUTO_PAD_CRC_STRIP_DISABLE (0)
#define EMAC_AUTO_PAD_CRC_STRIP_ENABLE (1)
#define EMAC_BACKOFF_LIMIT_10 (0)
#define EMAC_BACKOFF_LIMIT_8 (1)
#define EMAC_BACKOFF_LIMIT_4 (2)
#define EMAC_BACKOFF_LIMIT_1 (3)
#define EMAC_DEFERRAL_CHECK_DISABLE (0)
#define EMAC_DEFERRAL_CHECK_ENABLE (1)
#define EMAC_PREAMBLE_LENGTH_7 (0)
#define EMAC_PREAMBLE_LENGTH_5 (1)
#define EMAC_PREAMBLE_LENGTH_3 (2)
#define EMAC_RECEIVE_ALL_DISABLE (0)
#define EMAC_RECEIVE_ALL_ENABLE (1)
#define EMAC_SOURCE_ADDR_FILTER_DISABLE (0)
#define EMAC_SOURCE_ADDR_FILTER_NORMAL (2)
#define EMAC_SOURCE_ADDR_FILTER_INVERSE (3)
#define EMAC_CONTROL_FRAME_BLOCKALL (0)
#define EMAC_CONTROL_FRAME_FORWARDALL_PAUSE (1)
#define EMAC_CONTROL_FRAME_FORWARDALL (2)
#define EMAC_CONTROL_FRAME_FORWARDFILT (3)
#define EMAC_RECEPT_BROADCAST_ENABLE (0)
#define EMAC_RECEPT_BROADCAST_DISABLE (1)
#define EMAC_DEST_ADDR_FILTER_NORMAL (0)
#define EMAC_DEST_ADDR_FILTER_INVERSE (1)
#define EMAC_PROMISCUOUS_DISABLE (0)
#define EMAC_PROMISCUOUS_ENABLE (1)
#define EMAC_PAUSE_TIME 0x1648
#define EMAC_ZERO_QUANTA_PAUSE_ENABLE (0)
#define EMAC_ZERO_QUANTA_PAUSE_DISABLE (1)
#define EMAC_PAUSE_LOW_THRESHOLD_MINUS_4 (0)
#define EMAC_PAUSE_LOW_THRESHOLD_MINUS_28 (1)
#define EMAC_PAUSE_LOW_THRESHOLD_MINUS_144 (2)
#define EMAC_PAUSE_LOW_THRESHOLD_MINUS_256
#define EMAC_UNICAST_PAUSE_DETECT_DISABLE (0)
#define EMAC_UNICAST_PAUSE_DETECT_ENABLE (1)
#define EMAC_RECEIVE_FLOW_CONTROL_DISABLE (0)
#define EMAC_RECEIVE_FLOW_CONTROL_ENABLE (1)
#define EMAC_TRANSMIT_FLOW_CONTROL_DISABLE (0)
#define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE (1)
#define EMAC_DROP_TCPIP_CHECKSUM_ERROR_ENABLE (0)
#define EMAC_DROP_TCPIP_CHECKSUM_ERROR_DISABLE (1)
#define EMAC_RECEIVE_STORE_FORWARD_DISABLE (0)
#define EMAC_RECEIVE_STORE_FORWARD_ENABLE (1)
#define EMAC_FLUSH_RECEIVED_FRAME_ENABLE (0)
#define EMAC_FLUSH_RECEIVED_FRAME_DISABLE (1)
#define EMAC_TRANSMIT_STORE_FORWARD_DISABLE (0)
#define EMAC_TRANSMIT_STORE_FORWARD_ENABLE (1)
#define EMAC_TRANSMIT_THRESHOLD_CONTROL_64 (0)
#define EMAC_TRANSMIT_THRESHOLD_CONTROL_128 (1)
#define EMAC_TRANSMIT_THRESHOLD_CONTROL_192 (2)
#define EMAC_TRANSMIT_THRESHOLD_CONTROL_256 (3)
#define EMAC_TRANSMIT_THRESHOLD_CONTROL_40 (4)
#define EMAC_TRANSMIT_THRESHOLD_CONTROL_32 (5)
#define EMAC_TRANSMIT_THRESHOLD_CONTROL_24 (6)
#define EMAC_TRANSMIT_THRESHOLD_CONTROL_16 (7)
#define EMAC_FORWARD_ERROR_FRAME_DISABLE (0)
#define EMAC_FORWARD_ERROR_FRAME_ENABLE (1)
#define EMAC_FORWARD_UNDERSIZED_GOOD_FRAME_DISABLE (0)
#define EMAC_FORWARD_UNDERSIZED_GOOD_FRAME_ENABLE (1)
#define EMAC_RECEIVE_THRESHOLD_CONTROL_64 (0)
#define EMAC_RECEIVE_THRESHOLD_CONTROL_32 (1)
#define EMAC_RECEIVE_THRESHOLD_CONTROL_96 (2)
#define EMAC_RECEIVE_THRESHOLD_CONTROL_128 (3)
#define EMAC_OPERATE_SECOND_FRAME_DISABLE (0)
#define EMAC_OPERATE_SECOND_FRAME_ENABLE (1)
#define EMAC_MIXED_BURST_DISABLE (0)
#define EMAC_MIXED_BURST_ENABLE (1)
#define EMAC_ADDR_ALIGN_BEATS_DISABLE (0)
#define EMAC_ADDR_ALIGN_BEATS_ENABLE (1)
#define EMAC_UNUSE_SEPARATE_PBL (0)
#define EMAC_USE_SEPARATE_PBL (1)
#define EMAC_DMA_BURST_LENGTH_1BEAT (1)
#define EMAC_DMA_BURST_LENGTH_2BEAT (2)
#define EMAC_DMA_BURST_LENGTH_4BEAT (4)
#define EMAC_DMA_BURST_LENGTH_8BEAT (8)
#define EMAC_DMA_BURST_LENGTH_16BEAT (16)
#define EMAC_DMA_BURST_LENGTH_32BEAT (32)
#define EMAC_ENHANCED_DESCRIPTOR_DISABLE (0)
#define EMAC_ENHANCED_DESCRIPTOR_ENABLE (1)
#define EMAC_DMA_ARBITRATION_SCHEME_ROUNDROBIN (0)
#define EMAC_DMA_ARBITRATION_SCHEME_FIXEDPRIO (1)
#define EMAC_DMA_ARBITRATION_ROUNDROBIN_RXTX_1_1 (0)
#define EMAC_DMA_ARBITRATION_ROUNDROBIN_RXTX_2_1 (1)
#define EMAC_DMA_ARBITRATION_ROUNDROBIN_RXTX_3_1 (2)
#define EMAC_DMA_ARBITRATION_ROUNDROBIN_RXTX_4_1 (3)
/**
* @brief Ethernet DMA TX Descriptor
*
@ -315,20 +157,6 @@ typedef struct {
uint32_t TimeStampLow; /*!< Receive frame timestamp low */
uint32_t TimeStampHigh; /*!< Receive frame timestamp high */
} eth_dma_rx_descriptor_t;
#define EMAC_DMAPTPRXDESC_PTPMT_SYNC 0x00000100U /* SYNC message (all clock types) */
#define EMAC_DMAPTPRXDESC_PTPMT_FOLLOWUP 0x00000200U /* FollowUp message (all clock types) */
#define EMAC_DMAPTPRXDESC_PTPMT_DELAYREQ 0x00000300U /* DelayReq message (all clock types) */
#define EMAC_DMAPTPRXDESC_PTPMT_DELAYRESP 0x00000400U /* DelayResp message (all clock types) */
#define EMAC_DMAPTPRXDESC_PTPMT_PDELAYREQ_ANNOUNCE 0x00000500U /* PdelayReq message (peer-to-peer transparent clock) or Announce message (Ordinary or Boundary clock) */
#define EMAC_DMAPTPRXDESC_PTPMT_PDELAYRESP_MANAG 0x00000600U /* PdelayResp message (peer-to-peer transparent clock) or Management message (Ordinary or Boundary clock) */
#define EMAC_DMAPTPRXDESC_PTPMT_PDELAYRESPFOLLOWUP_SIGNAL 0x00000700U /* PdelayRespFollowUp message (peer-to-peer transparent clock) or Signaling message (Ordinary or Boundary clock) */
#define EMAC_DMAPTPRXDESC_IPPT_UDP 0x00000001U /* UDP payload encapsulated in the IP datagram */
#define EMAC_DMAPTPRXDESC_IPPT_TCP 0x00000002U /* TCP payload encapsulated in the IP datagram */
#define EMAC_DMAPTPRXDESC_IPPT_ICMP 0x00000003U /* ICMP payload encapsulated in the IP datagram */
#define EMAC_DMADESC_OWNER_CPU (0)
#define EMAC_DMADESC_OWNER_DMA (1)
_Static_assert(sizeof(eth_dma_rx_descriptor_t) == 32, "eth_dma_rx_descriptor_t should occupy 32 bytes in memory");
@ -341,20 +169,31 @@ typedef struct {
void *descriptors;
eth_dma_rx_descriptor_t *rx_desc;
eth_dma_tx_descriptor_t *tx_desc;
} emac_hal_context_t;
void emac_hal_init(emac_hal_context_t *hal, void *descriptors,
uint8_t **rx_buf, uint8_t **tx_buf);
void emac_hal_reset_desc_chain(emac_hal_context_t *hal);
void emac_hal_iomux_init_mii(void);
void emac_hal_lowlevel_init(emac_hal_context_t *hal);
void emac_hal_iomux_init_rmii(void);
void emac_hal_iomux_rmii_clk_input(void);
void emac_hal_iomux_rmii_clk_ouput(int num);
void emac_hal_iomux_init_tx_er(void);
void emac_hal_iomux_init_rx_er(void);
void emac_hal_reset_desc_chain(emac_hal_context_t *hal);
void emac_hal_reset(emac_hal_context_t *hal);
bool emac_hal_is_reset_done(emac_hal_context_t *hal);
void emac_hal_set_csr_clock_range(emac_hal_context_t *hal);
void emac_hal_set_csr_clock_range(emac_hal_context_t *hal, int freq);
void emac_hal_init_mac_default(emac_hal_context_t *hal);
@ -362,7 +201,7 @@ void emac_hal_init_dma_default(emac_hal_context_t *hal);
void emac_hal_set_speed(emac_hal_context_t *hal, uint32_t speed);
void emac_hal_set_duplex(emac_hal_context_t *hal, uint32_t duplex);
void emac_hal_set_duplex(emac_hal_context_t *hal, eth_duplex_t duplex);
void emac_hal_set_promiscuous(emac_hal_context_t *hal, bool enable);
@ -393,17 +232,13 @@ uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t
void emac_hal_enable_flow_ctrl(emac_hal_context_t *hal, bool enable);
void emac_hal_isr(void *arg);
uint32_t emac_hal_get_intr_enable_status(emac_hal_context_t *hal);
void emac_hal_tx_complete_cb(void *arg);
uint32_t emac_hal_get_intr_status(emac_hal_context_t *hal);
void emac_hal_tx_unavail_cb (void *arg);
void emac_hal_clear_corresponding_intr(emac_hal_context_t *hal, uint32_t bits);
void emac_hal_rx_complete_cb (void *arg);
void emac_hal_rx_early_cb(void *arg);
void emac_hal_rx_unavail_cb(void *arg);
void emac_hal_clear_all_intr(emac_hal_context_t *hal);
#ifdef __cplusplus
}

View File

@ -0,0 +1,65 @@
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#pragma once
/**
* @brief Ethernet frame CRC length
*
*/
#define ETH_CRC_LEN (4)
/**
* @brief Ethernet interface
*
*/
typedef enum {
EMAC_INTERFACE_MII, /*!< Media Independent Interface */
EMAC_INTERFACE_RMII /*!< Reduced Media Independent Interface */
} eth_data_interface_t;
/**
* @brief Ethernet link status
*
*/
typedef enum {
ETH_LINK_UP, /*!< Ethernet link is up */
ETH_LINK_DOWN /*!< Ethernet link is down */
} eth_link_t;
/**
* @brief Ethernet speed
*
*/
typedef enum {
ETH_SPEED_10M, /*!< Ethernet speed is 10Mbps */
ETH_SPEED_100M, /*!< Ethernet speed is 100Mbps */
ETH_SPEED_MAX /*!< Max speed mode (for checking purpose) */
} eth_speed_t;
/**
* @brief Ethernet duplex mode
*
*/
typedef enum {
ETH_DUPLEX_HALF, /*!< Ethernet is in half duplex */
ETH_DUPLEX_FULL, /*!< Ethernet is in full duplex */
} eth_duplex_t;
/**
* @brief Ethernet Checksum
*/
typedef enum {
ETH_CHECKSUM_SW, /*!< Ethernet checksum calculate by software */
ETH_CHECKSUM_HW /*!< Ethernet checksum calculate by hardware */
} eth_checksum_t;

View File

@ -67,6 +67,7 @@ INPUT = \
$(IDF_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_sensor_model_api.h \
$(IDF_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_time_scene_model_api.h \
$(IDF_PATH)/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h \
$(IDF_PATH)/components/hal/include/hal/eth_types.h \
$(IDF_PATH)/components/esp_eth/include/esp_eth.h \
$(IDF_PATH)/components/esp_eth/include/esp_eth_com.h \
$(IDF_PATH)/components/esp_eth/include/esp_eth_mac.h \