feat(esp_eth): a new folder structure of the driver and other improvements

Fixed memory leak in emac_esp_new_dma function.

Polished ESP EMAC cache management.

Added emac_periph definitions based on SoC features and improved(generalized) ESP EMAC GPIO
initialization.

Added ESP EMAC GPIO reservation.

Added check for frame error condition indicated by EMAC DMA and created a target test.
This commit is contained in:
Ondrej Kosta
2024-04-26 12:27:54 +02:00
parent ee8a9e8410
commit d15a9c2c48
63 changed files with 2068 additions and 1442 deletions
+18
View File
@@ -499,6 +499,24 @@ err:
return ret;
}
esp_err_t esp_eth_get_phy_instance(esp_eth_handle_t hdl, esp_eth_phy_t **phy)
{
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
ESP_RETURN_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, TAG, "ethernet driver handle can't be null");
ESP_RETURN_ON_FALSE(phy != NULL, ESP_ERR_INVALID_ARG, TAG, "can't store PHY instance to null");
*phy = eth_driver->phy;
return ESP_OK;
}
esp_err_t esp_eth_get_mac_instance(esp_eth_handle_t hdl, esp_eth_mac_t **mac)
{
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
ESP_RETURN_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, TAG, "ethernet driver handle can't be null");
ESP_RETURN_ON_FALSE(mac != NULL, ESP_ERR_INVALID_ARG, TAG, "can't store MAC instance to null");
*mac = eth_driver->mac;
return ESP_OK;
}
esp_err_t esp_eth_increase_reference(esp_eth_handle_t hdl)
{
esp_err_t ret = ESP_OK;
@@ -1,358 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_check.h"
#include "sdkconfig.h"
#include "esp_rom_gpio.h"
#include "driver/gpio.h"
#include "soc/soc_caps.h"
#include "soc/gpio_sig_map.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_periph.h"
#include "esp_private/gpio.h"
#include "esp_private/eth_mac_esp_gpio.h"
#include "esp_log.h"
static const char *TAG = "esp.emac.gpio";
void emac_esp32_gpio_init_smi(emac_esp_smi_gpio_config_t *smi_gpio)
{
if (smi_gpio->mdc_num >= 0) {
/* Setup SMI MDC GPIO */
gpio_set_direction(smi_gpio->mdc_num, GPIO_MODE_OUTPUT);
#if CONFIG_IDF_TARGET_ESP32
esp_rom_gpio_connect_out_signal(smi_gpio->mdc_num, EMAC_MDC_O_IDX, false, false);
#elif CONFIG_IDF_TARGET_ESP32P4
esp_rom_gpio_connect_out_signal(smi_gpio->mdc_num, GMII_MDC_PAD_OUT_IDX, false, false);
#endif
gpio_func_sel(smi_gpio->mdc_num, PIN_FUNC_GPIO);
}
if (smi_gpio->mdio_num >= 0) {
/* Setup SMI MDIO GPIO */
gpio_set_direction(smi_gpio->mdio_num, GPIO_MODE_INPUT_OUTPUT);
#if CONFIG_IDF_TARGET_ESP32
esp_rom_gpio_connect_out_signal(smi_gpio->mdio_num, EMAC_MDO_O_IDX, false, false);
esp_rom_gpio_connect_in_signal(smi_gpio->mdio_num, EMAC_MDI_I_IDX, false);
#elif CONFIG_IDF_TARGET_ESP32P4
esp_rom_gpio_connect_out_signal(smi_gpio->mdio_num, GMII_MDO_PAD_OUT_IDX, false, false);
esp_rom_gpio_connect_in_signal(smi_gpio->mdio_num, GMII_MDI_PAD_IN_IDX, false);
#endif
gpio_func_sel(smi_gpio->mdio_num, PIN_FUNC_GPIO);
}
}
esp_err_t emac_esp_iomux_init_mii(emac_esp_mii_gpio_config_t *mii_gpio)
{
(void)mii_gpio;
#if CONFIG_IDF_TARGET_ESP32
/* TX_CLK to GPIO0 */
gpio_func_sel(0, FUNC_GPIO0_EMAC_TX_CLK);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
/* TX_EN to GPIO21 */
gpio_func_sel(21, FUNC_GPIO21_EMAC_TX_EN);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
/* TXD0 to GPIO19 */
gpio_func_sel(19, FUNC_GPIO19_EMAC_TXD0);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
/* TXD1 to GPIO22 */
gpio_func_sel(22, FUNC_GPIO22_EMAC_TXD1);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
/* TXD2 to MTMS */
gpio_func_sel(14, FUNC_MTMS_EMAC_TXD2);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[14]);
/* TXD3 to MTDI */
gpio_func_sel(12, FUNC_MTDI_EMAC_TXD3);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[12]);
/* RX_CLK to GPIO5 */
gpio_func_sel(5, FUNC_GPIO5_EMAC_RX_CLK);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[5]);
/* RX_DV to GPIO27 */
gpio_func_sel(27, FUNC_GPIO27_EMAC_RX_DV);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
/* RXD0 to GPIO25 */
gpio_func_sel(25, FUNC_GPIO25_EMAC_RXD0);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
/* RXD1 to GPIO26 */
gpio_func_sel(26, FUNC_GPIO26_EMAC_RXD1);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
/* RXD2 to U0TXD */
gpio_func_sel(1, FUNC_U0TXD_EMAC_RXD2);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[1]);
/* RXD3 to MTDO */
gpio_func_sel(15, FUNC_MTDO_EMAC_RXD3);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[15]);
return ESP_OK;
#elif CONFIG_IDF_TARGET_ESP32P4
ESP_LOGW(TAG, "MII is currently not supported");
return ESP_ERR_NOT_SUPPORTED;
#endif
}
esp_err_t emac_esp_iomux_rmii_clk_input(int num)
{
#if CONFIG_IDF_TARGET_ESP32
if (num != 0) {
return ESP_ERR_INVALID_ARG;
}
/* REF_CLK(RMII mode) to GPIO0 */
gpio_func_sel(0, FUNC_GPIO0_EMAC_TX_CLK);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
#elif CONFIG_IDF_TARGET_ESP32P4
/* REF_CLK(RMII mode) to `num` */
switch(num) {
case 32:
gpio_func_sel(num, FUNC_GPIO32_GMAC_RMII_CLK_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[32]);
break;
case 44:
gpio_func_sel(num, FUNC_GPIO44_GMAC_RMII_CLK_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[44]);
break;
case 50:
gpio_func_sel(num, FUNC_GPIO50_GMAC_RMII_CLK_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[50]);
break;
default:
ESP_LOGE(TAG, "invalid RMII CLK input GPIO number. Expected [32, 44, 50], actual %i", num);
return ESP_ERR_INVALID_ARG;
}
#endif
return ESP_OK;
}
esp_err_t emac_esp_iomux_rmii_clk_ouput(int num)
{
#if CONFIG_IDF_TARGET_ESP32
switch (num) {
case 0:
/* APLL clock output to GPIO0 (must be configured to 50MHz!) */
gpio_func_sel(num, FUNC_GPIO0_CLK_OUT1);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[0]);
break;
case 16:
/* RMII CLK (50MHz) output to GPIO16 */
gpio_func_sel(num, FUNC_GPIO16_EMAC_CLK_OUT);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[16]);
break;
case 17:
/* RMII CLK (50MHz) output to GPIO17 */
gpio_func_sel(num, FUNC_GPIO17_EMAC_CLK_OUT_180);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[17]);
break;
default:
ESP_LOGE(TAG, "invalid RMII CLK output GPIO number. Expected [0, 16, 17], actual %i", num);
return ESP_ERR_INVALID_ARG;
}
#elif CONFIG_IDF_TARGET_ESP32P4
/*RMII CLK output to num */
switch (num) {
case 23:
gpio_func_sel(num, FUNC_GPIO23_REF_50M_CLK_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[23]);
break;
case 39:
gpio_func_sel(num, FUNC_GPIO39_REF_50M_CLK_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[39]);
break;
default:
ESP_LOGE(TAG, "invalid RMII CLK input GPIO number. Expected [23, 39], actual %i", num);
return ESP_ERR_INVALID_ARG;
}
#endif
return ESP_OK;
}
esp_err_t emac_esp_iomux_init_rmii(emac_esp_rmii_gpio_config_t *rmii_gpio)
{
#if CONFIG_IDF_TARGET_ESP32
(void)rmii_gpio;
/* TX_EN to GPIO21 */
gpio_func_sel(21, FUNC_GPIO21_EMAC_TX_EN);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
/* TXD0 to GPIO19 */
gpio_func_sel(19, FUNC_GPIO19_EMAC_TXD0);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
/* TXD1 to GPIO22 */
gpio_func_sel(22, FUNC_GPIO22_EMAC_TXD1);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
/* CRS_DV to GPIO27 */
gpio_func_sel(27, FUNC_GPIO27_EMAC_RX_DV);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
/* RXD0 to GPIO25 */
gpio_func_sel(25, FUNC_GPIO25_EMAC_RXD0);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
/* RXD1 to GPIO26 */
gpio_func_sel(26, FUNC_GPIO26_EMAC_RXD1);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
return ESP_OK;
#elif CONFIG_IDF_TARGET_ESP32P4
if (rmii_gpio == NULL) {
return ESP_ERR_INVALID_ARG;
}
/* TX_EN */
switch(rmii_gpio->tx_en_num) {
case 33:
gpio_func_sel(rmii_gpio->tx_en_num, FUNC_GPIO33_GMAC_PHY_TXEN_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[33]);
break;
case 40:
gpio_func_sel(rmii_gpio->tx_en_num, FUNC_GPIO40_GMAC_PHY_TXEN_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[40]);
break;
case 49:
gpio_func_sel(rmii_gpio->tx_en_num, FUNC_GPIO49_GMAC_PHY_TXEN_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[49]);
break;
default:
ESP_LOGE(TAG, "invalid TX_EN GPIO number. Expected [33, 40, 49], actual %" PRIu8, rmii_gpio->tx_en_num);
return ESP_ERR_INVALID_ARG;
}
/* TXD0 */
switch(rmii_gpio->txd0_num) {
case 34:
gpio_func_sel(rmii_gpio->txd0_num, FUNC_GPIO34_GMAC_PHY_TXD0_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[34]);
break;
case 41:
gpio_func_sel(rmii_gpio->txd0_num, FUNC_GPIO41_GMAC_PHY_TXD0_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[41]);
break;
default:
ESP_LOGE(TAG, "invalid TXD0 GPIO number. Expected [34, 41], actual %" PRIu8, rmii_gpio->txd0_num);
return ESP_ERR_INVALID_ARG;
}
/* TXD1 */
switch(rmii_gpio->txd1_num) {
case 35:
gpio_func_sel(rmii_gpio->txd1_num, FUNC_GPIO35_GMAC_PHY_TXD1_PAD );
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[35]);
break;
case 42:
gpio_func_sel(rmii_gpio->txd1_num, FUNC_GPIO42_GMAC_PHY_TXD1_PAD );
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[42]);
break;
default:
ESP_LOGE(TAG, "invalid TXD1 GPIO number. Expected [35, 42], actual %" PRIu8, rmii_gpio->txd1_num);
return ESP_ERR_INVALID_ARG;
}
/* CRS_DV */
switch(rmii_gpio->crs_dv_num) {
case 28:
gpio_func_sel(rmii_gpio->crs_dv_num, FUNC_GPIO28_GMAC_PHY_RXDV_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[28]);
break;
case 45:
gpio_func_sel(rmii_gpio->crs_dv_num, FUNC_GPIO45_GMAC_PHY_RXDV_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[45]);
break;
case 51:
gpio_func_sel(rmii_gpio->crs_dv_num, FUNC_GPIO51_GMAC_PHY_RXDV_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[51]);
break;
default:
ESP_LOGE(TAG, "invalid CRS_DV GPIO number. Expected [28, 45, 51], actual %" PRIu8, rmii_gpio->crs_dv_num);
return ESP_ERR_INVALID_ARG;
}
/* RXD0 */
switch(rmii_gpio->rxd0_num) {
case 29:
gpio_func_sel(rmii_gpio->rxd0_num, FUNC_GPIO29_GMAC_PHY_RXD0_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[29]);
break;
case 46:
gpio_func_sel(rmii_gpio->rxd0_num, FUNC_GPIO46_GMAC_PHY_RXD0_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[46]);
break;
case 52:
gpio_func_sel(rmii_gpio->rxd0_num, FUNC_GPIO52_GMAC_PHY_RXD0_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[52]);
break;
default:
ESP_LOGE(TAG, "invalid RXD0 GPIO number. Expected [29, 46, 52], actual %" PRIu8, rmii_gpio->rxd0_num);
return ESP_ERR_INVALID_ARG;
}
/* RXD1 */
switch(rmii_gpio->rxd1_num) {
case 30:
gpio_func_sel(rmii_gpio->rxd1_num, FUNC_GPIO30_GMAC_PHY_RXD1_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[30]);
break;
case 47:
gpio_func_sel(rmii_gpio->rxd1_num, FUNC_GPIO47_GMAC_PHY_RXD1_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[47]);
break;
case 53:
gpio_func_sel(rmii_gpio->rxd1_num, FUNC_GPIO53_GMAC_PHY_RXD1_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[53]);
break;
default:
ESP_LOGE(TAG, "invalid RXD1 GPIO number. Expected [30, 47, 53], actual %" PRIu8, rmii_gpio->rxd1_num);
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
#endif
}
esp_err_t emac_esp_iomux_init_tx_er(int num)
{
#if CONFIG_IDF_TARGET_ESP32
(void)num;
/* TX_ER to GPIO4 */
gpio_func_sel(4, FUNC_GPIO4_EMAC_TX_ER);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[4]);
#elif CONFIG_IDF_TARGET_ESP32P4
/* TX_ER */
switch (num)
{
case 36:
gpio_func_sel(num, FUNC_GPIO36_GMAC_PHY_TXER_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[36]);
break;
case 43:
gpio_func_sel(num, FUNC_GPIO43_GMAC_PHY_TXER_PAD);
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[43]);
break;
default:
ESP_LOGE(TAG, "invalid TX_ER GPIO number. Expected [36, 43], actual %i", num);
return ESP_ERR_INVALID_ARG;
}
#endif
return ESP_OK;
}
esp_err_t emac_esp_iomux_init_rx_er(int num)
{
#if CONFIG_IDF_TARGET_ESP32
(void)num;
/* RX_ER to MTCK */
gpio_func_sel(13, FUNC_MTCK_EMAC_RX_ER);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[13]);
#elif CONFIG_IDF_TARGET_ESP32P4
/* RX_ER */
switch (num)
{
case 31:
gpio_func_sel(num, FUNC_GPIO31_GMAC_PHY_RXER_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[31]);
break;
case 48:
gpio_func_sel(num, FUNC_GPIO48_GMAC_PHY_RXER_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[48]);
break;
case 54:
gpio_func_sel(num, FUNC_GPIO54_GMAC_PHY_RXER_PAD);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[54]);
break;
default:
ESP_LOGE(TAG, "invalid RX_ER GPIO number. Expected [31, 48, 54], actual %i", num);
return ESP_ERR_INVALID_ARG;
}
#endif
return ESP_OK;
}
@@ -6,7 +6,6 @@
#include <stdlib.h>
#include <inttypes.h>
#include "esp_netif.h"
#include "esp_eth_driver.h"
#include "esp_eth_netif_glue.h"
#include "esp_netif_net_stack.h"
#include "esp_event.h"
@@ -12,7 +12,6 @@
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_eth_driver.h"
#include "esp_pm.h"
#include "esp_mac.h"
#include "esp_cpu.h"
@@ -66,8 +65,6 @@ typedef struct {
uint32_t free_rx_descriptor;
uint32_t flow_control_high_water_mark;
uint32_t flow_control_low_water_mark;
emac_esp_smi_gpio_config_t smi_gpio;
eth_mac_clock_config_t clock_config;
uint8_t addr[ETH_ADDR_LEN];
bool isr_need_yield;
bool flow_ctrl_enabled; // indicates whether the user want to do flow control
@@ -82,19 +79,10 @@ typedef struct {
#ifdef CONFIG_IDF_TARGET_ESP32
esp_clock_output_mapping_handle_t rmii_clk_hdl; // we use the esp_clock_output driver to output a pre-configured APLL clock as the RMII reference clock
#endif
#ifdef CONFIG_IDF_TARGET_ESP32P4
eth_mac_clock_config_t clock_config_out_in;
union
{
emac_esp_mii_gpio_config_t mii_gpio;
emac_esp_rmii_gpio_config_t rmii_gpio;
};
#endif // CONFIG_IDF_TARGET_ESP32P4
} emac_esp32_t;
static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl);
static void esp_emac_free_driver_obj(emac_esp32_t *emac);
static esp_err_t emac_esp_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl);
static void emac_esp_free_driver_obj(emac_esp32_t *emac);
static esp_err_t emac_esp32_start(esp_eth_mac_t *mac);
static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac);
@@ -209,11 +197,11 @@ static esp_err_t emac_esp32_set_speed(esp_eth_mac_t *mac, eth_speed_t speed)
// Set RMII clk_rx/clk_tx divider to get 25MHz for 100mbps mode or 2.5MHz for 10mbps mode
if (emac_hal_get_phy_intf(&emac->hal) == EMAC_DATA_INTERFACE_RMII) {
if (speed == ETH_SPEED_10M) {
EMAC_IF_RCC_ATOMIC () {
EMAC_IF_RCC_ATOMIC() {
emac_hal_clock_rmii_rx_tx_div(&emac->hal, RMII_10M_SPEED_RX_TX_CLK_DIV);
}
} else {
EMAC_IF_RCC_ATOMIC () {
EMAC_IF_RCC_ATOMIC() {
emac_hal_clock_rmii_rx_tx_div(&emac->hal, RMII_100M_SPEED_RX_TX_CLK_DIV);
}
}
@@ -268,6 +256,28 @@ static esp_err_t emac_esp32_set_peer_pause_ability(esp_eth_mac_t *mac, uint32_t
return ESP_OK;
}
esp_err_t emac_esp_custom_ioctl(esp_eth_mac_t *mac, int cmd, void *data)
{
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
switch (cmd)
{
case ETH_MAC_ESP_CMD_PTP_ENABLE:
return ESP_ERR_NOT_SUPPORTED;
case ETH_MAC_ESP_CMD_SET_TDES0_CFG_BITS:
ESP_RETURN_ON_FALSE(data != NULL, ESP_ERR_INVALID_ARG, TAG, "cannot set DMA tx desc flag to null");
emac_esp_dma_set_tdes0_ctrl_bits(emac->emac_dma_hndl, *(uint32_t *)data);
break;
case ETH_MAC_ESP_CMD_CLEAR_TDES0_CFG_BITS:
ESP_RETURN_ON_FALSE(data != NULL, ESP_ERR_INVALID_ARG, TAG, "cannot clear DMA tx desc flag with null");
emac_esp_dma_clear_tdes0_ctrl_bits(emac->emac_dma_hndl, *(uint32_t *)data);
break;
default:
ESP_RETURN_ON_ERROR(ESP_ERR_INVALID_ARG, TAG, "unknown io command: %i", cmd);
}
return ESP_OK;
}
static esp_err_t emac_esp32_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length)
{
esp_err_t ret = ESP_OK;
@@ -304,7 +314,8 @@ static esp_err_t emac_esp32_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *
uint32_t expected_len = *length;
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
ESP_GOTO_ON_FALSE(buf && length, ESP_ERR_INVALID_ARG, err, TAG, "can't set buf and length to null");
uint32_t receive_len = emac_esp_dma_receive_frame(emac->emac_dma_hndl, buf, expected_len, &emac->frames_remain, &emac->free_rx_descriptor);
uint32_t receive_len = emac_esp_dma_receive_frame(emac->emac_dma_hndl, buf, expected_len);
emac_esp_dma_get_remain_frames(emac->emac_dma_hndl, &emac->frames_remain, &emac->free_rx_descriptor);
/* we need to check the return value in case the buffer size is not enough */
ESP_GOTO_ON_FALSE(expected_len >= receive_len, ESP_ERR_INVALID_SIZE, err, TAG, "received buffer longer than expected");
*length = receive_len;
@@ -327,12 +338,12 @@ static void emac_esp32_rx_task(void *arg)
buffer = emac_esp_dma_alloc_recv_buf(emac->emac_dma_hndl, &frame_len);
/* we have memory to receive the frame of maximal size previously defined */
if (buffer != NULL) {
uint32_t recv_len = emac_esp_dma_receive_frame(emac->emac_dma_hndl, buffer, EMAC_HAL_BUF_SIZE_AUTO, &emac->frames_remain, &emac->free_rx_descriptor);
uint32_t recv_len = emac_esp_dma_receive_frame(emac->emac_dma_hndl, buffer, EMAC_DMA_BUF_SIZE_AUTO);
if (recv_len == 0) {
ESP_LOGE(TAG, "frame copy error");
free(buffer);
/* ensure that interface to EMAC does not get stuck with unprocessed frames */
emac_esp_dma_flush_recv_frame(emac->emac_dma_hndl, &emac->frames_remain, &emac->free_rx_descriptor);
emac_esp_dma_flush_recv_frame(emac->emac_dma_hndl);
} else if (frame_len > recv_len) {
ESP_LOGE(TAG, "received frame was truncated");
free(buffer);
@@ -344,8 +355,9 @@ static void emac_esp32_rx_task(void *arg)
} else if (frame_len) {
ESP_LOGE(TAG, "no mem for receive buffer");
/* ensure that interface to EMAC does not get stuck with unprocessed frames */
emac_esp_dma_flush_recv_frame(emac->emac_dma_hndl, &emac->frames_remain, &emac->free_rx_descriptor);
emac_esp_dma_flush_recv_frame(emac->emac_dma_hndl);
}
emac_esp_dma_get_remain_frames(emac->emac_dma_hndl, &emac->frames_remain, &emac->free_rx_descriptor);
#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) {
@@ -401,8 +413,6 @@ static esp_err_t emac_esp32_init(esp_eth_mac_t *mac)
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
esp_eth_mediator_t *eth = emac->eth;
/* init gpio used by smi interface */
emac_esp32_gpio_init_smi(&emac->smi_gpio);
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);
@@ -451,7 +461,7 @@ static esp_err_t emac_esp32_start(esp_eth_mac_t *mac)
{
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
/* reset descriptor chain */
emac_esp_dma_reset_desc_chain(emac->emac_dma_hndl);
emac_esp_dma_reset(emac->emac_dma_hndl);
emac_hal_start(&emac->hal);
return ESP_OK;
}
@@ -474,8 +484,9 @@ static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac)
static esp_err_t emac_esp32_del(esp_eth_mac_t *mac)
{
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
esp_emac_free_driver_obj(emac);
/// disable bus clock
emac_esp_free_driver_obj(emac);
emac_esp_gpio_deinit_all();
// disable bus clock
PERIPH_RCC_ATOMIC() {
emac_ll_enable_bus_clock(0, false);
}
@@ -502,7 +513,7 @@ IRAM_ATTR void emac_isr_default_handler(void *args)
#endif
}
static void esp_emac_free_driver_obj(emac_esp32_t *emac)
static void emac_esp_free_driver_obj(emac_esp32_t *emac)
{
if (emac) {
if (emac->rx_task_hdl) {
@@ -537,7 +548,7 @@ static void esp_emac_free_driver_obj(emac_esp32_t *emac)
}
}
static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl)
static esp_err_t emac_esp_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl)
{
esp_err_t ret = ESP_OK;
emac_esp32_t *emac = NULL;
@@ -548,8 +559,7 @@ static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_
}
ESP_GOTO_ON_FALSE(emac, ESP_ERR_NO_MEM, err, TAG, "no mem for esp emac object");
emac_esp_dma_config_t emac_dma_config;
ESP_GOTO_ON_ERROR(emac_esp_new_dma(&emac_dma_config, &emac->emac_dma_hndl), err, TAG, "create EMAC DMA object failed");
ESP_GOTO_ON_ERROR(emac_esp_new_dma(NULL, &emac->emac_dma_hndl), err, TAG, "create EMAC DMA object failed");
/* alloc PM lock */
#ifdef CONFIG_PM_ENABLE
@@ -565,88 +575,65 @@ static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_
ESP_GOTO_ON_FALSE(xReturned == pdPASS, ESP_FAIL, err, TAG, "create emac_rx task failed");
*emac_out_hdl = emac;
return ESP_OK;
err:
esp_emac_free_driver_obj(emac);
return ret;
}
static esp_err_t esp_emac_config_data_interface(const eth_esp32_emac_config_t *esp32_emac_config, emac_esp32_t *emac)
static esp_err_t emac_esp_config_data_interface(const eth_esp32_emac_config_t *esp32_emac_config, emac_esp32_t *emac)
{
esp_err_t ret = ESP_OK;
switch (esp32_emac_config->interface) {
case EMAC_DATA_INTERFACE_MII:
emac->clock_config = esp32_emac_config->clock_config;
/* MII interface GPIO initialization */
ESP_GOTO_ON_ERROR(emac_esp_iomux_init_mii(NULL), err, TAG, "invalid EMAC MII data plane GPIO");
#if SOC_EMAC_MII_USE_GPIO_MATRIX
ESP_GOTO_ON_ERROR(emac_esp_gpio_matrix_init_mii(&esp32_emac_config->emac_dataif_gpio.mii), err, TAG, "failed to initialize EMAC MII GPIO Matrix");
#else
eth_mac_mii_gpio_config_t *mii_data_gpio = NULL;
#if SOC_EMAC_USE_MULTI_IO_MUX
mii_data_gpio = &esp32_emac_config->emac_dataif_gpio.mii;
#endif // SOC_EMAC_USE_MULTI_IO_MUX
ESP_GOTO_ON_ERROR(emac_esp_iomux_init_mii(mii_data_gpio), err, TAG, "invalid EMAC MII data plane GPIO");
#endif // SOC_EMAC_MII_USE_GPIO_MATRIX
/* Enable MII clock */
EMAC_IF_RCC_ATOMIC() {
emac_hal_clock_enable_mii(&emac->hal);
}
break;
case EMAC_DATA_INTERFACE_RMII:
// by default, the clock mode is selected at compile time (by Kconfig)
if (esp32_emac_config->clock_config.rmii.clock_mode == EMAC_CLK_DEFAULT) {
#ifdef CONFIG_IDF_TARGET_ESP32
#if CONFIG_ETH_RMII_CLK_INPUT
#if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
emac->clock_config.rmii.clock_mode = EMAC_CLK_EXT_IN;
emac->clock_config.rmii.clock_gpio = CONFIG_ETH_RMII_CLK_IN_GPIO;
#else
#error "ESP32 EMAC only support input RMII clock to GPIO0"
#endif // CONFIG_ETH_RMII_CLK_IN_GPIO == 0
#elif CONFIG_ETH_RMII_CLK_OUTPUT
emac->clock_config.rmii.clock_mode = EMAC_CLK_OUT;
#if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
emac->clock_config.rmii.clock_gpio = 0;
#elif CONFIG_ETH_RMII_CLK_OUT_GPIO
emac->clock_config.rmii.clock_gpio = CONFIG_ETH_RMII_CLK_OUT_GPIO;
#endif // CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
#else
#error "Unsupported RMII clock mode"
#endif // CONFIG_ETH_RMII_CLK_INPUT
#else // EMAC_CLK_DEFAULT "not supported for ESP32P4" - this configuration has been kept due to compatibility reasons for ESP32
ESP_LOGE(TAG, "EMAC_CLK_DEFAULT options is only supported by ESP32");
return ESP_ERR_INVALID_ARG;
#endif // CONFIG_IDF_TARGET_ESP32
} else {
emac->clock_config = esp32_emac_config->clock_config;
#ifdef CONFIG_IDF_TARGET_ESP32P4
emac->clock_config_out_in = esp32_emac_config->clock_config_out_in;
#endif // CONFIG_IDF_TARGET_ESP32P4
}
/* RMII interface GPIO initialization */
#ifdef CONFIG_IDF_TARGET_ESP32
ESP_GOTO_ON_ERROR(emac_esp_iomux_init_rmii(NULL), err, TAG, "invalid EMAC RMII data plane GPIO");
#else
ESP_GOTO_ON_ERROR(emac_esp_iomux_init_rmii(&emac->rmii_gpio), err, TAG, "invalid EMAC RMII data plane GPIO");
#endif // CONFIG_IDF_TARGET_ESP32
const eth_mac_rmii_gpio_config_t *rmii_data_gpio = NULL;
#if SOC_EMAC_USE_MULTI_IO_MUX
rmii_data_gpio = &esp32_emac_config->emac_dataif_gpio.rmii;
#endif // SOC_EMAC_USE_MULTI_IO_MUX
ESP_GOTO_ON_ERROR(emac_esp_iomux_init_rmii(rmii_data_gpio), err, TAG, "invalid EMAC RMII data plane GPIO");
/* If ref_clk is configured as input */
if (emac->clock_config.rmii.clock_mode == EMAC_CLK_EXT_IN) {
ESP_GOTO_ON_ERROR(emac_esp_iomux_rmii_clk_input(emac->clock_config.rmii.clock_gpio), err, TAG, "invalid EMAC RMII clock input GPIO");
if (esp32_emac_config->clock_config.rmii.clock_mode == EMAC_CLK_EXT_IN) {
ESP_GOTO_ON_ERROR(emac_esp_iomux_rmii_clk_input(esp32_emac_config->clock_config.rmii.clock_gpio), err, TAG, "invalid EMAC RMII clock input GPIO");
EMAC_IF_RCC_ATOMIC() {
emac_hal_clock_enable_rmii_input(&emac->hal);
}
} else if (emac->clock_config.rmii.clock_mode == EMAC_CLK_OUT) {
} else if (esp32_emac_config->clock_config.rmii.clock_mode == EMAC_CLK_OUT) {
ESP_GOTO_ON_ERROR(emac_config_pll_clock(emac), err, TAG, "Configure (A/M)PLL for RMII failed");
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_IDF_TARGET_ESP32P4
/* Output RMII clock is routed back to input externally */
ESP_GOTO_ON_FALSE(esp32_emac_config->clock_config_out_in.rmii.clock_mode == EMAC_CLK_EXT_IN && esp32_emac_config->clock_config_out_in.rmii.clock_gpio >= 0,
ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC input of output clock mode");
ESP_GOTO_ON_ERROR(emac_esp_iomux_rmii_clk_input(esp32_emac_config->clock_config_out_in.rmii.clock_gpio), err, TAG, "invalid EMAC RMII clock input GPIO");
EMAC_IF_RCC_ATOMIC() {
emac_hal_clock_enable_rmii_input(&emac->hal);
}
#elif CONFIG_IDF_TARGET_ESP32
// we can also use the IOMUX to route the APLL clock to specific GPIO
if (emac->clock_config.rmii.clock_gpio == EMAC_APPL_CLK_OUT_GPIO) {
if (esp32_emac_config->clock_config.rmii.clock_gpio == EMAC_APPL_CLK_OUT_GPIO) {
ESP_GOTO_ON_ERROR(esp_clock_output_start(CLKOUT_SIG_APLL, EMAC_APPL_CLK_OUT_GPIO, &emac->rmii_clk_hdl),
err, TAG, "start APLL clock output failed");
}
#elif CONFIG_IDF_TARGET_ESP32P4
/* Output RMII clock is routed back to input externally */
ESP_GOTO_ON_FALSE(emac->clock_config_out_in.rmii.clock_mode == EMAC_CLK_EXT_IN && emac->clock_config_out_in.rmii.clock_gpio >= 0,
ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC input of output clock mode");
ESP_GOTO_ON_ERROR(emac_esp_iomux_rmii_clk_input(emac->clock_config_out_in.rmii.clock_gpio), err, TAG, "invalid EMAC RMII clock input GPIO");
EMAC_IF_RCC_ATOMIC() {
emac_hal_clock_enable_rmii_input(&emac->hal);
}
} else
#endif
ESP_GOTO_ON_ERROR(emac_esp_iomux_rmii_clk_ouput(emac->clock_config.rmii.clock_gpio), err, TAG, "invalid EMAC RMII clock output GPIO");
{
ESP_GOTO_ON_ERROR(emac_esp_iomux_rmii_clk_ouput(esp32_emac_config->clock_config.rmii.clock_gpio), err, TAG, "invalid EMAC RMII clock output GPIO");
}
/* Enable RMII Output clock */
EMAC_IF_RCC_ATOMIC () {
EMAC_IF_RCC_ATOMIC() {
emac_hal_clock_enable_rmii_output(&emac->hal);
}
} else {
@@ -671,7 +658,7 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config
TAG, "invalid interrupt priority: %d", esp32_config->intr_priority);
}
ret_code = esp_emac_alloc_driver_obj(config, &emac);
ret_code = emac_esp_alloc_driver_obj(config, &emac);
ESP_RETURN_ON_FALSE(ret_code == ESP_OK, NULL, TAG, "alloc driver object failed");
// enable bus clock for the EMAC module, and reset the registers into default state
@@ -697,21 +684,15 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config
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 SOC_EMAC_USE_IO_MUX
emac->rmii_gpio.tx_en_num = esp32_config->emac_dataif_gpio.rmii.tx_en_num;
emac->rmii_gpio.txd0_num = esp32_config->emac_dataif_gpio.rmii.txd0_num;
emac->rmii_gpio.txd1_num = esp32_config->emac_dataif_gpio.rmii.txd1_num;
emac->rmii_gpio.crs_dv_num = esp32_config->emac_dataif_gpio.rmii.crs_dv_num;
emac->rmii_gpio.rxd0_num = esp32_config->emac_dataif_gpio.rmii.rxd0_num;
emac->rmii_gpio.rxd1_num = esp32_config->emac_dataif_gpio.rmii.rxd1_num;
#endif // SOC_EMAC_USE_IO_MUX
ret_code = esp_emac_config_data_interface(esp32_config, emac);
/* init GPIO used by SMI interface */
ret_code = emac_esp_gpio_init_smi(&esp32_config->smi_gpio);
ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "SMI GPIO init failed");
/* init GPIO and CLK for data interface */
ret_code = emac_esp_config_data_interface(esp32_config, emac);
ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "config emac interface failed");
emac->dma_burst_len = esp32_config->dma_burst_len;
emac->sw_reset_timeout_ms = config->sw_reset_timeout_ms;
emac->smi_gpio.mdc_num = esp32_config->smi_mdc_gpio_num;
emac->smi_gpio.mdio_num = esp32_config->smi_mdio_gpio_num;
emac->flow_control_high_water_mark = FLOW_CONTROL_HIGH_WATER_MARK;
emac->flow_control_low_water_mark = FLOW_CONTROL_LOW_WATER_MARK;
@@ -734,9 +715,11 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config
emac->parent.transmit = emac_esp32_transmit;
emac->parent.transmit_vargs = emac_esp32_transmit_multiple_bufs;
emac->parent.receive = emac_esp32_receive;
emac->parent.custom_ioctl = emac_esp_custom_ioctl;
return &(emac->parent);
err:
esp_emac_free_driver_obj(emac);
emac_esp_free_driver_obj(emac);
emac_esp_gpio_deinit_all();
return ret;
}
@@ -16,13 +16,36 @@
#define ETH_CRC_LENGTH (4)
#define EMAC_HAL_BUF_MAGIC_ID 0x1E1C8416
#define EMAC_ALLOC_BUF_MAGIC_ID 0x1E1C8416
#define EMAC_TDES0_FS_CTRL_FLAGS_MASK 0x0FCC0000 // modifiable bits mask associated with the First Segment
#define EMAC_TDES0_LS_CTRL_FLAGS_MASK 0x40000000 // modifiable bits mask associated with the Last Segment
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#define DMA_CACHE_WB(addr, size) do { \
esp_err_t msync_ret = esp_cache_msync((void *)addr, size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); \
assert(msync_ret == ESP_OK); \
} while(0)
#else
#define DMA_CACHE_WB(addr, size)
#endif
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#define DMA_CACHE_INVALIDATE(addr, size) do { \
esp_err_t msync_ret = esp_cache_msync((void *)addr, size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); \
assert(msync_ret == ESP_OK); \
} while(0)
#else
#define DMA_CACHE_INVALIDATE(addr, size)
#endif
static const char *TAG = "esp.emac.dma";
struct emac_esp_dma_t
{
emac_hal_context_t hal;
uint32_t tx_desc_flags;
uint32_t rx_desc_flags;
void *descriptors;
eth_dma_rx_descriptor_t *rx_desc;
eth_dma_tx_descriptor_t *tx_desc;
@@ -37,13 +60,8 @@ typedef struct {
uint32_t copy_len;
}__attribute__((packed)) emac_esp_dma_auto_buf_info_t;
void emac_esp_dma_reset_desc_chain(emac_esp_dma_handle_t emac_esp_dma)
void emac_esp_dma_reset(emac_esp_dma_handle_t emac_esp_dma)
{
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t cache_sync_len;
esp_err_t ret = ESP_OK;
#endif
/* reset DMA descriptors */
emac_esp_dma->rx_desc = (eth_dma_rx_descriptor_t *)(emac_esp_dma->descriptors);
emac_esp_dma->tx_desc = (eth_dma_tx_descriptor_t *)(emac_esp_dma->descriptors +
@@ -66,11 +84,7 @@ void emac_esp_dma_reset_desc_chain(emac_esp_dma_handle_t emac_esp_dma)
if (i == CONFIG_ETH_DMA_RX_BUFFER_NUM - 1) {
emac_esp_dma->rx_desc[i].Buffer2NextDescAddr = (uint32_t)(emac_esp_dma->rx_desc);
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
ret = esp_cache_msync((void *)&emac_esp_dma->rx_desc[i], cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(&emac_esp_dma->rx_desc[i], EMAC_HAL_DMA_DESC_SIZE);
}
/* init tx chain */
@@ -79,10 +93,6 @@ void emac_esp_dma_reset_desc_chain(emac_esp_dma_handle_t emac_esp_dma)
emac_esp_dma->tx_desc[i].TDES0.Own = EMAC_LL_DMADESC_OWNER_CPU;
emac_esp_dma->tx_desc[i].TDES0.SecondAddressChained = 1;
emac_esp_dma->tx_desc[i].TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
/* Enable Ethernet DMA Tx Descriptor interrupt */
emac_esp_dma->tx_desc[1].TDES0.InterruptOnComplete = 1;
/* Enable Transmit Timestamp */
emac_esp_dma->tx_desc[i].TDES0.TransmitTimestampEnable = 1;
/* point to the buffer */
emac_esp_dma->tx_desc[i].Buffer1Addr = (uint32_t)(emac_esp_dma->tx_buf[i]);
/* point to next descriptor */
@@ -92,24 +102,25 @@ void emac_esp_dma_reset_desc_chain(emac_esp_dma_handle_t emac_esp_dma)
if (i == CONFIG_ETH_DMA_TX_BUFFER_NUM - 1) {
emac_esp_dma->tx_desc[i].Buffer2NextDescAddr = (uint32_t)(emac_esp_dma->tx_desc);
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_tx_descriptor_t);
ret = esp_cache_msync((void *)&emac_esp_dma->tx_desc[i], cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(&emac_esp_dma->tx_desc[i], EMAC_HAL_DMA_DESC_SIZE);
}
/* set base address of the first descriptor */
emac_hal_set_rx_tx_desc_addr(&emac_esp_dma->hal, emac_esp_dma->rx_desc, emac_esp_dma->tx_desc);
}
void emac_esp_dma_set_tdes0_ctrl_bits(emac_esp_dma_handle_t emac_esp_dma, uint32_t flag)
{
emac_esp_dma->tx_desc_flags |= flag;
}
void emac_esp_dma_clear_tdes0_ctrl_bits(emac_esp_dma_handle_t emac_esp_dma, uint32_t flag)
{
emac_esp_dma->tx_desc_flags &= ~flag;
}
uint32_t emac_esp_dma_transmit_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t *buf, uint32_t length)
{
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_err_t ret;
size_t cache_sync_len;
#endif
/* Get the number of Tx buffers to use for the frame */
uint32_t bufcount = 0;
uint32_t lastlen = length;
@@ -128,11 +139,7 @@ uint32_t emac_esp_dma_transmit_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t
eth_dma_tx_descriptor_t *desc_iter = emac_esp_dma->tx_desc;
/* A frame is transmitted in multiple descriptor */
for (size_t i = 0; i < bufcount; i++) {
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_tx_descriptor_t);
ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
/* 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;
@@ -140,17 +147,16 @@ uint32_t emac_esp_dma_transmit_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t
/* Clear FIRST and LAST segment bits */
desc_iter->TDES0.FirstSegment = 0;
desc_iter->TDES0.LastSegment = 0;
desc_iter->TDES0.InterruptOnComplete = 0;
desc_iter->TDES0.Value &= ~(EMAC_TDES0_FS_CTRL_FLAGS_MASK | EMAC_TDES0_LS_CTRL_FLAGS_MASK);
if (i == 0) {
/* Setting the first segment bit */
desc_iter->TDES0.FirstSegment = 1;
//desc_iter->TDES0.DisableCRC = 1;
desc_iter->TDES0.Value |= emac_esp_dma->tx_desc_flags & EMAC_TDES0_FS_CTRL_FLAGS_MASK;
}
if (i == (bufcount - 1)) {
/* Setting the last segment bit */
desc_iter->TDES0.LastSegment = 1;
/* Enable transmit interrupt */
desc_iter->TDES0.InterruptOnComplete = 1;
desc_iter->TDES0.Value |= emac_esp_dma->tx_desc_flags & EMAC_TDES0_LS_CTRL_FLAGS_MASK;
/* Program size */
desc_iter->TDES1.TransmitBuffer1Size = lastlen;
/* copy data from uplayer stack buffer */
@@ -163,11 +169,7 @@ uint32_t emac_esp_dma_transmit_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t
memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE);
sentout += CONFIG_ETH_DMA_BUFFER_SIZE;
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = CONFIG_ETH_DMA_BUFFER_SIZE;
ret = esp_cache_msync((void *)desc_iter->Buffer1Addr, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(desc_iter->Buffer1Addr, CONFIG_ETH_DMA_BUFFER_SIZE);
/* Point to next descriptor */
desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
@@ -175,11 +177,7 @@ uint32_t emac_esp_dma_transmit_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
for (size_t i = 0; i < bufcount; i++) {
emac_esp_dma->tx_desc->TDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_tx_descriptor_t);
ret = esp_cache_msync((void *)emac_esp_dma->tx_desc, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(emac_esp_dma->tx_desc, EMAC_HAL_DMA_DESC_SIZE);
emac_esp_dma->tx_desc = (eth_dma_tx_descriptor_t *)(emac_esp_dma->tx_desc->Buffer2NextDescAddr);
}
emac_hal_transmit_poll_demand(&emac_esp_dma->hal);
@@ -190,11 +188,6 @@ err:
uint32_t emac_esp_dma_transmit_multiple_buf_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t **buffs, uint32_t *lengths, uint32_t buffs_cnt)
{
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_err_t ret;
size_t cache_sync_len;
#endif
/* Get the number of Tx buffers to use for the frame */
uint32_t dma_bufcount = 0;
uint32_t sentout = 0;
@@ -205,11 +198,7 @@ uint32_t emac_esp_dma_transmit_multiple_buf_frame(emac_esp_dma_handle_t emac_esp
eth_dma_tx_descriptor_t *desc_iter = emac_esp_dma->tx_desc;
/* A frame is transmitted in multiple descriptor */
while (dma_bufcount < CONFIG_ETH_DMA_TX_BUFFER_NUM) {
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_tx_descriptor_t);
ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
/* 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;
@@ -217,11 +206,12 @@ uint32_t emac_esp_dma_transmit_multiple_buf_frame(emac_esp_dma_handle_t emac_esp
/* Clear FIRST and LAST segment bits */
desc_iter->TDES0.FirstSegment = 0;
desc_iter->TDES0.LastSegment = 0;
desc_iter->TDES0.InterruptOnComplete = 0;
desc_iter->TDES0.Value &= ~(EMAC_TDES0_FS_CTRL_FLAGS_MASK | EMAC_TDES0_LS_CTRL_FLAGS_MASK);
desc_iter->TDES1.TransmitBuffer1Size = 0;
if (dma_bufcount == 0) {
/* Setting the first segment bit */
desc_iter->TDES0.FirstSegment = 1;
desc_iter->TDES0.Value |= emac_esp_dma->tx_desc_flags & EMAC_TDES0_FS_CTRL_FLAGS_MASK;
}
while (buffs_cnt > 0) {
@@ -259,11 +249,7 @@ uint32_t emac_esp_dma_transmit_multiple_buf_frame(emac_esp_dma_handle_t emac_esp
break;
}
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = CONFIG_ETH_DMA_BUFFER_SIZE;
ret = esp_cache_msync((void *)desc_iter->Buffer1Addr, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(desc_iter->Buffer1Addr, CONFIG_ETH_DMA_BUFFER_SIZE);
/* Increase counter of utilized DMA buffers */
dma_bufcount++;
@@ -271,8 +257,7 @@ uint32_t emac_esp_dma_transmit_multiple_buf_frame(emac_esp_dma_handle_t emac_esp
if (buffs_cnt == 0) {
/* Setting the last segment bit */
desc_iter->TDES0.LastSegment = 1;
/* Enable transmit interrupt */
desc_iter->TDES0.InterruptOnComplete = 1;
desc_iter->TDES0.Value |= emac_esp_dma->tx_desc_flags & EMAC_TDES0_LS_CTRL_FLAGS_MASK;
break;
}
@@ -283,11 +268,7 @@ uint32_t emac_esp_dma_transmit_multiple_buf_frame(emac_esp_dma_handle_t emac_esp
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
for (size_t i = 0; i < dma_bufcount; i++) {
emac_esp_dma->tx_desc->TDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_tx_descriptor_t);
ret = esp_cache_msync((void *)emac_esp_dma->tx_desc, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(emac_esp_dma->tx_desc, EMAC_HAL_DMA_DESC_SIZE);
emac_esp_dma->tx_desc = (eth_dma_tx_descriptor_t *)(emac_esp_dma->tx_desc->Buffer2NextDescAddr);
}
@@ -301,25 +282,20 @@ static esp_err_t emac_esp_dma_get_valid_recv_len(emac_esp_dma_handle_t emac_esp_
{
eth_dma_rx_descriptor_t *desc_iter = emac_esp_dma->rx_desc;
uint32_t used_descs = 0;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
esp_err_t ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
/* Traverse descriptors owned by CPU */
while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
while ((desc_iter->RDES0.Own == EMAC_LL_DMADESC_OWNER_CPU) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
used_descs++;
/* Last segment in frame */
if (desc_iter->RDES0.LastDescriptor) {
#if CONFIG_IDF_TARGET_ESP32P4
/* Since Store Forward must be disabled at ESP32P4, DMA descriptors may contain erroneous frames */
/* Since Store Forward must be disabled on some targets, DMA descriptors may contain erroneous frames */
/* In addition, "Descriptor Error" (no free descriptors) may truncate a frame even if Store Forward is enabled */
if (desc_iter->RDES0.ErrSummary) {
emac_esp_dma_flush_recv_frame(emac_esp_dma, NULL, NULL);
emac_esp_dma_flush_recv_frame(emac_esp_dma);
*ret_len = 0;
return ESP_FAIL;
}
#endif //CONFIG_IDF_TARGET_ESP32P4
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
*ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
break;
@@ -330,42 +306,31 @@ static esp_err_t emac_esp_dma_get_valid_recv_len(emac_esp_dma_handle_t emac_esp_
}
/* point to next descriptor */
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
esp_err_t ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
}
return ESP_OK;
}
static void emac_esp_dma_get_remain_frames(emac_esp_dma_handle_t emac_esp_dma, uint32_t *remain_frames, uint32_t *used_descs)
void emac_esp_dma_get_remain_frames(emac_esp_dma_handle_t emac_esp_dma, uint32_t *remain_frames, uint32_t *free_descs)
{
eth_dma_rx_descriptor_t *desc_iter = emac_esp_dma->rx_desc;
*remain_frames = 0;
*used_descs = 0;
uint32_t used_descs = 0;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
esp_err_t ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
/* Traverse descriptors owned by CPU */
while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (*used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
(*used_descs)++;
while ((desc_iter->RDES0.Own == EMAC_LL_DMADESC_OWNER_CPU) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
used_descs++;
/* Last segment in frame */
if (desc_iter->RDES0.LastDescriptor) {
(*remain_frames)++;
}
/* point to next descriptor */
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
esp_err_t ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
}
*free_descs = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
}
uint8_t *emac_esp_dma_alloc_recv_buf(emac_esp_dma_handle_t emac_esp_dma, uint32_t *size)
@@ -388,7 +353,7 @@ uint8_t *emac_esp_dma_alloc_recv_buf(emac_esp_dma_handle_t emac_esp_dma, uint32_
/* no need to check allocated buffer min length prior writing since we know that EMAC DMA is configured to
not forward erroneous or undersized frames (less than 64B) on ESP32, see emac_hal_init_dma_default */
#ifndef NDEBUG
buff_info->magic_id = EMAC_HAL_BUF_MAGIC_ID;
buff_info->magic_id = EMAC_ALLOC_BUF_MAGIC_ID;
#endif // NDEBUG
buff_info->copy_len = copy_len;
}
@@ -398,20 +363,14 @@ uint8_t *emac_esp_dma_alloc_recv_buf(emac_esp_dma_handle_t emac_esp_dma, uint32_
return buf;
}
uint32_t emac_esp_dma_receive_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t *buf, uint32_t size, uint32_t *frames_remain, uint32_t *free_desc)
uint32_t emac_esp_dma_receive_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t *buf, uint32_t size)
{
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t cache_sync_len;
esp_err_t ret;
#endif
eth_dma_rx_descriptor_t *desc_iter = emac_esp_dma->rx_desc;
eth_dma_rx_descriptor_t *first_desc = emac_esp_dma->rx_desc;
uint32_t ret_len = 0;
uint32_t copy_len = 0;
if (size != EMAC_HAL_BUF_SIZE_AUTO) {
if (size != EMAC_DMA_BUF_SIZE_AUTO) {
if (emac_esp_dma_get_valid_recv_len(emac_esp_dma, &ret_len) != ESP_OK) {
goto err;
return 0;
}
/* packets larger than expected will be truncated */
copy_len = ret_len > size ? size : ret_len;
@@ -419,106 +378,75 @@ uint32_t emac_esp_dma_receive_frame(emac_esp_dma_handle_t emac_esp_dma, uint8_t
emac_esp_dma_auto_buf_info_t *buff_info = (emac_esp_dma_auto_buf_info_t *)buf;
#ifndef NDEBUG
/* check that buffer was allocated by emac_esp_dma_alloc_recv_buf */
assert(buff_info->magic_id == EMAC_HAL_BUF_MAGIC_ID);
assert(buff_info->magic_id == EMAC_ALLOC_BUF_MAGIC_ID);
#endif // NDEBUG
copy_len = buff_info->copy_len;
ret_len = copy_len;
}
if (copy_len) {
desc_iter = first_desc;
eth_dma_rx_descriptor_t *desc_iter = emac_esp_dma->rx_desc;
while(copy_len > CONFIG_ETH_DMA_BUFFER_SIZE) {
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = CONFIG_ETH_DMA_BUFFER_SIZE;
ret = esp_cache_msync((void *)desc_iter->Buffer1Addr, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter->Buffer1Addr, CONFIG_ETH_DMA_BUFFER_SIZE);
memcpy(buf, (void *)(desc_iter->Buffer1Addr), CONFIG_ETH_DMA_BUFFER_SIZE);
buf += CONFIG_ETH_DMA_BUFFER_SIZE;
copy_len -= CONFIG_ETH_DMA_BUFFER_SIZE;
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE // TODO cleanup (IDF-8993)
cache_sync_len = CONFIG_ETH_DMA_BUFFER_SIZE;
ret = esp_cache_msync((void *)desc_iter->Buffer1Addr, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter->Buffer1Addr, CONFIG_ETH_DMA_BUFFER_SIZE);
memcpy(buf, (void *)(desc_iter->Buffer1Addr), copy_len);
desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
/* `copy_len` does not include CRC (which may be stored in separate buffer), hence check if we reached the last descriptor */
while (!desc_iter->RDES0.LastDescriptor) {
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
DMA_CACHE_WB(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
}
/* update rxdesc */
emac_esp_dma->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
/* poll rx demand */
emac_hal_receive_poll_demand(&emac_esp_dma->hal);
}
err:
/* check how many frames left to handle */
uint32_t used_descs = 0;
emac_esp_dma_get_remain_frames(emac_esp_dma, frames_remain, &used_descs);
*free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
return ret_len;
}
void emac_esp_dma_flush_recv_frame(emac_esp_dma_handle_t emac_esp_dma, uint32_t *frames_remain, uint32_t *free_desc)
void emac_esp_dma_flush_recv_frame(emac_esp_dma_handle_t emac_esp_dma)
{
eth_dma_rx_descriptor_t *desc_iter = emac_esp_dma->rx_desc;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t cache_sync_len;
esp_err_t ret;
cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert (ret == ESP_OK);
#endif
DMA_CACHE_INVALIDATE(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
/* While not last descriptor => return back to DMA */
while (!desc_iter->RDES0.LastDescriptor) {
desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert (ret == ESP_OK);
#endif
DMA_CACHE_WB(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
}
/* the last descriptor */
desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_sync_len = sizeof(eth_dma_rx_descriptor_t);
ret = esp_cache_msync((void *)desc_iter, cache_sync_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert (ret == ESP_OK);
#endif
DMA_CACHE_WB(desc_iter, EMAC_HAL_DMA_DESC_SIZE);
/* update rxdesc */
emac_esp_dma->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
/* poll rx demand */
emac_hal_receive_poll_demand(&emac_esp_dma->hal);
}
if (frames_remain != NULL && free_desc != NULL) {
/* check how many frames left to handle */
uint32_t used_descs = 0;
emac_esp_dma_get_remain_frames(emac_esp_dma, frames_remain, &used_descs);
*free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
esp_err_t emac_esp_del_dma(emac_esp_dma_handle_t emac_esp_dma)
{
if (emac_esp_dma) {
for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
free(emac_esp_dma->tx_buf[i]);
}
for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
free(emac_esp_dma->rx_buf[i]);
}
free(emac_esp_dma->descriptors);
free(emac_esp_dma);
}
return ESP_OK;
}
esp_err_t emac_esp_new_dma(const emac_esp_dma_config_t* config, emac_esp_dma_handle_t *ret_handle)
@@ -551,20 +479,6 @@ esp_err_t emac_esp_new_dma(const emac_esp_dma_config_t* config, emac_esp_dma_han
*ret_handle = emac_esp_dma;
return ESP_OK;
err:
emac_esp_del_dma(emac_esp_dma);
return ret;
}
esp_err_t emac_esp_del_dma(emac_esp_dma_handle_t emac_esp_dma)
{
if (emac_esp_dma) {
for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
free(emac_esp_dma->tx_buf[i]);
}
for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
free(emac_esp_dma->rx_buf[i]);
}
free(emac_esp_dma->descriptors);
free(emac_esp_dma);
}
return ESP_OK;
}
@@ -0,0 +1,265 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <inttypes.h>
#include "esp_check.h"
#include "sdkconfig.h"
#include "esp_rom_gpio.h"
#include "driver/gpio.h"
#include "soc/soc_caps.h"
#include "soc/gpio_sig_map.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_periph.h"
#include "soc/emac_periph.h"
#include "esp_private/gpio.h"
#include "esp_private/eth_mac_esp_gpio.h"
#include "esp_private/esp_gpio_reserve.h"
#include "esp_log.h"
#define GET_GPIO_OR_SINGLE(cfg, num) cfg == NULL ? GPIO_NUM_MAX : cfg->num
static const char *TAG = "esp.emac.gpio";
static uint64_t s_emac_esp_used_gpio_mask = 0x0;
static esp_err_t emac_esp_gpio_matrix_init(gpio_num_t gpio_num, uint32_t signal_in_idx, uint32_t signal_out_idx, gpio_mode_t mode)
{
// silently skip when user don't want to connect the signal to GPIO pad
if (gpio_num == GPIO_NUM_NC) {
ESP_LOGD(TAG, "%s skipping signal in_idx %" PRIu32 ", out_idx %" PRIu32, __func__, signal_in_idx, signal_out_idx);
return ESP_OK;
}
ESP_RETURN_ON_ERROR(gpio_set_direction(gpio_num, mode), TAG, "failed to set direction %i at GPIO #%i", mode, gpio_num);
switch(mode) {
case GPIO_MODE_INPUT:
ESP_RETURN_ON_FALSE(signal_in_idx != SIG_GPIO_OUT_IDX, ESP_ERR_NOT_SUPPORTED,
TAG, "requested periph signal cannot be connect via GPIO Matrix");
ESP_RETURN_ON_FALSE(esp_gpio_is_reserved(BIT64(gpio_num)) == false, ESP_ERR_INVALID_STATE,
TAG, "GPIO %i is reserved", gpio_num);
esp_rom_gpio_connect_in_signal(gpio_num, signal_in_idx, false);
break;
case GPIO_MODE_OUTPUT:
ESP_RETURN_ON_FALSE(signal_out_idx != SIG_GPIO_OUT_IDX, ESP_ERR_NOT_SUPPORTED,
TAG, "requested periph signal cannot be connect via GPIO Matrix");
ESP_RETURN_ON_FALSE((esp_gpio_reserve(BIT64(gpio_num)) & BIT64(gpio_num)) == 0, ESP_ERR_INVALID_STATE,
TAG, "GPIO %i is already reserved", gpio_num);
esp_rom_gpio_connect_out_signal(gpio_num, signal_out_idx, false, false);
break;
case GPIO_MODE_INPUT_OUTPUT:
ESP_RETURN_ON_FALSE(signal_in_idx != SIG_GPIO_OUT_IDX, ESP_ERR_NOT_SUPPORTED,
TAG, "requested periph signal cannot be connect via GPIO Matrix");
ESP_RETURN_ON_FALSE(signal_out_idx != SIG_GPIO_OUT_IDX, ESP_ERR_NOT_SUPPORTED,
TAG, "requested periph signal cannot be connect via GPIO Matrix");
ESP_RETURN_ON_FALSE((esp_gpio_reserve(BIT64(gpio_num)) & BIT64(gpio_num)) == 0, ESP_ERR_INVALID_STATE,
TAG, "GPIO %i is already reserved", gpio_num);
esp_rom_gpio_connect_out_signal(gpio_num, signal_out_idx, false, false);
esp_rom_gpio_connect_in_signal(gpio_num, signal_in_idx, false);
break;
default:
return ESP_ERR_INVALID_ARG;
}
s_emac_esp_used_gpio_mask |= BIT64(gpio_num);
ESP_RETURN_ON_ERROR(gpio_set_pull_mode(gpio_num, GPIO_FLOATING), TAG, "failed to set pull mode at GPIO %i", gpio_num);
ESP_RETURN_ON_ERROR(gpio_func_sel(gpio_num, PIN_FUNC_GPIO), TAG, "failed to set GPIO function at GPIO #%i", gpio_num);
return ESP_OK;
}
static esp_err_t emac_esp_iomux_init(gpio_num_t gpio_num, const emac_iomux_info_t *iomux_info, bool is_input)
{
// silently skip undefined iomux functions (for example, ESP32 does not use MII COL_IN/CRS_IN)
if (iomux_info == NULL) {
ESP_LOGD(TAG, "%s skipping target undefined iomux periph function", __func__);
return ESP_OK;
}
// loop over target iomux_info until reached end of list indicated by invalid GPIO num
while (iomux_info->gpio_num != GPIO_NUM_MAX) {
// if requested GPIO number can be IO muxed or select single pad that can be muxed on the target
if(gpio_num == iomux_info->gpio_num || gpio_num == GPIO_NUM_MAX) {
ESP_RETURN_ON_FALSE((esp_gpio_reserve(BIT64(iomux_info->gpio_num)) & BIT64(iomux_info->gpio_num)) == 0, ESP_ERR_INVALID_STATE,
TAG, "GPIO %i is already reserved", iomux_info->gpio_num);
s_emac_esp_used_gpio_mask |= BIT64(iomux_info->gpio_num);
ESP_RETURN_ON_ERROR(gpio_func_sel(iomux_info->gpio_num, iomux_info->func), TAG, "failed to set GPIO function at GPIO %i", iomux_info->gpio_num);
if (is_input) {
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[iomux_info->gpio_num]);
} else {
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[iomux_info->gpio_num]);
}
ESP_RETURN_ON_ERROR(gpio_set_pull_mode(iomux_info->gpio_num, GPIO_FLOATING),
TAG, "failed to set pull mode at GPIO %i", iomux_info->gpio_num);
return ESP_OK;
}
iomux_info++;
}
return ESP_FAIL;
}
esp_err_t emac_esp_gpio_init_smi(const emac_esp_smi_gpio_config_t *smi_gpio)
{
if (smi_gpio->mdc_num >= 0) {
/* Setup SMI MDC GPIO */
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(smi_gpio->mdc_num, 0, emac_io_idx.mdc_idx, GPIO_MODE_OUTPUT),
TAG, "MDC GPIO matrix config failed");
}
if (smi_gpio->mdio_num >= 0) {
/* Setup SMI MDIO GPIO */
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(smi_gpio->mdio_num, emac_io_idx.mdi_idx, emac_io_idx.mdo_idx, GPIO_MODE_INPUT_OUTPUT),
TAG, "MDIO GPIO matrix config failed");
}
return ESP_OK;
}
esp_err_t emac_esp_gpio_matrix_init_mii(const eth_mac_mii_gpio_config_t *mii_gpio)
{
ESP_RETURN_ON_FALSE(mii_gpio != NULL, ESP_ERR_INVALID_ARG, TAG, "MII IO matrix config cannot be NULL");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->tx_clk_num, emac_io_idx.mii_tx_clk_i_idx, 0, GPIO_MODE_INPUT),
TAG, "TX_CLK GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->tx_en_num, 0, emac_io_idx.mii_tx_en_o_idx, GPIO_MODE_OUTPUT),
TAG, "TX_EN GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->txd0_num, 0, emac_io_idx.mii_txd0_o_idx, GPIO_MODE_OUTPUT),
TAG, "TDX0 GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->txd1_num, 0, emac_io_idx.mii_txd1_o_idx, GPIO_MODE_OUTPUT),
TAG, "TDX1 GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->txd2_num, 0, emac_io_idx.mii_txd2_o_idx, GPIO_MODE_OUTPUT),
TAG, "TDX2 GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->txd3_num, 0, emac_io_idx.mii_txd3_o_idx, GPIO_MODE_OUTPUT),
TAG, "TDX3 GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->rx_clk_num, emac_io_idx.mii_rx_clk_i_idx, 0, GPIO_MODE_INPUT),
TAG, "RX_CLK GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->rxd0_num, emac_io_idx.mii_rxd0_i_idx, 0, GPIO_MODE_INPUT),
TAG, "RXD0 GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->rxd1_num, emac_io_idx.mii_rxd1_i_idx, 0, GPIO_MODE_INPUT),
TAG, "RXD1 GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->rxd2_num, emac_io_idx.mii_rxd2_i_idx, 0, GPIO_MODE_INPUT),
TAG, "RXD2 GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->rxd3_num, emac_io_idx.mii_rxd3_i_idx, 0, GPIO_MODE_INPUT),
TAG, "RXD3 GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->col_in_num, emac_io_idx.mii_col_i_idx, 0, GPIO_MODE_INPUT),
TAG, "COL_IN GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->crs_in_num, emac_io_idx.mii_crs_i_idx, 0, GPIO_MODE_INPUT),
TAG, "CRS_IN GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->tx_er_num, 0, emac_io_idx.mii_tx_er_o_idx, GPIO_MODE_OUTPUT),
TAG, "TX_ER GPIO matrix config failed");
ESP_RETURN_ON_ERROR(emac_esp_gpio_matrix_init(mii_gpio->rx_er_num, emac_io_idx.mii_rx_er_i_idx, 0, GPIO_MODE_INPUT),
TAG, "RX_ER GPIO matrix config failed");
return ESP_OK;
}
esp_err_t emac_esp_iomux_init_mii(const eth_mac_mii_gpio_config_t *mii_gpio)
{
ESP_RETURN_ON_FALSE(emac_mii_iomux_pins.clk_tx != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support MII IOMUX");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, tx_clk_num), emac_mii_iomux_pins.clk_tx, true),
TAG, "invalid TX_CLK GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, tx_en_num), emac_mii_iomux_pins.tx_en, false),
TAG, "invalid TX_EN GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd0_num), emac_mii_iomux_pins.txd0, false),
TAG, "invalid TXD0 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd1_num), emac_mii_iomux_pins.txd1, false),
TAG, "invalid TXD1 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd2_num), emac_mii_iomux_pins.txd2, false),
TAG, "invalid TXD2 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd3_num), emac_mii_iomux_pins.txd3, false),
TAG, "invalid TXD3 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rx_clk_num), emac_mii_iomux_pins.clk_rx, true),
TAG, "invalid RX_CLK GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rx_dv_num), emac_mii_iomux_pins.rx_dv, true),
TAG, "invalid RX_DV GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd0_num), emac_mii_iomux_pins.rxd0, true),
TAG, "invalid RXD0 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd1_num), emac_mii_iomux_pins.rxd1, true),
TAG, "invalid RXD1 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd2_num), emac_mii_iomux_pins.rxd2, true),
TAG, "invalid RXD2 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd3_num), emac_mii_iomux_pins.rxd3, true),
TAG, "invalid RXD3 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, col_in_num), emac_mii_iomux_pins.col_in, true),
TAG, "invalid COL_IN GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, crs_in_num), emac_mii_iomux_pins.crs_in, true),
TAG, "invalid CRS_IN GPIO number");
return ESP_OK;
}
esp_err_t emac_esp_iomux_rmii_clk_input(int num)
{
ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.clki != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII CLKI IOMUX");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.clki, true), TAG, "invalid RMII CLK input GPIO number");
return ESP_OK;
}
esp_err_t emac_esp_iomux_rmii_clk_ouput(int num)
{
ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.clko != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII CLKO IOMUX");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.clko, false), TAG, "invalid RMII CLK output GPIO number");
return ESP_OK;
}
esp_err_t emac_esp_iomux_init_rmii(const eth_mac_rmii_gpio_config_t *rmii_gpio)
{
ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.clki != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII IOMUX");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, tx_en_num), emac_rmii_iomux_pins.tx_en, false),
TAG, "invalid TX_EN GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, txd0_num), emac_rmii_iomux_pins.txd0, false),
TAG, "invalid TXD0 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, txd1_num), emac_rmii_iomux_pins.txd1, false),
TAG, "invalid TXD1 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, crs_dv_num), emac_rmii_iomux_pins.crs_dv, true),
TAG,"invalid CRS_DV GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, rxd0_num), emac_rmii_iomux_pins.rxd0, true),
TAG,"invalid RXD0 GPIO number");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, rxd1_num), emac_rmii_iomux_pins.rxd1, true),
TAG,"invalid RXD1 GPIO number");
return ESP_OK;
}
esp_err_t emac_esp_iomux_rmii_init_tx_er(int num)
{
ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.tx_er != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII TX_ER IOMUX");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.tx_er, false), TAG, "invalid TX_ER GPIO number");
return ESP_OK;
}
esp_err_t emac_esp_iomux_rmii_init_rx_er(int num)
{
ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.rx_er != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII RX_ER IOMUX");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.rx_er, true), TAG, "invalid RX_ER GPIO number");
return ESP_OK;
}
esp_err_t emac_esp_iomux_mii_init_tx_er(int num)
{
ESP_RETURN_ON_FALSE(emac_mii_iomux_pins.tx_er != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support MII TX_ER IOMUX");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_mii_iomux_pins.tx_er, false), TAG, "invalid TX_ER GPIO number");
return ESP_OK;
}
esp_err_t emac_esp_iomux_mii_init_rx_er(int num)
{
ESP_RETURN_ON_FALSE(emac_mii_iomux_pins.rx_er != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII RX_ER IOMUX");
ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_mii_iomux_pins.rx_er, true), TAG, "invalid RX_ER GPIO number");
return ESP_OK;
}
esp_err_t emac_esp_gpio_deinit_all(void)
{
for (int gpio_num = 0; gpio_num < 64; gpio_num++) {
if (BIT64(gpio_num) & s_emac_esp_used_gpio_mask) {
gpio_reset_pin(gpio_num);
esp_gpio_revoke(BIT64(gpio_num));
}
s_emac_esp_used_gpio_mask &= ~BIT64(gpio_num);
}
return ESP_OK;
}
@@ -21,12 +21,12 @@
#include "esp_log.h"
#include "esp_check.h"
#include "esp_cpu.h"
#include "esp_eth_driver.h"
#include "esp_intr_alloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "openeth.h"
#include "esp_mac.h"
#include "esp_eth_mac_openeth.h"
static const char *TAG = "opencores.emac";
@@ -11,7 +11,7 @@
#if CONFIG_IDF_TARGET_ESP32C3
/**
* @brief Since ESP32-C3 target in QEMU doesn't support Wifi, re-use its interrupt source for ethernet
* @brief Since ESP32-C3 target in QEMU doesn't support Wifi, reuse its interrupt source for ethernet
*/
#define ETS_ETH_MAC_INTR_SOURCE ETS_WIFI_MAC_INTR_SOURCE
@@ -114,7 +114,7 @@ extern "C" {
typedef struct {
uint16_t cs: 1; //!< Carrier sense lost (flag set by HW)
uint16_t df: 1; //!< Defer indication (flag set by HW)
uint16_t lc: 1; //!< Late collision occured (flag set by HW)
uint16_t lc: 1; //!< Late collision occurred (flag set by HW)
uint16_t rl: 1; //!< TX failed due to retransmission limit (flag set by HW)
uint16_t rtry: 4; //!< Number of retries before the frame was sent (set by HW)
uint16_t ur: 1; //!< Underrun status (flag set by HW)
@@ -62,7 +62,7 @@ typedef union {
*/
typedef union {
struct {
uint32_t op_mode : 3; /* Operation Mode Idicator */
uint32_t op_mode : 3; /* Operation Mode Indicator */
uint32_t force_mdix : 1; /* Force the MDIX channel to be selected */
uint32_t reserved1 : 4; /* Reserved */
uint32_t link_up : 1; /* Indicate the link status is OK or FAIL */
@@ -8,12 +8,12 @@
#include <stdlib.h>
#include <sys/cdefs.h>
#include <inttypes.h>
#include "esp_eth_mac_spi.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_eth_driver.h"
#include "esp_timer.h"
#include "esp_system.h"
#include "esp_intr_alloc.h"
@@ -67,7 +67,7 @@ typedef union {
uint32_t monsel1 : 1; /* Vendor monitor select */
uint32_t mdix_down : 1; /* Set 1 to disable HP Auto-MDIX */
uint32_t mdix_fix : 1; /* When mdix_down = 1, MDIX_CNTL value depend on the register value. */
uint32_t autoneg_lpbk : 1; /* Set 1 to enable autonegotioation loopback */
uint32_t autoneg_lpbk : 1; /* Set 1 to enable autonegotiation loopback */
uint32_t mdxi_cntl : 1; /* Polarity of MDI/MDIX value */
uint32_t reserved2 : 1; /* Reserved */
uint32_t nway_pwr : 1; /* Set 1 to enable power savings during autonegotiation period */
@@ -195,7 +195,7 @@ static esp_err_t dm9051_loopback(esp_eth_phy_t *phy, bool enable)
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
esp_eth_mediator_t *eth = phy_802_3->eth;
/* Set Loopback function */
// Enable Auto-negotiation loopback in Speficic control register
// Enable Auto-negotiation loopback in Specific control register
bmcr_reg_t bmcr;
scr_reg_t scr;
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
@@ -8,6 +8,7 @@
#include <string.h>
#include <inttypes.h>
#include "esp_eth_mac_spi.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_cpu.h"
@@ -17,7 +18,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_eth_driver.h"
#include "ksz8851.h"
#include "esp_timer.h"
@@ -6,6 +6,7 @@
* SPDX-FileContributor: 2021-2024 Espressif Systems (Shanghai) CO LTD
*/
#include <stdlib.h>
#include "esp_eth_phy.h"
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
@@ -13,7 +14,6 @@
#include "esp_rom_gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_eth_driver.h"
#include "ksz8851.h"
@@ -149,7 +149,7 @@ err:
/**
* @note This function is responsible for restarting a new auto-negotiation,
* the result of negotiation won't be relected to uppler layers.
* the result of negotiation won't be reflected to upper layers.
* Instead, the negotiation result is fetched by linker timer, see `phy_ksz8851_get_link()`
*/
static esp_err_t phy_ksz8851_autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *autonego_en_stat)
@@ -1,22 +1,11 @@
// Copyright (c) 2021 Vladimir Chistyakov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
/*
* SPDX-FileCopyrightText: 2021 Vladimir Chistyakov
*
* SPDX-License-Identifier: MIT
*
* SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD
*/
#pragma once
@@ -314,7 +303,7 @@ typedef enum {
P1ANAR_ADV_10_HALF = 0x0020U, ///< RW Adv 10 Half
P1ANLPR_NEXT_PAGE = 0x8000U, ///< RO Next page (not supported)
P1ANLPR_LP_ACK = 0x4000U, ///< RO LP ACK (not suppported)
P1ANLPR_LP_ACK = 0x4000U, ///< RO LP ACK (not supported)
P1ANLPR_REMOTE_FAULT = 0x2000U, ///< RO Remote fault (not supported)
P1ANLPR_PAUSE = 0x0400U, ///< RO Pause
P1ANLPR_ADV_100_FULL = 0x0100U, ///< RO Adv 100 Full
@@ -7,12 +7,12 @@
#include <stdlib.h>
#include <sys/cdefs.h>
#include <inttypes.h>
#include "esp_eth_mac_spi.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_eth_driver.h"
#include "esp_system.h"
#include "esp_intr_alloc.h"
#include "esp_heap_caps.h"
@@ -550,7 +550,7 @@ static esp_err_t emac_w5500_enable_flow_ctrl(esp_eth_mac_t *mac, bool enable)
static esp_err_t emac_w5500_set_peer_pause_ability(esp_eth_mac_t *mac, uint32_t ability)
{
/* w5500 doesn't suppport PAUSE function, so accept any value */
/* w5500 doesn't support PAUSE function, so accept any value */
return ESP_ERR_NOT_SUPPORTED;
}
@@ -823,7 +823,7 @@ static esp_err_t emac_w5500_init(esp_eth_mac_t *mac)
/* reset w5500 */
ESP_GOTO_ON_ERROR(w5500_reset(emac), err, TAG, "reset w5500 failed");
/* verify chip id */
ESP_GOTO_ON_ERROR(w5500_verify_id(emac), err, TAG, "vefiry chip ID failed");
ESP_GOTO_ON_ERROR(w5500_verify_id(emac), err, TAG, "verify chip ID failed");
/* default setup of internal registers */
ESP_GOTO_ON_ERROR(w5500_setup_default(emac), err, TAG, "w5500 default setup failed");
return ESP_OK;
@@ -6,9 +6,9 @@
#include <string.h>
#include <stdlib.h>
#include <sys/cdefs.h>
#include "esp_eth_phy.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_eth_driver.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"