diff --git a/components/eppp_link/CMakeLists.txt b/components/eppp_link/CMakeLists.txt index 48334fec24..72b0ee19f0 100644 --- a/components/eppp_link/CMakeLists.txt +++ b/components/eppp_link/CMakeLists.txt @@ -1,3 +1,22 @@ -idf_component_register(SRCS eppp_link.c eppp_sdio_slave.c eppp_sdio_host.c +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "5.3") + set(driver_deps esp_driver_gpio esp_driver_spi) +else() + set(driver_deps driver) +endif() + +if(CONFIG_EPPP_LINK_DEVICE_ETH) + set(transport_src eppp_eth.c) +endif() + +if(CONFIG_EPPP_LINK_DEVICE_SDIO) + set(transport_src eppp_sdio_slave.c eppp_sdio_host.c) +endif() + +idf_component_register(SRCS eppp_link.c ${transport_src} INCLUDE_DIRS "include" - PRIV_REQUIRES esp_netif esp_driver_spi esp_driver_gpio esp_timer driver) + PRIV_REQUIRES esp_netif esp_timer esp_eth ${driver_deps}) + +if(CONFIG_EPPP_LINK_DEVICE_ETH) + idf_component_get_property(ethernet_init espressif__ethernet_init COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PRIVATE ${ethernet_init}) +endif() diff --git a/components/eppp_link/Kconfig b/components/eppp_link/Kconfig index 2b7ef4a8ae..3cf2604d1c 100644 --- a/components/eppp_link/Kconfig +++ b/components/eppp_link/Kconfig @@ -28,6 +28,16 @@ menu "eppp_link" help Use SDIO. + config EPPP_LINK_DEVICE_ETH + bool "Ethernet" + depends on SOC_EMAC_SUPPORTED + help + Use Ethernet. + This transport could employ a full fledged Ethernet connection + between two EPPP nodes via standard Ethernet cable. + It could be also effectively connected directly on PCB, EMAC to EMAC, + without any Ethernet PHY chips (using eth_dummy_phy driver). + endchoice config EPPP_LINK_CONN_MAX_RETRY @@ -67,4 +77,14 @@ menu "eppp_link" endchoice + config EPPP_LINK_ETHERNET_OUR_ADDRESS + string "MAC address our local node" + default "06:00:00:00:00:01" + depends on EPPP_LINK_DEVICE_ETH + + config EPPP_LINK_ETHERNET_THEIR_ADDRESS + string "MAC address the remote node" + default "06:00:00:00:00:02" + depends on EPPP_LINK_DEVICE_ETH + endmenu diff --git a/components/eppp_link/README.md b/components/eppp_link/README.md index 4112c05919..8d2d8163f5 100644 --- a/components/eppp_link/README.md +++ b/components/eppp_link/README.md @@ -11,12 +11,12 @@ We usually call this node a SLAVE microcontroller. The "HOST" microcontroller ru brings in the WiFi connectivity from the "SLAVE" microcontroller. ``` - SLAVE micro HOST micro - \|/ +----------------+ +----------------+ - | | | serial line | | - +---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client | - | (server)| | | - +----------------+ +----------------+ + SLAVE micro HOST micro + \|/ +----------------+ +----------------+ + | | | (serial) line | | + +---+ WiFi NAT PPPoS |=== UART / SPI / SDIO / ETH ===| PPPoS client | + | (server)| | | + +----------------+ +----------------+ ``` ## API @@ -55,3 +55,9 @@ Tested with WiFi-NAPT example * TCP - 9Mbits/s * UDP - 11Mbits/s + +### Ethernet + +- Internal EMAC with real PHY chip + * TCP - 5Mbits/s + * UDP - 8Mbits/s diff --git a/components/eppp_link/eppp_eth.c b/components/eppp_link/eppp_eth.c new file mode 100644 index 0000000000..fdfe023947 --- /dev/null +++ b/components/eppp_link/eppp_eth.c @@ -0,0 +1,119 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_check.h" +#include "esp_event.h" +#include "esp_mac.h" +#include "eppp_link.h" +#include "eppp_transport.h" +#include "esp_eth_driver.h" +#include "ethernet_init.h" +#include "esp_eth_spec.h" + +typedef struct header { + uint8_t dst[ETH_ADDR_LEN]; + uint8_t src[ETH_ADDR_LEN]; + uint16_t len; +} __attribute__((packed)) header_t; + +static const char *TAG = "eppp_ethernet"; +static bool s_is_connected = false; +static esp_eth_handle_t *s_eth_handles = NULL; +static uint8_t s_out_buffer[ETH_MAX_PACKET_SIZE]; +static uint8_t s_their_mac[ETH_ADDR_LEN]; +static uint8_t s_our_mac[ETH_ADDR_LEN]; + +static void event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + ESP_LOGI(TAG, "Ethernet Link Up"); + s_is_connected = true; + break; + case ETHERNET_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "Ethernet Link Down"); + s_is_connected = false; + break; + case ETHERNET_EVENT_START: + ESP_LOGI(TAG, "Ethernet Started"); + break; + case ETHERNET_EVENT_STOP: + ESP_LOGI(TAG, "Ethernet Stopped"); + break; + default: + break; + } +} + +static esp_err_t receive(esp_eth_handle_t h, uint8_t *buffer, uint32_t len, void *netif) +{ + header_t *head = (header_t *)buffer; + size_t packet_len = head->len; + if (len >= packet_len) { + esp_err_t ret = esp_netif_receive(netif, buffer + ETH_HEADER_LEN, packet_len, NULL); + free(buffer); + return ret; + } + return ESP_FAIL; +} + +__attribute__((weak)) esp_err_t eppp_transport_ethernet_init(esp_eth_handle_t *handle_array[]) +{ + uint8_t eth_port_cnt = 0; + ESP_RETURN_ON_ERROR(ethernet_init_all(handle_array, ð_port_cnt), TAG, "Failed to init common eth drivers"); + ESP_RETURN_ON_FALSE(eth_port_cnt == 1, ESP_ERR_INVALID_ARG, TAG, "multiple Ethernet devices detected, please init only one"); + return ESP_OK; +} + +__attribute__((weak)) void eppp_transport_ethernet_deinit(esp_eth_handle_t *handle_array) +{ + ethernet_deinit_all(s_eth_handles); +} + + +esp_err_t eppp_transport_init(eppp_config_t *config, esp_netif_t *esp_netif) +{ + ESP_RETURN_ON_ERROR(eppp_transport_ethernet_init(&s_eth_handles), TAG, "Failed to initialize Ethernet driver"); + ESP_RETURN_ON_ERROR(esp_eth_update_input_path(s_eth_handles[0], receive, esp_netif), TAG, "Failed to set Ethernet Rx callback"); + sscanf(CONFIG_EPPP_LINK_ETHERNET_OUR_ADDRESS, "%2" PRIu8 ":%2" PRIu8 ":%2" PRIi8 ":%2" PRIu8 ":%2" PRIu8 ":%2" PRIu8, + &s_our_mac[0], &s_our_mac[1], &s_our_mac[2], &s_our_mac[3], &s_our_mac[4], &s_our_mac[5]); + + sscanf(CONFIG_EPPP_LINK_ETHERNET_THEIR_ADDRESS, "%2" PRIu8 ":%2" PRIu8 ":%2" PRIi8 ":%2" PRIu8 ":%2" PRIu8 ":%2" PRIu8, + &s_their_mac[0], &s_their_mac[1], &s_their_mac[2], &s_their_mac[3], &s_their_mac[4], &s_their_mac[5]); + esp_eth_ioctl(s_eth_handles[0], ETH_CMD_S_MAC_ADDR, s_our_mac); + ESP_RETURN_ON_ERROR(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL), TAG, "Failed to register Ethernet handlers"); + ESP_RETURN_ON_ERROR(esp_eth_start(s_eth_handles[0]), TAG, "Failed to start Ethernet driver"); + return ESP_OK; +} + +void eppp_transport_deinit(void) +{ + esp_eth_stop(s_eth_handles[0]); + eppp_transport_ethernet_deinit(s_eth_handles); +} + +esp_err_t eppp_transport_tx(void *h, void *buffer, size_t len) +{ + if (!s_is_connected) { + return ESP_FAIL; + } + // setup Ethernet header + header_t *head = (header_t *)s_out_buffer; + memcpy(head->dst, s_their_mac, ETH_ADDR_LEN); + memcpy(head->src, s_our_mac, ETH_ADDR_LEN); + head->len = len; + // support only payloads with len <= ETH_MAX_PAYLOAD_LEN + if (len > ETH_MAX_PAYLOAD_LEN) { + return ESP_FAIL; + } + memcpy(s_out_buffer + ETH_HEADER_LEN, buffer, len); + return esp_eth_transmit(s_eth_handles[0], s_out_buffer, len + ETH_HEADER_LEN); +} diff --git a/components/eppp_link/eppp_link.c b/components/eppp_link/eppp_link.c index 60f97cd00a..bf76ba4eb7 100644 --- a/components/eppp_link/eppp_link.c +++ b/components/eppp_link/eppp_link.c @@ -12,7 +12,7 @@ #include "esp_event.h" #include "esp_netif_ppp.h" #include "eppp_link.h" -#include "esp_serial_slave_link/essl_sdio.h" +#include "eppp_transport.h" #if CONFIG_EPPP_LINK_DEVICE_SPI #include "driver/spi_master.h" @@ -24,6 +24,12 @@ #include "driver/uart.h" #endif +#if CONFIG_EPPP_LINK_DEVICE_ETH +#define EPPP_NEEDS_TASK 0 +#else +#define EPPP_NEEDS_TASK 1 +#endif + static const int GOT_IPV4 = BIT0; static const int CONNECTION_FAILED = BIT1; #define CONNECT_BITS (GOT_IPV4|CONNECTION_FAILED) @@ -98,6 +104,8 @@ esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config); esp_err_t eppp_sdio_slave_init(void); void eppp_sdio_slave_deinit(void); void eppp_sdio_host_deinit(void); +#elif CONFIG_EPPP_LINK_DEVICE_ETH + #else static esp_err_t transmit(void *h, void *buffer, size_t len) { @@ -224,6 +232,8 @@ static esp_netif_t *netif_init(eppp_type_t role, eppp_config_t *eppp_config) .handle = h, #if CONFIG_EPPP_LINK_DEVICE_SDIO .transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx, +#elif CONFIG_EPPP_LINK_DEVICE_ETH + .transmit = eppp_transport_tx, #else .transmit = transmit, #endif @@ -691,6 +701,7 @@ esp_err_t eppp_perform(esp_netif_t *netif) #endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART +#if EPPP_NEEDS_TASK static void ppp_task(void *args) { esp_netif_t *netif = args; @@ -699,6 +710,7 @@ static void ppp_task(void *args) h->exited = true; vTaskDelete(NULL); } +#endif static bool have_some_eppp_netif(esp_netif_t *netif, void *ctx) { @@ -738,6 +750,8 @@ void eppp_deinit(esp_netif_t *netif) } else { eppp_sdio_slave_deinit(); } +#elif CONFIG_EPPP_LINK_DEVICE_ETH + eppp_transport_deinit(); #endif netif_deinit(netif); } @@ -781,6 +795,13 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config) ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret); return NULL; } +#elif CONFIG_EPPP_LINK_DEVICE_ETH + esp_err_t ret = eppp_transport_init(config, netif); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret); + return NULL; + } + #endif return netif; } @@ -834,12 +855,13 @@ esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_time } eppp_netif_start(netif); - +#if EPPP_NEEDS_TASK if (xTaskCreate(ppp_task, "ppp connect", config->task.stack_size, netif, config->task.priority, NULL) != pdTRUE) { ESP_LOGE(TAG, "Failed to create a ppp connection task"); eppp_deinit(netif); return NULL; } +#endif int netif_cnt = get_netif_num(netif); if (netif_cnt < 0) { eppp_close(netif); diff --git a/components/eppp_link/eppp_transport.h b/components/eppp_link/eppp_transport.h new file mode 100644 index 0000000000..8dbed9f46c --- /dev/null +++ b/components/eppp_link/eppp_transport.h @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +esp_err_t eppp_transport_init(eppp_config_t *config, esp_netif_t *esp_netif); + +esp_err_t eppp_transport_tx(void *h, void *buffer, size_t len); + +esp_err_t eppp_transport_rx(esp_netif_t *netif); + +void eppp_transport_deinit(void); diff --git a/components/eppp_link/examples/host/sdkconfig.ci.eth b/components/eppp_link/examples/host/sdkconfig.ci.eth new file mode 100644 index 0000000000..9b3f487dce --- /dev/null +++ b/components/eppp_link/examples/host/sdkconfig.ci.eth @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_EPPP_LINK_DEVICE_ETH=y diff --git a/components/eppp_link/examples/host/sdkconfig.ci.sdio b/components/eppp_link/examples/host/sdkconfig.ci.sdio new file mode 100644 index 0000000000..32fdc6aa5d --- /dev/null +++ b/components/eppp_link/examples/host/sdkconfig.ci.sdio @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32p4" +CONFIG_EPPP_LINK_DEVICE_SDIO=y diff --git a/components/eppp_link/examples/slave/sdkconfig.ci.eth b/components/eppp_link/examples/slave/sdkconfig.ci.eth new file mode 100644 index 0000000000..9b3f487dce --- /dev/null +++ b/components/eppp_link/examples/slave/sdkconfig.ci.eth @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_EPPP_LINK_DEVICE_ETH=y diff --git a/components/eppp_link/examples/slave/sdkconfig.ci.sdio b/components/eppp_link/examples/slave/sdkconfig.ci.sdio new file mode 100644 index 0000000000..395ff44868 --- /dev/null +++ b/components/eppp_link/examples/slave/sdkconfig.ci.sdio @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c6" +CONFIG_EPPP_LINK_DEVICE_SDIO=y diff --git a/components/eppp_link/idf_component.yml b/components/eppp_link/idf_component.yml index 44d0bf8d98..bf21675db4 100644 --- a/components/eppp_link/idf_component.yml +++ b/components/eppp_link/idf_component.yml @@ -4,3 +4,4 @@ description: The component provides a general purpose PPP connectivity, typicall dependencies: idf: '>=5.2' espressif/esp_serial_slave_link: "^1.1.0" + espressif/ethernet_init: '>=0.0.7' diff --git a/components/eppp_link/include/eppp_link.h b/components/eppp_link/include/eppp_link.h index 1f110db427..2159cec063 100644 --- a/components/eppp_link/include/eppp_link.h +++ b/components/eppp_link/include/eppp_link.h @@ -63,6 +63,7 @@ typedef enum eppp_transport { EPPP_TRANSPORT_UART, EPPP_TRANSPORT_SPI, EPPP_TRANSPORT_SDIO, + EPPP_TRANSPORT_ETHERNET, } eppp_transport_t;