diff --git a/main/ethernet_example_main.c b/main/ethernet_example_main.c index 27ed39a..327e574 100644 --- a/main/ethernet_example_main.c +++ b/main/ethernet_example_main.c @@ -24,95 +24,44 @@ #include "nvs_flash.h" #include "esp_private/wifi.h" #include "ethernet_init.h" +#include "esp_netif.h" +#include "esp_eth.h" -static const char *TAG = "eth2ap_example"; +static const char *TAG = "Watch"; static esp_eth_handle_t s_eth_handle = NULL; -static QueueHandle_t flow_control_queue = NULL; -static bool s_sta_is_connected = false; static bool s_ethernet_is_connected = false; -static uint8_t s_eth_mac[6]; -#define FLOW_CONTROL_QUEUE_TIMEOUT_MS (100) -#define FLOW_CONTROL_QUEUE_LENGTH (40) -#define FLOW_CONTROL_WIFI_SEND_TIMEOUT_MS (100) - -typedef struct { - void *packet; - uint16_t length; -} flow_control_msg_t; - -// Forward packets from Wi-Fi to Ethernet -static esp_err_t pkt_wifi2eth(void *buffer, uint16_t len, void *eb) +/** 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) { - if (s_ethernet_is_connected) { - if (esp_eth_transmit(s_eth_handle, buffer, len) != ESP_OK) { - ESP_LOGE(TAG, "Ethernet send packet failed"); - } - } - esp_wifi_internal_free_rx_buffer(eb); - return ESP_OK; -} + ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; + const esp_netif_ip_info_t *ip_info = &event->ip_info; -// 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, void *priv) -{ - esp_err_t ret = ESP_OK; - flow_control_msg_t msg = { - .packet = buffer, - .length = len - }; - if (xQueueSend(flow_control_queue, &msg, pdMS_TO_TICKS(FLOW_CONTROL_QUEUE_TIMEOUT_MS)) != pdTRUE) { - ESP_LOGE(TAG, "send flow control message failed or timeout"); - free(buffer); - ret = ESP_FAIL; - } - return ret; -} - -// This task will fetch the packet from the queue, and then send out through Wi-Fi. -// Wi-Fi handles packets slower than Ethernet, we might add some delay between each transmitting. -static void eth2wifi_flow_control_task(void *args) -{ - flow_control_msg_t msg; - int res = 0; - uint32_t timeout = 0; - while (1) { - if (xQueueReceive(flow_control_queue, &msg, pdMS_TO_TICKS(FLOW_CONTROL_QUEUE_TIMEOUT_MS)) == pdTRUE) { - timeout = 0; - if (s_sta_is_connected && msg.length) { - do { - vTaskDelay(pdMS_TO_TICKS(timeout)); - timeout += 2; - res = esp_wifi_internal_tx(WIFI_IF_AP, msg.packet, msg.length); - } while (res && timeout < FLOW_CONTROL_WIFI_SEND_TIMEOUT_MS); - if (res != ESP_OK) { - ESP_LOGE(TAG, "WiFi send packet failed: %d", res); - } - } - free(msg.packet); - } - } - vTaskDelete(NULL); + 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, "~~~~~~~~~~~"); } // Event handler for Ethernet static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { + uint8_t mac_addr[6] = {0}; switch (event_id) { case ETHERNET_EVENT_CONNECTED: ESP_LOGI(TAG, "Ethernet Link Up"); s_ethernet_is_connected = true; - esp_eth_ioctl(s_eth_handle, ETH_CMD_G_MAC_ADDR, s_eth_mac); - esp_wifi_set_mac(WIFI_IF_AP, s_eth_mac); - ESP_ERROR_CHECK(esp_wifi_start()); + ESP_LOGI(TAG, "Ethernet Link Up"); + ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x", + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); break; case ETHERNET_EVENT_DISCONNECTED: ESP_LOGI(TAG, "Ethernet Link Down"); s_ethernet_is_connected = false; - ESP_ERROR_CHECK(esp_wifi_stop()); break; case ETHERNET_EVENT_START: ESP_LOGI(TAG, "Ethernet Started"); @@ -125,33 +74,6 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base, } } -// Event handler for Wi-Fi -static void wifi_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - static uint8_t s_con_cnt = 0; - switch (event_id) { - case WIFI_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "Wi-Fi AP got a station connected"); - if (!s_con_cnt) { - s_sta_is_connected = true; - esp_wifi_internal_reg_rxcb(WIFI_IF_AP, pkt_wifi2eth); - } - s_con_cnt++; - break; - case WIFI_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "Wi-Fi AP got a station disconnected"); - s_con_cnt--; - if (!s_con_cnt) { - s_sta_is_connected = false; - esp_wifi_internal_reg_rxcb(WIFI_IF_AP, NULL); - } - break; - default: - break; - } -} - static void initialize_ethernet(void) { uint8_t eth_port_cnt = 0; @@ -160,53 +82,27 @@ static void initialize_ethernet(void) if (eth_port_cnt > 1) { ESP_LOGW(TAG, "multiple Ethernet devices detected, the first initialized is to be used!"); } + s_eth_handle = eth_handles[0]; free(eth_handles); - ESP_ERROR_CHECK(esp_eth_update_input_path(s_eth_handle, pkt_eth2wifi, NULL)); - bool eth_promiscuous = true; - ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_PROMISCUOUS, ð_promiscuous)); + + // Initialize TCP/IP network interface aka the esp-netif (should be called only once in application) + ESP_ERROR_CHECK(esp_netif_init()); + // Create default event loop that running in background + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // 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); + // Attach Ethernet driver to TCP/IP stack + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(s_eth_handle))); + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); ESP_ERROR_CHECK(esp_eth_start(s_eth_handle)); } -static void initialize_wifi(void) -{ - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .ap = { - .ssid = CONFIG_EXAMPLE_WIFI_SSID, - .ssid_len = strlen(CONFIG_EXAMPLE_WIFI_SSID), - .password = CONFIG_EXAMPLE_WIFI_PASSWORD, - .max_connection = CONFIG_EXAMPLE_MAX_STA_CONN, - .authmode = WIFI_AUTH_WPA_WPA2_PSK, - .channel = CONFIG_EXAMPLE_WIFI_CHANNEL // default: channel 1 - }, - }; - if (strlen(CONFIG_EXAMPLE_WIFI_PASSWORD) == 0) { - wifi_config.ap.authmode = WIFI_AUTH_OPEN; - } - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config)); -} - -static esp_err_t initialize_flow_control(void) -{ - flow_control_queue = xQueueCreate(FLOW_CONTROL_QUEUE_LENGTH, sizeof(flow_control_msg_t)); - if (!flow_control_queue) { - ESP_LOGE(TAG, "create flow control queue failed"); - return ESP_FAIL; - } - BaseType_t ret = xTaskCreate(eth2wifi_flow_control_task, "flow_ctl", 2048, NULL, (tskIDLE_PRIORITY + 2), NULL); - if (ret != pdTRUE) { - ESP_LOGE(TAG, "create flow control task failed"); - return ESP_FAIL; - } - return ESP_OK; -} - void app_main(void) { esp_err_t ret = nvs_flash_init(); @@ -215,8 +111,6 @@ void app_main(void) ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - ESP_ERROR_CHECK(initialize_flow_control()); - initialize_wifi(); + // ESP_ERROR_CHECK(esp_event_loop_create_default()); initialize_ethernet(); } diff --git a/main/olimex.original.c b/main/olimex.original.c new file mode 100644 index 0000000..af4901d --- /dev/null +++ b/main/olimex.original.c @@ -0,0 +1,119 @@ +/* Ethernet Basic Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_netif.h" +#include "esp_eth.h" +#include "esp_event.h" +#include "esp_log.h" +#include "ethernet_init.h" +#include "sdkconfig.h" + +static const char *TAG = "eth_example"; + +/** 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) +{ + uint8_t mac_addr[6] = {0}; + /* we can get the ethernet driver handle from event data */ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr); + ESP_LOGI(TAG, "Ethernet Link Up"); + ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x", + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + break; + case ETHERNET_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "Ethernet Link Down"); + break; + case ETHERNET_EVENT_START: + ESP_LOGI(TAG, "Ethernet Started"); + break; + case ETHERNET_EVENT_STOP: + 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) +{ + 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, "~~~~~~~~~~~"); +} + +void app_main(void) +{ + // Initialize Ethernet driver + uint8_t eth_port_cnt = 0; + esp_eth_handle_t *eth_handles; + ESP_ERROR_CHECK(example_eth_init(ð_handles, ð_port_cnt)); + + // Initialize TCP/IP network interface aka the esp-netif (should be called only once in application) + ESP_ERROR_CHECK(esp_netif_init()); + // Create default event loop that running in background + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // 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); + // Attach Ethernet driver to TCP/IP stack + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[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.). + esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); + esp_netif_config_t cfg_spi = { + .base = &esp_netif_config, + .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH + }; + char if_key_str[10]; + char if_desc_str[10]; + char num_str[3]; + for (int i = 0; i < eth_port_cnt; i++) { + itoa(i, num_str, 10); + strcat(strcpy(if_key_str, "ETH_"), num_str); + strcat(strcpy(if_desc_str, "eth"), num_str); + esp_netif_config.if_key = if_key_str; + esp_netif_config.if_desc = if_desc_str; + esp_netif_config.route_prio -= i*5; + esp_netif_t *eth_netif = esp_netif_new(&cfg_spi); + + // Attach Ethernet driver to TCP/IP stack + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[i]))); + } + } + + // 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)); + + // Start Ethernet driver state machine + for (int i = 0; i < eth_port_cnt; i++) { + ESP_ERROR_CHECK(esp_eth_start(eth_handles[i])); + } +} \ No newline at end of file