eth_connect.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include <string.h>
  7. #include "protocol_examples_common.h"
  8. #include "example_common_private.h"
  9. #include "esp_event.h"
  10. #include "esp_eth.h"
  11. #if CONFIG_ETH_USE_SPI_ETHERNET
  12. #include "driver/spi_master.h"
  13. #endif // CONFIG_ETH_USE_SPI_ETHERNET
  14. #include "esp_log.h"
  15. #include "driver/gpio.h"
  16. #include "freertos/FreeRTOS.h"
  17. #include "freertos/task.h"
  18. #include "freertos/event_groups.h"
  19. static const char *TAG = "ethernet_connect";
  20. static SemaphoreHandle_t s_semph_get_ip_addrs = NULL;
  21. static esp_netif_t *eth_start(void);
  22. static void eth_stop(void);
  23. /** Event handler for Ethernet events */
  24. static void eth_on_got_ip(void *arg, esp_event_base_t event_base,
  25. int32_t event_id, void *event_data)
  26. {
  27. ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
  28. if (!example_is_our_netif(EXAMPLE_NETIF_DESC_ETH, event->esp_netif)) {
  29. return;
  30. }
  31. ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
  32. if (s_semph_get_ip_addrs) {
  33. xSemaphoreGive(s_semph_get_ip_addrs);
  34. }
  35. }
  36. #if CONFIG_EXAMPLE_CONNECT_IPV6
  37. static void eth_on_got_ipv6(void *arg, esp_event_base_t event_base,
  38. int32_t event_id, void *event_data)
  39. {
  40. ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
  41. if (!example_is_our_netif(EXAMPLE_NETIF_DESC_ETH, event->esp_netif)) {
  42. return;
  43. }
  44. esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
  45. ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
  46. IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);
  47. if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
  48. xSemaphoreGive(s_semph_get_ip_addrs);
  49. }
  50. }
  51. static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
  52. int32_t event_id, void *event_data)
  53. {
  54. switch (event_id) {
  55. case ETHERNET_EVENT_CONNECTED:
  56. ESP_LOGI(TAG, "Ethernet Link Up");
  57. ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
  58. break;
  59. default:
  60. break;
  61. }
  62. }
  63. #endif // CONFIG_EXAMPLE_CONNECT_IPV6
  64. static esp_eth_handle_t s_eth_handle = NULL;
  65. static esp_eth_mac_t *s_mac = NULL;
  66. static esp_eth_phy_t *s_phy = NULL;
  67. static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
  68. static esp_netif_t *eth_start(void)
  69. {
  70. esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
  71. // Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
  72. esp_netif_config.if_desc = EXAMPLE_NETIF_DESC_ETH;
  73. esp_netif_config.route_prio = 64;
  74. esp_netif_config_t netif_config = {
  75. .base = &esp_netif_config,
  76. .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
  77. };
  78. esp_netif_t *netif = esp_netif_new(&netif_config);
  79. assert(netif);
  80. eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
  81. mac_config.rx_task_stack_size = CONFIG_EXAMPLE_ETHERNET_EMAC_TASK_STACK_SIZE;
  82. eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
  83. phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
  84. phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
  85. #if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
  86. eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
  87. esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
  88. esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
  89. s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
  90. #if CONFIG_EXAMPLE_ETH_PHY_IP101
  91. s_phy = esp_eth_phy_new_ip101(&phy_config);
  92. #elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
  93. s_phy = esp_eth_phy_new_rtl8201(&phy_config);
  94. #elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
  95. s_phy = esp_eth_phy_new_lan87xx(&phy_config);
  96. #elif CONFIG_EXAMPLE_ETH_PHY_DP83848
  97. s_phy = esp_eth_phy_new_dp83848(&phy_config);
  98. #elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
  99. s_phy = esp_eth_phy_new_ksz80xx(&phy_config);
  100. #endif
  101. #elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
  102. gpio_install_isr_service(0);
  103. spi_bus_config_t buscfg = {
  104. .miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
  105. .mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
  106. .sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
  107. .quadwp_io_num = -1,
  108. .quadhd_io_num = -1,
  109. };
  110. ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1));
  111. spi_device_interface_config_t spi_devcfg = {
  112. .mode = 0,
  113. .clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
  114. .spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
  115. .queue_size = 20
  116. };
  117. #if CONFIG_EXAMPLE_USE_DM9051
  118. /* dm9051 ethernet driver is based on spi driver */
  119. eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
  120. dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
  121. s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
  122. s_phy = esp_eth_phy_new_dm9051(&phy_config);
  123. #elif CONFIG_EXAMPLE_USE_W5500
  124. /* w5500 ethernet driver is based on spi driver */
  125. eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
  126. w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
  127. s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
  128. s_phy = esp_eth_phy_new_w5500(&phy_config);
  129. #endif
  130. #elif CONFIG_EXAMPLE_USE_OPENETH
  131. phy_config.autonego_timeout_ms = 100;
  132. s_mac = esp_eth_mac_new_openeth(&mac_config);
  133. s_phy = esp_eth_phy_new_dp83848(&phy_config);
  134. #endif
  135. // Install Ethernet driver
  136. esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
  137. ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
  138. #if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
  139. /* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
  140. 02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
  141. */
  142. ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
  143. 0x02, 0x00, 0x00, 0x12, 0x34, 0x56
  144. }));
  145. #endif
  146. // combine driver with netif
  147. s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
  148. esp_netif_attach(netif, s_eth_glue);
  149. // Register user defined event handers
  150. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &eth_on_got_ip, NULL));
  151. #ifdef CONFIG_EXAMPLE_CONNECT_IPV6
  152. ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
  153. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &eth_on_got_ipv6, NULL));
  154. #endif
  155. esp_eth_start(s_eth_handle);
  156. return netif;
  157. }
  158. static void eth_stop(void)
  159. {
  160. esp_netif_t *eth_netif = get_example_netif_from_desc(EXAMPLE_NETIF_DESC_ETH);
  161. ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, &eth_on_got_ip));
  162. #if CONFIG_EXAMPLE_CONNECT_IPV6
  163. ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &eth_on_got_ipv6));
  164. ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event));
  165. #endif
  166. ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle));
  167. ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
  168. ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle));
  169. s_eth_handle = NULL;
  170. ESP_ERROR_CHECK(s_phy->del(s_phy));
  171. ESP_ERROR_CHECK(s_mac->del(s_mac));
  172. esp_netif_destroy(eth_netif);
  173. }
  174. esp_eth_handle_t get_example_eth_handle(void)
  175. {
  176. return s_eth_handle;
  177. }
  178. /* tear down connection, release resources */
  179. void example_ethernet_shutdown(void)
  180. {
  181. if (s_semph_get_ip_addrs == NULL) {
  182. return;
  183. }
  184. vSemaphoreDelete(s_semph_get_ip_addrs);
  185. s_semph_get_ip_addrs = NULL;
  186. eth_stop();
  187. }
  188. esp_err_t example_ethernet_connect(void)
  189. {
  190. s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
  191. eth_start();
  192. ESP_LOGI(TAG, "Waiting for IP(s).");
  193. for (int i = 0; i < NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
  194. xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
  195. }
  196. return ESP_OK;
  197. }