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:
@@ -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"
|
||||
|
||||
+81
-98
@@ -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;
|
||||
}
|
||||
+91
-177
@@ -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;
|
||||
}
|
||||
+1
-1
@@ -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)
|
||||
+1
-1
@@ -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 */
|
||||
+1
-1
@@ -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"
|
||||
+2
-2
@@ -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");
|
||||
+1
-1
@@ -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"
|
||||
|
||||
+2
-2
@@ -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
|
||||
+3
-3
@@ -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;
|
||||
+1
-1
@@ -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"
|
||||
Reference in New Issue
Block a user