mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-29 18:27:31 +02:00
feat(eppp): Add support for transport via Ethernet link
This commit is contained in:
@ -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"
|
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()
|
||||||
|
@ -28,6 +28,16 @@ menu "eppp_link"
|
|||||||
help
|
help
|
||||||
Use SDIO.
|
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
|
endchoice
|
||||||
|
|
||||||
config EPPP_LINK_CONN_MAX_RETRY
|
config EPPP_LINK_CONN_MAX_RETRY
|
||||||
@ -67,4 +77,14 @@ menu "eppp_link"
|
|||||||
|
|
||||||
endchoice
|
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
|
endmenu
|
||||||
|
@ -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.
|
brings in the WiFi connectivity from the "SLAVE" microcontroller.
|
||||||
|
|
||||||
```
|
```
|
||||||
SLAVE micro HOST micro
|
SLAVE micro HOST micro
|
||||||
\|/ +----------------+ +----------------+
|
\|/ +----------------+ +----------------+
|
||||||
| | | serial line | |
|
| | | (serial) line | |
|
||||||
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client |
|
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO / ETH ===| PPPoS client |
|
||||||
| (server)| | |
|
| (server)| | |
|
||||||
+----------------+ +----------------+
|
+----------------+ +----------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
@ -55,3 +55,9 @@ Tested with WiFi-NAPT example
|
|||||||
|
|
||||||
* TCP - 9Mbits/s
|
* TCP - 9Mbits/s
|
||||||
* UDP - 11Mbits/s
|
* UDP - 11Mbits/s
|
||||||
|
|
||||||
|
### Ethernet
|
||||||
|
|
||||||
|
- Internal EMAC with real PHY chip
|
||||||
|
* TCP - 5Mbits/s
|
||||||
|
* UDP - 8Mbits/s
|
||||||
|
119
components/eppp_link/eppp_eth.c
Normal file
119
components/eppp_link/eppp_eth.c
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#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);
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_netif_ppp.h"
|
#include "esp_netif_ppp.h"
|
||||||
#include "eppp_link.h"
|
#include "eppp_link.h"
|
||||||
#include "esp_serial_slave_link/essl_sdio.h"
|
#include "eppp_transport.h"
|
||||||
|
|
||||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||||
#include "driver/spi_master.h"
|
#include "driver/spi_master.h"
|
||||||
@ -24,6 +24,12 @@
|
|||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
#endif
|
#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 GOT_IPV4 = BIT0;
|
||||||
static const int CONNECTION_FAILED = BIT1;
|
static const int CONNECTION_FAILED = BIT1;
|
||||||
#define CONNECT_BITS (GOT_IPV4|CONNECTION_FAILED)
|
#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);
|
esp_err_t eppp_sdio_slave_init(void);
|
||||||
void eppp_sdio_slave_deinit(void);
|
void eppp_sdio_slave_deinit(void);
|
||||||
void eppp_sdio_host_deinit(void);
|
void eppp_sdio_host_deinit(void);
|
||||||
|
#elif CONFIG_EPPP_LINK_DEVICE_ETH
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
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,
|
.handle = h,
|
||||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||||
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
|
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
|
||||||
|
#elif CONFIG_EPPP_LINK_DEVICE_ETH
|
||||||
|
.transmit = eppp_transport_tx,
|
||||||
#else
|
#else
|
||||||
.transmit = transmit,
|
.transmit = transmit,
|
||||||
#endif
|
#endif
|
||||||
@ -691,6 +701,7 @@ esp_err_t eppp_perform(esp_netif_t *netif)
|
|||||||
|
|
||||||
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
|
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
|
||||||
|
|
||||||
|
#if EPPP_NEEDS_TASK
|
||||||
static void ppp_task(void *args)
|
static void ppp_task(void *args)
|
||||||
{
|
{
|
||||||
esp_netif_t *netif = args;
|
esp_netif_t *netif = args;
|
||||||
@ -699,6 +710,7 @@ static void ppp_task(void *args)
|
|||||||
h->exited = true;
|
h->exited = true;
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool have_some_eppp_netif(esp_netif_t *netif, void *ctx)
|
static bool have_some_eppp_netif(esp_netif_t *netif, void *ctx)
|
||||||
{
|
{
|
||||||
@ -738,6 +750,8 @@ void eppp_deinit(esp_netif_t *netif)
|
|||||||
} else {
|
} else {
|
||||||
eppp_sdio_slave_deinit();
|
eppp_sdio_slave_deinit();
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_EPPP_LINK_DEVICE_ETH
|
||||||
|
eppp_transport_deinit();
|
||||||
#endif
|
#endif
|
||||||
netif_deinit(netif);
|
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);
|
ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret);
|
||||||
return NULL;
|
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
|
#endif
|
||||||
return netif;
|
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);
|
eppp_netif_start(netif);
|
||||||
|
#if EPPP_NEEDS_TASK
|
||||||
if (xTaskCreate(ppp_task, "ppp connect", config->task.stack_size, netif, config->task.priority, NULL) != pdTRUE) {
|
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");
|
ESP_LOGE(TAG, "Failed to create a ppp connection task");
|
||||||
eppp_deinit(netif);
|
eppp_deinit(netif);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
int netif_cnt = get_netif_num(netif);
|
int netif_cnt = get_netif_num(netif);
|
||||||
if (netif_cnt < 0) {
|
if (netif_cnt < 0) {
|
||||||
eppp_close(netif);
|
eppp_close(netif);
|
||||||
|
14
components/eppp_link/eppp_transport.h
Normal file
14
components/eppp_link/eppp_transport.h
Normal file
@ -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);
|
2
components/eppp_link/examples/host/sdkconfig.ci.eth
Normal file
2
components/eppp_link/examples/host/sdkconfig.ci.eth
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_IDF_TARGET="esp32"
|
||||||
|
CONFIG_EPPP_LINK_DEVICE_ETH=y
|
2
components/eppp_link/examples/host/sdkconfig.ci.sdio
Normal file
2
components/eppp_link/examples/host/sdkconfig.ci.sdio
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_IDF_TARGET="esp32p4"
|
||||||
|
CONFIG_EPPP_LINK_DEVICE_SDIO=y
|
2
components/eppp_link/examples/slave/sdkconfig.ci.eth
Normal file
2
components/eppp_link/examples/slave/sdkconfig.ci.eth
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_IDF_TARGET="esp32"
|
||||||
|
CONFIG_EPPP_LINK_DEVICE_ETH=y
|
2
components/eppp_link/examples/slave/sdkconfig.ci.sdio
Normal file
2
components/eppp_link/examples/slave/sdkconfig.ci.sdio
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_IDF_TARGET="esp32c6"
|
||||||
|
CONFIG_EPPP_LINK_DEVICE_SDIO=y
|
@ -4,3 +4,4 @@ description: The component provides a general purpose PPP connectivity, typicall
|
|||||||
dependencies:
|
dependencies:
|
||||||
idf: '>=5.2'
|
idf: '>=5.2'
|
||||||
espressif/esp_serial_slave_link: "^1.1.0"
|
espressif/esp_serial_slave_link: "^1.1.0"
|
||||||
|
espressif/ethernet_init: '>=0.0.7'
|
||||||
|
@ -63,6 +63,7 @@ typedef enum eppp_transport {
|
|||||||
EPPP_TRANSPORT_UART,
|
EPPP_TRANSPORT_UART,
|
||||||
EPPP_TRANSPORT_SPI,
|
EPPP_TRANSPORT_SPI,
|
||||||
EPPP_TRANSPORT_SDIO,
|
EPPP_TRANSPORT_SDIO,
|
||||||
|
EPPP_TRANSPORT_ETHERNET,
|
||||||
} eppp_transport_t;
|
} eppp_transport_t;
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user