diff --git a/examples/ethernet/basic/components/ethernet_init/CMakeLists.txt b/examples/ethernet/basic/components/ethernet_init/CMakeLists.txt index 382893ed87..ef299cdfd4 100644 --- a/examples/ethernet/basic/components/ethernet_init/CMakeLists.txt +++ b/examples/ethernet/basic/components/ethernet_init/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "ethernet_init.c" - PRIV_REQUIRES driver esp_eth + PRIV_REQUIRES esp_driver_gpio esp_eth INCLUDE_DIRS ".") diff --git a/examples/ethernet/basic/components/ethernet_init/ethernet_init.c b/examples/ethernet/basic/components/ethernet_init/ethernet_init.c index d5f4ea3417..b34304e4a3 100644 --- a/examples/ethernet/basic/components/ethernet_init/ethernet_init.c +++ b/examples/ethernet/basic/components/ethernet_init/ethernet_init.c @@ -9,11 +9,9 @@ #include "esp_mac.h" #include "driver/gpio.h" #include "sdkconfig.h" -#if CONFIG_ETH_USE_SPI_ETHERNET +#if CONFIG_EXAMPLE_USE_SPI_ETHERNET #include "driver/spi_master.h" -#endif // CONFIG_ETH_USE_SPI_ETHERNET - -static const char *TAG = "example_eth_init"; +#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET #if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM #define SPI_ETHERNETS_NUM CONFIG_EXAMPLE_SPI_ETHERNETS_NUM @@ -45,6 +43,12 @@ typedef struct { uint8_t *mac_addr; }spi_eth_module_config_t; +static const char *TAG = "example_eth_init"; +#if CONFIG_EXAMPLE_USE_SPI_ETHERNET +static bool gpio_isr_svc_init_by_eth = false; // indicates that we initialized the GPIO ISR service +#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET + + #if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET /** * @brief Internal ESP32 Ethernet initialization @@ -128,17 +132,19 @@ static esp_err_t spi_bus_init(void) { esp_err_t ret = ESP_OK; +#if (CONFIG_EXAMPLE_ETH_SPI_INT0_GPIO >= 0) || (CONFIG_EXAMPLE_ETH_SPI_INT1_GPIO > 0) // Install GPIO ISR handler to be able to service SPI Eth modules interrupts ret = gpio_install_isr_service(0); - if (ret != ESP_OK) { - if (ret == ESP_ERR_INVALID_STATE) { - ESP_LOGW(TAG, "GPIO ISR handler has been already installed"); - ret = ESP_OK; // ISR handler has been already installed so no issues - } else { - ESP_LOGE(TAG, "GPIO ISR handler install failed"); - goto err; - } + if (ret == ESP_OK) { + gpio_isr_svc_init_by_eth = true; + } else if (ret == ESP_ERR_INVALID_STATE) { + ESP_LOGW(TAG, "GPIO ISR handler has been already installed"); + ret = ESP_OK; // ISR handler has been already installed so no issues + } else { + ESP_LOGE(TAG, "GPIO ISR handler install failed"); + goto err; } +#endif // Init SPI bus spi_bus_config_t buscfg = { @@ -283,7 +289,7 @@ esp_err_t example_eth_init(esp_eth_handle_t *eth_handles_out[], uint8_t *eth_cnt ESP_GOTO_ON_FALSE(eth_handles[eth_cnt], ESP_FAIL, err, TAG, "SPI Ethernet init failed"); eth_cnt++; } -#endif // CONFIG_ETH_USE_SPI_ETHERNET +#endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET #else ESP_LOGD(TAG, "no Ethernet device selected to init"); #endif // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET || CONFIG_EXAMPLE_USE_SPI_ETHERNET @@ -297,3 +303,36 @@ err: return ret; #endif } + +esp_err_t example_eth_deinit(esp_eth_handle_t *eth_handles, uint8_t eth_cnt) +{ + ESP_RETURN_ON_FALSE(eth_handles != NULL, ESP_ERR_INVALID_ARG, TAG, "array of Ethernet handles cannot be NULL"); + for (int i = 0; i < eth_cnt; i++) { + esp_eth_mac_t *mac = NULL; + esp_eth_phy_t *phy = NULL; + if (eth_handles[i] != NULL) { + esp_eth_get_mac_instance(eth_handles[i], &mac); + esp_eth_get_phy_instance(eth_handles[i], &phy); + ESP_RETURN_ON_ERROR(esp_eth_driver_uninstall(eth_handles[i]), TAG, "Ethernet %p uninstall failed", eth_handles[i]); + } + if (mac != NULL) { + mac->del(mac); + } + if (phy != NULL) { + phy->del(phy); + } + } +#if CONFIG_EXAMPLE_USE_SPI_ETHERNET + spi_bus_free(CONFIG_EXAMPLE_ETH_SPI_HOST); +#if (CONFIG_EXAMPLE_ETH_SPI_INT0_GPIO >= 0) || (CONFIG_EXAMPLE_ETH_SPI_INT1_GPIO > 0) + // We installed the GPIO ISR service so let's uninstall it too. + // BE CAREFUL HERE though since the service might be used by other functionality! + if (gpio_isr_svc_init_by_eth) { + ESP_LOGW(TAG, "uninstalling GPIO ISR service!"); + gpio_uninstall_isr_service(); + } +#endif +#endif //CONFIG_EXAMPLE_USE_SPI_ETHERNET + free(eth_handles); + return ESP_OK; +} diff --git a/examples/ethernet/basic/main/Kconfig.projbuild b/examples/ethernet/basic/main/Kconfig.projbuild new file mode 100644 index 0000000000..27a8f9d742 --- /dev/null +++ b/examples/ethernet/basic/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "Example Configuration" + config EXAMPLE_ETH_DEINIT_AFTER_S + int "Stop and deinit Ethernet after elapsing number of secs" + range -1 300 + default -1 + help + This option is for demonstration purposes only to demonstrate deinitialization of the Ethernet driver. + Set to -1 to not deinitialize. +endmenu diff --git a/examples/ethernet/basic/main/ethernet_example_main.c b/examples/ethernet/basic/main/ethernet_example_main.c index b3033e3329..71f99a1687 100644 --- a/examples/ethernet/basic/main/ethernet_example_main.c +++ b/examples/ethernet/basic/main/ethernet_example_main.c @@ -75,14 +75,18 @@ void app_main(void) // Create default event loop that running in background ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_t *eth_netifs[eth_port_cnt]; + esp_eth_netif_glue_handle_t eth_netif_glues[eth_port_cnt]; + // Create instance(s) of esp-netif for Ethernet(s) if (eth_port_cnt == 1) { // Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and you don't need to modify // default esp-netif configuration parameters. esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t *eth_netif = esp_netif_new(&cfg); + eth_netifs[0] = esp_netif_new(&cfg); + eth_netif_glues[0] = esp_eth_new_netif_glue(eth_handles[0]); // Attach Ethernet driver to TCP/IP stack - ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0]))); + ESP_ERROR_CHECK(esp_netif_attach(eth_netifs[0], eth_netif_glues[0])); } else { // Use ESP_NETIF_INHERENT_DEFAULT_ETH when multiple Ethernet interfaces are used and so you need to modify // esp-netif configuration parameters for each interface (name, priority, etc.). @@ -101,10 +105,10 @@ void app_main(void) esp_netif_config.if_key = if_key_str; esp_netif_config.if_desc = if_desc_str; esp_netif_config.route_prio -= i*5; - esp_netif_t *eth_netif = esp_netif_new(&cfg_spi); - + eth_netifs[i] = esp_netif_new(&cfg_spi); + eth_netif_glues[i] = esp_eth_new_netif_glue(eth_handles[0]); // Attach Ethernet driver to TCP/IP stack - ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[i]))); + ESP_ERROR_CHECK(esp_netif_attach(eth_netifs[i], eth_netif_glues[i])); } } @@ -116,4 +120,21 @@ void app_main(void) for (int i = 0; i < eth_port_cnt; i++) { ESP_ERROR_CHECK(esp_eth_start(eth_handles[i])); } + +#if CONFIG_EXAMPLE_ETH_DEINIT_AFTER_S >= 0 + // For demonstration purposes, wait and then deinit Ethernet network + vTaskDelay(pdMS_TO_TICKS(CONFIG_EXAMPLE_ETH_DEINIT_AFTER_S * 1000)); + ESP_LOGI(TAG, "stop and deinitialize Ethernet network..."); + // Stop Ethernet driver state machine and destroy netif + for (int i = 0; i < eth_port_cnt; i++) { + ESP_ERROR_CHECK(esp_eth_stop(eth_handles[i])); + ESP_ERROR_CHECK(esp_eth_del_netif_glue(eth_netif_glues[i])); + esp_netif_destroy(eth_netifs[i]); + } + esp_netif_deinit(); + ESP_ERROR_CHECK(example_eth_deinit(eth_handles, eth_port_cnt)); + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); + ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); + ESP_ERROR_CHECK(esp_event_loop_delete_default()); +#endif // EXAMPLE_ETH_DEINIT_AFTER_S > 0 }