cmd_ethernet.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /* Console example — Ethernet commands
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "freertos/FreeRTOS.h"
  10. #include "freertos/event_groups.h"
  11. #include "esp_netif.h"
  12. #include "esp_log.h"
  13. #include "esp_console.h"
  14. #include "esp_event.h"
  15. #include "esp_eth.h"
  16. #include "esp_mac.h"
  17. #include "driver/gpio.h"
  18. #include "argtable3/argtable3.h"
  19. #include "iperf.h"
  20. #include "sdkconfig.h"
  21. #if CONFIG_ETH_USE_SPI_ETHERNET
  22. #include "driver/spi_master.h"
  23. #if CONFIG_EXAMPLE_USE_ENC28J60
  24. #include "esp_eth_enc28j60.h"
  25. #endif //CONFIG_EXAMPLE_USE_ENC28J60
  26. #endif // CONFIG_ETH_USE_SPI_ETHERNET
  27. static esp_netif_ip_info_t ip;
  28. static bool started = false;
  29. static EventGroupHandle_t eth_event_group;
  30. static const int GOTIP_BIT = BIT0;
  31. static esp_eth_handle_t eth_handle = NULL;
  32. static esp_netif_t *eth_netif = NULL;
  33. /* "ethernet" command */
  34. static struct {
  35. struct arg_str *control;
  36. struct arg_end *end;
  37. } eth_control_args;
  38. static int eth_cmd_control(int argc, char **argv)
  39. {
  40. int nerrors = arg_parse(argc, argv, (void **)&eth_control_args);
  41. if (nerrors != 0) {
  42. arg_print_errors(stderr, eth_control_args.end, argv[0]);
  43. return 1;
  44. }
  45. if (!strncmp(eth_control_args.control->sval[0], "info", 4)) {
  46. uint8_t mac_addr[6];
  47. esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
  48. printf("HW ADDR: " MACSTR "\r\n", MAC2STR(mac_addr));
  49. esp_netif_get_ip_info(eth_netif, &ip);
  50. printf("ETHIP: " IPSTR "\r\n", IP2STR(&ip.ip));
  51. printf("ETHMASK: " IPSTR "\r\n", IP2STR(&ip.netmask));
  52. printf("ETHGW: " IPSTR "\r\n", IP2STR(&ip.gw));
  53. }
  54. return 0;
  55. }
  56. /* "iperf" command */
  57. static struct {
  58. struct arg_str *ip;
  59. struct arg_lit *server;
  60. struct arg_lit *udp;
  61. struct arg_lit *version;
  62. struct arg_int *port;
  63. struct arg_int *length;
  64. struct arg_int *interval;
  65. struct arg_int *time;
  66. struct arg_int *bw_limit;
  67. struct arg_lit *abort;
  68. struct arg_end *end;
  69. } iperf_args;
  70. static int eth_cmd_iperf(int argc, char **argv)
  71. {
  72. int nerrors = arg_parse(argc, argv, (void **)&iperf_args);
  73. iperf_cfg_t cfg;
  74. if (nerrors != 0) {
  75. arg_print_errors(stderr, iperf_args.end, argv[0]);
  76. return 0;
  77. }
  78. memset(&cfg, 0, sizeof(cfg));
  79. // ethernet iperf only support IPV4 address
  80. cfg.type = IPERF_IP_TYPE_IPV4;
  81. /* iperf -a */
  82. if (iperf_args.abort->count != 0) {
  83. iperf_stop();
  84. return 0;
  85. }
  86. if (((iperf_args.ip->count == 0) && (iperf_args.server->count == 0)) ||
  87. ((iperf_args.ip->count != 0) && (iperf_args.server->count != 0))) {
  88. ESP_LOGE(__func__, "Wrong mode! ESP32 should run in client or server mode");
  89. return 0;
  90. }
  91. /* iperf -s */
  92. if (iperf_args.ip->count == 0) {
  93. cfg.flag |= IPERF_FLAG_SERVER;
  94. }
  95. /* iperf -c SERVER_ADDRESS */
  96. else {
  97. cfg.destination_ip4 = esp_ip4addr_aton(iperf_args.ip->sval[0]);
  98. cfg.flag |= IPERF_FLAG_CLIENT;
  99. }
  100. if (iperf_args.length->count == 0) {
  101. cfg.len_send_buf = 0;
  102. } else {
  103. cfg.len_send_buf = iperf_args.length->ival[0];
  104. }
  105. /* acquiring for ip, could blocked here */
  106. xEventGroupWaitBits(eth_event_group, GOTIP_BIT, pdFALSE, pdTRUE, portMAX_DELAY);
  107. cfg.source_ip4 = ip.ip.addr;
  108. if (cfg.source_ip4 == 0) {
  109. return 0;
  110. }
  111. /* iperf -u */
  112. if (iperf_args.udp->count == 0) {
  113. cfg.flag |= IPERF_FLAG_TCP;
  114. } else {
  115. cfg.flag |= IPERF_FLAG_UDP;
  116. }
  117. /* iperf -p */
  118. if (iperf_args.port->count == 0) {
  119. cfg.sport = IPERF_DEFAULT_PORT;
  120. cfg.dport = IPERF_DEFAULT_PORT;
  121. } else {
  122. if (cfg.flag & IPERF_FLAG_SERVER) {
  123. cfg.sport = iperf_args.port->ival[0];
  124. cfg.dport = IPERF_DEFAULT_PORT;
  125. } else {
  126. cfg.sport = IPERF_DEFAULT_PORT;
  127. cfg.dport = iperf_args.port->ival[0];
  128. }
  129. }
  130. /* iperf -i */
  131. if (iperf_args.interval->count == 0) {
  132. cfg.interval = IPERF_DEFAULT_INTERVAL;
  133. } else {
  134. cfg.interval = iperf_args.interval->ival[0];
  135. if (cfg.interval <= 0) {
  136. cfg.interval = IPERF_DEFAULT_INTERVAL;
  137. }
  138. }
  139. /* iperf -t */
  140. if (iperf_args.time->count == 0) {
  141. cfg.time = IPERF_DEFAULT_TIME;
  142. } else {
  143. cfg.time = iperf_args.time->ival[0];
  144. if (cfg.time <= cfg.interval) {
  145. cfg.time = cfg.interval;
  146. }
  147. }
  148. /* iperf -b */
  149. if (iperf_args.bw_limit->count == 0) {
  150. cfg.bw_lim = IPERF_DEFAULT_NO_BW_LIMIT;
  151. } else {
  152. cfg.bw_lim = iperf_args.bw_limit->ival[0];
  153. if (cfg.bw_lim <= 0) {
  154. cfg.bw_lim = IPERF_DEFAULT_NO_BW_LIMIT;
  155. }
  156. }
  157. printf("mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d\r\n",
  158. cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
  159. cfg.flag & IPERF_FLAG_SERVER ? "server" : "client",
  160. cfg.source_ip4 & 0xFF, (cfg.source_ip4 >> 8) & 0xFF, (cfg.source_ip4 >> 16) & 0xFF,
  161. (cfg.source_ip4 >> 24) & 0xFF, cfg.sport,
  162. cfg.destination_ip4 & 0xFF, (cfg.destination_ip4 >> 8) & 0xFF,
  163. (cfg.destination_ip4 >> 16) & 0xFF, (cfg.destination_ip4 >> 24) & 0xFF, cfg.dport,
  164. cfg.interval, cfg.time);
  165. iperf_start(&cfg);
  166. return 0;
  167. }
  168. static void event_handler(void *arg, esp_event_base_t event_base,
  169. int32_t event_id, void *event_data)
  170. {
  171. if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_START) {
  172. started = true;
  173. } else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_STOP) {
  174. xEventGroupClearBits(eth_event_group, GOTIP_BIT);
  175. started = false;
  176. } else if (event_base == IP_EVENT && event_id == IP_EVENT_ETH_GOT_IP) {
  177. ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
  178. memcpy(&ip, &event->ip_info, sizeof(ip));
  179. xEventGroupSetBits(eth_event_group, GOTIP_BIT);
  180. }
  181. }
  182. void register_ethernet(void)
  183. {
  184. eth_event_group = xEventGroupCreate();
  185. ESP_ERROR_CHECK(esp_netif_init());
  186. ESP_ERROR_CHECK(esp_event_loop_create_default());
  187. esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
  188. eth_netif = esp_netif_new(&cfg);
  189. eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
  190. eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
  191. phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
  192. phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
  193. #if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
  194. eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
  195. esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
  196. esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
  197. esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
  198. #if CONFIG_EXAMPLE_ETH_PHY_IP101
  199. esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
  200. #elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
  201. esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
  202. #elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
  203. esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config);
  204. #elif CONFIG_EXAMPLE_ETH_PHY_DP83848
  205. esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
  206. #elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
  207. esp_eth_phy_t *phy = esp_eth_phy_new_ksz80xx(&phy_config);
  208. #endif
  209. #elif CONFIG_ETH_USE_SPI_ETHERNET
  210. gpio_install_isr_service(0);
  211. spi_bus_config_t buscfg = {
  212. .miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
  213. .mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
  214. .sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
  215. .quadwp_io_num = -1,
  216. .quadhd_io_num = -1,
  217. };
  218. ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
  219. spi_device_interface_config_t spi_devcfg = {
  220. .mode = 0,
  221. .clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
  222. .spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
  223. .queue_size = 20
  224. };
  225. #if CONFIG_EXAMPLE_USE_KSZ8851SNL
  226. eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
  227. ksz8851snl_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
  228. esp_eth_mac_t *mac = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config);
  229. esp_eth_phy_t *phy = esp_eth_phy_new_ksz8851snl(&phy_config);
  230. #elif CONFIG_EXAMPLE_USE_DM9051
  231. eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
  232. dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
  233. esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
  234. esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
  235. #elif CONFIG_EXAMPLE_USE_W5500
  236. eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
  237. w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
  238. esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
  239. esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
  240. #elif CONFIG_EXAMPLE_USE_ENC28J60
  241. spi_devcfg.cs_ena_posttrans = enc28j60_cal_spi_cs_hold_time(CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ);
  242. eth_enc28j60_config_t enc28j60_config = ETH_ENC28J60_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
  243. enc28j60_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
  244. esp_eth_mac_t *mac = esp_eth_mac_new_enc28j60(&enc28j60_config, &mac_config);
  245. phy_config.autonego_timeout_ms = 0; // ENC28J60 doesn't support auto-negotiation
  246. phy_config.reset_gpio_num = -1; // ENC28J60 doesn't have a pin to reset internal PHY
  247. esp_eth_phy_t *phy = esp_eth_phy_new_enc28j60(&phy_config);
  248. #endif
  249. #endif // CONFIG_ETH_USE_SPI_ETHERNET
  250. esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
  251. ESP_ERROR_CHECK(esp_eth_driver_install(&config, &eth_handle));
  252. #if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
  253. /* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
  254. 02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
  255. */
  256. ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
  257. 0x02, 0x00, 0x00, 0x12, 0x34, 0x56
  258. }));
  259. #endif
  260. #if CONFIG_EXAMPLE_USE_ENC28J60 && CONFIG_EXAMPLE_ENC28J60_DUPLEX_FULL
  261. eth_duplex_t duplex = ETH_DUPLEX_FULL;
  262. ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex));
  263. #endif
  264. ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
  265. ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
  266. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &event_handler, NULL));
  267. ESP_ERROR_CHECK(esp_eth_start(eth_handle));
  268. eth_control_args.control = arg_str1(NULL, NULL, "<info>", "Get info of Ethernet");
  269. eth_control_args.end = arg_end(1);
  270. const esp_console_cmd_t cmd = {
  271. .command = "ethernet",
  272. .help = "Ethernet interface IO control",
  273. .hint = NULL,
  274. .func = eth_cmd_control,
  275. .argtable = &eth_control_args
  276. };
  277. ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
  278. iperf_args.ip = arg_str0("c", "client", "<ip>",
  279. "run in client mode, connecting to <host>");
  280. iperf_args.server = arg_lit0("s", "server", "run in server mode");
  281. iperf_args.udp = arg_lit0("u", "udp", "use UDP rather than TCP");
  282. iperf_args.version = arg_lit0("V", "ipv6_domain", "use IPV6 address rather than IPV4");
  283. iperf_args.port = arg_int0("p", "port", "<port>",
  284. "server port to listen on/connect to");
  285. iperf_args.length = arg_int0("l", "len", "<length>", "set read/write buffer size");
  286. iperf_args.interval = arg_int0("i", "interval", "<interval>",
  287. "seconds between periodic bandwidth reports");
  288. iperf_args.time = arg_int0("t", "time", "<time>", "time in seconds to transmit for (default 10 secs)");
  289. iperf_args.bw_limit = arg_int0("b", "bandwidth", "<bandwidth>", "bandwidth to send at in Mbits/sec");
  290. iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
  291. iperf_args.end = arg_end(1);
  292. const esp_console_cmd_t iperf_cmd = {
  293. .command = "iperf",
  294. .help = "iperf command",
  295. .hint = NULL,
  296. .func = &eth_cmd_iperf,
  297. .argtable = &iperf_args
  298. };
  299. ESP_ERROR_CHECK(esp_console_cmd_register(&iperf_cmd));
  300. }