From c3ee156df0df19207b374cd257109a2d5179c1a2 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 26 Nov 2019 17:48:38 +0800 Subject: [PATCH] ethernet: move netif glue && add ref counter 1. move netif glue into single file 2. add reference counter for Ethernet driver --- components/esp_eth/CMakeLists.txt | 17 +- components/esp_eth/component.mk | 3 + components/esp_eth/include/esp_eth.h | 102 +++++++--- components/esp_eth/include/esp_eth_mac.h | 20 +- .../esp_eth/include/esp_eth_netif_glue.h | 66 +++++++ components/esp_eth/include/esp_eth_phy.h | 9 +- components/esp_eth/src/esp_eth.c | 182 ++++++++---------- components/esp_eth/src/esp_eth_mac_dm9051.c | 9 +- components/esp_eth/src/esp_eth_mac_esp32.c | 23 +-- components/esp_eth/src/esp_eth_mac_openeth.c | 29 ++- components/esp_eth/src/esp_eth_netif_glue.c | 134 +++++++++++++ components/esp_eth/src/esp_eth_phy_dm9051.c | 6 +- components/esp_eth/src/esp_eth_phy_dp83848.c | 5 +- components/esp_eth/src/esp_eth_phy_ip101.c | 5 +- components/esp_eth/src/esp_eth_phy_lan8720.c | 5 +- components/esp_eth/src/esp_eth_phy_rtl8201.c | 5 +- components/esp_eth/test/test_dm9051.c | 130 +++++++++++++ components/esp_eth/test/test_emac.c | 134 ++++++------- components/esp_netif/include/esp_netif.h | 6 +- .../tcpip_adapter/tcpip_adapter_compat.c | 36 ++-- docs/Doxyfile | 1 + docs/en/api-reference/network/esp_eth.rst | 5 + .../protocol_examples_common/connect.c | 20 +- .../basic/main/ethernet_example_main.c | 12 +- examples/ethernet/basic/sdkconfig.defaults | 1 + .../eth2ap/main/ethernet_example_main.c | 4 +- examples/ethernet/eth2ap/sdkconfig.defaults | 1 + examples/ethernet/iperf/main/cmd_ethernet.c | 5 +- examples/ethernet/iperf/sdkconfig.defaults | 2 + .../protocols/icmp_echo/sdkconfig.defaults | 1 + tools/unit-test-app/sdkconfig.defaults | 1 + 31 files changed, 644 insertions(+), 335 deletions(-) create mode 100644 components/esp_eth/include/esp_eth_netif_glue.h create mode 100644 components/esp_eth/src/esp_eth_netif_glue.c create mode 100644 components/esp_eth/test/test_dm9051.c create mode 100644 examples/ethernet/basic/sdkconfig.defaults create mode 100644 examples/ethernet/eth2ap/sdkconfig.defaults create mode 100644 examples/protocols/icmp_echo/sdkconfig.defaults diff --git a/components/esp_eth/CMakeLists.txt b/components/esp_eth/CMakeLists.txt index b76d035de..21b64cc7a 100644 --- a/components/esp_eth/CMakeLists.txt +++ b/components/esp_eth/CMakeLists.txt @@ -1,10 +1,20 @@ +idf_build_get_property(components_to_build BUILD_COMPONENTS) + set(srcs) set(include) +set(priv_requires) # If Ethernet disabled in Kconfig, this is a config-only component if(CONFIG_ETH_ENABLED) set(srcs "src/esp_eth.c") set(include "include") + set(priv_requires "driver" "log") # require "driver" for using some GPIO APIs + + # esp_netif related + if(esp_netif IN_LIST components_to_build) + list(APPEND srcs "src/esp_eth_netif_glue.c") + list(APPEND priv_requires "esp_netif") + endif() if(CONFIG_ETH_USE_ESP32_EMAC) list(APPEND srcs "src/esp_eth_mac_esp32.c" @@ -26,5 +36,8 @@ endif() idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${include} - REQUIRES "esp_event" - PRIV_REQUIRES "esp_netif" "driver" "log") + REQUIRES "esp_event" # For using "ESP_EVENT_DECLARE_BASE" in header file + PRIV_REQUIRES ${priv_requires}) + +# uses C11 atomic feature +set_source_files_properties(src/esp_eth.c PROPERTIES COMPILE_FLAGS -std=gnu11) diff --git a/components/esp_eth/component.mk b/components/esp_eth/component.mk index 65702f29f..6a57b6872 100644 --- a/components/esp_eth/component.mk +++ b/components/esp_eth/component.mk @@ -15,3 +15,6 @@ endif ifndef CONFIG_ETH_USE_OPENETH COMPONENT_OBJEXCLUDE += src/esp_eth_mac_openeth.o endif + +# uses C11 atomic feature +src/esp_eth.o: CFLAGS += -std=gnu11 diff --git a/components/esp_eth/include/esp_eth.h b/components/esp_eth/include/esp_eth.h index 48f364f8b..db0124eaf 100644 --- a/components/esp_eth/include/esp_eth.h +++ b/components/esp_eth/include/esp_eth.h @@ -62,7 +62,7 @@ typedef struct { * - ESP_FAIL: error occurred when inputting buffer to upper stack * */ - esp_err_t (*stack_input)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length); + esp_err_t (*stack_input)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv); /** * @brief Callback function invoked when lowlevel initialization is finished @@ -116,33 +116,68 @@ typedef struct { */ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_t *out_hdl); -/** -* @brief Start ethernet driver **ONLY** in standalone mode, i.e. without TCP/IP stack -* -* Note that ethernet driver is typically started as soon as it is attached to esp-netif. -* This API should only be called if ethernet is used separately without esp-netif, for example -* when esp_eth_config_t.stack_input is not NULL. -* -* @param[in] eth_handle handle of Ethernet driver -* -* @return -* - ESP_OK: starts ethernet driver -* - ESP_ERR_INVALID_STATE: if event loop hasn't been initialized -*/ -esp_err_t esp_eth_driver_start(esp_eth_handle_t eth_handle); - /** * @brief Uninstall Ethernet driver +* @note It's not recommended to uninstall Ethernet driver unless it won't get used any more in application code. +* To uninstall Ethernet driver, you have to make sure, all references to the driver are released. +* Ethernet driver can only be uninstalled successfully when reference counter equals to one. * * @param[in] hdl: handle of Ethernet driver * * @return * - ESP_OK: uninstall esp_eth driver successfully * - ESP_ERR_INVALID_ARG: uninstall esp_eth driver failed because of some invalid argument +* - ESP_ERR_INVALID_STATE: uninstall esp_eth driver failed because it has more than one reference * - ESP_FAIL: uninstall esp_eth driver failed because some other error occurred */ esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl); +/** +* @brief Start Ethernet driver **ONLY** in standalone mode (i.e. without TCP/IP stack) +* +* @note This API will start driver state machine and internal software timer (for checking link status). +* +* @param[in] hdl handle of Ethernet driver +* +* @return +* - ESP_OK: start esp_eth driver successfully +* - ESP_ERR_INVALID_ARG: start esp_eth driver failed because of some invalid argument +* - ESP_FAIL: start esp_eth driver failed because some other error occurred +*/ +esp_err_t esp_eth_start(esp_eth_handle_t hdl); + +/** +* @brief Stop Ethernet driver +* +* @note This function does the oppsite operation of `esp_eth_start`. +* +* @param[in] hdl handle of Ethernet driver +* @return +* - ESP_OK: stop esp_eth driver successfully +* - ESP_ERR_INVALID_ARG: stop esp_eth driver failed because of some invalid argument +* - ESP_FAIL: stop esp_eth driver failed because some other error occurred +*/ +esp_err_t esp_eth_stop(esp_eth_handle_t hdl); + +/** +* @brief Update Ethernet data input path (i.e. specify where to pass the input buffer) +* +* @note After install driver, Ethernet still don't know where to deliver the input buffer. +* In fact, this API registers a callback function which get invoked when Ethernet received new packets. +* +* @param[in] hdl handle of Ethernet driver +* @param[in] stack_input function pointer, which does the actual process on incoming packets +* @param[in] priv private resource, which gets passed to `stack_input` callback without any modification +* @return +* - ESP_OK: update input path successfully +* - ESP_ERR_INVALID_ARG: update input path failed because of some invalid argument +* - ESP_FAIL: update input path failed because some other error occurred +*/ +esp_err_t esp_eth_update_input_path( + esp_eth_handle_t hdl, + esp_err_t (*stack_input)(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv), + void *priv); + /** * @brief General Transmit * @@ -155,7 +190,7 @@ esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl); * - ESP_ERR_INVALID_ARG: transmit frame buffer failed because of some invalid argument * - ESP_FAIL: transmit frame buffer failed because some other error occurred */ -esp_err_t esp_eth_transmit(void* hdl, void *buf, uint32_t length); +esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, uint32_t length); /** * @brief General Receive @@ -191,20 +226,29 @@ esp_err_t esp_eth_receive(esp_eth_handle_t hdl, uint8_t *buf, uint32_t *length); esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data); /** - * @brief Register default ethernet handlers - * - * @param[in] esp_netif esp network interface handle created for this driver - * (note: appropriate ethernet handle not yet properly initialized when setting up - * default handlers) - */ -esp_err_t esp_eth_set_default_handlers(void* esp_netif); +* @brief Increase Ethernet driver reference +* @note Ethernet driver handle can be obtained by os timer, netif, etc. +* It's dangerous when thread A is using Ethernet but thread B uninstall the driver. +* Using reference counter can prevent such risk, but care should be taken, when you obtain Ethernet driver, +* this API must be invoked so that the driver won't be uninstalled during your using time. +* +* +* @param[in] hdl: handle of Ethernet driver +* @return +* - ESP_OK: increase reference successfully +* - ESP_ERR_INVALID_ARG: increase reference failed because of some invalid argument +*/ +esp_err_t esp_eth_increase_reference(esp_eth_handle_t hdl); /** - * @brief Unregister default ethernet handlers - * - * @param[in] esp_netif esp network interface handle created for this driver - */ -esp_err_t esp_eth_clear_default_handlers(void* esp_netif); +* @brief Decrease Ethernet driver reference +* +* @param[in] hdl: handle of Ethernet driver +* @return +* - ESP_OK: increase reference successfully +* - ESP_ERR_INVALID_ARG: increase reference failed because of some invalid argument +*/ +esp_err_t esp_eth_decrease_reference(esp_eth_handle_t hdl); #ifdef __cplusplus } diff --git a/components/esp_eth/include/esp_eth_mac.h b/components/esp_eth/include/esp_eth_mac.h index 5e083e34b..4318b2b64 100644 --- a/components/esp_eth/include/esp_eth_mac.h +++ b/components/esp_eth/include/esp_eth_mac.h @@ -18,9 +18,8 @@ extern "C" { #endif #include -#include -#include "sdkconfig.h" #include "esp_eth_com.h" +#include "sdkconfig.h" #if CONFIG_ETH_USE_SPI_ETHERNET #include "driver/spi_master.h" #endif @@ -37,12 +36,6 @@ typedef struct esp_eth_mac_s esp_eth_mac_t; * */ struct esp_eth_mac_s { - /** - * @brief Reference count of MAC instance - * - */ - atomic_int ref_count; - /** * @brief Set mediator for Ethernet MAC * @@ -322,17 +315,6 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, #if CONFIG_ETH_USE_OPENETH -/** -* @brief Create OpenETH MAC instance -* -* @note This API is only used for qemu simulation -* -* @param config: Ethernet MAC configuration -* -* @return -* - instance: create MAC instance successfully -* - NULL: create MAC instance failed because some error occurred -*/ esp_eth_mac_t *esp_eth_mac_new_openeth(const eth_mac_config_t *config); #endif // CONFIG_ETH_USE_OPENETH diff --git a/components/esp_eth/include/esp_eth_netif_glue.h b/components/esp_eth/include/esp_eth_netif_glue.h new file mode 100644 index 000000000..25bc1cff6 --- /dev/null +++ b/components/esp_eth/include/esp_eth_netif_glue.h @@ -0,0 +1,66 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_eth.h" + +/** + * @brief Create a netif glue for Ethernet driver + * @note netif glue is used to attach io driver to TCP/IP netif + * + * @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); + +/** + * @brief Delete netif glue of Ethernet driver + * + * @param glue netif glue + * @return -ESP_OK: delete netif glue successfully + */ +esp_err_t esp_eth_del_netif_glue(void *glue); + +/** + * @brief Register default IP layer handlers for Ethernet + * + * @note: Ethernet handle might not yet properly initialized when setting up these 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) + * - 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); + +/** + * @brief Unregister default IP layer handlers for Ethernet + * + * @param[in] esp_netif esp network interface handle created for Ethernet driver + * @return + * - ESP_ERR_INVALID_ARG: invalid parameter (esp_netif is NULL) + * - ESP_OK: clear default IP layer handlers successfully + * - others: other failure occurred during unregister esp_event handler + */ +esp_err_t esp_eth_clear_default_handlers(void *esp_netif); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_eth/include/esp_eth_phy.h b/components/esp_eth/include/esp_eth_phy.h index f29b3096d..2e27350e3 100644 --- a/components/esp_eth/include/esp_eth_phy.h +++ b/components/esp_eth/include/esp_eth_phy.h @@ -18,9 +18,8 @@ extern "C" { #endif #include -#include -#include "sdkconfig.h" #include "esp_eth_com.h" +#include "sdkconfig.h" /** * @brief Ethernet PHY @@ -33,12 +32,6 @@ typedef struct esp_eth_phy_s esp_eth_phy_t; * */ struct esp_eth_phy_s { - /** - * @brief Reference count of PHY instance - * - */ - atomic_int ref_count; - /** * @brief Set mediator for PHY * diff --git a/components/esp_eth/src/esp_eth.c b/components/esp_eth/src/esp_eth.c index a5119db65..8b1f90e32 100644 --- a/components/esp_eth/src/esp_eth.c +++ b/components/esp_eth/src/esp_eth.c @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. #include +#include #include "esp_log.h" #include "esp_eth.h" #include "esp_event.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/timers.h" -#include "esp_netif.h" -#include "tcpip_adapter_compatible/tcpip_adapter_compat.h" static const char *TAG = "esp_eth"; #define ETH_CHECK(a, str, goto_tag, ret_value, ...) \ @@ -46,7 +45,6 @@ ESP_EVENT_DEFINE_BASE(ETH_EVENT); * In the callback, user can do any low level operations (e.g. enable/disable crystal clock). */ typedef struct { - esp_netif_driver_base_t base; esp_eth_mediator_t mediator; esp_eth_phy_t *phy; esp_eth_mac_t *mac; @@ -54,7 +52,9 @@ typedef struct { eth_speed_t speed; eth_duplex_t duplex; eth_link_t link; - esp_err_t (*stack_input)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length); + atomic_int ref_count; + void *priv; + esp_err_t (*stack_input)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv); esp_err_t (*on_lowlevel_init_done)(esp_eth_handle_t eth_handle); esp_err_t (*on_lowlevel_deinit_done)(esp_eth_handle_t eth_handle); } esp_eth_driver_t; @@ -85,10 +85,11 @@ static esp_err_t eth_phy_reg_write(esp_eth_mediator_t *eth, uint32_t phy_addr, u static esp_err_t eth_stack_input(esp_eth_mediator_t *eth, uint8_t *buffer, uint32_t length) { esp_eth_driver_t *eth_driver = __containerof(eth, esp_eth_driver_t, mediator); - if (!eth_driver->stack_input) { - return esp_netif_receive(eth_driver->base.netif, buffer, length, NULL); + if (eth_driver->stack_input) { + return eth_driver->stack_input((esp_eth_handle_t)eth_driver, buffer, length, eth_driver->priv); } else { - return eth_driver->stack_input((esp_eth_handle_t)eth_driver, buffer, length); + free(buffer); + return ESP_OK; } } @@ -148,37 +149,9 @@ static void eth_check_link_timer_cb(TimerHandle_t xTimer) { esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)pvTimerGetTimerID(xTimer); esp_eth_phy_t *phy = eth_driver->phy; - /* add reference to prevent other thread deleting the phy instance */ - atomic_fetch_add(&phy->ref_count, 1); + esp_eth_increase_reference(eth_driver); phy->get_link(phy); - /* only the timer obtains the instance, i.e. all other references to this phy has been released */ - if (atomic_load(&phy->ref_count) == 1) { - phy->del(phy); // since this phy doesn't have other owners, delete it - } else { - atomic_fetch_sub(&phy->ref_count, 1); - } -} - -static esp_err_t esp_eth_post_attach_driver_start(esp_netif_t * esp_netif, void * args) -{ - uint8_t eth_mac[6]; - esp_eth_driver_t *eth_driver = args; - eth_driver->base.netif = esp_netif; - - // Set driver related config to esp-netif - esp_netif_driver_ifconfig_t driver_ifconfig = { - .handle = 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(eth_driver, ETH_CMD_G_MAC_ADDR, eth_mac); - ESP_LOGI(TAG, "%x %x %x %x %x %x", eth_mac[0], eth_mac[1], eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); - - esp_netif_set_mac(esp_netif, eth_mac); - ESP_LOGI(TAG, "ETH netif started"); - return esp_eth_driver_start(eth_driver); + esp_eth_decrease_reference(eth_driver); } ////////////////////////////////User face APIs//////////////////////////////////////////////// @@ -186,21 +159,6 @@ static esp_err_t esp_eth_post_attach_driver_start(esp_netif_t * esp_netif, void // Different Ethernet driver instance is identified with a unique handle. // It's helpful for us to support multiple Ethernet port on ESP32. ////////////////////////////////////////////////////////////////////////////////////////////// -esp_err_t esp_eth_driver_start(esp_eth_handle_t eth_handle) -{ - esp_err_t ret = ESP_OK; - esp_eth_driver_t *eth_driver = eth_handle; - ETH_CHECK(xTimerStart(eth_driver->check_link_timer, 0) == pdPASS, "start eth_link_timer failed", err_start_timer, ESP_FAIL); - - ETH_CHECK(esp_event_post(ETH_EVENT, ETHERNET_EVENT_START, ð_driver, sizeof(eth_driver), 0) == ESP_OK, - "send ETHERNET_EVENT_START event failed", err_event, ESP_FAIL); - return ret; -err_start_timer: - xTimerDelete(eth_driver->check_link_timer, 0); -err_event: - esp_eth_driver_uninstall(eth_driver); - return ret; -} esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_t *out_hdl) { @@ -212,10 +170,9 @@ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_ ETH_CHECK(mac && phy, "can't set eth->mac or eth->phy to null", err, ESP_ERR_INVALID_ARG); esp_eth_driver_t *eth_driver = calloc(1, sizeof(esp_eth_driver_t)); ETH_CHECK(eth_driver, "request memory for eth_driver failed", err, ESP_ERR_NO_MEM); + atomic_init(ð_driver->ref_count, 1); eth_driver->mac = mac; eth_driver->phy = phy; - atomic_fetch_add(&phy->ref_count, 1); - atomic_fetch_add(&mac->ref_count, 1); eth_driver->link = ETH_LINK_DOWN; eth_driver->duplex = ETH_DUPLEX_HALF; eth_driver->speed = ETH_SPEED_10M; @@ -235,9 +192,14 @@ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_ eth_driver->check_link_timer = xTimerCreate("eth_link_timer", pdMS_TO_TICKS(config->check_link_period_ms), pdTRUE, eth_driver, eth_check_link_timer_cb); ETH_CHECK(eth_driver->check_link_timer, "create eth_link_timer failed", err_create_timer, ESP_FAIL); - eth_driver->base.post_attach = esp_eth_post_attach_driver_start; *out_hdl = (esp_eth_handle_t)eth_driver; + + // for backward compatible to 4.0, and will get removed in 5.0 +#if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER + extern esp_err_t tcpip_adapter_compat_start_eth(void *eth_driver); tcpip_adapter_compat_start_eth(eth_driver); +#endif + return ESP_OK; err_create_timer: phy->deinit(phy); @@ -245,8 +207,6 @@ err_init_phy: mac->deinit(mac); err_init_mac: err_mediator: - atomic_fetch_sub(&phy->ref_count, 1); - atomic_fetch_sub(&mac->ref_count, 1); free(eth_driver); err: return ret; @@ -257,22 +217,66 @@ esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl) esp_err_t ret = ESP_OK; esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG); + // don't uninstall driver unless there's only one reference + ETH_CHECK(atomic_load(ð_driver->ref_count) == 1, + "more than one reference to ethernet driver", err, ESP_ERR_INVALID_STATE); esp_eth_mac_t *mac = eth_driver->mac; esp_eth_phy_t *phy = eth_driver->phy; ETH_CHECK(xTimerDelete(eth_driver->check_link_timer, 0) == pdPASS, "delete eth_link_timer failed", err, ESP_FAIL); - ETH_CHECK(esp_event_post(ETH_EVENT, ETHERNET_EVENT_STOP, ð_driver, sizeof(eth_driver), 0) == ESP_OK, - "send ETHERNET_EVENT_STOP event failed", err, ESP_FAIL); ETH_CHECK(phy->deinit(phy) == ESP_OK, "deinit phy failed", err, ESP_FAIL); ETH_CHECK(mac->deinit(mac) == ESP_OK, "deinit mac failed", err, ESP_FAIL); - atomic_fetch_sub(&phy->ref_count, 1); - atomic_fetch_sub(&mac->ref_count, 1); free(eth_driver); return ESP_OK; err: return ret; } -esp_err_t esp_eth_transmit(void* hdl, void *buf, uint32_t length) +esp_err_t esp_eth_start(esp_eth_handle_t hdl) +{ + esp_err_t ret = ESP_OK; + esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; + ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG); + ETH_CHECK(xTimerStart(eth_driver->check_link_timer, 0) == pdPASS, + "start eth_link_timer failed", err, ESP_FAIL); + ETH_CHECK(esp_event_post(ETH_EVENT, ETHERNET_EVENT_START, ð_driver, sizeof(eth_driver), 0) == ESP_OK, + "send ETHERNET_EVENT_START event failed", err_event, ESP_FAIL); + return ESP_OK; +err_event: + xTimerStop(eth_driver->check_link_timer, 0); +err: + return ret; +} + +esp_err_t esp_eth_stop(esp_eth_handle_t hdl) +{ + esp_err_t ret = ESP_OK; + esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; + ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG); + ETH_CHECK(xTimerStop(eth_driver->check_link_timer, 0) == pdPASS, + "stop eth_link_timer failed", err, ESP_FAIL); + ETH_CHECK(esp_event_post(ETH_EVENT, ETHERNET_EVENT_STOP, ð_driver, sizeof(eth_driver), 0) == ESP_OK, + "send ETHERNET_EVENT_STOP event failed", err, ESP_FAIL); + return ESP_OK; +err: + return ret; +} + +esp_err_t esp_eth_update_input_path( + esp_eth_handle_t hdl, + esp_err_t (*stack_input)(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv), + void *priv) +{ + esp_err_t ret = ESP_OK; + esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; + eth_driver->priv = priv; + ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG); + eth_driver->stack_input = stack_input; + return ESP_OK; +err: + return ret; +} + +esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, uint32_t length) { esp_err_t ret = ESP_OK; esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; @@ -334,54 +338,24 @@ err: return ret; } -esp_err_t esp_eth_clear_default_handlers(void* esp_netif) +esp_err_t esp_eth_increase_reference(esp_eth_handle_t hdl) { - esp_err_t ret; - ETH_CHECK(esp_netif, "esp-netif handle can't be null", fail, ESP_ERR_INVALID_ARG); - - 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); + esp_err_t ret = ESP_OK; + esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; + ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG); + atomic_fetch_add(ð_driver->ref_count, 1); return ESP_OK; -fail: +err: return ret; } -esp_err_t esp_eth_set_default_handlers(void* esp_netif) +esp_err_t esp_eth_decrease_reference(esp_eth_handle_t hdl) { - esp_err_t ret; - ETH_CHECK(esp_netif, "esp-netif handle can't be null", fail, ESP_ERR_INVALID_ARG); - - ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - - ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_STOP, esp_netif_action_stop, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - - ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, esp_netif_action_connected, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - - ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, esp_netif_action_disconnected, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - - ret = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, esp_netif_action_got_ip, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - + esp_err_t ret = ESP_OK; + esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; + ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG); + atomic_fetch_sub(ð_driver->ref_count, 1); return ESP_OK; - -fail: - esp_eth_clear_default_handlers(esp_netif); +err: return ret; } diff --git a/components/esp_eth/src/esp_eth_mac_dm9051.c b/components/esp_eth/src/esp_eth_mac_dm9051.c index 625cbdd6c..599f1b655 100644 --- a/components/esp_eth/src/esp_eth_mac_dm9051.c +++ b/components/esp_eth/src/esp_eth_mac_dm9051.c @@ -709,11 +709,9 @@ static esp_err_t emac_dm9051_deinit(esp_eth_mac_t *mac) static esp_err_t emac_dm9051_del(esp_eth_mac_t *mac) { emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent); - if (atomic_fetch_sub(&mac->ref_count, 1) == 1) { - vTaskDelete(emac->rx_task_hdl); - vSemaphoreDelete(emac->spi_lock); - free(emac); - } + vTaskDelete(emac->rx_task_hdl); + vSemaphoreDelete(emac->spi_lock); + free(emac); return ESP_OK; } @@ -745,7 +743,6 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, emac->parent.set_promiscuous = emac_dm9051_set_promiscuous; emac->parent.transmit = emac_dm9051_transmit; emac->parent.receive = emac_dm9051_receive; - atomic_init(&emac->parent.ref_count, 1); /* create mutex */ emac->spi_lock = xSemaphoreCreateMutex(); MAC_CHECK(emac->spi_lock, "create lock failed", err, NULL); diff --git a/components/esp_eth/src/esp_eth_mac_esp32.c b/components/esp_eth/src/esp_eth_mac_esp32.c index 61d28a030..03a5b53bb 100644 --- a/components/esp_eth/src/esp_eth_mac_esp32.c +++ b/components/esp_eth/src/esp_eth_mac_esp32.c @@ -334,19 +334,17 @@ static esp_err_t emac_esp32_deinit(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); - if (atomic_fetch_sub(&mac->ref_count, 1) == 1) { - esp_intr_free(emac->intr_hdl); - vTaskDelete(emac->rx_task_hdl); - int i = 0; - for (i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) { - free(emac->hal.rx_buf[i]); - } - for (i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) { - free(emac->hal.tx_buf[i]); - } - free(emac->hal.descriptors); - free(emac); + esp_intr_free(emac->intr_hdl); + vTaskDelete(emac->rx_task_hdl); + int i = 0; + for (i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) { + free(emac->hal.rx_buf[i]); } + for (i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) { + free(emac->hal.tx_buf[i]); + } + free(emac->hal.descriptors); + free(emac); return ESP_OK; } @@ -407,7 +405,6 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config) emac->parent.set_promiscuous = emac_esp32_set_promiscuous; emac->parent.transmit = emac_esp32_transmit; emac->parent.receive = emac_esp32_receive; - atomic_init(&emac->parent.ref_count, 1); /* Interrupt configuration */ MAC_CHECK(esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, ESP_INTR_FLAG_IRAM, emac_esp32_isr_handler, &emac->hal, &(emac->intr_hdl)) == ESP_OK, diff --git a/components/esp_eth/src/esp_eth_mac_openeth.c b/components/esp_eth/src/esp_eth_mac_openeth.c index 1c3afca34..e110e405b 100644 --- a/components/esp_eth/src/esp_eth_mac_openeth.c +++ b/components/esp_eth/src/esp_eth_mac_openeth.c @@ -66,7 +66,7 @@ static esp_err_t emac_opencores_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32 static IRAM_ATTR void emac_opencores_isr_handler(void *args) { - emac_opencores_t *emac = (emac_opencores_t *) args; + emac_opencores_t *emac = (emac_opencores_t*) args; BaseType_t high_task_wakeup; uint32_t status = REG_READ(OPENETH_INT_SOURCE_REG); @@ -94,7 +94,7 @@ static void emac_opencores_rx_task(void *arg) uint32_t length = 0; while (1) { if (ulTaskNotifyTake(pdFALSE, portMAX_DELAY)) { - while (true) { + while(true) { buffer = (uint8_t *)malloc(ETH_MAX_PACKET_SIZE); length = ETH_MAX_PACKET_SIZE; if (emac_opencores_receive(&emac->parent, buffer, &length) == ESP_OK) { @@ -243,7 +243,7 @@ static esp_err_t emac_opencores_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint3 while (bytes_remaining > 0) { uint32_t will_write = MIN(bytes_remaining, DMA_BUF_SIZE); memcpy(emac->tx_buf[emac->cur_tx_desc], buf, will_write); - openeth_tx_desc_t *desc_ptr = openeth_tx_desc(emac->cur_tx_desc); + openeth_tx_desc_t* desc_ptr = openeth_tx_desc(emac->cur_tx_desc); openeth_tx_desc_t desc_val = *desc_ptr; desc_val.wr = (emac->cur_tx_desc == TX_BUF_COUNT - 1); desc_val.len = will_write; @@ -294,7 +294,7 @@ static esp_err_t emac_opencores_init(esp_eth_mac_t *mac) esp_eth_mediator_t *eth = emac->eth; MAC_CHECK(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL) == ESP_OK, "lowlevel init failed", err, ESP_FAIL); MAC_CHECK(esp_read_mac(emac->addr, ESP_MAC_ETH) == ESP_OK, "fetch ethernet mac address failed", err, ESP_FAIL); - + // Sanity check if (REG_READ(OPENETH_MODER_REG) != OPENETH_MODER_DEFAULT) { ESP_LOGE(TAG, "CONFIG_ETH_USE_OPENETH should only be used when running in QEMU."); @@ -323,17 +323,15 @@ static esp_err_t emac_opencores_deinit(esp_eth_mac_t *mac) static esp_err_t emac_opencores_del(esp_eth_mac_t *mac) { emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent); - if (atomic_fetch_sub(&mac->ref_count, 1) == 1) { - esp_intr_free(emac->intr_hdl); - vTaskDelete(emac->rx_task_hdl); - for (int i = 0; i < RX_BUF_COUNT; i++) { - free(emac->rx_buf[i]); - } - for (int i = 0; i < TX_BUF_COUNT; i++) { - free(emac->tx_buf[i]); - } - free(emac); + esp_intr_free(emac->intr_hdl); + vTaskDelete(emac->rx_task_hdl); + for (int i = 0; i < RX_BUF_COUNT; i++) { + free(emac->rx_buf[i]); } + for (int i = 0; i < TX_BUF_COUNT; i++) { + free(emac->tx_buf[i]); + } + free(emac); return ESP_OK; } @@ -380,8 +378,7 @@ esp_eth_mac_t *esp_eth_mac_new_openeth(const eth_mac_config_t *config) emac->parent.set_promiscuous = emac_opencores_set_promiscuous; emac->parent.transmit = emac_opencores_transmit; emac->parent.receive = emac_opencores_receive; - atomic_init(&emac->parent.ref_count, 1); - + // Initialize the interrupt MAC_CHECK(esp_intr_alloc(OPENETH_INTR_SOURCE, ESP_INTR_FLAG_IRAM, emac_opencores_isr_handler, emac, &(emac->intr_hdl)) == ESP_OK, diff --git a/components/esp_eth/src/esp_eth_netif_glue.c b/components/esp_eth/src/esp_eth_netif_glue.c new file mode 100644 index 000000000..7a4e5e1a7 --- /dev/null +++ b/components/esp_eth/src/esp_eth_netif_glue.c @@ -0,0 +1,134 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "esp_netif.h" +#include "esp_eth.h" +#include "esp_eth_netif_glue.h" +#include "esp_event.h" +#include "esp_log.h" + +const static char *TAG = "esp_eth.netif.glue"; + +typedef struct { + esp_netif_driver_base_t base; + esp_eth_handle_t eth_driver; +} esp_eth_netif_glue_t; + +static esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv) +{ + return esp_netif_receive((esp_netif_t *)priv, buffer, length, NULL); +} + +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_update_input_path(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, + .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_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]); + + esp_netif_set_mac(esp_netif, eth_mac); + ESP_LOGI(TAG, "ethernet attached to netif"); + + 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_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); + + return ESP_OK; +} + +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; + } + + ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_STOP, esp_netif_action_stop, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, esp_netif_action_connected, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, esp_netif_action_disconnected, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, esp_netif_action_got_ip, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + return ESP_OK; + +fail: + esp_eth_clear_default_handlers(esp_netif); + return ret; +} diff --git a/components/esp_eth/src/esp_eth_phy_dm9051.c b/components/esp_eth/src/esp_eth_phy_dm9051.c index 19db41267..655967a4b 100644 --- a/components/esp_eth/src/esp_eth_phy_dm9051.c +++ b/components/esp_eth/src/esp_eth_phy_dm9051.c @@ -276,9 +276,7 @@ err: static esp_err_t dm9051_del(esp_eth_phy_t *phy) { phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent); - if (atomic_fetch_sub(&phy->ref_count, 1) == 1) { - free(dm9051); - } + free(dm9051); return ESP_OK; } @@ -335,8 +333,6 @@ esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config) dm9051->parent.get_addr = dm9051_get_addr; dm9051->parent.set_addr = dm9051_set_addr; dm9051->parent.del = dm9051_del; - atomic_init(&dm9051->parent.ref_count, 1); - return &(dm9051->parent); err: return NULL; diff --git a/components/esp_eth/src/esp_eth_phy_dp83848.c b/components/esp_eth/src/esp_eth_phy_dp83848.c index bb82cb8c3..0c1cd99cd 100644 --- a/components/esp_eth/src/esp_eth_phy_dp83848.c +++ b/components/esp_eth/src/esp_eth_phy_dp83848.c @@ -274,9 +274,7 @@ err: static esp_err_t dp83848_del(esp_eth_phy_t *phy) { phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); - if (atomic_fetch_sub(&phy->ref_count, 1) == 1) { - free(dp83848); - } + free(dp83848); return ESP_OK; } @@ -332,7 +330,6 @@ esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config) dp83848->parent.get_addr = dp83848_get_addr; dp83848->parent.set_addr = dp83848_set_addr; dp83848->parent.del = dp83848_del; - atomic_init(&dp83848->parent.ref_count, 1); return &(dp83848->parent); err: diff --git a/components/esp_eth/src/esp_eth_phy_ip101.c b/components/esp_eth/src/esp_eth_phy_ip101.c index 5bb92ec0a..307dca6eb 100644 --- a/components/esp_eth/src/esp_eth_phy_ip101.c +++ b/components/esp_eth/src/esp_eth_phy_ip101.c @@ -311,9 +311,7 @@ err: static esp_err_t ip101_del(esp_eth_phy_t *phy) { phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent); - if (atomic_fetch_sub(&phy->ref_count, 1) == 1) { - free(ip101); - } + free(ip101); return ESP_OK; } @@ -366,7 +364,6 @@ esp_eth_phy_t *esp_eth_phy_new_ip101(const eth_phy_config_t *config) ip101->parent.get_addr = ip101_get_addr; ip101->parent.set_addr = ip101_set_addr; ip101->parent.del = ip101_del; - atomic_init(&ip101->parent.ref_count, 1); return &(ip101->parent); err: diff --git a/components/esp_eth/src/esp_eth_phy_lan8720.c b/components/esp_eth/src/esp_eth_phy_lan8720.c index 8289faf59..82ae78b1d 100644 --- a/components/esp_eth/src/esp_eth_phy_lan8720.c +++ b/components/esp_eth/src/esp_eth_phy_lan8720.c @@ -355,9 +355,7 @@ err: static esp_err_t lan8720_del(esp_eth_phy_t *phy) { phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent); - if (atomic_fetch_sub(&phy->ref_count, 1) == 1) { - free(lan8720); - } + free(lan8720); return ESP_OK; } @@ -412,7 +410,6 @@ esp_eth_phy_t *esp_eth_phy_new_lan8720(const eth_phy_config_t *config) lan8720->parent.get_addr = lan8720_get_addr; lan8720->parent.set_addr = lan8720_set_addr; lan8720->parent.del = lan8720_del; - atomic_init(&lan8720->parent.ref_count, 1); return &(lan8720->parent); err: diff --git a/components/esp_eth/src/esp_eth_phy_rtl8201.c b/components/esp_eth/src/esp_eth_phy_rtl8201.c index be3c3038a..7ec624f82 100644 --- a/components/esp_eth/src/esp_eth_phy_rtl8201.c +++ b/components/esp_eth/src/esp_eth_phy_rtl8201.c @@ -262,9 +262,7 @@ err: static esp_err_t rtl8201_del(esp_eth_phy_t *phy) { phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent); - if (atomic_fetch_sub(&phy->ref_count, 1) == 1) { - free(rtl8201); - } + free(rtl8201); return ESP_OK; } @@ -320,7 +318,6 @@ esp_eth_phy_t *esp_eth_phy_new_rtl8201(const eth_phy_config_t *config) rtl8201->parent.get_addr = rtl8201_get_addr; rtl8201->parent.set_addr = rtl8201_set_addr; rtl8201->parent.del = rtl8201_del; - atomic_init(&rtl8201->parent.ref_count, 1); return &(rtl8201->parent); err: diff --git a/components/esp_eth/test/test_dm9051.c b/components/esp_eth/test/test_dm9051.c new file mode 100644 index 000000000..0f86f7371 --- /dev/null +++ b/components/esp_eth/test/test_dm9051.c @@ -0,0 +1,130 @@ +#include +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "unity.h" +#include "test_utils.h" +#include "esp_event.h" +#include "esp_eth.h" +#include "esp_log.h" +#include "driver/gpio.h" + +static const char *TAG = "dm9051_test"; + +#define ETH_START_BIT BIT(0) +#define ETH_STOP_BIT BIT(1) +#define ETH_CONNECT_BIT BIT(2) +#define ETH_GOT_IP_BIT BIT(3) + +#define ETH_START_TIMEOUT_MS (10000) +#define ETH_CONNECT_TIMEOUT_MS (40000) +#define ETH_STOP_TIMEOUT_MS (10000) +#define ETH_GET_IP_TIMEOUT_MS (60000) + +/** 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) +{ + EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT); + ESP_LOGI(TAG, "Ethernet Link Up"); + break; + case ETHERNET_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "Ethernet Link Down"); + break; + case ETHERNET_EVENT_START: + xEventGroupSetBits(eth_event_group, ETH_START_BIT); + ESP_LOGI(TAG, "Ethernet Started"); + break; + case ETHERNET_EVENT_STOP: + xEventGroupSetBits(eth_event_group, ETH_STOP_BIT); + ESP_LOGI(TAG, "Ethernet Stopped"); + break; + default: + break; + } +} + +/** Event handler for IP_EVENT_ETH_GOT_IP */ +static void got_ip_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + const esp_netif_ip_info_t *ip_info = &event->ip_info; + ESP_LOGI(TAG, "Ethernet Got IP Address"); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); + ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); + ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + xEventGroupSetBits(eth_event_group, ETH_GOT_IP_BIT); +} + +#if CONFIG_ETH_USE_SPI_ETHERNET +TEST_CASE("dm9051 io test", "[ethernet][dm9051][ignore]") +{ + spi_device_handle_t spi_handle = NULL; + spi_bus_config_t buscfg = { + .miso_io_num = 25, + .mosi_io_num = 23, + .sclk_io_num = 19, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + }; + TEST_ESP_OK(spi_bus_initialize(HSPI_HOST, &buscfg, 1)); + spi_device_interface_config_t devcfg = { + .command_bits = 1, + .address_bits = 7, + .mode = 0, + .clock_speed_hz = 20 * 1000 * 1000, + .spics_io_num = 22, + .queue_size = 20 + }; + TEST_ESP_OK(spi_bus_add_device(HSPI_HOST, &devcfg, &spi_handle)); + gpio_install_isr_service(0); + test_case_uses_tcpip(); + TEST_ESP_OK(esp_event_loop_create_default()); + // create TCP/IP netif + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); + esp_netif_t *eth_netif = esp_netif_new(&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, ð_event_handler, NULL)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); + eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); + esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config); + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); + esp_eth_handle_t eth_handle = NULL; + // install Ethernet driver + TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle)); + // combine driver with netif + void *glue = esp_eth_new_netif_glue(eth_handle); + TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // start Ethernet driver + TEST_ESP_OK(esp_eth_start(eth_handle)); + /* wait for IP lease */ + vTaskDelay(pdMS_TO_TICKS(portMAX_DELAY)); + // stop Ethernet driver + TEST_ESP_OK(esp_eth_stop(eth_handle)); + TEST_ESP_OK(esp_eth_del_netif_glue(glue)); + TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); + 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_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()); + TEST_ESP_OK(spi_bus_remove_device(spi_handle)); + TEST_ESP_OK(spi_bus_free(HSPI_HOST)); +} +#endif diff --git a/components/esp_eth/test/test_emac.c b/components/esp_eth/test/test_emac.c index 644dbcdd4..07fc324d7 100644 --- a/components/esp_eth/test/test_emac.c +++ b/components/esp_eth/test/test_emac.c @@ -1,6 +1,5 @@ #include #include -#include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" @@ -9,16 +8,12 @@ #include "esp_event.h" #include "esp_eth.h" #include "esp_log.h" -#include "driver/gpio.h" #include "lwip/inet.h" #include "lwip/netdb.h" #include "lwip/sockets.h" #include "ping/ping_sock.h" -#define GOT_IP_BIT BIT(0) -#define ETHERNET_GET_IP_TIMEOUT_MS (20000) - -static const char *TAG = "esp_eth_test"; +static const char *TAG = "esp32_eth_test"; #define ETH_START_BIT BIT(0) #define ETH_STOP_BIT BIT(1) @@ -115,9 +110,25 @@ static void test_on_ping_end(esp_ping_handle_t hdl, void *args) } } +static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_wait) +{ + int i = 0; + ms_to_wait += 100; + for (i = 0; i < ms_to_wait / 100; i++) { + vTaskDelay(pdMS_TO_TICKS(100)); + if (esp_eth_driver_uninstall(eth_hdl) == ESP_OK) { + break; + } + } + if (i < ms_to_wait / 10) { + return ESP_OK; + } else { + return ESP_FAIL; + } +} + TEST_CASE("esp32 ethernet io test", "[ethernet][test_env=UT_T2_Ethernet]") { - TEST_ESP_OK(esp_event_loop_create_default()); 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(); @@ -125,7 +136,6 @@ TEST_CASE("esp32 ethernet io test", "[ethernet][test_env=UT_T2_Ethernet]") esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); esp_eth_handle_t eth_handle = NULL; TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - vTaskDelay(pdMS_TO_TICKS(1000)); /* get MAC address */ uint8_t mac_addr[6]; memset(mac_addr, 0, sizeof(mac_addr)); @@ -141,7 +151,6 @@ TEST_CASE("esp32 ethernet io test", "[ethernet][test_env=UT_T2_Ethernet]") TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); TEST_ESP_OK(phy->del(phy)); TEST_ESP_OK(mac->del(mac)); - TEST_ESP_OK(esp_event_loop_delete_default()); } TEST_CASE("esp32 ethernet event test", "[ethernet][test_env=UT_T2_Ethernet]") @@ -150,8 +159,6 @@ TEST_CASE("esp32 ethernet event test", "[ethernet][test_env=UT_T2_Ethernet]") EventGroupHandle_t eth_event_group = xEventGroupCreate(); TEST_ASSERT(eth_event_group != NULL); TEST_ESP_OK(esp_event_loop_create_default()); - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t* eth_netif = esp_netif_new(&cfg); TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_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); @@ -160,23 +167,26 @@ TEST_CASE("esp32 ethernet event test", "[ethernet][test_env=UT_T2_Ethernet]") esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); esp_eth_handle_t eth_handle = NULL; TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - TEST_ESP_OK(esp_netif_attach(eth_netif, eth_handle)); + // this test only test layer2 event, so don't need to register input callback (i.e. esp_eth_update_input_path) + TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for connection start */ bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true, pdMS_TO_TICKS(ETH_START_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT); /* wait for connection establish */ bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); + // stop Ethernet driver + TEST_ESP_OK(esp_eth_stop(eth_handle)); /* wait for connection stop */ bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); + /* driver should be uninstalled within 2 seconds */ + TEST_ESP_OK(test_uninstall_driver(eth_handle, 2000)); TEST_ESP_OK(phy->del(phy)); TEST_ESP_OK(mac->del(mac)); TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); TEST_ESP_OK(esp_event_loop_delete_default()); vEventGroupDelete(eth_event_group); - esp_netif_destroy(eth_netif); } TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") @@ -186,10 +196,12 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") TEST_ASSERT(eth_event_group != NULL); test_case_uses_tcpip(); TEST_ESP_OK(esp_event_loop_create_default()); - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t* eth_netif = esp_netif_new(&cfg); + // 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, ð_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(); @@ -198,24 +210,32 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); esp_eth_handle_t eth_handle = NULL; + // install Ethernet driver TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - TEST_ESP_OK(esp_netif_attach(eth_netif, eth_handle)); - + // combine driver with netif + void *glue = esp_eth_new_netif_glue(eth_handle); + TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // start Ethernet driver + TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ bits = xEventGroupWaitBits(eth_event_group, ETH_GOT_IP_BIT, true, true, pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); + // stop Ethernet driver + TEST_ESP_OK(esp_eth_stop(eth_handle)); /* wait for connection stop */ bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); + TEST_ESP_OK(esp_eth_del_netif_glue(glue)); + /* driver should be uninstalled within 2 seconds */ + TEST_ESP_OK(test_uninstall_driver(eth_handle, 2000)); 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_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); - esp_netif_destroy(eth_netif); } TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") @@ -225,10 +245,12 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") TEST_ASSERT(eth_event_group != NULL); test_case_uses_tcpip(); TEST_ESP_OK(esp_event_loop_create_default()); - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t* eth_netif = esp_netif_new(&cfg); + // 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, ð_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(); @@ -238,7 +260,11 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); esp_eth_handle_t eth_handle = NULL; TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - TEST_ESP_OK(esp_netif_attach(eth_netif, eth_handle)); + // combine driver with netif + void *glue = esp_eth_new_netif_glue(eth_handle); + TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // start Ethernet driver + TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ bits = xEventGroupWaitBits(eth_event_group, ETH_GOT_IP_BIT, true, true, pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT); @@ -251,7 +277,7 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") memset(&target_addr, 0, sizeof(target_addr)); /* convert URL to IP */ TEST_ASSERT(getaddrinfo("www.baidu.com", NULL, &hint, &res) == 0); - struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr; + struct in_addr addr4 = ((struct sockaddr_in *)(res->ai_addr))->sin_addr; inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4); freeaddrinfo(res); @@ -285,63 +311,19 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") /* de-initialize ping process */ TEST_ESP_OK(esp_ping_delete_session(ping)); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); + // stop Ethernet driver + TEST_ESP_OK(esp_eth_stop(eth_handle)); /* wait for connection stop */ bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); + TEST_ESP_OK(esp_eth_del_netif_glue(glue)); + /* driver should be uninstalled within 2 seconds */ + TEST_ESP_OK(test_uninstall_driver(eth_handle, 2000)); 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); - esp_netif_destroy(eth_netif); } - -#if CONFIG_ETH_USE_SPI_ETHERNET -TEST_CASE("dm9051 io test", "[ethernet][ignore]") -{ - spi_device_handle_t spi_handle = NULL; - spi_bus_config_t buscfg = { - .miso_io_num = 25, - .mosi_io_num = 23, - .sclk_io_num = 19, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - }; - TEST_ESP_OK(spi_bus_initialize(HSPI_HOST, &buscfg, 1)); - spi_device_interface_config_t devcfg = { - .command_bits = 1, - .address_bits = 7, - .mode = 0, - .clock_speed_hz = 20 * 1000 * 1000, - .spics_io_num = 22, - .queue_size = 20 - }; - TEST_ESP_OK(spi_bus_add_device(HSPI_HOST, &devcfg, &spi_handle)); - gpio_install_isr_service(0); - esp_netif_init(); - TEST_ESP_OK(esp_event_loop_create_default()); - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t* eth_netif = esp_netif_new(&cfg); - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); - esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config); - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); - esp_eth_handle_t eth_handle = NULL; - TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle)); - TEST_ESP_OK(esp_netif_attach(eth_netif, eth_handle)); - vTaskDelay(pdMS_TO_TICKS(portMAX_DELAY)); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); - TEST_ESP_OK(phy->del(phy)); - TEST_ESP_OK(mac->del(mac)); - TEST_ESP_OK(esp_event_loop_delete_default()); - TEST_ESP_OK(spi_bus_remove_device(spi_handle)); - TEST_ESP_OK(spi_bus_free(HSPI_HOST)); -} -#endif diff --git a/components/esp_netif/include/esp_netif.h b/components/esp_netif/include/esp_netif.h index 946bf1f6c..2f4416037 100644 --- a/components/esp_netif/include/esp_netif.h +++ b/components/esp_netif/include/esp_netif.h @@ -16,12 +16,16 @@ #define _ESP_NETIF_H_ #include -#include "esp_wifi_types.h" #include "sdkconfig.h" +#include "esp_wifi_types.h" #include "esp_netif_ip_addr.h" #include "esp_netif_types.h" #include "esp_netif_defaults.h" +#if CONFIG_ETH_ENABLED +#include "esp_eth_netif_glue.h" +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/components/tcpip_adapter/tcpip_adapter_compat.c b/components/tcpip_adapter/tcpip_adapter_compat.c index 919306c24..1d2dee5b1 100644 --- a/components/tcpip_adapter/tcpip_adapter_compat.c +++ b/components/tcpip_adapter/tcpip_adapter_compat.c @@ -106,15 +106,9 @@ void tcpip_adapter_init(void) } #if CONFIG_ETH_ENABLED -static void tcpip_adapter_attach_eth_to_netif(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) -{ - esp_eth_handle_t eth_handle = *(esp_eth_handle_t*)data; - esp_netif_attach(esp_netif, eth_handle); -} esp_err_t tcpip_adapter_clear_default_eth_handlers(void) { - ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_START, tcpip_adapter_attach_eth_to_netif)); return esp_eth_clear_default_handlers(netif_from_if(TCPIP_ADAPTER_IF_ETH)); } @@ -125,18 +119,25 @@ 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; - // provide a separate "after driver start" hook to attach - esp_err_t ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, tcpip_adapter_attach_eth_to_netif, eth_netif); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to register "); - return ret; - } return esp_eth_set_default_handlers(eth_netif); } return ESP_OK; } + +esp_err_t tcpip_adapter_compat_start_eth(void *eth_driver) +{ + if (s_tcpip_adapter_compat) { + esp_netif_t *esp_netif = netif_from_if(TCPIP_ADAPTER_IF_ETH); + if (esp_netif) { + esp_netif_attach(esp_netif, esp_eth_new_netif_glue(eth_driver)); + } + esp_eth_start(eth_driver); + } + return ESP_OK; +} + #endif esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb) @@ -154,15 +155,6 @@ esp_err_t tcpip_adapter_ap_input(void *buffer, uint16_t len, void *eb) return esp_netif_receive(netif_from_if(TCPIP_ADAPTER_IF_AP), buffer, len, eb); } -esp_err_t tcpip_adapter_compat_start_eth(void* eth_driver) -{ - if (s_tcpip_adapter_compat) { - esp_netif_t *esp_netif = netif_from_if(TCPIP_ADAPTER_IF_ETH); - esp_netif_attach(esp_netif, eth_driver); - } - return ESP_OK; -} - esp_err_t tcpip_adapter_set_default_wifi_handlers(void) { #if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER @@ -382,4 +374,4 @@ esp_err_t tcpip_adapter_compat_start_eth(void* eth_driver) return ESP_OK; } -#endif \ No newline at end of file +#endif diff --git a/docs/Doxyfile b/docs/Doxyfile index ce15c0433..e2a2827e1 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -80,6 +80,7 @@ INPUT = \ ../../components/esp_eth/include/esp_eth_com.h \ ../../components/esp_eth/include/esp_eth_mac.h \ ../../components/esp_eth/include/esp_eth_phy.h \ + ../../components/esp_eth/include/esp_eth_netif_glue.h \ ## ## Peripherals - API Reference ## diff --git a/docs/en/api-reference/network/esp_eth.rst b/docs/en/api-reference/network/esp_eth.rst index 78a1ea1f7..66d018d8e 100644 --- a/docs/en/api-reference/network/esp_eth.rst +++ b/docs/en/api-reference/network/esp_eth.rst @@ -51,3 +51,8 @@ API Reference - PHY Interface ----------------------------- .. include:: /_build/inc/esp_eth_phy.inc + +API Reference - Glue for esp_netif +---------------------------------- + +.. include:: /_build/inc/esp_eth_netif_glue.inc diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index f71b323b2..f33aa7051 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -134,7 +134,7 @@ static void start(void) esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_WIFI_STA(); - esp_netif_t* netif = esp_netif_new(&netif_config); + esp_netif_t *netif = esp_netif_new(&netif_config); assert(netif); @@ -212,15 +212,12 @@ static esp_eth_phy_t *s_phy = NULL; static void start(void) { esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_ETH(); - - esp_netif_t* netif = esp_netif_new(&netif_config); - + esp_netif_t *netif = esp_netif_new(&netif_config); assert(netif); - - ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif)); - s_example_esp_netif = netif; - + // 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)); @@ -274,11 +271,12 @@ static void start(void) s_phy = esp_eth_phy_new_dp83848(&phy_config); #endif + // Install Ethernet driver esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy); - ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle)); - - esp_netif_attach(netif, s_eth_handle); + // combine driver with netif + esp_netif_attach(netif, esp_eth_new_netif_glue(s_eth_handle)); + esp_eth_start(s_eth_handle); s_connection_name = "Ethernet"; } diff --git a/examples/ethernet/basic/main/ethernet_example_main.c b/examples/ethernet/basic/main/ethernet_example_main.c index f7df43ed7..0ed7c189f 100644 --- a/examples/ethernet/basic/main/ethernet_example_main.c +++ b/examples/ethernet/basic/main/ethernet_example_main.c @@ -65,12 +65,15 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base, void app_main(void) { + // Initialize TCP/IP network interface (should be called only once in application) esp_netif_init(); - + // Create default event loop that running in background ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t* eth_netif = esp_netif_new(&cfg); + 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, ð_event_handler, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); @@ -120,5 +123,8 @@ void app_main(void) 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, ð_handle)); - ESP_ERROR_CHECK(esp_netif_attach(eth_netif, eth_handle)); + /* attach Ethernet driver to TCP/IP stack */ + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); + /* start Ethernet driver state machine */ + ESP_ERROR_CHECK(esp_eth_start(eth_handle)); } diff --git a/examples/ethernet/basic/sdkconfig.defaults b/examples/ethernet/basic/sdkconfig.defaults new file mode 100644 index 000000000..2facc67ab --- /dev/null +++ b/examples/ethernet/basic/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=n diff --git a/examples/ethernet/eth2ap/main/ethernet_example_main.c b/examples/ethernet/eth2ap/main/ethernet_example_main.c index 413c6a414..bc5adc3ff 100644 --- a/examples/ethernet/eth2ap/main/ethernet_example_main.c +++ b/examples/ethernet/eth2ap/main/ethernet_example_main.c @@ -51,7 +51,7 @@ static esp_err_t pkt_wifi2eth(void *buffer, uint16_t len, void *eb) // Forward packets from Ethernet to Wi-Fi // Note that, Ethernet works faster than Wi-Fi on ESP32, // so we need to add an extra queue to balance their speed difference. -static esp_err_t pkt_eth2wifi(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t len) +static esp_err_t pkt_eth2wifi(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t len, void* priv) { esp_err_t ret = ESP_OK; flow_control_msg_t msg = { @@ -190,7 +190,7 @@ static void initialize_ethernet(void) config.stack_input = pkt_eth2wifi; ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle)); esp_eth_ioctl(s_eth_handle, ETH_CMD_S_PROMISCUOUS, (void *)true); - esp_eth_driver_start(s_eth_handle); + esp_eth_start(s_eth_handle); } static void initialize_wifi(void) diff --git a/examples/ethernet/eth2ap/sdkconfig.defaults b/examples/ethernet/eth2ap/sdkconfig.defaults new file mode 100644 index 000000000..2facc67ab --- /dev/null +++ b/examples/ethernet/eth2ap/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=n diff --git a/examples/ethernet/iperf/main/cmd_ethernet.c b/examples/ethernet/iperf/main/cmd_ethernet.c index 5f0fda926..63985c7d3 100644 --- a/examples/ethernet/iperf/main/cmd_ethernet.c +++ b/examples/ethernet/iperf/main/cmd_ethernet.c @@ -25,7 +25,7 @@ static bool started = false; static EventGroupHandle_t eth_event_group; static const int GOTIP_BIT = BIT0; static esp_eth_handle_t eth_handle = NULL; -static esp_netif_t* eth_netif = NULL; +static esp_netif_t *eth_netif = NULL; /* "ethernet" command */ static struct { @@ -231,7 +231,8 @@ void register_ethernet(void) #endif esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); ESP_ERROR_CHECK(esp_eth_driver_install(&config, ð_handle)); - ESP_ERROR_CHECK(esp_netif_attach(eth_netif, eth_handle)); + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); + ESP_ERROR_CHECK(esp_eth_start(eth_handle)); eth_control_args.control = arg_str1(NULL, NULL, "", "Get info of Ethernet"); eth_control_args.end = arg_end(1); diff --git a/examples/ethernet/iperf/sdkconfig.defaults b/examples/ethernet/iperf/sdkconfig.defaults index 1bdcdc720..353d4cce4 100644 --- a/examples/ethernet/iperf/sdkconfig.defaults +++ b/examples/ethernet/iperf/sdkconfig.defaults @@ -15,3 +15,5 @@ CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y # ESP32-specific CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 + +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=n diff --git a/examples/protocols/icmp_echo/sdkconfig.defaults b/examples/protocols/icmp_echo/sdkconfig.defaults new file mode 100644 index 000000000..2facc67ab --- /dev/null +++ b/examples/protocols/icmp_echo/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=n diff --git a/tools/unit-test-app/sdkconfig.defaults b/tools/unit-test-app/sdkconfig.defaults index 4a654a479..832f52e26 100644 --- a/tools/unit-test-app/sdkconfig.defaults +++ b/tools/unit-test-app/sdkconfig.defaults @@ -27,3 +27,4 @@ CONFIG_EFUSE_VIRTUAL=y CONFIG_SPIRAM_BANKSWITCH_ENABLE=n CONFIG_FATFS_ALLOC_EXTRAM_FIRST=y CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=n