1
6
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
36
37
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
108
111
112
113
116
119
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
150
151
152
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
195
196
197
198
203
204
209
210
215
216
217
218
219
220
221
222
226
227
230
233
234
235
238
241
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
285
286
287
288
289
294
295
296
297
298
299
300
301
302
303
306
307
308
309
310
311
312
327
328
338
339
340
/* ... */
#include "ethernet_init.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_mac.h"
#include "driver/gpio.h"
#include "sdkconfig.h"6 includes
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
#include "driver/spi_master.h"
#endif
#if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM
#define SPI_ETHERNETS_NUM CONFIG_EXAMPLE_SPI_ETHERNETS_NUM
#else
#define SPI_ETHERNETS_NUM 0
#endif
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
#define INTERNAL_ETHERNETS_NUM 1
#else
#define INTERNAL_ETHERNETS_NUM 0
#endif
#define INIT_SPI_ETH_MODULE_CONFIG(eth_module_config, num) \
do { \
eth_module_config[num].spi_cs_gpio = CONFIG_EXAMPLE_ETH_SPI_CS ##num## _GPIO; \
eth_module_config[num].int_gpio = CONFIG_EXAMPLE_ETH_SPI_INT ##num## _GPIO; \
eth_module_config[num].polling_ms = CONFIG_EXAMPLE_ETH_SPI_POLLING ##num## _MS; \
eth_module_config[num].phy_reset_gpio = CONFIG_EXAMPLE_ETH_SPI_PHY_RST ##num## _GPIO; \
eth_module_config[num].phy_addr = CONFIG_EXAMPLE_ETH_SPI_PHY_ADDR ##num; \
}{...} while(0)...
typedef struct {
uint8_t spi_cs_gpio;
int8_t int_gpio;
uint32_t polling_ms;
int8_t phy_reset_gpio;
uint8_t phy_addr;
uint8_t *mac_addr;
}{ ... }spi_eth_module_config_t;
static const char *TAG = "example_eth_init";
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
static bool gpio_isr_svc_init_by_eth = false;
#endif
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
/* ... */
static esp_eth_handle_t eth_init_internal(esp_eth_mac_t **mac_out, esp_eth_phy_t **phy_out)
{
esp_eth_handle_t ret = NULL;
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
esp32_emac_config.smi_gpio.mdc_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
esp32_emac_config.smi_gpio.mdio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
esp32_emac_config.dma_burst_len = ETH_DMA_BURST_LEN_4;/* ... */
#endif
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
#if CONFIG_EXAMPLE_ETH_PHY_GENERIC
esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_IP101
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
esp_eth_phy_t *phy = esp_eth_phy_new_ksz80xx(&phy_config);
#endif
esp_eth_handle_t eth_handle = NULL;
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
ESP_GOTO_ON_FALSE(esp_eth_driver_install(&config, ð_handle) == ESP_OK, NULL,
err, TAG, "Ethernet driver install failed");
if (mac_out != NULL) {
*mac_out = mac;
}{...}
if (phy_out != NULL) {
*phy_out = phy;
}{...}
return eth_handle;
err:
if (eth_handle != NULL) {
esp_eth_driver_uninstall(eth_handle);
}{...}
if (mac != NULL) {
mac->del(mac);
}{...}
if (phy != NULL) {
phy->del(phy);
}{...}
return ret;
}{ ... }
#endif/* ... */
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
/* ... */
static esp_err_t spi_bus_init(void)
{
esp_err_t ret = ESP_OK;
#if (CONFIG_EXAMPLE_ETH_SPI_INT0_GPIO >= 0) || (CONFIG_EXAMPLE_ETH_SPI_INT1_GPIO > 0)
ret = gpio_install_isr_service(0);
if (ret == ESP_OK) {
gpio_isr_svc_init_by_eth = true;
}{...} else if (ret == ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG, "GPIO ISR handler has been already installed");
ret = ESP_OK;
}{...} else {
ESP_LOGE(TAG, "GPIO ISR handler install failed");
goto err;
}{...}
/* ... */#endif
spi_bus_config_t buscfg = {
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
}{...};
ESP_GOTO_ON_ERROR(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO),
err, TAG, "SPI host #%d init failed", CONFIG_EXAMPLE_ETH_SPI_HOST);
err:
return ret;
}{...}
/* ... */
static esp_eth_handle_t eth_init_spi(spi_eth_module_config_t *spi_eth_module_config, esp_eth_mac_t **mac_out, esp_eth_phy_t **phy_out)
{
esp_eth_handle_t ret = NULL;
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = spi_eth_module_config->phy_addr;
phy_config.reset_gpio_num = spi_eth_module_config->phy_reset_gpio;
spi_device_interface_config_t spi_devcfg = {
.mode = 0,
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
.queue_size = 20,
.spics_io_num = spi_eth_module_config->spi_cs_gpio
}{...};
#if CONFIG_EXAMPLE_USE_KSZ8851SNL
eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
ksz8851snl_config.int_gpio_num = spi_eth_module_config->int_gpio;
ksz8851snl_config.poll_period_ms = spi_eth_module_config->polling_ms;
esp_eth_mac_t *mac = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_ksz8851snl(&phy_config);/* ... */
#elif CONFIG_EXAMPLE_USE_DM9051
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
dm9051_config.int_gpio_num = spi_eth_module_config->int_gpio;
dm9051_config.poll_period_ms = spi_eth_module_config->polling_ms;
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);/* ... */
#elif CONFIG_EXAMPLE_USE_W5500
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
w5500_config.int_gpio_num = spi_eth_module_config->int_gpio;
w5500_config.poll_period_ms = spi_eth_module_config->polling_ms;
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);/* ... */
#endif
esp_eth_handle_t eth_handle = NULL;
esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac, phy);
ESP_GOTO_ON_FALSE(esp_eth_driver_install(ð_config_spi, ð_handle) == ESP_OK, NULL, err, TAG, "SPI Ethernet driver install failed");
if (spi_eth_module_config->mac_addr != NULL) {
ESP_GOTO_ON_FALSE(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, spi_eth_module_config->mac_addr) == ESP_OK,
NULL, err, TAG, "SPI Ethernet MAC address config failed");
}{...}
if (mac_out != NULL) {
*mac_out = mac;
}{...}
if (phy_out != NULL) {
*phy_out = phy;
}{...}
return eth_handle;
err:
if (eth_handle != NULL) {
esp_eth_driver_uninstall(eth_handle);
}{...}
if (mac != NULL) {
mac->del(mac);
}{...}
if (phy != NULL) {
phy->del(phy);
}{...}
return ret;
}{...}
/* ... */#endif
esp_err_t example_eth_init(esp_eth_handle_t *eth_handles_out[], uint8_t *eth_cnt_out)
{
esp_err_t ret = ESP_OK;
esp_eth_handle_t *eth_handles = NULL;
uint8_t eth_cnt = 0;
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET || CONFIG_EXAMPLE_USE_SPI_ETHERNET
ESP_GOTO_ON_FALSE(eth_handles_out != NULL && eth_cnt_out != NULL, ESP_ERR_INVALID_ARG,
err, TAG, "invalid arguments: initialized handles array or number of interfaces");
eth_handles = calloc(SPI_ETHERNETS_NUM + INTERNAL_ETHERNETS_NUM, sizeof(esp_eth_handle_t));
ESP_GOTO_ON_FALSE(eth_handles != NULL, ESP_ERR_NO_MEM, err, TAG, "no memory");
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
eth_handles[eth_cnt] = eth_init_internal(NULL, NULL);
ESP_GOTO_ON_FALSE(eth_handles[eth_cnt], ESP_FAIL, err, TAG, "internal Ethernet init failed");
eth_cnt++;/* ... */
#endif
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
ESP_GOTO_ON_ERROR(spi_bus_init(), err, TAG, "SPI bus init failed");
spi_eth_module_config_t spi_eth_module_config[CONFIG_EXAMPLE_SPI_ETHERNETS_NUM] = { 0 };
INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 0);
uint8_t base_mac_addr[ETH_ADDR_LEN];
ESP_GOTO_ON_ERROR(esp_efuse_mac_get_default(base_mac_addr), err, TAG, "get EFUSE MAC failed");
uint8_t local_mac_1[ETH_ADDR_LEN];
esp_derive_local_mac(local_mac_1, base_mac_addr);
spi_eth_module_config[0].mac_addr = local_mac_1;
#if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM > 1
INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 1);
uint8_t local_mac_2[ETH_ADDR_LEN];
base_mac_addr[ETH_ADDR_LEN - 1] += 1;
esp_derive_local_mac(local_mac_2, base_mac_addr);
spi_eth_module_config[1].mac_addr = local_mac_2;/* ... */
#endif
#if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM > 2
#error Maximum number of supported SPI Ethernet devices is currently limited to 2 by this example.
#endif
for (int i = 0; i < CONFIG_EXAMPLE_SPI_ETHERNETS_NUM; i++) {
eth_handles[eth_cnt] = eth_init_spi(&spi_eth_module_config[i], NULL, NULL);
ESP_GOTO_ON_FALSE(eth_handles[eth_cnt], ESP_FAIL, err, TAG, "SPI Ethernet init failed");
eth_cnt++;
}{...}
#endif/* ... */ /* ... */
#else
ESP_LOGD(TAG, "no Ethernet device selected to init");
#endif
*eth_handles_out = eth_handles;
*eth_cnt_out = eth_cnt;
return ret;
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET || CONFIG_EXAMPLE_USE_SPI_ETHERNET
err:
free(eth_handles);
return ret;/* ... */
#endif
}{ ... }
esp_err_t example_eth_deinit(esp_eth_handle_t *eth_handles, uint8_t eth_cnt)
{
ESP_RETURN_ON_FALSE(eth_handles != NULL, ESP_ERR_INVALID_ARG, TAG, "array of Ethernet handles cannot be NULL");
for (int i = 0; i < eth_cnt; i++) {
esp_eth_mac_t *mac = NULL;
esp_eth_phy_t *phy = NULL;
if (eth_handles[i] != NULL) {
esp_eth_get_mac_instance(eth_handles[i], &mac);
esp_eth_get_phy_instance(eth_handles[i], &phy);
ESP_RETURN_ON_ERROR(esp_eth_driver_uninstall(eth_handles[i]), TAG, "Ethernet %p uninstall failed", eth_handles[i]);
}{...}
if (mac != NULL) {
mac->del(mac);
}{...}
if (phy != NULL) {
phy->del(phy);
}{...}
}{...}
#if CONFIG_EXAMPLE_USE_SPI_ETHERNET
spi_bus_free(CONFIG_EXAMPLE_ETH_SPI_HOST);
#if (CONFIG_EXAMPLE_ETH_SPI_INT0_GPIO >= 0) || (CONFIG_EXAMPLE_ETH_SPI_INT1_GPIO > 0)
if (gpio_isr_svc_init_by_eth) {
ESP_LOGW(TAG, "uninstalling GPIO ISR service!");
gpio_uninstall_isr_service();
}{...}
#endif/* ... */
/* ... */#endif
free(eth_handles);
return ESP_OK;
}{ ... }