Skip to content

Commit

Permalink
Merge branch 'bugfix/eth_error' into 'master'
Browse files Browse the repository at this point in the history
fix: modift ETH to used on latest AT version

See merge request application/esp-at!406
  • Loading branch information
xcguang committed Feb 28, 2020
2 parents 12f44a5 + a577c79 commit e4606e0
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 232 deletions.
86 changes: 7 additions & 79 deletions docs/ESP32_AT_Ethernet.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,87 +2,15 @@
Initialises the Ethernet interface and enables it, then sends DHCP requests and tries to obtain a DHCP lease. If successful then you will be able to ping the device.

# PHY Configuration
Use `make menuconfig` to set the PHY model and the PHY address, and configure the SMI I/O pins (see below). These configuration items will vary depending on the hardware configuration you are using.
Use `make menuconfig` to set the PHY model. These configuration items will vary depending on the hardware configuration you are using.

The default configuration is correct for Espressif's Ethernet board with TLK110 PHY. Other hardware will require different configuration and/or changes to the default.

## PHY Address
The PHY 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
* Address 1 for the common Waveshare LAN8720 PHY breakout
* Address 0 for other LAN8720 breakouts

If the PHY address is incorrect then the EMAC will initialise, but all attempts to read/write configuration registers on the PHY will fail.

## PHY Clock Wiring
The ESP32 and the Ethernet PHY need a common 50MHz reference clock. This clock can either be be provided externally by a crystal oscillator (e.g. crystal connected to the PHY or a seperate crystal oscillator) or internally by using the EPS32's APLL.

Because of its freqency the signal integrity has to be observed (ringing, capacitive load, resisitive load, skew, length of PCB trace). It is recommended to add a 33Ω resistor in series to reduce ringing.

Possible configurations of the 50MHz clock signal:

| 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. Signal quality might be an issue. |
| internal | `GPIO16` | `EMAC_CLK_OUT` | Output of 50MHz APLL clock. |
| internal | `GPIO17` | `EMAC_CLK_180` | Inverted output of 50MHz APLL clock. Found to be best suitable for LAN8720 with long signal lines. |


#### External PHY Clock
The external reference clock of 50MHz must be supplied on `GPIO0`. See note about `GPIO0` below.

#### Internal PHY Clock
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) external PHY has to be used.

On different test setups clock output on `GPIO0` was found unstable because in most designs the signal path is not ideal for this high frequency (the PCB trace has several devices added to it and therefore the capacitive load is relatively high)

The inverted clock signal `EMAC_CLK_180` was found working best with a LAN8720 PHY.

## RMII PHY Wiring
The following PHY connections are required for RMII PHY data connections. These `GPIO` pin assignments cannot be changed.

| GPIO | RMII Signal | ESP32 EMAC Function | Notes |
| -------- | ----------- | ------------------- | ----- |
| `GPIO21` | `TX_EN` | `EMAC_TX_EN` | |
| `GPIO19` | `TX0` | `EMAC_TXD0` | |
| `GPIO22` | `TX1` | `EMAC_TXD1` | |
| `GPIO25` | `RX0` | `EMAC_RXD0` | |
| `GPIO26` | `RX1` | `EMAC_RXD1` | |
| `GPIO27` | `CRS_DV` | `EMAC_RX_DRV` | |

## RMII PHY SMI Wiring

The following PHY connections are required for RMII PHY SMI (aka MDIO) management interface. These GPIO pin assignments can be changed to any unused GPIO pin.

For the AT, these pins are configured via `make menuconfig` under the configuration.

| Default GPIO | RMII Signal | Notes |
| -------------------- | ----------- | ------------- |
| `GPIO23` | `MDC` | Output to PHY |
| `GPIO18` | `MDIO` | Bidirectional |

The defaults in the menuconfig are correct for Espressif's Ethernet development board.

## Note about `GPIO0`

Because `GPIO0` is a strapping pin for entering UART flashing mode on reset, care must be taken when also 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 source code to see how the "power pin" GPIO can be managed in software.

The defaults is 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.
The default configuration is correct for Espressif's Ethernet board with TP101 PHY. ESP32 AT supports up to four Ethernet PHY: `LAN8720`, `IP101`, `DP83848` and `RTL8201`.
`TLK110` PHY is no longer supported because TI stoped production.
If you want to use other phy, follow the [document](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html) to design.

## Compiling

1. `make menuconfig` -> `Serial flasher config` to configure the serial port for downloading.
2. `make menuconfig` -> `Component config` -> `AT` -> `AT ethernet support` to enable ethernet.
3. Due to both the `TXD` of `UART1` and `power pin` of ethernet are `GPIO17` in the esp-at project by default, which causes pin conflicts, you have to change `uart_tx_pin` and `uart_rx_pin` to other pins referring to [How_To_Set_AT_Port_Pin.md](How_To_Set_AT_Port_Pin.md), for example, changes as following in `esp-at/components/customized_partitions/raw_data/factory_param/factory_param_data.csv`.

| platform | module_name | magic_flag | ... | uart_baudrate | uart\_tx_pin | uart\_rx_pin | uart\_ctx_pin | uart\_rts_pin |...
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
PLATFORM_ESP32 | WROOM-32| 0xfcfc |...|115200|1|3|15|14|...

4. Recompile the `esp-at` project, download the new `factory_param.bin` and AT bin into flash.
2. `make menuconfig` -> `Component config` -> `AT` -> `AT ethernet support` to enable ethernet.
3. `make menuconfig` -> `Component config` -> `AT` -> `Ethernet PHY` to choose ethernet.
4. Recompile the `esp-at` project, download AT bin into flash.
94 changes: 14 additions & 80 deletions main/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -170,103 +170,37 @@ config AT_ETHERNET_SUPPORT
default "n"
depends on AT_ENABLE
help
Please pay attention to the conflict of the pin. You can refer to the ESP32_AT_Ethernet.md and get more details.
Please pay attention to the usage. You can refer to the ESP32_AT_Ethernet.md and get more details.

choice PHY_MODEL
prompt "Ethernet PHY"
default CONFIG_PHY_TLK110
default CONFIG_PHY_IP101
depends on AT_ETHERNET_SUPPORT
help
Select the PHY driver to use for ESP32 AT.

config PHY_TLK110
bool "TI TLK110 PHY"
config PHY_IP101
bool "IP101 PHY"
help
Select this to use the TI TLK110 PHY
Select this to use the IP101 PHY

config PHY_LAN8720
bool "Microchip LAN8720 PHY"
help
Select this to use the Microchip LAN8720 PHY

endchoice

config PHY_ADDRESS
int "PHY Address (0-31)"
default 31
range 0 31
depends on AT_ETHERNET_SUPPORT
help
Select the PHY Address (0-31) for the hardware configuration and PHY model.

choice PHY_CLOCK_MODE
prompt "EMAC clock mode"
default PHY_CLOCK_GPIO0_IN
depends on AT_ETHERNET_SUPPORT
help
Select external (input on GPIO0) or internal (output on GPIO0, GPIO16 or GPIO17) clock


config PHY_CLOCK_GPIO0_IN
bool "GPIO0 input"
help
Input of 50MHz refclock on GPIO0

config PHY_CLOCK_GPIO0_OUT
bool "GPIO0 output"
config PHY_RTL8201
bool "RTL8201 PHY"
help
Output the internal 50MHz APLL clock on GPIO0
Select this to use the RTL8201 PHY

config PHY_CLOCK_GPIO16_OUT
bool "GPIO16 output"
config PHY_DP83848
bool "DP83848 PHY"
help
Output the internal 50MHz APLL clock on GPIO16
Select this to use the DP83848 PHY

config PHY_CLOCK_GPIO17_OUT
bool "GPIO17 output (inverted)"
config PHY_LAN8720
bool "Microchip LAN8720 PHY"
help
Output the internal 50MHz APLL clock on GPIO17 (inverted signal)
Select this to use the Microchip LAN8720 PHY

endchoice

config PHY_CLOCK_MODE
int
default 0 if PHY_CLOCK_GPIO0_IN
default 1 if PHY_CLOCK_GPIO0_OUT
default 2 if PHY_CLOCK_GPIO16_OUT
default 3 if PHY_CLOCK_GPIO17_OUT
depends on AT_ETHERNET_SUPPORT

config PHY_USE_POWER_PIN
bool "Use PHY Power (enable/disable) pin"
default y
depends on AT_ETHERNET_SUPPORT
help
Use a GPIO "power pin" to power the PHY on/off during operation.

config PHY_POWER_PIN
int "PHY Power GPIO"
default 17
range 0 33
depends on PHY_USE_POWER_PIN
help
GPIO number to use for powering on/off the PHY.

config PHY_SMI_MDC_PIN
int "SMI MDC Pin"
default 23
range 0 33
depends on AT_ETHERNET_SUPPORT
help
GPIO number to use for SMI clock output MDC to PHY.

config PHY_SMI_MDIO_PIN
int "SMI MDIO Pin"
default 18
depends on AT_ETHERNET_SUPPORT
range 0 33
help
GPIO number to use for SMI data pin MDIO to/from PHY.
endif

config AT_EAP_COMMAND_SUPPORT
Expand Down
91 changes: 18 additions & 73 deletions main/at_eth_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,86 +24,31 @@
#include "tcpip_adapter.h"

#ifdef CONFIG_AT_ETHERNET_SUPPORT

#ifdef CONFIG_PHY_LAN8720
#include "eth_phy/phy_lan8720.h"
#define DEFAULT_ETHERNET_PHY_CONFIG phy_lan8720_default_ethernet_config
#endif
#ifdef CONFIG_PHY_TLK110
#include "eth_phy/phy_tlk110.h"
#define DEFAULT_ETHERNET_PHY_CONFIG phy_tlk110_default_ethernet_config
#endif

#define PIN_PHY_POWER CONFIG_PHY_POWER_PIN
#define PIN_SMI_MDC CONFIG_PHY_SMI_MDC_PIN
#define PIN_SMI_MDIO CONFIG_PHY_SMI_MDIO_PIN

#ifdef CONFIG_PHY_USE_POWER_PIN
/* This replaces the default PHY power on/off function with one that
also uses a GPIO for power on/off.
If this GPIO is not connected on your device (and PHY is always powered), you can use the default PHY-specific power
on/off function rather than overriding with this one.
*/
static void phy_device_power_enable_via_gpio(bool enable)
{
assert(DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable);

if (!enable) {
/* Do the PHY-specific power_enable(false) function before powering down */
DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(false);
}

gpio_pad_select_gpio(PIN_PHY_POWER);
gpio_set_direction(PIN_PHY_POWER,GPIO_MODE_OUTPUT);
if(enable == true) {
gpio_set_level(PIN_PHY_POWER, 1);
printf("phy_device_power_enable(TRUE)");
} else {
gpio_set_level(PIN_PHY_POWER, 0);
printf("power_enable(FALSE)");
}

// Allow the power up/down to take effect, min 300us
vTaskDelay(1);

if (enable) {
/* Run the PHY-specific power on operations now the PHY has power */
DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(true);
}
}
#endif

static void eth_gpio_config_rmii(void)
{
phy_rmii_configure_data_interface_pins();
phy_rmii_smi_configure_pins(PIN_SMI_MDC, PIN_SMI_MDIO);
}
#include "esp_eth.h"

bool at_eth_init(void)
{
esp_err_t ret = ESP_OK;
eth_config_t config = DEFAULT_ETHERNET_PHY_CONFIG;
/* Set the PHY address in the configuration */
config.phy_addr = CONFIG_PHY_ADDRESS;
config.gpio_config = eth_gpio_config_rmii;
config.tcpip_input = tcpip_adapter_eth_input;
config.clock_mode = CONFIG_PHY_CLOCK_MODE;

#ifdef CONFIG_PHY_USE_POWER_PIN
/* Replace the default 'power enable' function with an specific
one that toggles a power GPIO. */
config.phy_power_enable = phy_device_power_enable_via_gpio;
ESP_ERROR_CHECK(tcpip_adapter_set_default_eth_handlers());

eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
#if CONFIG_PHY_IP101
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
#elif CONFIG_PHY_RTL8201
esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
#elif CONFIG_PHY_LAN8720
esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config);
#elif CONFIG_PHY_DP83848
esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
#endif

ret = esp_eth_init(&config);

if(ret == ESP_OK) {
esp_eth_enable();
return true;
}
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
esp_eth_handle_t eth_handle = NULL;
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &eth_handle));

return false;
return true;
}
#endif

0 comments on commit e4606e0

Please sign in to comment.