esp_event: fix bug in set_default_eth_handler

This commit is contained in:
suda-morris 2019-05-30 12:55:09 +08:00
parent b68f5b4f8c
commit c187f1ef6b
4 changed files with 85 additions and 89 deletions

View file

@ -19,7 +19,7 @@
/* mesh event callback handler */
mesh_event_cb_t g_mesh_event_cb = NULL;
void esp_event_mesh_hook(system_event_t* event)
esp_err_t esp_event_mesh_hook(system_event_t *event)
{
if (event->event_id == SYSTEM_EVENT_STA_GOT_IP || event->event_id == SYSTEM_EVENT_STA_LOST_IP) {
if (g_mesh_event_cb) {
@ -33,4 +33,5 @@ void esp_event_mesh_hook(system_event_t* event)
g_mesh_event_cb(mevent);
}
}
return ESP_OK;
}

View file

@ -21,7 +21,7 @@
#include "esp_err.h"
#include "esp_log.h"
static const char* TAG = "tcpip_adapter";
static const char *TAG = "tcpip_adapter";
#define API_CALL_CHECK(info, api_call, ret) \
do{\
@ -34,21 +34,21 @@ do{\
typedef esp_err_t (*system_event_handler_t)(system_event_t *e);
static void handle_ap_start(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_ap_stop(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_sta_start(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_sta_stop(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_sta_connected(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_sta_disconnected(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_sta_got_ip(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_ap_start(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_ap_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_sta_start(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_sta_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_sta_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_sta_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_eth_start(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_eth_stop(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_eth_connected(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_eth_disconnected(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_eth_got_ip(void* arg, esp_event_base_t base, int32_t event_id, void* data);
static void handle_eth_start(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_eth_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_eth_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_eth_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_eth_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_eth_start(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_eth_start(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_ip_info_t eth_ip;
uint8_t eth_mac[6];
@ -58,12 +58,12 @@ static void handle_eth_start(void* arg, esp_event_base_t base, int32_t event_id,
tcpip_adapter_eth_start(eth_mac, &eth_ip);
}
static void handle_eth_stop(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_eth_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_stop(TCPIP_ADAPTER_IF_ETH);
}
static void handle_eth_connected(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_eth_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_dhcp_status_t status;
@ -92,32 +92,32 @@ static void handle_eth_connected(void* arg, esp_event_base_t base, int32_t event
}
}
static void handle_eth_disconnected(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_eth_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_down(TCPIP_ADAPTER_IF_ETH);
}
static void handle_sta_got_ip(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
API_CALL_CHECK("esp_wifi_internal_set_sta_ip", esp_wifi_internal_set_sta_ip(), ESP_OK);
const ip_event_got_ip_t* event= (const ip_event_got_ip_t*) data;
const ip_event_got_ip_t *event = (const ip_event_got_ip_t *) data;
ESP_LOGI(TAG, "sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
IP2STR(&event->ip_info.ip),
IP2STR(&event->ip_info.netmask),
IP2STR(&event->ip_info.gw));
IP2STR(&event->ip_info.ip),
IP2STR(&event->ip_info.netmask),
IP2STR(&event->ip_info.gw));
}
static void handle_eth_got_ip(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_eth_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
const ip_event_got_ip_t* event= (const ip_event_got_ip_t*) data;
const ip_event_got_ip_t *event = (const ip_event_got_ip_t *) data;
ESP_LOGI(TAG, "eth ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
IP2STR(&event->ip_info.ip),
IP2STR(&event->ip_info.netmask),
IP2STR(&event->ip_info.gw));
IP2STR(&event->ip_info.ip),
IP2STR(&event->ip_info.netmask),
IP2STR(&event->ip_info.gw));
}
static void handle_ap_start(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_ap_start(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_ip_info_t ap_ip;
uint8_t ap_mac[6];
@ -129,14 +129,14 @@ static void handle_ap_start(void* arg, esp_event_base_t base, int32_t event_id,
tcpip_adapter_ap_start(ap_mac, &ap_ip);
}
static void handle_ap_stop(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_ap_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, NULL), ESP_OK);
tcpip_adapter_stop(TCPIP_ADAPTER_IF_AP);
}
static void handle_sta_start(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_sta_start(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_ip_info_t sta_ip;
uint8_t sta_mac[6];
@ -146,12 +146,12 @@ static void handle_sta_start(void* arg, esp_event_base_t base, int32_t event_id,
tcpip_adapter_sta_start(sta_mac, &sta_ip);
}
static void handle_sta_stop(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_sta_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_stop(TCPIP_ADAPTER_IF_STA);
}
static void handle_sta_connected(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_sta_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_dhcp_status_t status;
@ -191,7 +191,7 @@ static void handle_sta_connected(void* arg, esp_event_base_t base, int32_t event
}
}
static void handle_sta_disconnected(void* arg, esp_event_base_t base, int32_t event_id, void* data)
static void handle_sta_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
tcpip_adapter_down(TCPIP_ADAPTER_IF_STA);
API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, NULL), ESP_OK);
@ -236,11 +236,6 @@ esp_err_t tcpip_adapter_set_default_wifi_handlers()
goto fail;
}
err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, handle_eth_got_ip, NULL);
if (err != ESP_OK) {
goto fail;
}
err = esp_register_shutdown_handler((shutdown_handler_t)esp_wifi_stop);
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
goto fail;
@ -262,7 +257,6 @@ esp_err_t tcpip_adapter_clear_default_wifi_handlers()
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_AP_START, handle_ap_start);
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_AP_STOP, handle_ap_stop);
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, handle_sta_got_ip);
esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, handle_eth_got_ip);
esp_unregister_shutdown_handler((shutdown_handler_t)esp_wifi_stop);
return ESP_OK;
@ -291,6 +285,11 @@ esp_err_t tcpip_adapter_set_default_eth_handlers()
goto fail;
}
err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, handle_eth_got_ip, NULL);
if (err != ESP_OK) {
goto fail;
}
return ESP_OK;
fail:
@ -304,6 +303,6 @@ esp_err_t tcpip_adapter_clear_default_eth_handlers()
esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, handle_eth_stop);
esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, handle_eth_connected);
esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, handle_eth_disconnected);
esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, handle_eth_got_ip);
return ESP_OK;
}

View file

@ -3,50 +3,49 @@
## Overview
This example demonstrates basic usage of `Ethernet driver` together with `tcpip_adapter`. The work flow of the example could be as follow:
This example demonstrates basic usage of `Ethernet driver` together with `tcpip_adapter`. The work flow of the example could be as follows:
1. Initialises the Ethernet interface and enables it
2. Send DHCP requests and tries to obtain a DHCP lease
3. If successful then you will be able to ping the device
1. Initialize the Ethernet interface and enable it
2. Send DHCP requests and wait for a DHCP lease
3. If get IP address successfully, then you will be able to ping the device
If you have a new Ethernet applicaion to go (for example, connect to IoT cloud via Ethernet), try this as a basic template, then add your own code.
If you have a new Ethernet application to go (for example, connect to IoT cloud via Ethernet), try this as a basic template, then add your own code.
## How to use example
### Hardware Required
To run this example, you should have one ESP32 dev board integrated with an Ethernet interface, or just connect your ESP32 core board to a breakout board which featured in RMII Etherent PHY. Currently esp-idf officially support only two Ethernet PHY: `TLK110` from Texas Instruments and `LAN8720` from microchip.
To run this example, you should have one ESP32 dev board integrated with an Ethernet interface, or just connect your ESP32 core board to a breakout board which featured with RMII Ethernet PHY. **Currently ESP-IDF officially supports three Ethernet PHY: `TLK110`, `LAN8720` and `IP101`, additional PHY drivers can be implemented by users themselves.**
### Configure the project
Enter `make menuconfig` if you are using GNU Make based build system or enter `idf.py menuconfig` if you' are using CMake based build system. Then go into `Example Configuration` menu.
* Choose PHY device under `Ethernet PHY option` option
* Choose PHY device under `Ethernet PHY Device` option
* Set PHY address under `PHY address` option, this address depends on the hardware and the PHY configuration. Consult the documentation/datasheet for the PHY hardware you have.
* Address 31 (default) for Espressif's Ethernet board with TLK110 PHY by default
* Address 1 for the common Waveshare LAN8720 PHY breakout
* Address 0 for other LAN8720 breakouts
* Set PHY address under `Ethernet PHY address` option, this address depends on the hardware and the PHY configuration. Consult the documentation/datasheet for the PHY hardware you have.
* Address 1 for the common Waveshare LAN8720 PHY breakout and the official ESP32-Ethernet-Kit board
* Check whether or not to control PHY's power (if true, you need also to set PHY Power GPIO number later)
* Check whether or not to control PHY's power under `Use PHY Power (enable / disable) pin` option, (if set true, you also need to set PHY Power GPIO number under `PHY Power GPIO` option)
* Set SMI MDC/MDIO GPIO number according to board schemetic, default these two GPIOs are set as below:
* Set SMI MDC/MDIO GPIO number according to board schematic, default these two GPIOs are set as below:
| Default Example GPIO | RMII Signal | Notes |
| -------------------- | ----------- | ------------- |
| GPIO23 | MDC | Output to PHY |
| GPIO18 | MDIO | Bidirectional |
* Select one kind of EMAC clock mode under `EMAC clock mode` option. Possible configurations of the clock are listed as below:
* Select one kind of EMAC clock mode under `Ethernet PHY Clock Mode` option. Possible configurations of the clock are listed as below:
| Mode | GPIO Pin | Signal name | Notes |
| -------- | -------- | ------------ | ------------------------------------------------------------ |
| external | GPIO0 | EMAC_TX_CLK | Input of 50MHz PHY clock |
| internal | GPIO0 | CLK_OUT1 | Output of 50MHz APLL clock |
| internal | GPIO16 | EMAC_CLK_OUT | Output of 50MHz APLL clock |
| internal | GPIO17 | EMAC_CLK_180 | Inverted output of 50MHz APLL clock (suitable for long clock trace) |
* The external reference clock of 50MHz must be supplied on `GPIO0`.
* The ESP32 can generate a 50MHz clock using its APLL. When the APLL is already used as clock source for other purposes (most likely I²S), you have no choice but choose external clock.
* The ESP32 can generate a 50MHz clock using internal APLL. When the APLL is already used as clock source for other purposes (most likely I²S), you have no choice but choose external clock.
### Build and Flash
@ -60,36 +59,35 @@ See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/l
```bash
I (0) cpu_start: App cpu up.
I (281) heap_init: Initializing. RAM available for dynamic allocation:
I (288) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (294) heap_init: At 3FFB4358 len 0002BCA8 (175 KiB): DRAM
I (300) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (307) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (313) heap_init: At 4008966C len 00016994 (90 KiB): IRAM
I (319) cpu_start: Pro cpu start user code
I (113) cpu_start: Starting scheduler on PRO CPU.
I (265) heap_init: Initializing. RAM available for dynamic allocation:
I (272) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (278) heap_init: At 3FFB3FF0 len 0002C010 (176 KiB): DRAM
I (284) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (291) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (297) heap_init: At 4008851C len 00017AE4 (94 KiB): IRAM
I (303) cpu_start: Pro cpu start user code
I (322) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (116) eth_example: Power On Ethernet PHY
I (126) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (126) emac: emac reset done
I (126) eth_example: Ethernet Started
I (2126) eth_example: Ethernet Link Up
I (11616) event: eth ip: 192.168.2.156, mask: 255.255.255.0, gw: 192.168.2.2
I (11616) eth_example: Ethernet Got IP Addr
I (11616) eth_example: ~~~~~~~~~~~
I (11616) eth_example: ETHIP:192.168.2.156
I (11626) eth_example: ETHMASK:255.255.255.0
I (11626) eth_example: ETHGW:192.168.2.2
I (11636) eth_example: ~~~~~~~~~~~
I (325) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (325) emac: emac reset done
I (335) eth_example: Ethernet Started
I (4335) eth_example: Ethernet Link Up
I (6325) tcpip_adapter: eth ip: 192.168.2.164, mask: 255.255.255.0, gw: 192.168.2.2
I (6325) eth_example: Ethernet Got IP Address
I (6325) eth_example: ~~~~~~~~~~~
I (6325) eth_example: ETHIP:192.168.2.164
I (6335) eth_example: ETHMASK:255.255.255.0
I (6335) eth_example: ETHGW:192.168.2.2
I (6345) eth_example: ~~~~~~~~~~~
```
## Troubleshooting
* If the PHY address is incorrect then the EMAC will still be initialised, but all attempts to read/write configuration registers in the PHY's register will fail, for example, waiting for auto-negotiation done.
* If the PHY address is incorrect then the EMAC will still be initialized, but all attempts to read/write configuration registers in the PHY's register will fail, for example, waiting for auto-negotiation done.
* Check PHY Clock
> The ESP32's MAC and the External PHY device need a common 50MHz reference clock. This clock can either be provided externally by a crystal oscillator (e.g. crystal connected to the PHY or a seperate crystal oscillator) or internally by generating from EPS32's APLL. The signal integrity of this clock is strict, so it is highly recommended to add a 33Ω resistor in series to reduce ringing.
> The ESP32's MAC and the External PHY device need a common 50MHz reference clock. This clock can either be provided externally by a crystal oscillator (e.g. crystal connected to the PHY or a separate crystal oscillator) or internally by generating from EPS32's APLL. The signal integrity of this clock is strict, so it is highly recommended to add a 33Ω resistor in series to reduce ringing.
* Check GPIO connections, the RMII PHY wiring is fixed which can not be changed through either IOMUX or GPIO Matrix. They're described as below:
@ -104,5 +102,5 @@ I (11636) eth_example: ~~~~~~~~~~~
* Check GPIO0
> GPIO0 is a strapping pin for entering UART flashing mode on reset, care must be taken when using this pin as `EMAC_TX_CLK`. If the clock output from the PHY is oscillating during reset, the ESP32 may randomly enter UART flashing mode. One solution is to use an additional GPIO as a "power pin", which either powers the PHY on/off or enables/disables the PHY's own oscillator. This prevents the clock signal from being active during a system reset. For this configuration to work, `GPIO0` also needs a pullup resistor and the "power pin" GPIO will need a pullup/pulldown resistor - as appropriate in order to keep the PHY clock disabled when the ESP32 is in reset. See the example source code to see how the "power pin" GPIO can be managed in software. The example defaults to using `GPIO17` for this function, but it can be overriden. On Espressif's Ethernet development board, `GPIO17` is the power pin used to enable/disable the PHY oscillator.
> GPIO0 is a strapping pin for entering UART flashing mode on reset, care must be taken when using this pin as `EMAC_TX_CLK`. If the clock output from the PHY is oscillating during reset, the ESP32 may randomly enter UART flashing mode. One solution is to use an additional GPIO as a "power pin", which either powers the PHY on/off or enables/disables the PHY's own oscillator. This prevents the clock signal from being active during a system reset. For this configuration to work, `GPIO0` also needs a pullup resistor and the "power pin" GPIO will need a pullup/pulldown resistor - as appropriate in order to keep the PHY clock disabled when the ESP32 is in reset. See the example source code to see how the "power pin" GPIO can be managed in software.

View file

@ -16,7 +16,7 @@ This example is based on esp-idf's console component. For more information about
* Debian/Ubuntu: `sudo apt-get install iperf`
* macOS: `brew install iperf`(if using Homebrew) or `sudo port install iperf`(if using MacPorts)
* Windows(MSYS2): Downloads binaries from [here]( https://iperf.fr/iperf-download.php#windows)
2. Initialise Ethernet on ESP32, run `ethernet start`
2. Initialize Ethernet on ESP32, run `ethernet start`
3. Get ip information(optional), run `ethernet info`
### Configure the project
@ -25,15 +25,12 @@ Enter `make menuconfig` if you are using GNU Make based build system or enter `i
* Check whether or not to store the history command into flash under `Store command history in flash` option
* Set PHY address under `PHY address` option, this address depends on the hardware and the PHY configuration. Consult the documentation/datasheet for the PHY hardware you have.
- Address 31 (default) for Espressif's Ethernet board with TLK110 PHY by default
- Address 1 for the common Waveshare LAN8720 PHY breakout
- Address 0 for other LAN8720 breakouts
* Set PHY address under `Ethernet PHY address` option, this address depends on the hardware and the PHY configuration. Consult the documentation/datasheet for the PHY hardware you have.
- Address 1 for the common Waveshare LAN8720 PHY breakout and official ESP32-Ethernet-Kit board
* Check whether or not to control PHY's power (if true, you need also to set PHY Power GPIO number later)
* Set SMI MDC/MDIO GPIO number according to board schemetic, default these two GPIOs are set as below:
* Set SMI MDC/MDIO GPIO number according to board schematic, default these two GPIOs are set as below:
| Default Example GPIO | RMII Signal | Notes |
| -------------------- | ----------- | ------------- |
@ -45,6 +42,7 @@ Enter `make menuconfig` if you are using GNU Make based build system or enter `i
| Mode | GPIO Pin | Signal name | Notes |
| -------- | -------- | ------------ | ------------------------------------------------------------ |
| external | GPIO0 | EMAC_TX_CLK | Input of 50MHz PHY clock |
| internal | GPIO0 | CLK_OUT1 | Output of 50MHz APLL clock |
| internal | GPIO16 | EMAC_CLK_OUT | Output of 50MHz APLL clock |
| internal | GPIO17 | EMAC_CLK_180 | Inverted output of 50MHz APLL clock (suitable for long clock trace) |
@ -154,11 +152,11 @@ I (2534456) iperf: want recv=16384
## Troubleshooting
- If the PHY address is incorrect then the EMAC will still be initialised, but all attempts to read/write configuration registers in the PHY's register will fail, for example, waiting for auto-negotiation done.
- If the PHY address is incorrect then the EMAC will still be initialized, but all attempts to read/write configuration registers in the PHY's register will fail, for example, waiting for auto-negotiation done.
- Check PHY Clock
> The ESP32's MAC and the External PHY device need a common 50MHz reference clock. This clock can either be provided externally by a crystal oscillator (e.g. crystal connected to the PHY or a seperate crystal oscillator) or internally by generating from EPS32's APLL. The signal integrity of this clock is strict, so it is highly recommended to add a 33Ω resistor in series to reduce ringing.
> The ESP32's MAC and the External PHY device need a common 50MHz reference clock. This clock can either be provided externally by a crystal oscillator (e.g. crystal connected to the PHY or a separate crystal oscillator) or internally by generating from EPS32's APLL. The signal integrity of this clock is strict, so it is highly recommended to add a 33Ω resistor in series to reduce ringing.
- Check GPIO connections, the RMII PHY wiring is fixed which can not be changed through either IOMUX or GPIO Matrix. They're described as below:
@ -173,4 +171,4 @@ I (2534456) iperf: want recv=16384
- Check GPIO0
> GPIO0 is a strapping pin for entering UART flashing mode on reset, care must be taken when using this pin as `EMAC_TX_CLK`. If the clock output from the PHY is oscillating during reset, the ESP32 may randomly enter UART flashing mode. One solution is to use an additional GPIO as a "power pin", which either powers the PHY on/off or enables/disables the PHY's own oscillator. This prevents the clock signal from being active during a system reset. For this configuration to work, `GPIO0` also needs a pullup resistor and the "power pin" GPIO will need a pullup/pulldown resistor - as appropriate in order to keep the PHY clock disabled when the ESP32 is in reset. See the example source code to see how the "power pin" GPIO can be managed in software. The example defaults to using `GPIO17` for this function, but it can be overriden. On Espressif's Ethernet development board, `GPIO17` is the power pin used to enable/disable the PHY oscillator.
> GPIO0 is a strapping pin for entering UART flashing mode on reset, care must be taken when using this pin as `EMAC_TX_CLK`. If the clock output from the PHY is oscillating during reset, the ESP32 may randomly enter UART flashing mode. One solution is to use an additional GPIO as a "power pin", which either powers the PHY on/off or enables/disables the PHY's own oscillator. This prevents the clock signal from being active during a system reset. For this configuration to work, `GPIO0` also needs a pullup resistor and the "power pin" GPIO will need a pullup/pulldown resistor - as appropriate in order to keep the PHY clock disabled when the ESP32 is in reset. See the example source code to see how the "power pin" GPIO can be managed in software.