Merge branch 'feature/dual_eth' into 'master'

esp_eth: add support for multiple Ethernets modules at a time

Closes IDFGH-5596

See merge request espressif/esp-idf!14640
pull/7497/head
Ondrej Kosta 2021-08-27 06:11:48 +00:00
commit 300618e5be
12 zmienionych plików z 564 dodań i 256 usunięć

Wyświetl plik

@ -19,6 +19,12 @@
extern "C" {
#endif
/**
* @brief Handle of netif glue - an intermediate layer between netif and Ethernet driver
*
*/
typedef struct esp_eth_netif_glue_t* esp_eth_netif_glue_handle_t;
/**
* @brief Create a netif glue for Ethernet driver
* @note netif glue is used to attach io driver to TCP/IP netif
@ -26,20 +32,23 @@ extern "C" {
* @param eth_hdl Ethernet driver handle
* @return glue object, which inherits esp_netif_driver_base_t
*/
void *esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl);
esp_eth_netif_glue_handle_t esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl);
/**
* @brief Delete netif glue of Ethernet driver
*
* @param glue netif glue
* @param eth_netif_glue netif glue
* @return -ESP_OK: delete netif glue successfully
*/
esp_err_t esp_eth_del_netif_glue(void *glue);
esp_err_t esp_eth_del_netif_glue(esp_eth_netif_glue_handle_t eth_netif_glue);
/**
* @brief Register default IP layer handlers for Ethernet
*
* @note: Ethernet handle might not yet properly initialized when setting up these default handlers
* @warning: This function is deprecated and is kept here only for compatibility reasons. Registration
* of default IP layer handlers for Ethernet is now handled automatically. Do not call this
* function if you want to use multiple Ethernet instances at a time.
*
* @param[in] esp_netif esp network interface handle created for Ethernet driver
* @return
@ -47,12 +56,15 @@ esp_err_t esp_eth_del_netif_glue(void *glue);
* - ESP_OK: set default IP layer handlers successfully
* - others: other failure occurred during register esp_event handler
*/
esp_err_t esp_eth_set_default_handlers(void *esp_netif);
esp_err_t esp_eth_set_default_handlers(void *esp_netif) __attribute__ ((deprecated));
/**
* @brief Unregister default IP layer handlers for Ethernet
*
* @warning: This function is deprecated and is kept here only for compatibility reasons. Unregistration
* of default IP layer handlers for Ethernet is now handled automatically if not registered
* by calling esp_eth_set_default_handlers.
*
* @param[in] esp_netif esp network interface handle created for Ethernet driver
* @return
* - ESP_ERR_INVALID_ARG: invalid parameter (esp_netif is NULL)

Wyświetl plik

@ -17,13 +17,23 @@
#include "esp_eth_netif_glue.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_check.h"
const static char *TAG = "esp_eth.netif.glue";
const static char *TAG = "esp_eth.netif.netif_glue";
typedef struct {
typedef struct esp_eth_netif_glue_t esp_eth_netif_glue_t;
struct esp_eth_netif_glue_t {
esp_netif_driver_base_t base;
esp_eth_handle_t eth_driver;
} esp_eth_netif_glue_t;
esp_event_handler_instance_t start_ctx_handler;
esp_event_handler_instance_t stop_ctx_handler;
esp_event_handler_instance_t connect_ctx_handler;
esp_event_handler_instance_t disconnect_ctx_handler;
esp_event_handler_instance_t get_ip_ctx_handler;
};
bool s_netif_glue_legacy_events_registered = false;
static esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv)
{
@ -33,20 +43,20 @@ static esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer
static esp_err_t esp_eth_post_attach(esp_netif_t *esp_netif, void *args)
{
uint8_t eth_mac[6];
esp_eth_netif_glue_t *glue = (esp_eth_netif_glue_t *)args;
glue->base.netif = esp_netif;
esp_eth_netif_glue_t *netif_glue = (esp_eth_netif_glue_t *)args;
netif_glue->base.netif = esp_netif;
esp_eth_update_input_path(glue->eth_driver, eth_input_to_netif, esp_netif);
esp_eth_update_input_path(netif_glue->eth_driver, eth_input_to_netif, esp_netif);
// set driver related config to esp-netif
esp_netif_driver_ifconfig_t driver_ifconfig = {
.handle = glue->eth_driver,
.handle = netif_glue->eth_driver,
.transmit = esp_eth_transmit,
.driver_free_rx_buffer = NULL
};
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));
esp_eth_ioctl(glue->eth_driver, ETH_CMD_G_MAC_ADDR, eth_mac);
esp_eth_ioctl(netif_glue->eth_driver, ETH_CMD_G_MAC_ADDR, eth_mac);
ESP_LOGI(TAG, "%02x:%02x:%02x:%02x:%02x:%02x", eth_mac[0], eth_mac[1],
eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]);
@ -56,39 +66,18 @@ static esp_err_t esp_eth_post_attach(esp_netif_t *esp_netif, void *args)
return ESP_OK;
}
void *esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl)
{
esp_eth_netif_glue_t *glue = calloc(1, sizeof(esp_eth_netif_glue_t));
if (!glue) {
ESP_LOGE(TAG, "create netif glue failed");
return NULL;
}
glue->eth_driver = eth_hdl;
glue->base.post_attach = esp_eth_post_attach;
esp_eth_increase_reference(eth_hdl);
return &glue->base;
}
esp_err_t esp_eth_del_netif_glue(void *g)
{
esp_eth_netif_glue_t *glue = (esp_eth_netif_glue_t *)g;
esp_eth_decrease_reference(glue->eth_driver);
free(glue);
return ESP_OK;
}
esp_err_t esp_eth_clear_default_handlers(void *esp_netif)
{
if (!esp_netif) {
ESP_LOGE(TAG, "esp-netif handle can't be null");
return ESP_ERR_INVALID_ARG;
}
ESP_RETURN_ON_FALSE(esp_netif, ESP_ERR_INVALID_ARG, TAG, "esp_netif handle can't be null");
esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start);
esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, esp_netif_action_stop);
esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, esp_netif_action_connected);
esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, esp_netif_action_disconnected);
esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, esp_netif_action_got_ip);
s_netif_glue_legacy_events_registered = false;
return ESP_OK;
}
@ -96,10 +85,7 @@ esp_err_t esp_eth_set_default_handlers(void *esp_netif)
{
esp_err_t ret;
if (!esp_netif) {
ESP_LOGE(TAG, "esp-netif handle can't be null");
return ESP_ERR_INVALID_ARG;
}
ESP_RETURN_ON_FALSE(esp_netif, ESP_ERR_INVALID_ARG, TAG, "esp_netif handle can't be null");
ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start, esp_netif);
if (ret != ESP_OK) {
@ -126,9 +112,158 @@ esp_err_t esp_eth_set_default_handlers(void *esp_netif)
goto fail;
}
s_netif_glue_legacy_events_registered = true;
return ESP_OK;
fail:
esp_eth_clear_default_handlers(esp_netif);
return ret;
}
static void eth_action_start(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
esp_eth_netif_glue_t *netif_glue = handler_args;
ESP_LOGD(TAG, "eth_action_start: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data);
if (netif_glue->eth_driver == eth_handle) {
esp_netif_action_start(netif_glue->base.netif, base, event_id, event_data);
}
}
static void eth_action_stop(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
esp_eth_netif_glue_t *netif_glue = handler_args;
ESP_LOGD(TAG, "eth_action_stop: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data);
if (netif_glue->eth_driver == eth_handle) {
esp_netif_action_stop(netif_glue->base.netif, base, event_id, event_data);
}
}
static void eth_action_connected(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
esp_eth_netif_glue_t *netif_glue = handler_args;
ESP_LOGD(TAG, "eth_action_connected: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data);
if (netif_glue->eth_driver == eth_handle) {
esp_netif_action_connected(netif_glue->base.netif, base, event_id, event_data);
}
}
static void eth_action_disconnected(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
esp_eth_netif_glue_t *netif_glue = handler_args;
ESP_LOGD(TAG, "eth_action_disconnected: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data);
if (netif_glue->eth_driver == eth_handle) {
esp_netif_action_disconnected(netif_glue->base.netif, base, event_id, event_data);
}
}
static void eth_action_got_ip(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ip_event_got_ip_t *ip_event = (ip_event_got_ip_t *)event_data;
esp_eth_netif_glue_t *netif_glue = handler_args;
ESP_LOGD(TAG, "eth_action_got_ip: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data);
if (netif_glue->base.netif == ip_event->esp_netif) {
esp_netif_action_got_ip(ip_event->esp_netif, base, event_id, event_data);
}
}
static esp_err_t esp_eth_clear_glue_instance_handlers(esp_eth_netif_glue_handle_t eth_netif_glue)
{
ESP_RETURN_ON_FALSE(eth_netif_glue, ESP_ERR_INVALID_ARG, TAG, "eth_netif_glue handle can't be null");
if (eth_netif_glue->start_ctx_handler) {
esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_START, eth_netif_glue->start_ctx_handler);
eth_netif_glue->start_ctx_handler = NULL;
}
if (eth_netif_glue->stop_ctx_handler) {
esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, eth_netif_glue->stop_ctx_handler);
eth_netif_glue->stop_ctx_handler = NULL;
}
if (eth_netif_glue->connect_ctx_handler) {
esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, eth_netif_glue->connect_ctx_handler);
eth_netif_glue->connect_ctx_handler = NULL;
}
if (eth_netif_glue->disconnect_ctx_handler) {
esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, eth_netif_glue->disconnect_ctx_handler);
eth_netif_glue->disconnect_ctx_handler = NULL;
}
if (eth_netif_glue->get_ip_ctx_handler) {
esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, eth_netif_glue->get_ip_ctx_handler);
eth_netif_glue->get_ip_ctx_handler = NULL;
}
return ESP_OK;
}
static esp_err_t esp_eth_set_glue_instance_handlers(esp_eth_netif_glue_handle_t eth_netif_glue)
{
ESP_RETURN_ON_FALSE(eth_netif_glue, ESP_ERR_INVALID_ARG, TAG, "eth_netif_glue handle can't be null");
esp_err_t ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_START, eth_action_start, eth_netif_glue, &eth_netif_glue->start_ctx_handler);
if (ret != ESP_OK) {
goto fail;
}
ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_STOP, eth_action_stop, eth_netif_glue, &eth_netif_glue->stop_ctx_handler);
if (ret != ESP_OK) {
goto fail;
}
ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, eth_action_connected, eth_netif_glue, &eth_netif_glue->connect_ctx_handler);
if (ret != ESP_OK) {
goto fail;
}
ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, eth_action_disconnected, eth_netif_glue, &eth_netif_glue->disconnect_ctx_handler);
if (ret != ESP_OK) {
goto fail;
}
ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, eth_action_got_ip, eth_netif_glue, &eth_netif_glue->get_ip_ctx_handler);
if (ret != ESP_OK) {
goto fail;
}
return ESP_OK;
fail:
esp_eth_clear_glue_instance_handlers(eth_netif_glue);
return ret;
}
esp_err_t esp_eth_del_netif_glue(esp_eth_netif_glue_handle_t eth_netif_glue)
{
esp_eth_clear_glue_instance_handlers(eth_netif_glue);
esp_eth_decrease_reference(eth_netif_glue->eth_driver);
free(eth_netif_glue);
return ESP_OK;
}
esp_eth_netif_glue_handle_t esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl)
{
esp_eth_netif_glue_t *netif_glue = calloc(1, sizeof(esp_eth_netif_glue_t));
if (!netif_glue) {
ESP_LOGE(TAG, "create netif glue failed");
return NULL;
}
netif_glue->eth_driver = eth_hdl;
netif_glue->base.post_attach = esp_eth_post_attach;
esp_eth_increase_reference(eth_hdl);
if (s_netif_glue_legacy_events_registered == false) {
if (esp_eth_set_glue_instance_handlers(netif_glue) != ESP_OK) {
esp_eth_del_netif_glue(netif_glue);
return NULL;
}
}
return netif_glue;
}

Wyświetl plik

@ -218,11 +218,7 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]")
// create TCP/IP netif
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&netif_cfg);
// set default handlers to do layer 3 (and up) stuffs
TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif));
// register user defined event handers
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_event_group));
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
@ -232,8 +228,11 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]")
// install Ethernet driver
TEST_ESP_OK(esp_eth_driver_install(&eth_config, &eth_handle));
// combine driver with netif
void *glue = esp_eth_new_netif_glue(eth_handle);
esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle);
TEST_ESP_OK(esp_netif_attach(eth_netif, glue));
// register user defined event handers
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_event_group));
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
// start Ethernet driver
TEST_ESP_OK(esp_eth_start(eth_handle));
/* wait for IP lease */
@ -251,7 +250,6 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]")
TEST_ESP_OK(mac->del(mac));
TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler));
TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler));
TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif));
esp_netif_destroy(eth_netif);
TEST_ESP_OK(esp_event_loop_delete_default());
vEventGroupDelete(eth_event_group);
@ -267,11 +265,7 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et
// create TCP/IP netif
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&netif_cfg);
// set default handlers to do layer 3 (and up) stuffs
TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif));
// register user defined event handers
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_event_group));
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
@ -281,8 +275,11 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et
// install Ethernet driver
TEST_ESP_OK(esp_eth_driver_install(&eth_config, &eth_handle));
// combine driver with netif
void *glue = esp_eth_new_netif_glue(eth_handle);
esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle);
TEST_ESP_OK(esp_netif_attach(eth_netif, glue));
// register user defined event handers
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_event_group));
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
for (int i = 0; i < 10; i++) {
// start Ethernet driver
@ -304,7 +301,6 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et
TEST_ESP_OK(mac->del(mac));
TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler));
TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler));
TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif));
esp_netif_destroy(eth_netif);
TEST_ESP_OK(esp_event_loop_delete_default());
vEventGroupDelete(eth_event_group);
@ -320,11 +316,7 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]")
// create TCP/IP netif
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&netif_cfg);
// set default handlers to do layer 3 (and up) stuffs
TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif));
// register user defined event handers
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_event_group));
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
@ -333,8 +325,11 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]")
esp_eth_handle_t eth_handle = NULL;
TEST_ESP_OK(esp_eth_driver_install(&eth_config, &eth_handle));
// combine driver with netif
void *glue = esp_eth_new_netif_glue(eth_handle);
esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle);
TEST_ESP_OK(esp_netif_attach(eth_netif, glue));
// register user defined event handers
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_event_group));
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
// start Ethernet driver
TEST_ESP_OK(esp_eth_start(eth_handle));
/* wait for IP lease */
@ -395,7 +390,6 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]")
TEST_ESP_OK(phy->del(phy));
TEST_ESP_OK(mac->del(mac));
TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler));
TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif));
esp_netif_destroy(eth_netif);
TEST_ESP_OK(esp_event_loop_delete_default());
vEventGroupDelete(eth_event_group);
@ -458,11 +452,7 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t
// create TCP/IP netif
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&netif_cfg);
// set default handlers to do layer 3 (and up) stuffs
TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif));
// register user defined event handers
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_event_group));
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
@ -472,8 +462,11 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t
// install Ethernet driver
TEST_ESP_OK(esp_eth_driver_install(&eth_config, &eth_handle));
// combine driver with netif
void *glue = esp_eth_new_netif_glue(eth_handle);
esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle);
TEST_ESP_OK(esp_netif_attach(eth_netif, glue));
// register user defined event handers
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_event_group));
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
// start Ethernet driver
TEST_ESP_OK(esp_eth_start(eth_handle));
/* wait for IP lease */
@ -506,7 +499,6 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t
TEST_ESP_OK(mac->del(mac));
TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler));
TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler));
TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif));
esp_netif_destroy(eth_netif);
TEST_ESP_OK(esp_event_loop_delete_default());
vEventGroupDelete(eth_event_group);

Wyświetl plik

@ -109,7 +109,7 @@ void tcpip_adapter_init(void)
esp_err_t tcpip_adapter_clear_default_eth_handlers(void)
{
return esp_eth_clear_default_handlers(netif_from_if(TCPIP_ADAPTER_IF_ETH));
return ESP_OK;
}
esp_err_t tcpip_adapter_set_default_eth_handlers(void)
@ -119,8 +119,6 @@ esp_err_t tcpip_adapter_set_default_eth_handlers(void)
esp_netif_t *eth_netif = esp_netif_new(&cfg);
s_esp_netifs[TCPIP_ADAPTER_IF_ETH] = eth_netif;
return esp_eth_set_default_handlers(eth_netif);
}
return ESP_OK;

Wyświetl plik

@ -225,6 +225,24 @@ EMAC ``REF_CLK`` can be optionally configured from user application code.
Install Driver
--------------
To install the Ethernet driver, we need to combine the instance of MAC and PHY and set some additional high-level configurations (i.e. not specific to either MAC or PHY) in :cpp:class:`esp_eth_config_t`:
* :cpp:member:`mac`: instance that created from MAC generator (e.g. :cpp:func:`esp_eth_mac_new_esp32`).
* :cpp:member:`phy`: instance that created from PHY generator (e.g. :cpp:func:`esp_eth_phy_new_ip101`).
* :cpp:member:`check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds.
* :cpp:member:`stack_input`: In most of Ethernet IoT applications, any Ethernet frame that received by driver should be passed to upper layer (e.g. TCP/IP stack). This field is set to a function which is responsible to deal with the incoming frames. You can even update this field at runtime via function :cpp:func:`esp_eth_update_input_path` after driver installation.
* :cpp:member:`on_lowlevel_init_done` and :cpp:member:`on_lowlevel_deinit_done`: These two fields are used to specify the hooks which get invoked when low level hardware has been initialized or de-initialized.
ESP-IDF provides a default configuration for driver installation in macro :c:macro:`ETH_DEFAULT_CONFIG`.
.. highlight:: c
::
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration
esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver
esp_eth_driver_install(&config, &eth_handle); // install driver
Ethernet driver also includes event-driven model, which will send useful and important event to user space. We need to initialize the event loop before installing the Ethernet driver. For more information about event-driven programming, please refer to :doc:`ESP Event <../system/esp_event>`.
.. highlight:: c
@ -244,7 +262,7 @@ Ethernet driver also includes event-driven model, which will send useful and imp
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ESP_LOGI(TAG, "Ethernet Link Up");
ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "Ethernet Link Down");
@ -263,24 +281,6 @@ Ethernet driver also includes event-driven model, which will send useful and imp
esp_event_loop_create_default(); // create a default event loop that running in background
esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL); // register Ethernet event handler (to deal with user specific stuffs when event like link up/down happened)
To install the Ethernet driver, we need to combine the instance of MAC and PHY and set some additional high-level configurations (i.e. not specific to either MAC or PHY) in :cpp:class:`esp_eth_config_t`:
* :cpp:member:`mac`: instance that created from MAC generator (e.g. :cpp:func:`esp_eth_mac_new_esp32`).
* :cpp:member:`phy`: instance that created from PHY generator (e.g. :cpp:func:`esp_eth_phy_new_ip101`).
* :cpp:member:`check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds.
* :cpp:member:`stack_input`: In most of Ethernet IoT applications, any Ethernet frame that received by driver should be passed to upper layer (e.g. TCP/IP stack). This field is set to a function which is responsible to deal with the incoming frames. You can even update this field at runtime via function :cpp:func:`esp_eth_update_input_path` after driver installation.
* :cpp:member:`on_lowlevel_init_done` and :cpp:member:`on_lowlevel_deinit_done`: These two fields are used to specify the hooks which get invoked when low level hardware has been initialized or de-initialized.
ESP-IDF provides a default configuration for driver installation in macro :c:macro:`ETH_DEFAULT_CONFIG`.
.. highlight:: c
::
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration
esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver
esp_eth_driver_install(&config, &eth_handle); // install driver
Start Ethernet Driver
---------------------
@ -303,8 +303,8 @@ The TCP/IP stack used in ESP-IDF is called LwIP, for more information about it,
To connect Ethernet driver to TCP/IP stack, these three steps need to follow:
1. Create network interface for Ethernet driver
2. Register IP event handlers
3. Attach the network interface to Ethernet driver
2. Attach the network interface to Ethernet driver
3. Register IP event handlers
More information about network interface, please refer to :doc:`Network Interface <esp_netif>`.
@ -330,12 +330,14 @@ More information about network interface, please refer to :doc:`Network Interfac
esp_netif_init()); // Initialize TCP/IP network interface (should be called only once in application)
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); // apply default network interface configuration for Ethernet
esp_netif_t *eth_netif = esp_netif_new(&cfg); // create network interface for Ethernet driver
esp_eth_set_default_handlers(eth_netif); // set default handlers to process TCP/IP stuffs
esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // register user defined IP event handlers
esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)); // attach Ethernet driver to TCP/IP stack
esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // register user defined IP event handlers
esp_eth_start(eth_handle); // start Ethernet driver state machine
.. warning::
It is recommended to fully initialize the Ethernet driver and network interface prior registering user's Ethernet/IP event handlers, i.e. register the event handlers as the last thing prior starting the Ethernet driver. Such approach ensures that Ethernet/IP events get executed first by the Ethernet driver or network interface and so the system is in expected state when executing user's handlers.
.. _misc-operation-of-driver:
Misc control of Ethernet driver

Wyświetl plik

@ -343,7 +343,7 @@ static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
ESP_LOGI(TAG, "Ethernet Link Up");
esp_netif_create_ip6_linklocal(esp_netif);
ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
break;
default:
break;
@ -355,7 +355,7 @@ static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
static esp_eth_handle_t s_eth_handle = NULL;
static esp_eth_mac_t *s_mac = NULL;
static esp_eth_phy_t *s_phy = NULL;
static void *s_eth_glue = NULL;
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
static esp_netif_t *eth_start(void)
{
@ -373,14 +373,7 @@ static esp_netif_t *eth_start(void)
esp_netif_t *netif = esp_netif_new(&netif_config);
assert(netif);
free(desc);
// Set default handlers to process TCP/IP stuffs
ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif));
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL));
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
#endif
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
@ -460,6 +453,14 @@ static esp_netif_t *eth_start(void)
// combine driver with netif
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
esp_netif_attach(netif, s_eth_glue);
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL));
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
#endif
esp_eth_start(s_eth_handle);
return netif;
}
@ -474,7 +475,6 @@ static void eth_stop(void)
#endif
ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle));
ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
ESP_ERROR_CHECK(esp_eth_clear_default_handlers(eth_netif));
ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle));
ESP_ERROR_CHECK(s_phy->del(s_phy));
ESP_ERROR_CHECK(s_mac->del(s_mac));

Wyświetl plik

@ -28,29 +28,29 @@ See the [README.md](../README.md) file in the upper level [examples](../) direct
### Using SPI ethernet modules
* SPI Ethernet modules (DM9051, W5500, ...) typically consume one SPI interface plus an interrupt and reset GPIO. By default they're connected as follows:
* SPI Ethernet modules (DM9051, W5500, ...) typically consume one SPI interface plus an interrupt and reset GPIO. They can be connected as follows for ESP32 as an example. However, they can be remapped to any pin using the GPIO Matrix.
| GPIO | DM9051 |
| ------ | ----------- |
| GPIO19 | SPI_CLK |
| GPIO23 | SPI_MOSI |
| GPIO25 | SPI_MISO |
| GPIO22 | SPI_CS |
| GPIO14 | SPI_CLK |
| GPIO13 | SPI_MOSI |
| GPIO12 | SPI_MISO |
| GPIO15 | SPI_CS |
| GPIO4 | Interrupt |
| GPIO5 | Reset |
| NC | Reset |
Please consult Espressif Technical reference manual for assigning any other pins, especially when choosing from system configuration menu for the ethernet examples,
some pins cannot be used.
Please consult Espressif Technical reference manual along with datasheet for specific ESP Module you use when assigning any other pins, especially when choosing from system configuration menu for the ethernet examples, some pins cannot be used (they may already be utilized for different purpose like SPI Flash/RAM, etc.).
## Common Configurations
1. In the `Example Configuration` menu:
* Choose the kind of Ethernet under `Ethernet Type`.
* Choose the kind of Ethernet.
* If `Internal EMAC` is selected:
* Choose PHY device under `Ethernet PHY Device`, by default, the **ESP32-Ethernet-Kit** has an `IP101` on board.
* Set GPIO number used by SMI signal under `SMI MDC GPIO number` and `SMI MDIO GPIO number` respectively.
* If `DM9051 Module` is selected:
* Set SPI specific configuration, including SPI host number, GPIO number and clock rate.
* If `SPI Ethernet` is selected:
* Set SPI specific configuration, including SPI host number, GPIO numbers and clock rate.
* Multiple Ethernet SPI modules of the same type can be connected to single SPI interface at a time. The modules then share data and CLK signals. The CS, interrupt and reset pins need to be specifically configured for each module separately.
* Set GPIO number used by PHY chip reset under `PHY Reset GPIO number`, you may have to change the default value according to your board schematic. **PHY hardware reset can be disabled by set this value to -1**.
* Set PHY address under `PHY Address`, you may have to change the default value according to your board schematic.
@ -61,7 +61,7 @@ some pins cannot be used.
* If `Output RMII clock from internal` is enabled, you also have to set the GPIO number that used to output the RMII clock, under `RMII clock GPIO number`. In this case, you can set the GPIO number to 16 or 17.
* If `Output RMII clock from GPIO0 (Experimental!)` is also enabled, then you have no choice but GPIO0 to output the RMII clock.
* In `Amount of Ethernet DMA Rx buffers` and `Amount of Ethernet DMA Tx buffers`, you can set the amount of DMA buffers used for Tx and Rx.
* Under `Support SPI to Ethernet Module` sub-menu, select the SPI module that you used for this example. Currently ESP-IDF only supports `DM9051`.
* Under `Support SPI to Ethernet Module` sub-menu, select the SPI module that you used for this example. Currently ESP-IDF only supports `DM9051`, `W5500` and `KSZ8851SNL`.
## Common Troubleshooting

Wyświetl plik

@ -17,12 +17,19 @@ If you have a new Ethernet application to go (for example, connect to IoT cloud
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a supported Ethernet PHY chip. Up until now, ESP-IDF supports up to four Ethernet PHY: `LAN8720`, `IP101`, `DP83848` and `RTL8201`, additional PHY drivers should be implemented by users themselves.
Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). This example will take the **DM9051** as an example, illustrating how to install the Ethernet driver in the same manner.
Besides that, `esp_eth` component can drive third-party Ethernet module which integrates MAC and PHY and provides common communication interface (e.g. SPI, USB, etc). This example will take the `DM9051`, `W5500` or `KSZ8851SNL` SPI modules as an example, illustrating how to install the Ethernet driver in the same manner.
The ESP-IDF supports the usage of multiple Ethernet interfaces at a time when external modules are utilized which is also demonstrated by this example. There are several options you can combine:
* Internal EMAC and one SPI Ethernet module.
* Two SPI Ethernet modules of the same type connected to single SPI interface and accessed by switching appropriate CS.
* Internal EMAC and two SPI Ethernet modules of the same type.
#### Pin Assignment
See common pin assignments for Ethernet examples from [upper level](../README.md#common-pin-assignments).
When using two Ethernet SPI modules at a time, they are to be connected to single SPI interface. Both modules then share data (MOSI/MISO) and CLK signals. However, the CS, interrupt and reset pins need to be connected to separate GPIO for each Ethernet SPI module.
### Configure the project
```

Wyświetl plik

@ -1,46 +1,21 @@
menu "Example Configuration"
config EXAMPLE_USE_SPI_ETHERNET
bool
config EXAMPLE_GPIO_RANGE_MIN
int
default 0
choice EXAMPLE_ETHERNET_TYPE
prompt "Ethernet Type"
default EXAMPLE_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32
default EXAMPLE_USE_W5500
config EXAMPLE_GPIO_RANGE_MAX
int
default 33 if IDF_TARGET_ESP32
default 46 if IDF_TARGET_ESP32S2
default 19 if IDF_TARGET_ESP32C3
config EXAMPLE_USE_INTERNAL_ETHERNET
depends on IDF_TARGET_ESP32
select ETH_USE_ESP32_EMAC
bool "Internal EMAC"
help
Select which kind of Ethernet will be used in the example.
config EXAMPLE_USE_INTERNAL_ETHERNET
depends on IDF_TARGET_ESP32
select ETH_USE_ESP32_EMAC
bool "Internal EMAC"
help
Select internal Ethernet MAC controller.
config EXAMPLE_USE_DM9051
bool "DM9051 Module"
select EXAMPLE_USE_SPI_ETHERNET
select ETH_USE_SPI_ETHERNET
select ETH_SPI_ETHERNET_DM9051
help
Select external SPI-Ethernet module (DM9051).
config EXAMPLE_USE_W5500
bool "W5500 Module"
select EXAMPLE_USE_SPI_ETHERNET
select ETH_USE_SPI_ETHERNET
select ETH_SPI_ETHERNET_W5500
help
Select external SPI-Ethernet module (W5500).
config EXAMPLE_USE_KSZ8851SNL
bool "KSZ8851SNL Module"
select EXAMPLE_USE_SPI_ETHERNET
select ETH_USE_SPI_ETHERNET
select ETH_SPI_ETHERNET_KSZ8851SNL
help
Select external SPI-Ethernet module (KSZ8851SNL).
endchoice # EXAMPLE_ETHERNET_TYPE
Use internal Ethernet MAC controller.
if EXAMPLE_USE_INTERNAL_ETHERNET
choice EXAMPLE_ETH_PHY_MODEL
@ -95,18 +70,75 @@ menu "Example Configuration"
config EXAMPLE_ETH_MDC_GPIO
int "SMI MDC GPIO number"
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 23
help
Set the GPIO number used by SMI MDC.
config EXAMPLE_ETH_MDIO_GPIO
int "SMI MDIO GPIO number"
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 18
help
Set the GPIO number used by SMI MDIO.
config EXAMPLE_ETH_PHY_RST_GPIO
int "PHY Reset GPIO number"
range -1 EXAMPLE_GPIO_RANGE_MAX
default 5
help
Set the GPIO number used to reset PHY chip.
Set to -1 to disable PHY chip hardware reset.
config EXAMPLE_ETH_PHY_ADDR
int "PHY Address"
range 0 31
default 1
help
Set PHY address according your board schematic.
endif # EXAMPLE_USE_INTERNAL_ETHERNET
config EXAMPLE_USE_SPI_ETHERNET
bool "SPI Ethernet"
default y
select ETH_USE_SPI_ETHERNET
help
Use external SPI-Ethernet module(s).
if EXAMPLE_USE_SPI_ETHERNET
config EXAMPLE_SPI_ETHERNETS_NUM
int "Number of SPI Ethernet modules to use at a time"
range 1 2
default 1
help
Set the number of SPI Ethernet modules you want to use at a time. Multiple SPI modules can be connected
to one SPI interface and can be separately accessed based on state of associated Chip Select (CS).
choice EXAMPLE_ETHERNET_TYPE_SPI
prompt "Ethernet SPI"
default EXAMPLE_USE_W5500
help
Select which kind of Ethernet will be used in the example.
config EXAMPLE_USE_DM9051
bool "DM9051 Module"
select ETH_SPI_ETHERNET_DM9051
help
Select external SPI-Ethernet module (DM9051).
config EXAMPLE_USE_KSZ8851SNL
bool "KSZ8851SNL Module"
select ETH_SPI_ETHERNET_KSZ8851SNL
help
Select external SPI-Ethernet module (KSZ8851SNL).
config EXAMPLE_USE_W5500
bool "W5500 Module"
select ETH_SPI_ETHERNET_W5500
help
Select external SPI-Ethernet module (W5500).
endchoice
config EXAMPLE_ETH_SPI_HOST
int "SPI Host Number"
range 0 2
@ -116,48 +148,31 @@ menu "Example Configuration"
config EXAMPLE_ETH_SPI_SCLK_GPIO
int "SPI SCLK GPIO number"
range 0 34 if IDF_TARGET_ESP32
range 0 46 if IDF_TARGET_ESP32S2
range 0 19 if IDF_TARGET_ESP32C3
default 18 if IDF_TARGET_ESP32
default 20 if IDF_TARGET_ESP32S2
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 14 if IDF_TARGET_ESP32
default 12 if IDF_TARGET_ESP32S2
default 6 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI SCLK.
config EXAMPLE_ETH_SPI_MOSI_GPIO
int "SPI MOSI GPIO number"
range 0 34 if IDF_TARGET_ESP32
range 0 46 if IDF_TARGET_ESP32S2
range 0 19 if IDF_TARGET_ESP32C3
default 23 if IDF_TARGET_ESP32
default 19 if IDF_TARGET_ESP32S2
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 13 if IDF_TARGET_ESP32
default 11 if IDF_TARGET_ESP32S2
default 7 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI MOSI.
config EXAMPLE_ETH_SPI_MISO_GPIO
int "SPI MISO GPIO number"
range 0 34 if IDF_TARGET_ESP32
range 0 46 if IDF_TARGET_ESP32S2
range 0 19 if IDF_TARGET_ESP32C3
default 19 if IDF_TARGET_ESP32
default 18 if IDF_TARGET_ESP32S2
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 12 if IDF_TARGET_ESP32
default 13 if IDF_TARGET_ESP32S2
default 2 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI MISO.
config EXAMPLE_ETH_SPI_CS_GPIO
int "SPI CS GPIO number"
range 0 34 if IDF_TARGET_ESP32
range 0 46 if IDF_TARGET_ESP32S2
range 0 19 if IDF_TARGET_ESP32C3
default 16 if IDF_TARGET_ESP32
default 21 if IDF_TARGET_ESP32S2
default 10 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI CS.
config EXAMPLE_ETH_SPI_CLOCK_MHZ
int "SPI clock speed (MHz)"
range 5 80
@ -166,25 +181,70 @@ menu "Example Configuration"
help
Set the clock speed (MHz) of SPI interface.
config EXAMPLE_ETH_SPI_INT_GPIO
int "Interrupt GPIO number"
default 17 if IDF_TARGET_ESP32
default 4 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3
config EXAMPLE_ETH_SPI_CS0_GPIO
int "SPI CS0 GPIO number for SPI Ethernet module #1"
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 15 if IDF_TARGET_ESP32
default 10 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3
help
Set the GPIO number used by the SPI Ethernet module interrupt line.
Set the GPIO number used by SPI CS0, i.e. Chip Select associated with the first SPI Eth module).
config EXAMPLE_ETH_SPI_CS1_GPIO
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
int "SPI CS1 GPIO number for SPI Ethernet module #2"
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 32 if IDF_TARGET_ESP32
default 7 if IDF_TARGET_ESP32S2
default 8 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI CS1, i.e. Chip Select associated with the second SPI Eth module.
config EXAMPLE_ETH_SPI_INT0_GPIO
int "Interrupt GPIO number SPI Ethernet module #1"
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 4 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3
help
Set the GPIO number used by the first SPI Ethernet module interrupt line.
config EXAMPLE_ETH_SPI_INT1_GPIO
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
int "Interrupt GPIO number SPI Ethernet module #2"
range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX
default 33 if IDF_TARGET_ESP32
default 5 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3
help
Set the GPIO number used by the second SPI Ethernet module interrupt line.
config EXAMPLE_ETH_SPI_PHY_RST0_GPIO
int "PHY Reset GPIO number of SPI Ethernet Module #1"
range -1 EXAMPLE_GPIO_RANGE_MAX
default -1
help
Set the GPIO number used to reset PHY chip on the first SPI Ethernet module.
Set to -1 to disable PHY chip hardware reset.
config EXAMPLE_ETH_SPI_PHY_RST1_GPIO
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
int "PHY Reset GPIO number of SPI Ethernet Module #2"
range -1 EXAMPLE_GPIO_RANGE_MAX
default -1
help
Set the GPIO number used to reset PHY chip on the second SPI Ethernet module.
Set to -1 to disable PHY chip hardware reset.
config EXAMPLE_ETH_SPI_PHY_ADDR0
int "PHY Address of SPI Ethernet Module #1"
range 0 31
default 1
help
Set the first SPI Ethernet module PHY address according your board schematic.
config EXAMPLE_ETH_SPI_PHY_ADDR1
depends on EXAMPLE_SPI_ETHERNETS_NUM > 1
int "PHY Address of SPI Ethernet Module #2"
range 0 31
default 1
help
Set the second SPI Ethernet module PHY address according your board schematic.
endif # EXAMPLE_USE_SPI_ETHERNET
config EXAMPLE_ETH_PHY_RST_GPIO
int "PHY Reset GPIO number"
default 5
help
Set the GPIO number used to reset PHY chip.
Set to -1 to disable PHY chip hardware reset.
config EXAMPLE_ETH_PHY_ADDR
int "PHY Address"
range 0 31
default 1
help
Set PHY address according your board schematic.
endmenu

Wyświetl plik

@ -22,6 +22,23 @@
static const char *TAG = "eth_example";
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
#define INIT_SPI_ETH_MODULE_CONFIG(eth_module_config, num) \
do { \
eth_module_config[num].spi_cs_gpio = CONFIG_EXAMPLE_ETH_SPI_CS ##num## _GPIO; \
eth_module_config[num].int_gpio = CONFIG_EXAMPLE_ETH_SPI_INT ##num## _GPIO; \
eth_module_config[num].phy_reset_gpio = CONFIG_EXAMPLE_ETH_SPI_PHY_RST ##num## _GPIO; \
eth_module_config[num].phy_addr = CONFIG_EXAMPLE_ETH_SPI_PHY_ADDR ##num; \
} while(0)
typedef struct {
uint8_t spi_cs_gpio;
uint8_t int_gpio;
int8_t phy_reset_gpio;
uint8_t phy_addr;
}spi_eth_module_config_t;
#endif
/** Event handler for Ethernet events */
static void eth_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
@ -72,19 +89,18 @@ void app_main(void)
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
// Create new default instance of esp-netif for Ethernet
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
// Set default handlers to process TCP/IP stuffs
ESP_ERROR_CHECK(esp_eth_set_default_handlers(eth_netif));
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
// Init MAC and PHY configs to default
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
@ -101,9 +117,43 @@ void app_main(void)
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ8081
esp_eth_phy_t *phy = esp_eth_phy_new_ksz8081(&phy_config);
#endif
#elif CONFIG_ETH_USE_SPI_ETHERNET
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
esp_eth_handle_t eth_handle = NULL;
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &eth_handle));
/* attach Ethernet driver to TCP/IP stack */
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
#endif //CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
// Create instance(s) of esp-netif for SPI Ethernet(s)
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
esp_netif_config_t cfg_spi = {
.base = &esp_netif_config,
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
};
esp_netif_t *eth_netif_spi[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM] = { NULL };
char if_key_str[10];
char if_desc_str[10];
char num_str[3];
for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) {
itoa(i, num_str, 10);
strcat(strcpy(if_key_str, "ETH_SPI_"), num_str);
strcat(strcpy(if_desc_str, "eth"), num_str);
esp_netif_config.if_key = if_key_str;
esp_netif_config.if_desc = if_desc_str;
esp_netif_config.route_prio = 30 - i;
eth_netif_spi[i] = esp_netif_new(&cfg_spi);
}
// Init MAC and PHY configs to default
eth_mac_config_t mac_config_spi = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config_spi = ETH_PHY_DEFAULT_CONFIG();
// Install GPIO ISR handler to be able to service SPI Eth modlues interrupts
gpio_install_isr_service(0);
spi_device_handle_t spi_handle = NULL;
// Init SPI bus
spi_device_handle_t spi_handle[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM] = { NULL };
spi_bus_config_t buscfg = {
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
@ -111,66 +161,121 @@ void app_main(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));
// Init specific SPI Ethernet module configuration from Kconfig (CS GPIO, Interrupt GPIO, etc.)
spi_eth_module_config_t spi_eth_module_config[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM];
INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 0);
#if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM > 1
INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 1);
#endif
// Configure SPI interface and Ethernet driver for specific SPI module
esp_eth_mac_t *mac_spi[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM];
esp_eth_phy_t *phy_spi[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM];
esp_eth_handle_t eth_handle_spi[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM] = { NULL };
#if CONFIG_EXAMPLE_USE_KSZ8851SNL
spi_device_interface_config_t devcfg = {
.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
};
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
/* KSZ8851SNL ethernet driver is based on spi driver */
eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle);
ksz8851snl_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_ksz8851snl(&phy_config);
for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) {
// Set SPI module Chip Select GPIO
devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio;
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle[i]));
// KSZ8851SNL ethernet driver is based on spi driver
eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle[i]);
// Set remaining GPIO numbers and configuration used by the SPI module
ksz8851snl_config.int_gpio_num = spi_eth_module_config[i].int_gpio;
phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr;
phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio;
mac_spi[i] = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config_spi);
phy_spi[i] = esp_eth_phy_new_ksz8851snl(&phy_config_spi);
}
#elif CONFIG_EXAMPLE_USE_DM9051
spi_device_interface_config_t devcfg = {
.command_bits = 1,
.address_bits = 7,
.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
};
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
/* dm9051 ethernet driver is based on spi driver */
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) {
// Set SPI module Chip Select GPIO
devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio;
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle[i]));
// dm9051 ethernet driver is based on spi driver
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle[i]);
// Set remaining GPIO numbers and configuration used by the SPI module
dm9051_config.int_gpio_num = spi_eth_module_config[i].int_gpio;
phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr;
phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio;
mac_spi[i] = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config_spi);
phy_spi[i] = esp_eth_phy_new_dm9051(&phy_config_spi);
}
#elif CONFIG_EXAMPLE_USE_W5500
spi_device_interface_config_t devcfg = {
.command_bits = 16, // Actually it's the address phase in W5500 SPI frame
.address_bits = 8, // Actually it's the control phase in W5500 SPI frame
.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
};
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
/* w5500 ethernet driver is based on spi driver */
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
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);
#endif
#endif // CONFIG_ETH_USE_SPI_ETHERNET
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
esp_eth_handle_t eth_handle = NULL;
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &eth_handle));
#if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) {
// Set SPI module Chip Select GPIO
devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio;
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle[i]));
// w5500 ethernet driver is based on spi driver
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle[i]);
// Set remaining GPIO numbers and configuration used by the SPI module
w5500_config.int_gpio_num = spi_eth_module_config[i].int_gpio;
phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr;
phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio;
mac_spi[i] = esp_eth_mac_new_w5500(&w5500_config, &mac_config_spi);
phy_spi[i] = esp_eth_phy_new_w5500(&phy_config_spi);
}
#endif //CONFIG_EXAMPLE_USE_W5500
for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) {
esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac_spi[i], phy_spi[i]);
ESP_ERROR_CHECK(esp_eth_driver_install(&eth_config_spi, &eth_handle_spi[i]));
/* The SPI Ethernet module might not have a burned factory MAC address, we cat to set it manually.
02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
*/
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
0x02, 0x00, 0x00, 0x12, 0x34, 0x56
}));
#endif
/* attach Ethernet driver to TCP/IP stack */
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
*/
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle_spi[i], ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
0x02, 0x00, 0x00, 0x12, 0x34, 0x56 + i
}));
// attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_netif_spi[i], esp_eth_new_netif_glue(eth_handle_spi[i])));
}
#endif // CONFIG_ETH_USE_SPI_ETHERNET
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
/* start Ethernet driver state machine */
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
#endif // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) {
ESP_ERROR_CHECK(esp_eth_start(eth_handle_spi[i]));
}
#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET
}

Wyświetl plik

@ -74,11 +74,6 @@ void app_main(void)
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&netif_cfg);
// Set default handlers to process TCP/IP stuffs
ESP_ERROR_CHECK(esp_eth_set_default_handlers(eth_netif));
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
spi_bus_config_t buscfg = {
.miso_io_num = CONFIG_EXAMPLE_ENC28J60_MISO_GPIO,
@ -134,6 +129,9 @@ void app_main(void)
/* attach Ethernet driver to TCP/IP stack */
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
/* start Ethernet driver state machine */
ESP_ERROR_CHECK(esp_eth_start(eth_handle));

Wyświetl plik

@ -188,9 +188,6 @@ void register_ethernet(void)
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
eth_netif = esp_netif_new(&cfg);
ESP_ERROR_CHECK(esp_eth_set_default_handlers(eth_netif));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &event_handler, NULL));
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
@ -304,6 +301,8 @@ void register_ethernet(void)
}));
#endif
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &event_handler, NULL));
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
#if CONFIG_EXAMPLE_USE_ENC28J60 && CONFIG_EXAMPLE_ENC28J60_DUPLEX_FULL