mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
enc28j60: fix stability of the ENC28J60 Ethernet driver example
Resolved possible race conditions when accessing registers in different banks. Added Tx ready semaphore when requesting packet to transmit (ENC is slow => access to it needs to be controlled). Added setting of CS hold time based on Data sheet. Added option to set the ENC28J60 to Full Duplex mode. Addressed several ENC28J60 Erratas. Restructured ENC28J60 example folder structure so the driver could be easily linked from different projects. Extended the README to guide users of how to properly use the ENC28J60 chip. Extended iperf example to include ENC28J60. Closes https://github.com/espressif/esp-idf/issues/4747 Closes https://github.com/espressif/esp-idf/issues/7117 Closes https://github.com/espressif/esp-idf/issues/7156
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/system/console/advanced/components
|
||||
$ENV{IDF_PATH}/examples/common_components/iperf)
|
||||
$ENV{IDF_PATH}/examples/common_components/iperf
|
||||
$ENV{IDF_PATH}/examples/ethernet/enc28j60/components/eth_enc28j60)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(ethernet_iperf)
|
||||
|
@@ -8,6 +8,7 @@ PROJECT_NAME := ethernet_iperf
|
||||
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/system/console/advanced/components
|
||||
EXTRA_COMPONENT_DIRS += $(IDF_PATH)/examples/wifi/iperf/components
|
||||
EXTRA_COMPONENT_DIRS += $(IDF_PATH)/examples/common_components/iperf
|
||||
EXTRA_COMPONENT_DIRS += $(IDF_PATH)/examples/ethernet/enc28j60/components/eth_enc28j60
|
||||
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
@@ -39,6 +39,14 @@ menu "Example Configuration"
|
||||
select ETH_SPI_ETHERNET_W5500
|
||||
help
|
||||
Select external SPI-Ethernet module (W5500).
|
||||
|
||||
config EXAMPLE_USE_ENC28J60
|
||||
bool "ENC28J60 Module"
|
||||
select EXAMPLE_USE_SPI_ETHERNET
|
||||
select ETH_USE_SPI_ETHERNET
|
||||
select ETH_SPI_ETHERNET_ENC28J60
|
||||
help
|
||||
Select external SPI-Ethernet module (ENC28J60).
|
||||
endchoice # EXAMPLE_ETHERNET_TYPE
|
||||
|
||||
if EXAMPLE_USE_INTERNAL_ETHERNET
|
||||
@@ -131,6 +139,7 @@ menu "Example Configuration"
|
||||
config EXAMPLE_ETH_SPI_CLOCK_MHZ
|
||||
int "SPI clock speed (MHz)"
|
||||
range 5 80
|
||||
default 8 if EXAMPLE_USE_ENC28J60
|
||||
default 36
|
||||
help
|
||||
Set the clock speed (MHz) of SPI interface.
|
||||
@@ -155,4 +164,24 @@ menu "Example Configuration"
|
||||
default 1
|
||||
help
|
||||
Set PHY address according your board schematic.
|
||||
|
||||
if EXAMPLE_USE_ENC28J60
|
||||
choice EXAMPLE_ENC28J60_DUPLEX_MODE
|
||||
prompt "Duplex Mode"
|
||||
default EXAMPLE_ENC28J60_DUPLEX_HALF
|
||||
help
|
||||
Select ENC28J60 Duplex operation mode.
|
||||
|
||||
config EXAMPLE_ENC28J60_DUPLEX_FULL
|
||||
bool "Full Duplex"
|
||||
help
|
||||
Set ENC28J60 to Full Duplex mode. Do not forget to manually set the remote node (switch, router
|
||||
or Ethernet controller) to full-duplex operation mode too.
|
||||
|
||||
config EXAMPLE_ENC28J60_DUPLEX_HALF
|
||||
bool "Half Duplex"
|
||||
help
|
||||
Set ENC28J60 to Half Duplex mode.
|
||||
endchoice # EXAMPLE_ENC28J60_DUPLEX_MODE
|
||||
endif # ETH_SPI_ETHERNET_ENC28J60
|
||||
endmenu
|
||||
|
@@ -21,6 +21,9 @@
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_ETH_USE_SPI_ETHERNET
|
||||
#include "driver/spi_master.h"
|
||||
#if CONFIG_EXAMPLE_USE_ENC28J60
|
||||
#include "esp_eth_enc28j60.h"
|
||||
#endif //CONFIG_EXAMPLE_USE_ENC28J60
|
||||
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
||||
|
||||
static esp_netif_ip_info_t ip;
|
||||
@@ -218,7 +221,7 @@ void register_ethernet(void)
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
};
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1));
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
#if CONFIG_EXAMPLE_USE_DM9051
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 1,
|
||||
@@ -249,6 +252,29 @@ void register_ethernet(void)
|
||||
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
||||
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
|
||||
#elif CONFIG_EXAMPLE_USE_ENC28J60
|
||||
/* ENC28J60 ethernet driver is based on spi driver */
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 3,
|
||||
.address_bits = 5,
|
||||
.mode = 0,
|
||||
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
||||
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
|
||||
.queue_size = 20,
|
||||
.cs_ena_posttrans = enc28j60_cal_spi_cs_hold_time(CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ)
|
||||
};
|
||||
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
||||
|
||||
eth_enc28j60_config_t enc28j60_config = ETH_ENC28J60_DEFAULT_CONFIG(spi_handle);
|
||||
enc28j60_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
||||
|
||||
mac_config.smi_mdc_gpio_num = -1; // ENC28J60 doesn't have SMI interface
|
||||
mac_config.smi_mdio_gpio_num = -1;
|
||||
esp_eth_mac_t *mac = esp_eth_mac_new_enc28j60(&enc28j60_config, &mac_config);
|
||||
|
||||
phy_config.autonego_timeout_ms = 0; // ENC28J60 doesn't support auto-negotiation
|
||||
phy_config.reset_gpio_num = -1; // ENC28J60 doesn't have a pin to reset internal PHY
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_enc28j60(&phy_config);
|
||||
#endif
|
||||
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
@@ -264,6 +290,10 @@ void register_ethernet(void)
|
||||
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
|
||||
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
|
||||
|
||||
#if CONFIG_EXAMPLE_USE_ENC28J60 && CONFIG_EXAMPLE_ENC28J60_DUPLEX_FULL
|
||||
enc28j60_set_phy_duplex(phy, ETH_DUPLEX_FULL);
|
||||
#endif
|
||||
|
||||
eth_control_args.control = arg_str1(NULL, NULL, "<info>", "Get info of Ethernet");
|
||||
eth_control_args.end = arg_end(1);
|
||||
const esp_console_cmd_t cmd = {
|
||||
|
Reference in New Issue
Block a user