Skip to content

Instantly share code, notes, and snippets.

@xk
Last active January 9, 2024 19:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xk/0c08f8a2c49b35a5e0a38aad2dc6f0ee to your computer and use it in GitHub Desktop.
Save xk/0c08f8a2c49b35a5e0a38aad2dc6f0ee to your computer and use it in GitHub Desktop.
Investigating the LAN8710/8720A boot up sequence with an esp32.
#include <ETH.h>
#include <esp_eth.h>
#include <esp_wifi.h>
#include <driver/gpio.h>
//#define __GEORGE__
#define ETH_TXD0_PIN 19
#define ETH_TXEN_PIN 21
#define ETH_TXD1_PIN 22
#define ETH_RXD0_PIN 25
#define ETH_RXD1_PIN 26
#define ETH_MODE2_PIN 27
#define ETH_TYPE ETH_PHY_LAN8720
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
#ifdef __GEORGE__
#define ETH_MDC_PIN 18
#define ETH_MDIO_PIN 23
#define ETH_POWER_PIN -1
#define ETH_ADDR 1
#else
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18
#define ETH_POWER_PIN 12
#define ETH_ADDR 0
#endif
char* sta_ssid= "SSID";
char* sta_pwd= "PWD";
char* ap_ssid= "WiFi_ESP32";
char* ap_pwd= "wifiesp32pwd";
uint32_t events_ctr= 0;
void onWiFiEvent (WiFiEvent_t id) {
/*
* WiFi Events
0 SYSTEM_EVENT_WIFI_READY < ESP32 WiFi ready
1 SYSTEM_EVENT_SCAN_DONE < ESP32 finish scanning AP
2 SYSTEM_EVENT_STA_START < ESP32 station start
3 SYSTEM_EVENT_STA_STOP < ESP32 station stop
4 SYSTEM_EVENT_STA_CONNECTED < ESP32 station connected to AP
5 SYSTEM_EVENT_STA_DISCONNECTED < ESP32 station disconnected from AP
6 SYSTEM_EVENT_STA_AUTHMODE_CHANGE < the auth mode of AP connected by ESP32 station changed
7 SYSTEM_EVENT_STA_GOT_IP < ESP32 station got IP from connected AP
8 SYSTEM_EVENT_STA_LOST_IP < ESP32 station lost IP and the IP is reset to 0
9 SYSTEM_EVENT_STA_WPS_ER_SUCCESS < ESP32 station wps succeeds in enrollee mode
10 SYSTEM_EVENT_STA_WPS_ER_FAILED < ESP32 station wps fails in enrollee mode
11 SYSTEM_EVENT_STA_WPS_ER_TIMEOUT < ESP32 station wps timeout in enrollee mode
12 SYSTEM_EVENT_STA_WPS_ER_PIN < ESP32 station wps pin code in enrollee mode
13 SYSTEM_EVENT_AP_START < ESP32 soft-AP start
14 SYSTEM_EVENT_AP_STOP < ESP32 soft-AP stop
15 SYSTEM_EVENT_AP_STACONNECTED < a station connected to ESP32 soft-AP
16 SYSTEM_EVENT_AP_STADISCONNECTED < a station disconnected from ESP32 soft-AP
17 SYSTEM_EVENT_AP_STAIPASSIGNED < ESP32 soft-AP assign an IP to a connected station
18 SYSTEM_EVENT_AP_PROBEREQRECVED < Receive probe request packet in soft-AP interface
19 SYSTEM_EVENT_GOT_IP6 < ESP32 station or ap or ethernet interface v6IP addr is preferred
20 SYSTEM_EVENT_ETH_START < ESP32 ethernet start
21 SYSTEM_EVENT_ETH_STOP < ESP32 ethernet stop
22 SYSTEM_EVENT_ETH_CONNECTED < ESP32 ethernet phy link up
23 SYSTEM_EVENT_ETH_DISCONNECTED < ESP32 ethernet phy link down
24 SYSTEM_EVENT_ETH_GOT_IP < ESP32 ethernet got IP from connected AP
25 SYSTEM_EVENT_MAX
*/
events_ctr++;
String r= "";
r= "[Event #"+ String(events_ctr)+ "] "+ String(id)+ ": ";
switch (id) {
case SYSTEM_EVENT_WIFI_READY:
r+= "WiFi interface ready\r\n";
break;
case SYSTEM_EVENT_SCAN_DONE:
r+= "Completed scan of access points\r\n";
break;
case SYSTEM_EVENT_STA_START:
r+= "STA client started\r\n";
break;
case SYSTEM_EVENT_STA_STOP:
r+= "STA clients stopped\r\n";
break;
case SYSTEM_EVENT_STA_CONNECTED:
r+= "STA Connected to access point\r\n";
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
r+= "STA Disconnected from WiFi access point\r\n";
break;
case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
r+= "STA Authentication mode of access point has changed\r\n";
break;
case SYSTEM_EVENT_STA_GOT_IP:
r+= "STA Obtained IP address: "+ WiFi.localIP().toString()+ "\r\n";
//set wifi hostname here
WiFi.setHostname("esp32-wifi");
break;
case SYSTEM_EVENT_STA_LOST_IP:
r+= "STA Lost IP address and IP address is reset to 0\r\n";
break;
case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
r+= "STA Protected Setup (WPS): succeeded in enrollee mode\r\n";
break;
case SYSTEM_EVENT_STA_WPS_ER_FAILED:
r+= "STA Protected Setup (WPS): failed in enrollee mode\r\n";
break;
case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
r+= "STA Protected Setup (WPS): timeout in enrollee mode\r\n";
break;
case SYSTEM_EVENT_STA_WPS_ER_PIN:
r+= "STA Protected Setup (WPS): pin code in enrollee mode\r\n";
break;
case SYSTEM_EVENT_AP_START:
r+= "AP access point started\r\n";
break;
case SYSTEM_EVENT_AP_STOP:
r+= "AP stopped\r\n";
break;
case SYSTEM_EVENT_AP_STACONNECTED:
r+= "AP Client connected\r\n";
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
r+= "AP Client disconnected\r\n";
break;
case SYSTEM_EVENT_AP_STAIPASSIGNED:
r+= "AP Assigned IP address to client\r\n";
break;
case SYSTEM_EVENT_AP_PROBEREQRECVED:
r+= "AP Received probe request\r\n";
break;
case SYSTEM_EVENT_GOT_IP6:
r+= "IPv6 is preferred\r\n";
break;
case SYSTEM_EVENT_ETH_START:
r+= "ETH started\r\n";
break;
case SYSTEM_EVENT_ETH_STOP:
r+= "ETH stopped\r\n";
break;
case SYSTEM_EVENT_ETH_CONNECTED:
r+= "ETH connected\r\n";
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
r+= "ETH disconnected\r\n";
break;
case SYSTEM_EVENT_ETH_GOT_IP:
r+= "ETH Obtained IP address\r\n";
r+= "ETH MAC:"+ ETH.macAddress()+ " IP:"+ETH.localIP().toString();
r+= " "+ String(ETH.linkSpeed())+ "Mbps";
if (ETH.fullDuplex()) r+= "/FD";
r+= "\r\n";
//set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
}
Serial.print(r);
}
uint16_t bin2u16 (const char* s) {
uint16_t r= 0;
uint16_t peso= 1;
int len= strlen(s);
while (len>0) {
len-= 1;
char c= s[len];
if (c == ' ') continue;
if (c == '1') r+= peso;
peso*= 2;
}
return r;
}
void eth_off () {
#ifdef __GEORGE__
//I use another pin (5 not 12) with reversed polarity.
pinMode(5, OUTPUT);
digitalWrite(5, 1);
//esp_err_t err= gpio_set_drive_capability(gpio_num_t GPIO_NUM_12, gpio_drive_cap_t GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(GPIO_NUM_5, GPIO_DRIVE_CAP_3);
#else
pinMode(ETH_POWER_PIN, OUTPUT);
digitalWrite(ETH_POWER_PIN, 0);
//esp_err_t err= gpio_set_drive_capability(gpio_num_t GPIO_NUM_12, gpio_drive_cap_t GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(GPIO_NUM_12, GPIO_DRIVE_CAP_3);
#endif
//Turn off all the pins connected to the 8710.
pinMode(ETH_MDC_PIN, INPUT_PULLDOWN);
pinMode(ETH_TXD0_PIN, INPUT_PULLDOWN);
pinMode(ETH_TXD1_PIN, INPUT_PULLDOWN);
pinMode(ETH_TXEN_PIN, INPUT_PULLDOWN);
pinMode(17, INPUT_PULLDOWN);
pinMode(ETH_RXD0_PIN, INPUT_PULLDOWN);
pinMode(ETH_RXD1_PIN, INPUT_PULLDOWN);
pinMode(ETH_MODE2_PIN, INPUT_PULLDOWN);
pinMode(ETH_MDIO_PIN, INPUT_PULLDOWN);
}
void eth_on () {
//Some pins MUST be HIGH when turning on.
//this is MODE0, must be 1
pinMode(ETH_RXD0_PIN, INPUT_PULLUP);
//this is MODE1, must be 1
pinMode(ETH_RXD1_PIN, INPUT_PULLUP);
//this is MODE2, must be 1
pinMode(ETH_MODE2_PIN, INPUT_PULLUP);
//this should be 1
pinMode(ETH_MDIO_PIN, INPUT_PULLUP);
//because the pullups are weak...
delay(10);
#ifdef __GEORGE__
//I use another pin (5 not 12) with reversed polarity.
pinMode(5, OUTPUT);
digitalWrite(5, 0);
//esp_err_t err= gpio_set_drive_capability(gpio_num_t GPIO_NUM_12, gpio_drive_cap_t GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(GPIO_NUM_5, GPIO_DRIVE_CAP_3);
#else
pinMode(ETH_POWER_PIN, OUTPUT);
digitalWrite(ETH_POWER_PIN, 1);
gpio_set_drive_capability(GPIO_NUM_12, GPIO_DRIVE_CAP_3);
#endif
}
String say_hi () {
String r= "";
//Fecha y hora a la que se compiló esto.
//Ver: Arduino predefined constants: https://gist.github.com/ah01/762576
r+= String("\r\n")+ __DATE__+ " "+ __TIME__;
r+= String()+ "\r\nIDF-VERSION: "+ esp_get_idf_version()+ "\r\n";
r+= "ESP. getSketchSize(): "+ String(ESP.getSketchSize())+ "\r\n";
r+= "ESP.getFreeSketchSpace(): "+ String(ESP.getFreeSketchSpace())+ "\r\n";
{
//ver:
//https://github.com/espressif/esp-idf/blob/master/examples/system/base_mac_address/main/base_mac_address_example_main.c
uint8_t base_mac_addr[6] = {0};
if (esp_read_mac(base_mac_addr, ESP_MAC_WIFI_STA) == ESP_OK) {
r+= "STA MAC Address: ";
for (int i=0 ; i<6 ; i++) {
String hex= String(base_mac_addr[i], HEX);
if (hex.length()<2) hex= "0"+ hex;
r+= hex+ " ";
}
r+= "\r\n";
}
if (esp_read_mac(base_mac_addr, ESP_MAC_WIFI_SOFTAP) == ESP_OK) {
r+= " AP MAC Address: ";
for (int i=0 ; i<6 ; i++) {
String hex= String(base_mac_addr[i], HEX);
if (hex.length()<2) hex= "0"+ hex;
r+= hex+ " ";
}
r+= "\r\n";
}
if (esp_read_mac(base_mac_addr, ESP_MAC_BT) == ESP_OK) {
r+= " BT MAC Address: ";
for (int i=0 ; i<6 ; i++) {
String hex= String(base_mac_addr[i], HEX);
if (hex.length()<2) hex= "0"+ hex;
r+= hex+ " ";
}
r+= "\r\n";
}
if (esp_read_mac(base_mac_addr, ESP_MAC_ETH) == ESP_OK) {
r+= "ETH MAC Address: ";
for (int i=0 ; i<6 ; i++) {
String hex= String(base_mac_addr[i], HEX);
if (hex.length()<2) hex= "0"+ hex;
r+= hex+ " ";
}
r+= "\r\n";
}
}
r+= "\r\nHi!\a\a\a ";
return r;
}
void dr () {
Serial.print(" r0:");
Serial.print(esp_eth_smi_read(0), HEX);
Serial.print(" r1:");
Serial.print(esp_eth_smi_read(1), HEX);
Serial.print(" r2:");
Serial.print(esp_eth_smi_read(2), HEX);
Serial.print(" r3:");
Serial.print(esp_eth_smi_read(3), HEX);
Serial.print(" r4:");
Serial.print(esp_eth_smi_read(4), HEX);
Serial.print(" r5:");
Serial.print(esp_eth_smi_read(5), HEX);
Serial.print(" r6:");
Serial.print(esp_eth_smi_read(6), HEX);
Serial.print(" r16:");
Serial.print(esp_eth_smi_read(16), HEX);
Serial.print(" r17:");
Serial.print(esp_eth_smi_read(17), HEX);
Serial.print(" r18:");
Serial.print(esp_eth_smi_read(18), HEX);
Serial.print(" r26:");
Serial.print(esp_eth_smi_read(26), HEX);
Serial.print(" r27:");
Serial.print(esp_eth_smi_read(27), HEX);
Serial.print(" r28:");
Serial.print(esp_eth_smi_read(28), HEX);
Serial.print(" r29:");
Serial.print(esp_eth_smi_read(29), HEX);
Serial.print(" r30:");
Serial.print(esp_eth_smi_read(30), HEX);
Serial.print(" r31:");
Serial.print(esp_eth_smi_read(31), HEX);
Serial.print("\r\n");
}
void eth_10 () {
//Force 10BASE-T max.
esp_eth_smi_write(4, bin2u16("000000 0 0011 00001"));
//Force renegotiation.
esp_eth_smi_write(0, bin2u16("0001 0010 00000000"));
}
void eth_100 () {
//Allow 100BASE-T.
esp_eth_smi_write(4, bin2u16("000000 0 1111 00001"));
//Force renegotiation.
esp_eth_smi_write(0, bin2u16("0001 0010 00000000"));
}
void commander (String cmd) {
int ok= 1;
if (cmd == "dr") dr();
else if (cmd == "ethon") eth_on();
else if (cmd == "eth10") eth_10();
else if (cmd == "eth100") eth_100();
else if (cmd == "ethoff") eth_off();
else if (cmd == "wifioff") WiFi.mode(WIFI_OFF);
else if (cmd == "wifiap") WiFi.softAP(ap_ssid, ap_pwd);
else if (cmd == "wifista") WiFi.begin(sta_ssid, sta_pwd);
else if (cmd == "reboot") {
eth_off();
WiFi.mode(WIFI_OFF);
esp_restart();
}
else ok= 0;
if (ok) Serial.print(" ok\r\n");
else Serial.print(" Watt?\r\n");
}
String command= "";
void console_handle () {
int c;
while (Serial.available()) {
c= Serial.read();
if ((c == '\r') || (c == '\n')) {
if (command.length()) commander(command);
else Serial.print("\r\n");
command= "";
}
else {
Serial.write(c);
command+= (char)c;
}
}
}
void setup () {
unsigned long now= millis();
eth_off();
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.print(say_hi());
WiFi.onEvent(onWiFiEvent);
WiFi.mode(WIFI_OFF);
while ((millis()-now)<888) ;
eth_on();
//delay(1);
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);
eth_10();
}
uint32_t ctr= 0;
uint8_t primeravez= 1;
void loop () {
ctr+= 1;
if (primeravez) {
primeravez= 0;
Serial.print("We're in the loop()\r\n\r\n");
}
console_handle();
}
@MikeZomo
Copy link

MikeZomo commented Jan 9, 2024

Hi,
When I try to build the above code in the Arduino IDE I get the following compile errors:
'esp_eth_smi_read' was not declared in this scope
'esp_eth_smi_write' was not declared in this scope

I am obviously missing something. I need to turn off auto negotiation and set the mode to 100Mb. Any help you can provide in pointing me in the right direction would be greatly appreciated.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment