Skip to content

Commit da05de2

Browse files
committed
feat(eppp): Add support for transport via Ethernet EMAC-2-EMAC
1 parent 776e40c commit da05de2

File tree

5 files changed

+197
-13
lines changed

5 files changed

+197
-13
lines changed

components/eppp_link/Kconfig

+30
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,34 @@ menu "eppp_link"
8787
default "06:00:00:00:00:02"
8888
depends on EPPP_LINK_DEVICE_ETH
8989

90+
config EPPP_LINK_ETHERNET_USE_DUMMY_PHY
91+
bool "Use dummy phy (emac2emac)"
92+
default n
93+
depends on EPPP_LINK_DEVICE_ETH
94+
95+
choice EPPP_LINK_ETHERNET_CLK_ROLE
96+
prompt "RMII CLK Role"
97+
default EPPP_LINK_ETHERNET_CLK_SOURCE
98+
depends on EPPP_LINK_ETHERNET_USE_DUMMY_PHY
99+
help
100+
Configure device type. ESP32 device which is RMII CLK source needs to wait
101+
with its Ethernet initialization for the "RMII CLK Sink Device" since
102+
the RMII CLK input pin (GPIO0) is also used as a boot strap pin. If
103+
the "RMII CLK Source Device" didn't wait, the "RMII CLK Sink Device"
104+
could boot into incorrect mode.
105+
106+
config EPPP_LINK_ETHERNET_CLK_SOURCE
107+
bool "RMII CLK Source Device"
108+
config EPPP_LINK_ETHERNET_CLK_SINK
109+
bool "RMII CLK Sink Device"
110+
endchoice
111+
112+
config EPPP_LINK_ETHERNET_SINK_READY_GPIO
113+
int "RMII CLK Sink Device is ready GPIO"
114+
default 4
115+
depends on EPPP_LINK_ETHERNET_USE_DUMMY_PHY
116+
help
117+
GPIO number at which the "RMII CLK Sink Device" is ready and so the "RMII
118+
CLK Source Device" can continue in its Ethernet initialization.
119+
90120
endmenu

components/eppp_link/eppp_eth.c

+153-13
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "esp_eth_driver.h"
1717
#include "ethernet_init.h"
1818
#include "esp_eth_spec.h"
19+
#include "driver/gpio.h"
20+
#include "esp_eth_phy_dummy.h"
1921

2022
typedef struct header {
2123
uint8_t dst[ETH_ADDR_LEN];
@@ -65,30 +67,23 @@ static esp_err_t receive(esp_eth_handle_t h, uint8_t *buffer, uint32_t len, void
6567
return ESP_FAIL;
6668
}
6769

70+
static esp_err_t eth_init(void);
71+
6872
esp_err_t eppp_transport_init(eppp_config_t *config, esp_netif_t *esp_netif)
6973
{
70-
uint8_t eth_port_cnt = 0;
71-
ESP_ERROR_CHECK(ethernet_init_all(&s_eth_handles, &eth_port_cnt));
72-
if (eth_port_cnt > 1) {
73-
ESP_LOGW(TAG, "multiple Ethernet devices detected, the first initialized is to be used!");
74-
}
75-
ESP_ERROR_CHECK(esp_eth_update_input_path(s_eth_handles[0], receive, esp_netif));
74+
ESP_RETURN_ON_ERROR(eth_init(), TAG, "Failed to initialize Ethernet driver");
75+
ESP_RETURN_ON_ERROR(esp_eth_update_input_path(s_eth_handles[0], receive, esp_netif), TAG, "Failed to set Ethernet Rx callback");
7676
sscanf(CONFIG_EPPP_LINK_ETHERNET_OUR_ADDRESS, "%2" PRIu8 ":%2" PRIu8 ":%2" PRIi8 ":%2" PRIu8 ":%2" PRIu8 ":%2" PRIu8,
7777
&s_our_mac[0], &s_our_mac[1], &s_our_mac[2], &s_our_mac[3], &s_our_mac[4], &s_our_mac[5]);
7878

7979
sscanf(CONFIG_EPPP_LINK_ETHERNET_THEIR_ADDRESS, "%2" PRIu8 ":%2" PRIu8 ":%2" PRIi8 ":%2" PRIu8 ":%2" PRIu8 ":%2" PRIu8,
8080
&s_their_mac[0], &s_their_mac[1], &s_their_mac[2], &s_their_mac[3], &s_their_mac[4], &s_their_mac[5]);
8181
esp_eth_ioctl(s_eth_handles[0], ETH_CMD_S_MAC_ADDR, s_our_mac);
82-
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL));
83-
ESP_ERROR_CHECK(esp_eth_start(s_eth_handles[0]));
82+
ESP_RETURN_ON_ERROR(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL), TAG, "Failed to register Ethernet handlers");
83+
ESP_RETURN_ON_ERROR(esp_eth_start(s_eth_handles[0]), TAG, "Failed to start Ethernet driver");
8484
return ESP_OK;
8585
}
8686

87-
void eppp_transport_deinit(void)
88-
{
89-
ethernet_deinit_all(s_eth_handles);
90-
}
91-
9287
esp_err_t eppp_transport_tx(void *h, void *buffer, size_t len)
9388
{
9489
if (!s_is_connected) {
@@ -107,3 +102,148 @@ esp_err_t eppp_transport_tx(void *h, void *buffer, size_t len)
107102
memcpy(s_out_buffer + ETH_HEADER_LEN, buffer, len);
108103
return esp_eth_transmit(s_eth_handles[0], s_out_buffer, frame_payload_len + ETH_HEADER_LEN);
109104
}
105+
106+
#ifdef CONFIG_EPPP_LINK_ETHERNET_USE_DUMMY_PHY
107+
108+
static esp_eth_mac_t *s_mac = NULL;
109+
static esp_eth_phy_t *s_phy = NULL;
110+
111+
#if CONFIG_EPPP_LINK_ETHERNET_CLK_SOURCE
112+
IRAM_ATTR static void gpio_isr_handler(void *arg)
113+
{
114+
BaseType_t high_task_wakeup = pdFALSE;
115+
TaskHandle_t task_handle = (TaskHandle_t)arg;
116+
117+
vTaskNotifyGiveFromISR(task_handle, &high_task_wakeup);
118+
if (high_task_wakeup != pdFALSE) {
119+
portYIELD_FROM_ISR();
120+
}
121+
}
122+
#else
123+
#define STARTUP_DELAY_MS 500
124+
#endif
125+
126+
static esp_err_t eth_init(void)
127+
{
128+
#if CONFIG_EPPP_LINK_ETHERNET_CLK_SOURCE
129+
esp_rom_gpio_pad_select_gpio(EMAC_CLK_OUT_180_GPIO);
130+
gpio_set_pull_mode(EMAC_CLK_OUT_180_GPIO, GPIO_FLOATING); // to not affect GPIO0 (so the Sink Device could be flashed)
131+
gpio_install_isr_service(0);
132+
gpio_config_t gpio_source_cfg = {
133+
.pin_bit_mask = (1ULL << CONFIG_EPPP_LINK_ETHERNET_SINK_READY_GPIO),
134+
.mode = GPIO_MODE_INPUT,
135+
.pull_up_en = GPIO_PULLUP_DISABLE,
136+
.pull_down_en = GPIO_PULLDOWN_ENABLE,
137+
.intr_type = GPIO_INTR_ANYEDGE
138+
};
139+
gpio_config(&gpio_source_cfg);
140+
TaskHandle_t task_handle = xTaskGetHandle(pcTaskGetName(NULL));
141+
gpio_isr_handler_add(CONFIG_EPPP_LINK_ETHERNET_SINK_READY_GPIO, gpio_isr_handler, task_handle);
142+
ESP_LOGW(TAG, "waiting for RMII CLK sink device interrupt");
143+
ESP_LOGW(TAG, "if RMII CLK sink device is already running, reset it by `EN` button");
144+
while (1) {
145+
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
146+
if (gpio_get_level(CONFIG_EPPP_LINK_ETHERNET_SINK_READY_GPIO) == 1) {
147+
break;
148+
}
149+
}
150+
ESP_LOGI(TAG, "starting Ethernet initialization");
151+
#else
152+
gpio_config_t gpio_sink_cfg = {
153+
.pin_bit_mask = (1ULL << CONFIG_EPPP_LINK_ETHERNET_SINK_READY_GPIO),
154+
.mode = GPIO_MODE_OUTPUT,
155+
.pull_up_en = GPIO_PULLUP_DISABLE,
156+
.pull_down_en = GPIO_PULLDOWN_DISABLE,
157+
.intr_type = GPIO_INTR_DISABLE
158+
};
159+
gpio_config(&gpio_sink_cfg);
160+
gpio_set_level(CONFIG_EPPP_LINK_ETHERNET_SINK_READY_GPIO, 0);
161+
vTaskDelay(pdMS_TO_TICKS(STARTUP_DELAY_MS));
162+
gpio_set_level(CONFIG_EPPP_LINK_ETHERNET_SINK_READY_GPIO, 1);
163+
#endif // CONFIG_EPPP_LINK_ETHERNET_CLK_SOURCE
164+
165+
// --- Initialize Ethernet driver ---
166+
// Init common MAC and PHY configs to default
167+
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
168+
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
169+
170+
// Update PHY config based on board specific configuration
171+
phy_config.reset_gpio_num = -1; // no HW reset
172+
173+
// Init vendor specific MAC config to default
174+
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
175+
// Update vendor specific MAC config based on board configuration
176+
// No SMI, speed/duplex must be statically configured the same in both devices
177+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
178+
esp32_emac_config.smi_gpio.mdc_num = -1;
179+
esp32_emac_config.smi_gpio.mdio_num = -1;
180+
#else
181+
esp32_emac_config.smi_mdc_gpio_num = -1;
182+
esp32_emac_config.smi_mdio_gpio_num = -1;
183+
#endif
184+
#if CONFIG_EPPP_LINK_ETHERNET_CLK_SOURCE
185+
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT;
186+
esp32_emac_config.clock_config.rmii.clock_gpio = EMAC_CLK_OUT_180_GPIO;
187+
#else
188+
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_EXT_IN;
189+
esp32_emac_config.clock_config.rmii.clock_gpio = EMAC_CLK_IN_GPIO;
190+
#endif // CONFIG_EPPP_LINK_ETHERNET_CLK_SOURCE
191+
192+
// Create new ESP32 Ethernet MAC instance
193+
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
194+
// Create dummy PHY instance
195+
s_phy = esp_eth_phy_new_dummy(&phy_config);
196+
197+
// Init Ethernet driver to default and install it
198+
s_eth_handles = malloc(sizeof(esp_eth_handle_t));
199+
ESP_RETURN_ON_FALSE(s_eth_handles, ESP_ERR_NO_MEM, TAG, "Our of memory");
200+
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
201+
#if CONFIG_EPPP_LINK_ETHERNET_CLK_SINK
202+
// REF RMII CLK sink device performs multiple EMAC init attempts since RMII CLK source device may not be ready yet
203+
int i;
204+
for (i = 1; i <= 5; i++) {
205+
ESP_LOGI(TAG, "Ethernet driver install attempt: %i", i);
206+
if (esp_eth_driver_install(&config, &s_eth_handles[0]) == ESP_OK) {
207+
break;
208+
}
209+
vTaskDelay(pdMS_TO_TICKS(100));
210+
}
211+
ESP_RETURN_ON_FALSE(i <= 5, ESP_FAIL, TAG, "Ethernet driver install failed");
212+
#else
213+
ESP_RETURN_ON_ERROR(esp_eth_driver_install(&config, &s_eth_handles[0]), TAG, "Ethernet driver install failed");
214+
#endif // CONFIG_EPPP_LINK_ETHERNET_CLK_SINK
215+
return ESP_OK;
216+
}
217+
218+
void eppp_transport_deinit(void)
219+
{
220+
if (esp_eth_driver_uninstall(&s_eth_handles[0]) != ESP_OK) {
221+
ESP_LOGE(TAG, "Unable to deinitialize ethernet handle");
222+
}
223+
if (s_mac) {
224+
s_mac->del(s_mac);
225+
s_mac = NULL;
226+
}
227+
if (s_phy) {
228+
s_phy->del(s_phy);
229+
s_phy = NULL;
230+
}
231+
free(s_eth_handles);
232+
s_eth_handles = NULL;
233+
}
234+
235+
#else
236+
static esp_err_t eth_init(void)
237+
{
238+
uint8_t eth_port_cnt = 0;
239+
ESP_RETURN_ON_ERROR(ethernet_init_all(&s_eth_handles, &eth_port_cnt), TAG, "Failed to init common eth drivers");
240+
ESP_RETURN_ON_FALSE(eth_port_cnt > 1, ESP_ERR_INVALID_ARG, TAG, "multiple Ethernet devices detected, please init only one");
241+
return ESP_OK;
242+
}
243+
244+
void eppp_transport_deinit(void)
245+
{
246+
ethernet_deinit_all(s_eth_handles);
247+
}
248+
249+
#endif // CONFIG_EPPP_LINK_ETHERNET_USE_DUMMY_PHY
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CONFIG_IDF_TARGET="esp32"
2+
CONFIG_EPPP_LINK_DEVICE_ETH=y
3+
CONFIG_EPPP_LINK_ETHERNET_USE_DUMMY_PHY=y
4+
CONFIG_EPPP_LINK_ETHERNET_CLK_SOURCE=y
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CONFIG_IDF_TARGET="esp32"
2+
CONFIG_EPPP_LINK_DEVICE_ETH=y
3+
CONFIG_EPPP_LINK_ETHERNET_OUR_ADDRESS="06:00:00:00:00:02"
4+
CONFIG_EPPP_LINK_ETHERNET_THEIR_ADDRESS="06:00:00:00:00:01"
5+
CONFIG_EPPP_LINK_ETHERNET_USE_DUMMY_PHY=y
6+
CONFIG_EPPP_LINK_ETHERNET_CLK_SINK=y

components/eppp_link/idf_component.yml

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ dependencies:
55
idf: '>=5.2'
66
espressif/esp_serial_slave_link: "^1.1.0"
77
espressif/ethernet_init: '>=0.0.7'
8+
espressif/eth_dummy_phy:
9+
version: '*'
10+
rules:
11+
- if: "target in [esp32, esp32p4]"

0 commit comments

Comments
 (0)