Select one of the symbols to view example projects that use it.
 
Outline
#include "ethernet_init.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_mac.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "driver/spi_master.h"
#define SPI_ETHERNETS_NUM
#define SPI_ETHERNETS_NUM
#define INTERNAL_ETHERNETS_NUM
#define INTERNAL_ETHERNETS_NUM
spi_eth_module_config_t
TAG
eth_init_internal(esp_eth_mac_t **, esp_eth_phy_t **)
example_eth_init(esp_eth_handle_t **, uint8_t *)
example_eth_deinit(esp_eth_handle_t *, uint8_t)
Files
loading...
SourceVuESP-IDF Framework and ExamplesESP-IDFexamples/ethernet/basic/components/ethernet_init/ethernet_init.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 *//* ... */ #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 // CONFIG_EXAMPLE_USE_SPI_ETHERNET #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; // indicates that we initialized the GPIO ISR service #endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET #if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET /** * @brief Internal ESP32 Ethernet initialization * * @param[out] mac_out optionally returns Ethernet MAC object * @param[out] phy_out optionally returns Ethernet PHY object * @return * - esp_eth_handle_t if init succeeded * - NULL if init failed *//* ... */ 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; // Init common MAC and PHY configs to default eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // Update PHY config based on board specific configuration phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO; // Init vendor specific MAC config to default eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); // Update vendor specific MAC config based on board configuration 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 // The DMA is shared resource between EMAC and the SPI. Therefore, adjust // EMAC DMA burst length when SPI Ethernet is used along with EMAC. esp32_emac_config.dma_burst_len = ETH_DMA_BURST_LEN_4;/* ... */ #endif // CONFIG_EXAMPLE_USE_SPI_ETHERNET // Create new ESP32 Ethernet MAC instance esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // Create new PHY instance based on board configuration #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 // Init Ethernet driver to default and install it 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, &eth_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/* ... */ // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET #if CONFIG_EXAMPLE_USE_SPI_ETHERNET /** * @brief SPI bus initialization (to be used by Ethernet SPI modules) * * @return * - ESP_OK on success *//* ... */ 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) // Install GPIO ISR handler to be able to service SPI Eth modules interrupts 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; // ISR handler has been already installed so no issues }{...} else { ESP_LOGE(TAG, "GPIO ISR handler install failed"); goto err; }{...} /* ... */#endif // Init SPI bus 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; }{...} /** * @brief Ethernet SPI modules initialization * * @param[in] spi_eth_module_config specific SPI Ethernet module configuration * @param[out] mac_out optionally returns Ethernet MAC object * @param[out] phy_out optionally returns Ethernet PHY object * @return * - esp_eth_handle_t if init succeeded * - NULL if init failed *//* ... */ 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; // Init common MAC and PHY configs to default eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // Update PHY config based on board specific configuration phy_config.phy_addr = spi_eth_module_config->phy_addr; phy_config.reset_gpio_num = spi_eth_module_config->phy_reset_gpio; // Configure SPI interface for specific SPI module 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 }{...}; // Init vendor specific MAC config to default, and create new SPI Ethernet MAC instance // and new PHY instance based on board configuration #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 //CONFIG_EXAMPLE_USE_W5500 // Init Ethernet driver to default and install it 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(&eth_config_spi, &eth_handle) == ESP_OK, NULL, err, TAG, "SPI Ethernet driver install failed"); // The SPI Ethernet module might not have a burned factory MAC address, we can set it manually. 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 // CONFIG_EXAMPLE_USE_SPI_ETHERNET 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 //CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET #if CONFIG_EXAMPLE_USE_SPI_ETHERNET ESP_GOTO_ON_ERROR(spi_bus_init(), err, TAG, "SPI bus init failed"); // Init specific SPI Ethernet module configuration from Kconfig (CS GPIO, Interrupt GPIO, etc.) 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); // The SPI Ethernet module(s) might not have a burned factory MAC address, hence use manually configured address(es). // In this example, Locally Administered MAC address derived from ESP32x base MAC address is used. // Note that Locally Administered OUI range should be used only when testing on a LAN under your control! 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/* ... */ // CONFIG_EXAMPLE_USE_SPI_ETHERNET/* ... */ #else ESP_LOGD(TAG, "no Ethernet device selected to init"); #endif // CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET || CONFIG_EXAMPLE_USE_SPI_ETHERNET *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) // We installed the GPIO ISR service so let's uninstall it too. // BE CAREFUL HERE though since the service might be used by other functionality! if (gpio_isr_svc_init_by_eth) { ESP_LOGW(TAG, "uninstalling GPIO ISR service!"); gpio_uninstall_isr_service(); }{...} #endif/* ... */ /* ... */#endif //CONFIG_EXAMPLE_USE_SPI_ETHERNET free(eth_handles); return ESP_OK; }{ ... }
Details