-
Notifications
You must be signed in to change notification settings - Fork 5
/
ethernet.ino
218 lines (198 loc) · 8.3 KB
/
ethernet.ino
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
/* The Ethernet low-level stuff */
static eth_clock_mode_t eth_clock_mode = ETH_CLK_MODE;
esp_eth_handle_t eth_handle;
uint8_t isEthLinkUp;
uint8_t nFailedEthTransmissions;
/*********************************************/
uint32_t nTotalEthReceiveBytes; /* total number of bytes which has been received from the ethernet port */
uint32_t nTotalTransmittedBytes;
uint8_t mytransmitbuffer[MY_ETH_TRANSMIT_BUFFER_LEN];
uint8_t mytransmitbufferLen=0; /* The number of used bytes in the ethernet transmit buffer */
uint8_t myreceivebuffer[MY_ETH_RECEIVE_BUFFER_LEN];
uint16_t myreceivebufferLen;
uint8_t myMAC[6] = {0xDC, 0x0e, 0xa1, 0x11, 0x67, 0x09}; /* just a default MAC address. Will be overwritten by the PHY MAC. */
uint8_t nMaxInMyEthernetReceiveCallback, nInMyEthernetReceiveCallback;
uint16_t nTcpPacketsReceived;
/* based on template in WiFiGeneric.cpp, function _arduino_event_cb() */
void myEthernetEventCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_CONNECTED) {
log_v("Ethernet Link Up");
isEthLinkUp = 1;
} else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_DISCONNECTED) {
log_v("Ethernet Link Down");
isEthLinkUp = 0;
} else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_START) {
log_v("Ethernet Started");
isEthLinkUp = 0;
} else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_STOP) {
log_v("Ethernet Stopped");
isEthLinkUp = 0;
}
}
/* The receive function, which is called by the esp32-ethernet-driver. */
esp_err_t myEthernetReceiveCallback(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv) {
nInMyEthernetReceiveCallback++;
if (nInMyEthernetReceiveCallback>nMaxInMyEthernetReceiveCallback) nMaxInMyEthernetReceiveCallback = nInMyEthernetReceiveCallback;
nTotalEthReceiveBytes+=length;
/* We received an ethernet package. Determine its type, and dispatch it to the related handler. */
uint16_t etherType = getEtherType(buffer);
//Serial.println("EtherType" + String(etherType, HEX) + " size " + String(length));
uint32_t L;
sanityCheck("Start of eth rx");
L=length;
if (L>=MY_ETH_RECEIVE_BUFFER_LEN) {
addToTrace("Ethernet rx: limiting " + String(L) + " to " + String(MY_ETH_RECEIVE_BUFFER_LEN) + " bytes");
L=MY_ETH_RECEIVE_BUFFER_LEN;
}
memcpy(myreceivebuffer, buffer, L); /* possible improvement: copy of buffer is not really necessary. We could directly work
on the buffer provided by the ethernet driver. This was allocated especially for each
single received message, and will be present until the application frees it. */
myreceivebufferLen=L;
sanityCheck("Step2 of eth rx");
showAsHex(myreceivebuffer, myreceivebufferLen, "eth.myreceivebuffer");
if (etherType == 0x88E1) { /* it is a HomePlug message */
Serial.println("Its a HomePlug message.");
evaluateReceivedHomeplugPacket();
} else if (etherType == 0x86dd) { /* it is an IPv6 frame */
Serial.println("Its a IPv6 message.");
ipv6_evaluateReceivedPacket();
} else {
//Serial.println("Other message.");
}
sanityCheck("End of eth rx");
nInMyEthernetReceiveCallback--;
free(buffer); /* We need to free the buffer, because the driver will NOT do this (at least in Arduino 2.0.4 with esp-idf4.4.4) */
return ESP_OK;
}
/* The Ethernet transmit function. */
void myEthTransmit(void) {
uint16_t retval;
nTotalTransmittedBytes += mytransmitbufferLen;
showAsHex(mytransmitbuffer, mytransmitbufferLen, "myEthTransmit");
retval = esp_eth_transmit(eth_handle, mytransmitbuffer, mytransmitbufferLen);
if (retval!=ESP_OK) {
addToTrace("esp_eth_transmit went wrong, " + String(retval));
nFailedEthTransmissions++;
addToTrace("In total " + String(nFailedEthTransmissions) + " failed transmissions.");
if (nFailedEthTransmissions>=4) {
addToTrace("Restarting the Ethernet driver");
(void)esp_eth_stop(eth_handle);
(void)esp_eth_start(eth_handle);
}
} else {
nFailedEthTransmissions=0;
}
}
/* The Ethernet initialization function.
Based on code snippets from ETH.cpp ETHClass::begin */
bool initEth(void) {
uint8_t i;
int rc;
uint8_t phy_addr=ETH_PHY_ADDR;
int power=ETH_PHY_POWER;
int mdc=ETH_PHY_MDC;
int mdio=ETH_PHY_MDIO;
#ifdef VERBOSE_INIT_ETH
log_v("This is initEth.");
#endif
//log_printf(ARDUHAL_LOG_FORMAT(I, "phy_addr %d"), phy_addr);
//log_printf(ARDUHAL_LOG_FORMAT(I, "power %d"), power);
//log_printf(ARDUHAL_LOG_FORMAT(I, "mdc %d"), mdc);
//log_printf(ARDUHAL_LOG_FORMAT(I, "mdio %d"), mdio);
//log_printf(ARDUHAL_LOG_FORMAT(I, "type %d"), type);
//log_printf(ARDUHAL_LOG_FORMAT(I, "clock_mode %d"), clock_mode);
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
esp_eth_mac_t *eth_mac = NULL;
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
mac_config.clock_config.rmii.clock_mode = (eth_clock_mode) ? EMAC_CLK_OUT : EMAC_CLK_EXT_IN;
mac_config.clock_config.rmii.clock_gpio = (1 == eth_clock_mode) ? EMAC_APPL_CLK_OUT_GPIO : (2 == eth_clock_mode) ? EMAC_CLK_OUT_GPIO : (3 == eth_clock_mode) ? EMAC_CLK_OUT_180_GPIO : EMAC_CLK_IN_GPIO;
mac_config.smi_mdc_gpio_num = mdc;
mac_config.smi_mdio_gpio_num = mdio;
mac_config.sw_reset_timeout_ms = 1000;
mac_config.rx_task_stack_size = 4096; /* discussed in https://esp32.com/viewtopic.php?t=26603. Default 2048 may cause stack canary failure. */
#ifdef VERBOSE_INIT_ETH
log_v("calling esp_eth_mac_new_esp32");
#endif
eth_mac = esp_eth_mac_new_esp32(&mac_config);
if(eth_mac == NULL){
log_e("esp_eth_mac_new_esp32 failed");
return false;
}
#ifdef VERBOSE_INIT_ETH
log_v("done");
#endif
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = phy_addr;
phy_config.reset_gpio_num = power;
esp_eth_phy_t *eth_phy = NULL;
#ifdef VERBOSE_INIT_ETH
log_v("calling esp_eth_phy_new_lan8720");
#endif
eth_phy = esp_eth_phy_new_lan8720(&phy_config);
if(eth_phy == NULL){
log_e("esp_eth_phy_new failed");
return false;
}
#ifdef VERBOSE_INIT_ETH
log_v("done");
#endif
eth_handle = NULL;
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(eth_mac, eth_phy);
#ifdef VERBOSE_INIT_ETH
log_v("Calling esp_eth_driver_install.");
#endif
if(esp_eth_driver_install(ð_config, ð_handle) != ESP_OK || eth_handle == NULL){
log_e("esp_eth_driver_install failed");
return false;
}
#ifdef VERBOSE_INIT_ETH
log_v("done");
#endif
#ifdef VERBOSE_INIT_ETH
log_v("creating event loop");
#endif
esp_err_t err = esp_event_loop_create_default();
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
log_e("esp_event_loop_create_default failed!");
return false;
}
//log_v("done");
/* registering the event callback from the ethernet driver */
#ifdef VERBOSE_INIT_ETH
log_v("registering the event callback from the ethernet driver.");
#endif
rc = esp_event_handler_instance_register(ETH_EVENT, ESP_EVENT_ANY_ID, &myEthernetEventCallback, NULL, NULL);
//log_v("returned %d", rc);
if(rc) {
log_e("event_handler_instance_register for ETH_EVENT Failed! rc %d", rc);
return false;
}
//log_v("done");
#ifdef VERBOSE_INIT_ETH
log_v("registering the receive callback from the ethernet driver.");
#endif
rc = esp_eth_update_input_path(eth_handle, &myEthernetReceiveCallback, NULL);
//log_v("returned %d", rc);
if(rc) {
log_e("esp_eth_update_input_path Failed! rc %d", rc);
return false;
}
//log_v("done");
/* starting the ethernet driver in standalone mode, means without TCP/IP etc. */
#ifdef VERBOSE_INIT_ETH
log_v("starting the ethernet driver in standalone mode.");
#endif
if(esp_eth_start(eth_handle) != ESP_OK){
log_e("esp_eth_start failed");
return false;
}
//log_v("esp_eth_start done");
//log_v("requesting MAC.");
rc = esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, myMAC);
log_v("myMAC %hx:%hx:%hx:%hx:%hx:%hx", myMAC[0], myMAC[1], myMAC[2], myMAC[3], myMAC[4], myMAC[5]);
// holds a few milliseconds to enter into a good state
// FIX ME -- adresses issue https://github.com/espressif/arduino-esp32/issues/5733
delay(50);
return true;
}