Allow configuration of Ethernet PHY clock source (#916)

* Allow configuration of Ethernet PHY clock source
Refer to https://github.com/espressif/esp-idf/pull/1127
The internal APLL can be used to generate the 50MHz clock for the internal EMAC and the external Ethernet PHY.
The clock can either be input on GPIO0 (as before) or output on GPIO0, GPIO16 or GPIO17 (only GPIO17 extensively tested).
New example available.

* Allow configuration of Ethernet PHY clock source
Refer to https://github.com/espressif/esp-idf/pull/1127
The internal APLL can be used to generate the 50MHz clock for the internal EMAC and the external Ethernet PHY.
The clock can either be input on GPIO0 (as before) or output on GPIO0, GPIO16 or GPIO17 (only GPIO17 extensively tested).
New example available.
This commit is contained in:
Frank Sautter 2017-12-19 14:06:01 +01:00 committed by Me No Dev
parent 20db2ee421
commit 75bc1e648b
3 changed files with 109 additions and 3 deletions

View File

@ -0,0 +1,100 @@
/*
This sketch shows how to configure different external or internal clock sources for the Ethernet PHY
*/
#include <ETH.h>
/*
* ETH_CLOCK_GPIO0_IN - default: external clock from crystal oscillator
* ETH_CLOCK_GPIO0_OUT - 50MHz clock from internal APLL output on GPIO0 - possibly an inverter is needed for LAN8720
* ETH_CLOCK_GPIO16_OUT - 50MHz clock from internal APLL output on GPIO16 - possibly an inverter is needed for LAN8720
* ETH_CLOCK_GPIO17_OUT - 50MHz clock from internal APLL inverted output on GPIO17 - tested with LAN8720
*/
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
// Pin# of the enable signal for the external crystal oscillator (-1 to disable for internal APLL source)
#define ETH_POWER_PIN -1
// Type of the Ethernet PHY (LAN8720 or TLK110)
#define ETH_TYPE ETH_PHY_LAN8720
// I²C-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110)
#define ETH_ADDR 0
// Pin# of the I²C clock signal for the Ethernet PHY
#define ETH_MDC_PIN 15
// Pin# of the I²C IO signal for the Ethernet PHY
#define ETH_MDIO_PIN 2
static bool eth_connected = false;
void WiFiEvent(WiFiEvent_t event) {
switch (event) {
case SYSTEM_EVENT_ETH_START:
Serial.println("ETH Started");
//set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
Serial.print("ETH MAC: ");
Serial.print(ETH.macAddress());
Serial.print(", IPv4: ");
Serial.print(ETH.localIP());
if (ETH.fullDuplex()) {
Serial.print(", FULL_DUPLEX");
}
Serial.print(", ");
Serial.print(ETH.linkSpeed());
Serial.println("Mbps");
eth_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
}
void testClient(const char * host, uint16_t port) {
Serial.print("\nconnecting to ");
Serial.println(host);
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("connection failed");
return;
}
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
while (client.connected() && !client.available());
while (client.available()) {
Serial.write(client.read());
}
Serial.println("closing connection\n");
client.stop();
}
void setup() {
Serial.begin(115200);
WiFi.onEvent(WiFiEvent);
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);
}
void loop() {
if (eth_connected) {
testClient("google.com", 80);
}
delay(10000);
}

View File

@ -30,6 +30,7 @@ extern void tcpipInit();
static int _eth_phy_mdc_pin = -1; static int _eth_phy_mdc_pin = -1;
static int _eth_phy_mdio_pin = -1; static int _eth_phy_mdio_pin = -1;
static int _eth_phy_power_pin = -1; static int _eth_phy_power_pin = -1;
static eth_clock_mode_t _eth_clk_mode = ETH_CLOCK_GPIO0_IN;
static eth_phy_power_enable_func _eth_phy_power_enable_orig = NULL; static eth_phy_power_enable_func _eth_phy_power_enable_orig = NULL;
static void _eth_phy_config_gpio(void) static void _eth_phy_config_gpio(void)
@ -56,7 +57,7 @@ ETHClass::ETHClass():initialized(false),started(false),staticIP(false)
ETHClass::~ETHClass() ETHClass::~ETHClass()
{} {}
bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t type) bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t type, eth_clock_mode_t clock_mode)
{ {
esp_err_t err; esp_err_t err;
if(initialized){ if(initialized){
@ -84,6 +85,7 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ
} }
eth_config.phy_addr = (eth_phy_base_t)phy_addr; eth_config.phy_addr = (eth_phy_base_t)phy_addr;
eth_config.clock_mode = clock_mode;
eth_config.gpio_config = _eth_phy_config_gpio; eth_config.gpio_config = _eth_phy_config_gpio;
eth_config.tcpip_input = tcpip_adapter_eth_input; eth_config.tcpip_input = tcpip_adapter_eth_input;
if(_eth_phy_power_pin >= 0){ if(_eth_phy_power_pin >= 0){

View File

@ -44,6 +44,10 @@
#define ETH_PHY_MDIO 18 #define ETH_PHY_MDIO 18
#endif #endif
#ifndef ETH_CLK_MODE
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN
#endif
typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_MAX } eth_phy_type_t; typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_MAX } eth_phy_type_t;
class ETHClass { class ETHClass {
@ -56,7 +60,7 @@ class ETHClass {
ETHClass(); ETHClass();
~ETHClass(); ~ETHClass();
bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, eth_phy_type_t type=ETH_PHY_TYPE); bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE);
// NOT WORKING YET! // NOT WORKING YET!
//bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000); //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000);