diff --git a/docs/source/Hardware/Hardware.rst b/docs/source/Hardware/Hardware.rst index 231c69d61f..8887e3cabd 100644 --- a/docs/source/Hardware/Hardware.rst +++ b/docs/source/Hardware/Hardware.rst @@ -3,8 +3,6 @@ Hardware page ************* -Overview -======== ESPEasy has some centralized hardware configuration settings, shown in this page, and divided in sections. @@ -203,13 +201,34 @@ To activate a new configuration, a reboot is needed. Ethernet PHY type ^^^^^^^^^^^^^^^^^ -Select the used PHY controller type: +ESP boards can be equiped with Ethernet. +This is more stable and reliable compared to WiFi and allows for better responsiveness. -* LAN8710 (LAN8720 is also supported, but none of the newer features are supported) -* TLK110 -* RTL8201 (since ESP32 IDF 4.4) -* DP83848 (since ESP32 IDF 4.4) -* DM9051 (since ESP32 IDF 4.4) +Actual transfer speed (at least when using RMII) is also higher than can be achieved via WiFi, but this is less of a concern for typical use cases where ESPEasy is used. + +Ethernet chips/boards for ESP32-variant boards exist with 2 types of interfaces to the ESP. + +* RMII interface - Faster actual transfer speeds possible, uses more GPIO pins, only supported on ESP32-classic (and upcoming ESP32-P4). +* SPI interface - (Added: 2024/02) Supported on all ESP32-variants (not all tested) on builds based on ESP-IDF 5.1 + SPI Ethernet adapters do obviously require the SPI interface to be configured. + +N.B. Only ESP32-variant builds with LittleFS support SPI Ethernet. (starting February 2024) + +Supported Ethernet chips: + +* RMII Interface: + * LAN8710 (LAN8720 is also supported, but none of the newer features are supported) + * TLK110 + * RTL8201 (since ESP32 IDF 4.4) + * JL1101 (since ESP32 IDF 4.4) + * DP83848 (since ESP32 IDF 4.4) + * KSZ8041 (since ESP32 IDF 4.4) + * KSZ8081 (since ESP32 IDF 4.4) + +* SPI Interface: (since ESP32 IDF 5.1) + * DM9051 + * W5500 + * KSZ8851 .. note:: The LAN8710 and LAN8720 are also available with an "A" suffix. These are the same chips, only produced after the brand SMSC was taken over by Microchip Technology. @@ -219,19 +238,22 @@ Ethernet PHY Address The PHY address depends on the hardware and the PHY configuration. On some chips, like the LAN8720, the board designer may set this address by pulling some pins either high or low at power on. -In theory, one could use multiple PHY adapters on the same RMII bus, but this is not supported by ESPEasy. +In theory, one could use multiple PHY adapters on the same RMII/SPI bus, but this is (currently) not supported by ESPEasy. * Espressif's Ethernet board with TLK110 PHY use PHY address 31. * Common Waveshare LAN8720 PHY breakout board (and clones) use PHY address 1. * Olimex ESP32 EVB REV B IoT LAN8710 PHY Board with CAN use PHY address 0. * Other LAN8720 breakouts often use PHY address 0. +* ETH01-EVO (ESP32-C3 based board) uses PHY address 1. If the PHY address is incorrect then the EMAC will initialise but all attempts to read/write configuration registers on the PHY will fail. N.B. There is support for an auto detect of this PHY address, by setting it to -1, but at least on the LAN8720 this does not seem to work. -GPIO pins -^^^^^^^^^ +RMII Ethernet +^^^^^^^^^^^^^ + +As mentioned above, the RMII interface is only present on ESP32-classic (and is mentioned on the announced ESP32-P4). RMII PHY SMI Wiring """"""""""""""""""" @@ -281,7 +303,41 @@ Apart from these GPIO pins, there is a number of other pins reserved on the ESP3 Since these GPIO pin assignments cannot be changed, it is also not needed to configure them. However, they also cannot be used when *RMII PHY* is used. -.. include:: ../Reference/Ethernet_PHY_ESP32.rst +.. include:: ../Reference/RMII_Ethernet_PHY_ESP32.rst + +RMII Ethernet ESP32 Boards +"""""""""""""""""""""""""" + +.. include:: ../Reference/RMII_Ethernet_ESP32_boards.rst + + +SPI Ethernet +^^^^^^^^^^^^ + +(Added: 2024/02) + +As mentioned above, these SPI based Ethernet interfaces require the SPI interface to be configured. + +The SPI bus can be shared, but the SPI Ethernet chips are a bit specific about the used frequency. +Currently the default SPI frequency of 20 MHz is used, so not all other SPI devices may work together with SPI Ethernet. + +Some boards like the ETH01-EVO (ESP32-C3 based) do not even have the SPI bus pins made accesible. + + +GPIO Configuration +"""""""""""""""""" + +* CS pin: Just as any SPI device, it needs a CS pin to tell the device it is being addressed. +* IRQ/INT pin: Allows the Ethernet chip to signal the ESP about new data. (Optional for W5500) +* RST pin: ESP will try to reset the Ethernet adapter during boot. Not all boards may have this wired. + + +SPI Ethernet ESP32 Boards +""""""""""""""""""""""""" + +.. include:: ../Reference/SPI_Ethernet_ESP32_boards.rst + + Ethernet with PoE ^^^^^^^^^^^^^^^^^ @@ -291,13 +347,33 @@ Some ethernet boards support Power over Ethernet (PoE), so only a single (ethern For Olimex boards in the ESP32-POE range, the supplier has documented this warning: .. warning:: - **Important notice**: Olimex ESP32-PoE has **no galvano isolation** from Ethernet's power supply, when you program the board via the micro USB connector the Ethernet cable should be disconnected (if you have power over the Ethernet cable)! + **Important notice**: Olimex ESP32-PoE has **no galvanic isolation** from Ethernet's power supply, when you program the board via the micro USB connector the Ethernet cable should be disconnected (if you have power over the Ethernet cable)! Consider using Olimex USB-ISO to protect your computer and board from accidental short circuit. Also consider instead using Olimex ESP32-PoE-ISO board, which *is* insulated. Most likely, this warning is applicable to other brands as well. +Ethernet Isolation +^^^^^^^^^^^^^^^^^^ + +Most Ethernet RJ45 phy (the connector on the PCB) have isolation transformers in them. +This does isolate the TX/RX pins to make sure there is no direct connection between the long cables and the Ethernet controller chip. +The isolation does protect the Ethernet chip from picked up high voltage spikes and ESD surges when inserting the Ethernet cable. +However not all ESP boards with Ethernet have these installed. + +Apart from the isolation of the TX/RX pins the metallic enclosure of the phy should also be isolated from the rest of the circuit of the ESP board. +Typically this is done by connecting the metal enclosure of the phy via a capacitor to GND of the rest of the circuit. +A lot of boards with Ethernet have these directly connected to GND, which may impose a problem when connecting the ESP board to your PC. + +.. warning:: + **Important notice**: For ESP boards with Ethernet which need debugging, never use Ethernet cables with metal shielding on the Ethernet connector. + +Using shielded Ethernet cable will connect the metal shield of the RJ45 phy to the ground of the switch and this may be connected to other appliances which may be badly grounded. +This will add a significant voltage offset between the ESP board and your PC while debugging. +Such a high voltage is very likely to destroy electronics. + + ------------------- GPIO boot states ------------------- diff --git a/docs/source/Reference/GPIO.rst b/docs/source/Reference/GPIO.rst index 76cf1f270f..101d622646 100644 --- a/docs/source/Reference/GPIO.rst +++ b/docs/source/Reference/GPIO.rst @@ -325,7 +325,7 @@ Typical uses in ESPEasy where an interrupt of a GPIO pin is used are: Pins used for RMII Ethernet PHY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. include:: ../Reference/Ethernet_PHY_ESP32.rst +.. include:: ../Reference/RMII_Ethernet_PHY_ESP32.rst Best pins to use on ESP32-C3 diff --git a/docs/source/Reference/RMII_Ethernet_ESP32_boards.rst b/docs/source/Reference/RMII_Ethernet_ESP32_boards.rst new file mode 100644 index 0000000000..48370e4764 --- /dev/null +++ b/docs/source/Reference/RMII_Ethernet_ESP32_boards.rst @@ -0,0 +1,93 @@ + + +There is a number of ESP32 boards available with Ethernet connected via RMII. + +However it is not always clear which configuration should be used. + + +.. warning:: + **Important notice**: It is possible to actually damage the Ethernet chip when a wrong configuration is used. + +.. list-table:: RMII PHY Boards + :widths: 30 15 10 10 10 20 30 + :header-rows: 1 + + * - Board + - Ethernet Chip + - Addr + - MDC + - MDIO + - Power/RST + - Clock + * - Olimex ESP32 PoE + - LAN8720 + - 0 + - 23 + - 18 + - 12 + - 50MHz Inv Output GPIO17 + * - Olimex ESP32 EVB + - LAN8720 + - 0 + - 23 + - 18 + - (no power pin) + - External clock + * - Olimex ESP32 Gateway + - LAN8720 + - 0 + - 23 + - 18 + - 5 + - 50MHz Inv Output GPIO17 + * - wESP32 + - LAN8720 + - 0 + - 16 + - 17 + - (no power pin) + - External clock + * - WT32 ETH01 + - LAN8720 + - 1 + - 23 + - 18 + - ? + - External clock + * - TTGO T-Internet-POE ESP32 + - LAN8720 + - 0 + - 23 + - 18 + - 5 (RST) + - 50MHz Inv Output GPIO17 + * - TTGO T-ETH-POE-PRO + - LAN8720 + - 0 + - 23 + - 18 + - 5 (RST) + - 50MHz Output GPIO0 + * - TTGO T-INTER_COM + - LAN8720 + - 0 + - 23 + - 18 + - 4 (RST) + - 50MHz Output GPIO0 + * - TTGO T-EH-Lite-ESP32 + - RTL8201 + - 0 + - 23 + - 18 + - 12 + - External clock + +See: + +* `ESP32 datasheet `_ +* `TTGO/LilyGO Ethernet boards `_ +* `Olimex ESP32-PoE `_ +* `Olimex ESP32-POE-ISO `_ +* `Olimex ESP32-EVB `_ +* `Olimex ESP32-GATEWAY `_ diff --git a/docs/source/Reference/Ethernet_PHY_ESP32.rst b/docs/source/Reference/RMII_Ethernet_PHY_ESP32.rst similarity index 74% rename from docs/source/Reference/Ethernet_PHY_ESP32.rst rename to docs/source/Reference/RMII_Ethernet_PHY_ESP32.rst index cdce3b01b8..99b3d84c9e 100644 --- a/docs/source/Reference/Ethernet_PHY_ESP32.rst +++ b/docs/source/Reference/RMII_Ethernet_PHY_ESP32.rst @@ -10,10 +10,18 @@ The following PHY connections are required for RMII PHY data connections: - RMII Signal - ESP32 EMAC Function - Notes - * - 0 + * - 0 / 16 / 17 - REF_CLK - EMAC_TX_CLK - See desciption about the clock + * - 18 + - MDIO + - EMAC_MDIO + - In theory user configurable, but almost always used as MDIO pin + * - 23 + - MDC + - EMAC_MDC + - In theory user configurable, but almost always used as MDC pin * - 21 - TX_EN - EMAC_TX_EN diff --git a/docs/source/Reference/SPI_Ethernet_ESP32_boards.rst b/docs/source/Reference/SPI_Ethernet_ESP32_boards.rst new file mode 100644 index 0000000000..7d8524d2de --- /dev/null +++ b/docs/source/Reference/SPI_Ethernet_ESP32_boards.rst @@ -0,0 +1,126 @@ + +There is a number of ESP32 boards available with Ethernet connected via SPI + +However it is not always clear which configuration should be used. + +.. note:: SPI Ethernet is only supported on builds based on ESP-IDF 5.1 or newer. Thus only on ESP32-builds with LittleFS support made after 2024/02. + + +N.B. As there is not yet support in ESPEasy for multiple SPI busses, it cannot be configured. + When later versions of ESPEasy will support multiple SPI busses, the SPI bus information may be needed for the configuration. + Therefore it is included in the table below. + +.. list-table:: SPI Ethernet Boards + :widths: 30 15 15 10 10 10 10 10 10 10 15 + :header-rows: 1 + + * - Board + - ESP chip + - Ethernet Chip + - Addr + - CS + - IRQ/INT + - RST + - SPI Clock + - SPI MISO + - SPI MOSI + - SPI bus + * - ETH01-EVO + - ESP32-C3 + - DM9051 + - 1 + - 9 + - 8 + - 6 + - 7 + - 3 + - 10 + - SPI2_HOST + * - M5Stack Atom PoE Kit (ATOM LITE) + - ESP32-classic + - W5500 + - + - 19 + - + - + - 22 + - 23 + - 33 + - SPI2_HOST + * - M5Stack Base LAN (End-of-life) + - M5Core + - W5500 + - + - 26 + - 34 + - 13 + - 18 + - 19 + - 23 + - SPI2_HOST + * - M5Stack LAN (PoE) BASE V12 + - M5Core + - W5500 + - + - 26 + - 34 + - 13 + - 18 + - 19 + - 23 + - SPI2_HOST + * - M5Stack LAN Module 13.2 + - M5Core + - W5500 + - + - 5/15 + - 35/34 + - 0/13 + - 18 + - 19 + - 23 + - SPI2_HOST + * - M5Stack LAN Module 13.2 + - M5Core2 + - W5500 + - + - 33/2 + - 35/34 + - 0/19 + - 18 + - 38 + - 23 + - SPI2_HOST + * - M5Stack LAN Module 13.2 + - M5CoreS3 + - W5500 + - + - 1/13 + - 10/14 + - 0/7 + - 36 + - 35 + - 37 + - SPI2_HOST + * - T-ETH-Lite-ESP32S3 + - ESP32-S3 + - W5500 + - 1 + - 9 + - 13 + - 14 + - 10 + - 11 + - 12 + - SPI2_HOST + + +See: + +* `M5 Stack Base LAN `_ +* `M5 Stack LAN Base V12 `_ +* `M5 Stack LAN PoE Base V12 `_ +* `M5 Stack LAN Module V13.2 `_ +* `M5 Stack ATOM PoE `_ +* `M5 Stack Base PoE `_ +* `TTGO/LilyGO Ethernet boards `_ diff --git a/platformio_core_defs.ini b/platformio_core_defs.ini index e0c91185ef..ce6774ed55 100644 --- a/platformio_core_defs.ini +++ b/platformio_core_defs.ini @@ -209,8 +209,8 @@ lib_ignore = ; ESP_IDF 5.1 [core_esp32_IDF5_1__3_0_0] platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.11/platform-espressif32.zip -platform_packages = -;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1917/framework-arduinoespressif32-release_v5.1-d4d5f8a.zip +;platform_packages = +platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1944/framework-arduinoespressif32-release_v5.1-561aaa3.zip build_flags = -DESP32_STAGE -DESP_IDF_VERSION_MAJOR=5 -DLIBRARIES_NO_LOG=1 diff --git a/platformio_esp32_solo1.ini b/platformio_esp32_solo1.ini index 2b22fa358d..944bee566f 100644 --- a/platformio_esp32_solo1.ini +++ b/platformio_esp32_solo1.ini @@ -18,7 +18,7 @@ build_unflags = ${esp32_base.build_unflags} ; IDF 5.1.2 [esp32_solo1_common_LittleFS] extends = esp32_base_idf5 -platform_packages = framework-arduino-solo1 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1918/framework-arduinoespressif32-solo1-release_v5.1-d4d5f8a.zip +platform_packages = framework-arduino-solo1 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1947/framework-arduinoespressif32-solo1-release_v5.1-561aaa3.zip build_flags = ${esp32_base_idf5.build_flags} -DFEATURE_ARDUINO_OTA=1 -DUSE_LITTLEFS diff --git a/platformio_esp32c3_envs.ini b/platformio_esp32c3_envs.ini index 64978d9d35..36983a99c1 100644 --- a/platformio_esp32c3_envs.ini +++ b/platformio_esp32c3_envs.ini @@ -55,6 +55,15 @@ build_flags = ${esp32c3_common_LittleFS.build_flags} extra_scripts = ${esp32c3_common_LittleFS.extra_scripts} pre:tools/pio/pre_custom_esp32.py +[env:custom_ESP32c3_4M316k_LittleFS_CDC_ETH] +extends = esp32c3_common_LittleFS +board = esp32c3cdc +build_flags = ${esp32c3_common_LittleFS.build_flags} + -DPLUGIN_BUILD_CUSTOM + -DFEATURE_ETHERNET=1 +extra_scripts = ${esp32c3_common_LittleFS.extra_scripts} + pre:tools/pio/pre_custom_esp32.py + [env:normal_ESP32c3_4M316k_CDC] diff --git a/src/src/Commands/Networks.cpp b/src/src/Commands/Networks.cpp index 46c7a8d7e9..0db3581d08 100644 --- a/src/src/Commands/Networks.cpp +++ b/src/src/Commands/Networks.cpp @@ -76,17 +76,17 @@ String Command_ETH_Phy_Addr (struct EventStruct *event, const char* Line) String Command_ETH_Pin_mdc (struct EventStruct *event, const char* Line) { - return Command_GetORSetInt8_t(event, F("ETH_Pin_mdc:"), Line, reinterpret_cast(&Settings.ETH_Pin_mdc),1); + return Command_GetORSetInt8_t(event, F("ETH_Pin_mdc_cs:"), Line, reinterpret_cast(&Settings.ETH_Pin_mdc_cs),1); } String Command_ETH_Pin_mdio (struct EventStruct *event, const char* Line) { - return Command_GetORSetInt8_t(event, F("ETH_Pin_mdio:"), Line, reinterpret_cast(&Settings.ETH_Pin_mdio),1); + return Command_GetORSetInt8_t(event, F("ETH_Pin_mdio_irq:"), Line, reinterpret_cast(&Settings.ETH_Pin_mdio_irq),1); } String Command_ETH_Pin_power (struct EventStruct *event, const char* Line) { - return Command_GetORSetInt8_t(event, F("ETH_Pin_power:"), Line, reinterpret_cast(&Settings.ETH_Pin_power),1); + return Command_GetORSetInt8_t(event, F("ETH_Pin_power_rst:"), Line, reinterpret_cast(&Settings.ETH_Pin_power_rst),1); } String Command_ETH_Phy_Type (struct EventStruct *event, const char* Line) diff --git a/src/src/CustomBuild/ESPEasyDefaults.h b/src/src/CustomBuild/ESPEasyDefaults.h index 399265aab1..b9057e18b7 100644 --- a/src/src/CustomBuild/ESPEasyDefaults.h +++ b/src/src/CustomBuild/ESPEasyDefaults.h @@ -252,13 +252,21 @@ #define DEFAULT_ETH_PHY_ADDR 0 #endif #ifndef DEFAULT_ETH_PHY_TYPE -#define DEFAULT_ETH_PHY_TYPE EthPhyType_t::LAN8710 +#define DEFAULT_ETH_PHY_TYPE EthPhyType_t::notSet #endif #ifndef DEFAULT_ETH_PIN_MDC +#ifdef ESP32_CLASSIC #define DEFAULT_ETH_PIN_MDC 23 +#else +#define DEFAULT_ETH_PIN_MDC -1 +#endif #endif #ifndef DEFAULT_ETH_PIN_MDIO +#ifdef ESP32_CLASSIC #define DEFAULT_ETH_PIN_MDIO 18 +#else +#define DEFAULT_ETH_PIN_MDIO -1 +#endif #endif #ifndef DEFAULT_ETH_PIN_POWER #define DEFAULT_ETH_PIN_POWER -1 diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 2016378311..d49727f20c 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -3253,6 +3253,14 @@ To create/register a plugin, you have to : # endif #endif +// Make sure CONFIG_ETH_USE_ESP32_EMAC is defined on older SDK versions. +#if FEATURE_ETHERNET && ESP_IDF_VERSION_MAJOR<5 +#ifndef CONFIG_ETH_USE_ESP32_EMAC +#ifdef ESP32_CLASSIC +#define CONFIG_ETH_USE_ESP32_EMAC 1 +#endif +#endif +#endif #if defined(DISABLE_NEOPIXEL_PLUGINS) && DISABLE_NEOPIXEL_PLUGINS // Disable NeoPixel plugins diff --git a/src/src/DataStructs/EthernetEventData.cpp b/src/src/DataStructs/EthernetEventData.cpp index 1955b8b07b..9699e0f8d4 100644 --- a/src/src/DataStructs/EthernetEventData.cpp +++ b/src/src/DataStructs/EthernetEventData.cpp @@ -12,6 +12,19 @@ #define ESPEASY_ETH_GOT_IP 1 #define ESPEASY_ETH_SERVICES_INITIALIZED 2 + +#if FEATURE_USE_IPV6 +#include + +// ----------------------------------------------------------------------------------------------------------------------- +// ---------------------------------------------------- Private functions ------------------------------------------------ +// ----------------------------------------------------------------------------------------------------------------------- + +esp_netif_t* get_esp_interface_netif(esp_interface_t interface); +#endif + + + bool EthernetEventData_t::EthConnectAllowed() const { if (!ethConnectAttemptNeeded) return false; if (last_eth_connect_attempt_moment.isSet()) { @@ -170,8 +183,18 @@ void EthernetEventData_t::markConnected() { processedConnect = false; #if FEATURE_USE_IPV6 ETH.enableIPv6(true); + // workaround for the race condition in LWIP, see https://github.com/espressif/arduino-esp32/pull/9016#discussion_r1451774885 + { + uint32_t i = 5; // try 5 times only + while (esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_ETH)) != ESP_OK) { + delay(1); + if (i-- == 0) { +// addLog(LOG_LEVEL_ERROR, ">>>> HELP"); + break; + } + } + } #endif - } String EthernetEventData_t::ESPEasyEthStatusToString() const { diff --git a/src/src/DataStructs/FactoryDefault_Network_NVS.cpp b/src/src/DataStructs/FactoryDefault_Network_NVS.cpp index 97a65c4437..97a725e8c1 100644 --- a/src/src/DataStructs/FactoryDefault_Network_NVS.cpp +++ b/src/src/DataStructs/FactoryDefault_Network_NVS.cpp @@ -35,9 +35,9 @@ bool FactoryDefault_Network_NVS::applyToSettings_from_NVS(ESPEasy_NVS_Helper& pr if (preferences.getPreference(F(FACTORY_DEFAULT_NVS_ETH_HW_CONF_KEY), ETH_HW_conf)) { Settings.ETH_Phy_Addr = bits.ETH_Phy_Addr; - Settings.ETH_Pin_mdc = bits.ETH_Pin_mdc; - Settings.ETH_Pin_mdio = bits.ETH_Pin_mdio; - Settings.ETH_Pin_power = bits.ETH_Pin_power; + Settings.ETH_Pin_mdc_cs = bits.ETH_Pin_mdc_cs; + Settings.ETH_Pin_mdio_irq = bits.ETH_Pin_mdio_irq; + Settings.ETH_Pin_power_rst = bits.ETH_Pin_power_rst; Settings.ETH_Phy_Type = static_cast(bits.ETH_Phy_Type); Settings.ETH_Clock_Mode = static_cast(bits.ETH_Clock_Mode); Settings.NetworkMedium = static_cast(bits.NetworkMedium); @@ -64,9 +64,9 @@ void FactoryDefault_Network_NVS::fromSettings_to_NVS(ESPEasy_NVS_Helper& prefere } { bits.ETH_Phy_Addr = Settings.ETH_Phy_Addr; - bits.ETH_Pin_mdc = Settings.ETH_Pin_mdc; - bits.ETH_Pin_mdio = Settings.ETH_Pin_mdio; - bits.ETH_Pin_power = Settings.ETH_Pin_power; + bits.ETH_Pin_mdc_cs = Settings.ETH_Pin_mdc_cs; + bits.ETH_Pin_mdio_irq = Settings.ETH_Pin_mdio_irq; + bits.ETH_Pin_power_rst = Settings.ETH_Pin_power_rst; bits.ETH_Phy_Type = static_cast(Settings.ETH_Phy_Type); bits.ETH_Clock_Mode = static_cast(Settings.ETH_Clock_Mode); bits.NetworkMedium = static_cast(Settings.NetworkMedium); diff --git a/src/src/DataStructs/FactoryDefault_Network_NVS.h b/src/src/DataStructs/FactoryDefault_Network_NVS.h index 7ed42dc243..1aa0b3bd67 100644 --- a/src/src/DataStructs/FactoryDefault_Network_NVS.h +++ b/src/src/DataStructs/FactoryDefault_Network_NVS.h @@ -29,9 +29,9 @@ class FactoryDefault_Network_NVS { union { struct { int8_t ETH_Phy_Addr; - int8_t ETH_Pin_mdc; - int8_t ETH_Pin_mdio; - int8_t ETH_Pin_power; + int8_t ETH_Pin_mdc_cs; + int8_t ETH_Pin_mdio_irq; + int8_t ETH_Pin_power_rst; uint8_t ETH_Phy_Type; uint8_t ETH_Clock_Mode; uint8_t NetworkMedium; diff --git a/src/src/DataStructs/GpioFactorySettingsStruct.cpp b/src/src/DataStructs/GpioFactorySettingsStruct.cpp index fd0415f17e..b0e6838a8b 100644 --- a/src/src/DataStructs/GpioFactorySettingsStruct.cpp +++ b/src/src/DataStructs/GpioFactorySettingsStruct.cpp @@ -107,7 +107,7 @@ GpioFactorySettingsStruct::GpioFactorySettingsStruct(DeviceModel model) #endif -#ifdef ESP32 +# if CONFIG_ETH_USE_ESP32_EMAC case DeviceModel::DeviceModel_Olimex_ESP32_PoE: button[0] = 34; // BUT1 Button relais[0] = -1; // No LED's or relays on board @@ -115,7 +115,7 @@ GpioFactorySettingsStruct::GpioFactorySettingsStruct(DeviceModel model) i2c_sda = 13; i2c_scl = 16; eth_phyaddr = 0; - eth_phytype = EthPhyType_t::LAN8710; + eth_phytype = EthPhyType_t::LAN8720; eth_mdc = 23; eth_mdio = 18; eth_power = 12; @@ -131,7 +131,7 @@ GpioFactorySettingsStruct::GpioFactorySettingsStruct(DeviceModel model) i2c_sda = 13; i2c_scl = 16; eth_phyaddr = 0; - eth_phytype = EthPhyType_t::LAN8710; + eth_phytype = EthPhyType_t::LAN8720; eth_mdc = 23; eth_mdio = 18; eth_power = -1; // No Ethernet power pin @@ -146,7 +146,7 @@ GpioFactorySettingsStruct::GpioFactorySettingsStruct(DeviceModel model) i2c_sda = -1; i2c_scl = -1; eth_phyaddr = 0; - eth_phytype = EthPhyType_t::LAN8710; + eth_phytype = EthPhyType_t::LAN8720; eth_mdc = 23; eth_mdio = 18; eth_power = 5; @@ -178,7 +178,7 @@ GpioFactorySettingsStruct::GpioFactorySettingsStruct(DeviceModel model) i2c_sda = 15; i2c_scl = 4; eth_phyaddr = 0; - eth_phytype = EthPhyType_t::LAN8710; + eth_phytype = EthPhyType_t::LAN8720; eth_mdc = 16; eth_mdio = 17; eth_power = -1; @@ -191,7 +191,7 @@ GpioFactorySettingsStruct::GpioFactorySettingsStruct(DeviceModel model) i2c_sda = 21; i2c_scl = 22; eth_phyaddr = 1; - eth_phytype = EthPhyType_t::LAN8710; + eth_phytype = EthPhyType_t::LAN8720; eth_mdc = 23; eth_mdio = 18; eth_power = 12; // TODO TD-er: Better to use GPIO-16? as shown here: https://letscontrolit.com/forum/viewtopic.php?p=50133#p50133 @@ -199,12 +199,6 @@ GpioFactorySettingsStruct::GpioFactorySettingsStruct(DeviceModel model) network_medium = NetworkMedium_t::Ethernet; break; - #else - case DeviceModel::DeviceModel_Olimex_ESP32_PoE: - case DeviceModel::DeviceModel_Olimex_ESP32_EVB: - case DeviceModel::DeviceModel_Olimex_ESP32_GATEWAY: - case DeviceModel::DeviceModel_wESP32: - case DeviceModel::DeviceModel_WT32_ETH01: #endif case DeviceModel::DeviceModel_default: diff --git a/src/src/DataStructs/SettingsStruct.h b/src/src/DataStructs/SettingsStruct.h index c01ba255d8..10a46b06c2 100644 --- a/src/src/DataStructs/SettingsStruct.h +++ b/src/src/DataStructs/SettingsStruct.h @@ -15,6 +15,9 @@ #include "../DataTypes/TimeSource.h" #include "../Globals/Plugins.h" +#ifdef ESP32 +#include +#endif //we disable SPI if not defined #ifndef DEFAULT_SPI @@ -285,6 +288,10 @@ class SettingsStruct_tmpl bool getSPI_pins(int8_t spi_gpios[3]) const; + #ifdef ESP32 + spi_host_device_t getSPI_host() const; + #endif + // Return true when pin is one of the SPI pins and SPI is enabled bool isSPI_pin(int8_t pin) const; @@ -450,10 +457,10 @@ class SettingsStruct_tmpl uint16_t SyslogPort = DEFAULT_SYSLOG_PORT; int8_t ETH_Phy_Addr = -1; - int8_t ETH_Pin_mdc = -1; - int8_t ETH_Pin_mdio = -1; - int8_t ETH_Pin_power = -1; - EthPhyType_t ETH_Phy_Type = EthPhyType_t::LAN8710; + int8_t ETH_Pin_mdc_cs = -1; + int8_t ETH_Pin_mdio_irq = -1; + int8_t ETH_Pin_power_rst = -1; + EthPhyType_t ETH_Phy_Type = EthPhyType_t::notSet; EthClockMode_t ETH_Clock_Mode = EthClockMode_t::Ext_crystal_osc; uint8_t ETH_IP[4] = {0}; uint8_t ETH_Gateway[4] = {0}; diff --git a/src/src/DataStructs/WiFiEventData.cpp b/src/src/DataStructs/WiFiEventData.cpp index 59326fb7a6..ac4ea7d70f 100644 --- a/src/src/DataStructs/WiFiEventData.cpp +++ b/src/src/DataStructs/WiFiEventData.cpp @@ -13,6 +13,19 @@ #define CONNECT_TIMEOUT_MAX 4000 // in milliSeconds + +#if FEATURE_USE_IPV6 +#include + +// ----------------------------------------------------------------------------------------------------------------------- +// ---------------------------------------------------- Private functions ------------------------------------------------ +// ----------------------------------------------------------------------------------------------------------------------- + +esp_netif_t* get_esp_interface_netif(esp_interface_t interface); +#endif + + + bool WiFiEventData_t::WiFiConnectAllowed() const { if (WiFi.status() == WL_IDLE_STATUS) { // FIXME TD-er: What to do now? Set a timer? @@ -204,6 +217,21 @@ void WiFiEventData_t::markDisconnect(WiFiDisconnectReason reason) { lastDisconnectReason = reason; processedDisconnect = false; wifiConnectInProgress = false; + +#if FEATURE_USE_IPV6 + WiFi.enableIPv6(true); + // workaround for the race condition in LWIP, see https://github.com/espressif/arduino-esp32/pull/9016#discussion_r1451774885 + { + uint32_t i = 5; // try 5 times only + while (esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA)) != ESP_OK) { + delay(1); + if (i-- == 0) { + break; + } + } + } +#endif + } void WiFiEventData_t::markConnected(const String& ssid, const uint8_t bssid[6], uint8_t channel) { diff --git a/src/src/DataStructs_templ/SettingsStruct.cpp b/src/src/DataStructs_templ/SettingsStruct.cpp index 5abc49eaaa..195929f912 100644 --- a/src/src/DataStructs_templ/SettingsStruct.cpp +++ b/src/src/DataStructs_templ/SettingsStruct.cpp @@ -20,6 +20,7 @@ #if ESP_IDF_VERSION_MAJOR >= 5 #include +#include "include/esp32x_fixes.h" #endif @@ -565,9 +566,9 @@ void SettingsStruct_tmpl::clearMisc() { #ifdef ESP32 // Ethernet related settings are never used on ESP8266 ETH_Phy_Addr = DEFAULT_ETH_PHY_ADDR; - ETH_Pin_mdc = DEFAULT_ETH_PIN_MDC; - ETH_Pin_mdio = DEFAULT_ETH_PIN_MDIO; - ETH_Pin_power = DEFAULT_ETH_PIN_POWER; + ETH_Pin_mdc_cs = DEFAULT_ETH_PIN_MDC; + ETH_Pin_mdio_irq = DEFAULT_ETH_PIN_MDIO; + ETH_Pin_power_rst = DEFAULT_ETH_PIN_POWER; ETH_Phy_Type = DEFAULT_ETH_PHY_TYPE; ETH_Clock_Mode = DEFAULT_ETH_CLOCK_MODE; #endif @@ -873,6 +874,41 @@ bool SettingsStruct_tmpl::getSPI_pins(int8_t spi_gpios[3]) const { return false; } +#ifdef ESP32 +template +spi_host_device_t SettingsStruct_tmpl::getSPI_host() const +{ + if (isSPI_valid()) { + const SPI_Options_e SPI_selection = static_cast(InitSPI); + switch (SPI_selection) { + case SPI_Options_e::Vspi_Fspi: + { + return VSPI_HOST; + } +#ifdef ESP32_CLASSIC + case SPI_Options_e::Hspi: + { + return HSPI_HOST; + } +#endif + case SPI_Options_e::UserDefined: + { + return HSPI_HOST; + } + case SPI_Options_e::None: + break; + } + + } + #if ESP_IDF_VERSION_MAJOR < 5 + return SPI_HOST; + #else + return spi_host_device_t::SPI_HOST_MAX; + #endif +} +#endif + + template bool SettingsStruct_tmpl::isSPI_pin(int8_t pin) const { if (pin < 0) { return false; } @@ -938,9 +974,9 @@ bool SettingsStruct_tmpl::isEthernetPinOptional(int8_t pin) const { if (pin < 0) return false; if (NetworkMedium == NetworkMedium_t::Ethernet) { if (isGpioUsedInETHClockMode(ETH_Clock_Mode, pin)) return true; - if (ETH_Pin_mdc == pin) return true; - if (ETH_Pin_mdio == pin) return true; - if (ETH_Pin_power == pin) return true; + if (ETH_Pin_mdc_cs == pin) return true; + if (ETH_Pin_mdio_irq == pin) return true; + if (ETH_Pin_power_rst == pin) return true; } #endif // if FEATURE_ETHERNET return false; diff --git a/src/src/DataTypes/DeviceModel.h b/src/src/DataTypes/DeviceModel.h index 18c994d552..3af8f1f459 100644 --- a/src/src/DataTypes/DeviceModel.h +++ b/src/src/DataTypes/DeviceModel.h @@ -21,11 +21,13 @@ enum class DeviceModel : uint8_t { DeviceModel_Sonoff_POWr2, DeviceModel_Shelly1, DeviceModel_ShellyPLUG_S, +# if CONFIG_ETH_USE_ESP32_EMAC DeviceModel_Olimex_ESP32_PoE, DeviceModel_Olimex_ESP32_EVB, DeviceModel_Olimex_ESP32_GATEWAY, DeviceModel_wESP32, DeviceModel_WT32_ETH01, +#endif DeviceModel_MAX diff --git a/src/src/DataTypes/EthernetParameters.cpp b/src/src/DataTypes/EthernetParameters.cpp index f6f5313ffb..3f5d4b1cf8 100644 --- a/src/src/DataTypes/EthernetParameters.cpp +++ b/src/src/DataTypes/EthernetParameters.cpp @@ -14,7 +14,7 @@ bool isValid(EthClockMode_t clockMode) { } bool isGpioUsedInETHClockMode(EthClockMode_t clockMode, - int8_t gpio) { + int8_t gpio) { if (((clockMode == EthClockMode_t::Int_50MHz_GPIO_0) && (gpio == 0)) || ((clockMode == EthClockMode_t::Int_50MHz_GPIO_16) && (gpio == 16)) || ((clockMode == EthClockMode_t::Int_50MHz_GPIO_17_inv) && (gpio == 17))) { @@ -23,7 +23,7 @@ bool isGpioUsedInETHClockMode(EthClockMode_t clockMode, return false; } -const __FlashStringHelper * toString(EthClockMode_t clockMode) { +const __FlashStringHelper* toString(EthClockMode_t clockMode) { switch (clockMode) { case EthClockMode_t::Ext_crystal_osc: return F("External crystal oscillator"); case EthClockMode_t::Int_50MHz_GPIO_0: return F("50MHz APLL Output on GPIO0"); @@ -37,32 +37,119 @@ const __FlashStringHelper * toString(EthClockMode_t clockMode) { bool isValid(EthPhyType_t phyType) { switch (phyType) { - case EthPhyType_t::LAN8710: +#if CONFIG_ETH_USE_ESP32_EMAC + case EthPhyType_t::LAN8720: case EthPhyType_t::TLK110: - return true; +# if ESP_IDF_VERSION_MAJOR > 3 case EthPhyType_t::RTL8201: + case EthPhyType_t::JL1101: case EthPhyType_t::DP83848: - case EthPhyType_t::DM9051: - #if ESP_IDF_VERSION_MAJOR > 3 - return true; // FIXME TD-er: Must check if supported per IDF version - #else - return false; - #endif + case EthPhyType_t::KSZ8041: + case EthPhyType_t::KSZ8081: +# endif // if ESP_IDF_VERSION_MAJOR > 3 + return true; +#endif // if CONFIG_ETH_USE_ESP32_EMAC - // Do not use default: as this allows the compiler to detect any missing cases. +#if ESP_IDF_VERSION_MAJOR >= 5 +# if CONFIG_ETH_SPI_ETHERNET_DM9051 + case EthPhyType_t::DM9051: return true; +# endif // if CONFIG_ETH_SPI_ETHERNET_DM9051 +# if CONFIG_ETH_SPI_ETHERNET_W5500 + case EthPhyType_t::W5500: return true; +# endif // if CONFIG_ETH_SPI_ETHERNET_W5500 +# if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + case EthPhyType_t::KSZ8851: return true; +# endif // if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL +#endif // if ESP_IDF_VERSION_MAJOR >= 5 + case EthPhyType_t::notSet: + break; } return false; } -const __FlashStringHelper * toString(EthPhyType_t phyType) { +#if FEATURE_ETHERNET +bool isSPI_EthernetType(EthPhyType_t phyType) { +# if ESP_IDF_VERSION_MAJOR >= 5 + return +# if CONFIG_ETH_SPI_ETHERNET_DM9051 + phyType == EthPhyType_t::DM9051 || +# endif // if CONFIG_ETH_SPI_ETHERNET_DM9051 +# if CONFIG_ETH_SPI_ETHERNET_W5500 + phyType == EthPhyType_t::W5500 || +# endif // if CONFIG_ETH_SPI_ETHERNET_W5500 +# if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + phyType == EthPhyType_t::KSZ8851 || +# endif // if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + false; +# else // if ESP_IDF_VERSION_MAJOR >= 5 + return false; +# endif // if ESP_IDF_VERSION_MAJOR >= 5 +} + +eth_phy_type_t to_ESP_phy_type(EthPhyType_t phyType) +{ switch (phyType) { - case EthPhyType_t::LAN8710: return F("LAN8710/LAN8720"); - case EthPhyType_t::TLK110: return F("TLK110"); - case EthPhyType_t::RTL8201: return F("RTL8201"); - case EthPhyType_t::DP83848: return F("DP83848"); - case EthPhyType_t::DM9051: return F("DM9051"); +# if CONFIG_ETH_USE_ESP32_EMAC + case EthPhyType_t::LAN8720: return ETH_PHY_LAN8720; + case EthPhyType_t::TLK110: return ETH_PHY_TLK110; +# if ESP_IDF_VERSION_MAJOR > 3 + case EthPhyType_t::RTL8201: return ETH_PHY_RTL8201; + case EthPhyType_t::JL1101: return ETH_PHY_JL1101; + case EthPhyType_t::DP83848: return ETH_PHY_DP83848; + case EthPhyType_t::KSZ8041: return ETH_PHY_KSZ8041; + case EthPhyType_t::KSZ8081: return ETH_PHY_KSZ8081; +# endif // if ESP_IDF_VERSION_MAJOR > 3 +# endif // if CONFIG_ETH_USE_ESP32_EMAC + +# if ESP_IDF_VERSION_MAJOR >= 5 +# if CONFIG_ETH_SPI_ETHERNET_DM9051 + case EthPhyType_t::DM9051: return ETH_PHY_DM9051; +# endif // if CONFIG_ETH_SPI_ETHERNET_DM9051 +# if CONFIG_ETH_SPI_ETHERNET_W5500 + case EthPhyType_t::W5500: return ETH_PHY_W5500; +# endif // if CONFIG_ETH_SPI_ETHERNET_W5500 +# if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + case EthPhyType_t::KSZ8851: return ETH_PHY_KSZ8851; +# endif // if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL +# endif // if ESP_IDF_VERSION_MAJOR >= 5 + case EthPhyType_t::notSet: + break; + } + return ETH_PHY_MAX; +} + +#endif // if FEATURE_ETHERNET + + +const __FlashStringHelper* toString(EthPhyType_t phyType) { + switch (phyType) { +#if CONFIG_ETH_USE_ESP32_EMAC + case EthPhyType_t::LAN8720: return F("LAN8710/LAN8720"); + case EthPhyType_t::TLK110: return F("TLK110"); +# if ESP_IDF_VERSION_MAJOR > 3 + case EthPhyType_t::RTL8201: return F("RTL8201"); + case EthPhyType_t::JL1101: return F("JL1101"); + case EthPhyType_t::DP83848: return F("DP83848"); + case EthPhyType_t::KSZ8041: return F("KSZ8041"); + case EthPhyType_t::KSZ8081: return F("KSZ8081"); +# endif // if ESP_IDF_VERSION_MAJOR > 3 +#endif // if CONFIG_ETH_USE_ESP32_EMAC + +#if ESP_IDF_VERSION_MAJOR >= 5 +# if CONFIG_ETH_SPI_ETHERNET_DM9051 + case EthPhyType_t::DM9051: return F("DM9051(SPI)"); +# endif // if CONFIG_ETH_SPI_ETHERNET_DM9051 +# if CONFIG_ETH_SPI_ETHERNET_W5500 + case EthPhyType_t::W5500: return F("W5500(SPI)"); +# endif // if CONFIG_ETH_SPI_ETHERNET_W5500 +# if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + case EthPhyType_t::KSZ8851: return F("KSZ8851(SPI)"); +# endif // if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL +#endif // if ESP_IDF_VERSION_MAJOR >= 5 + case EthPhyType_t::notSet: + break; // Do not use default: as this allows the compiler to detect any missing cases. } - return F("Unknown"); + return F("- None -"); } diff --git a/src/src/DataTypes/EthernetParameters.h b/src/src/DataTypes/EthernetParameters.h index 08441fb874..0f356813ed 100644 --- a/src/src/DataTypes/EthernetParameters.h +++ b/src/src/DataTypes/EthernetParameters.h @@ -3,6 +3,7 @@ #include "../../ESPEasy_common.h" + // Is stored in settings enum class EthClockMode_t : uint8_t { Ext_crystal_osc = 0, @@ -20,16 +21,43 @@ bool isGpioUsedInETHClockMode(EthClockMode_t clockMode, // Is stored in settings enum class EthPhyType_t : uint8_t { - LAN8710 = 0, +#if CONFIG_ETH_USE_ESP32_EMAC + LAN8720 = 0, TLK110 = 1, +#if ESP_IDF_VERSION_MAJOR > 3 + RTL8201 = 2, - DP83848 = 3, - DM9051 = 4 - //,KSZ8081 = 5 + JL1101 = 3, + DP83848 = 4, + KSZ8041 = 5, + KSZ8081 = 6, +#endif +#endif +#if ESP_IDF_VERSION_MAJOR >= 5 +#if CONFIG_ETH_SPI_ETHERNET_DM9051 + DM9051 = 10, +#endif +#if CONFIG_ETH_SPI_ETHERNET_W5500 + W5500 = 11, +#endif +#if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + KSZ8851 = 12, +#endif +#endif + notSet = 255 }; bool isValid(EthPhyType_t phyType); +#if FEATURE_ETHERNET +#include + +bool isSPI_EthernetType(EthPhyType_t phyType); + +// Convert to internal enum type as those enum values may not always be the same int value +eth_phy_type_t to_ESP_phy_type(EthPhyType_t phyType); +#endif + const __FlashStringHelper * toString(EthPhyType_t phyType); diff --git a/src/src/ESPEasyCore/ESPEasyEth.cpp b/src/src/ESPEasyCore/ESPEasyEth.cpp index cd2b3eeeeb..e2af6a5e36 100644 --- a/src/src/ESPEasyCore/ESPEasyEth.cpp +++ b/src/src/ESPEasyCore/ESPEasyEth.cpp @@ -64,11 +64,13 @@ void ethSetupStaticIPconfig() { bool ethCheckSettings() { return isValid(Settings.ETH_Phy_Type) - && isValid(Settings.ETH_Clock_Mode) +#if CONFIG_ETH_USE_ESP32_EMAC + && (isValid(Settings.ETH_Clock_Mode)/* || isSPI_EthernetType(Settings.ETH_Phy_Type)*/) +#endif && isValid(Settings.NetworkMedium) - && validGpio(Settings.ETH_Pin_mdc) - && validGpio(Settings.ETH_Pin_mdio) - && (validGpio(Settings.ETH_Pin_power) || (Settings.ETH_Pin_power == -1)); // Some boards have fixed power + && validGpio(Settings.ETH_Pin_mdc_cs) + && validGpio(Settings.ETH_Pin_mdio_irq) + && (validGpio(Settings.ETH_Pin_power_rst) || (Settings.ETH_Pin_power_rst == -1)); // Some boards have fixed power } bool ethPrepare() { @@ -89,14 +91,16 @@ void ethPrintSettings() { log += toString(Settings.ETH_Phy_Type); log += F(" PHY Addr: "); log += Settings.ETH_Phy_Addr; - log += F(" Eth Clock mode: "); - log += toString(Settings.ETH_Clock_Mode); - log += F(" MDC Pin: "); - log += String(Settings.ETH_Pin_mdc); - log += F(" MIO Pin: "); - log += String(Settings.ETH_Pin_mdio); - log += F(" Power Pin: "); - log += String(Settings.ETH_Pin_power); + + if (!isSPI_EthernetType(Settings.ETH_Phy_Type)) { + log += F(" Eth Clock mode: "); + log += toString(Settings.ETH_Clock_Mode); + } + log += strformat(isSPI_EthernetType(Settings.ETH_Phy_Type) + ? F(" CS: %d IRQ: %d RST: %d") : F(" MDC: %d MIO: %d PWR: %d"), + Settings.ETH_Pin_mdc_cs, + Settings.ETH_Pin_mdio_irq, + Settings.ETH_Pin_power_rst); addLogMove(LOG_LEVEL_INFO, log); } } @@ -152,27 +156,57 @@ bool ETHConnectRelaxed() { registerEthEventHandler(); if (!EthEventData.ethInitSuccess) { - ethResetGPIOpins(); #if ESP_IDF_VERSION_MAJOR < 5 EthEventData.ethInitSuccess = ETH.begin( Settings.ETH_Phy_Addr, - Settings.ETH_Pin_power, - Settings.ETH_Pin_mdc, - Settings.ETH_Pin_mdio, + Settings.ETH_Pin_power_rst, + Settings.ETH_Pin_mdc_cs, + Settings.ETH_Pin_mdio_irq, (eth_phy_type_t)Settings.ETH_Phy_Type, (eth_clock_mode_t)Settings.ETH_Clock_Mode); #else - #if FEATURE_USE_IPV6 - ETH.enableIPv6(true); - #endif +#if FEATURE_USE_IPV6 + ETH.enableIPv6(true); +#endif + if (isSPI_EthernetType(Settings.ETH_Phy_Type)) { + spi_host_device_t SPI_host = Settings.getSPI_host(); + if (SPI_host == spi_host_device_t::SPI_HOST_MAX) { + addLog(LOG_LEVEL_ERROR, F("SPI not enabled")); + #ifdef ESP32C3 + // FIXME TD-er: Fallback for ETH01-EVO board + SPI_host = spi_host_device_t::SPI2_HOST; + Settings.InitSPI = static_cast(SPI_Options_e::UserDefined); + Settings.SPI_SCLK_pin = 7; + Settings.SPI_MISO_pin = 3; + Settings.SPI_MOSI_pin = 10; + #endif + } + // else + { + EthEventData.ethInitSuccess = ETH.begin( + to_ESP_phy_type(Settings.ETH_Phy_Type), + Settings.ETH_Phy_Addr, + Settings.ETH_Pin_mdc_cs, + Settings.ETH_Pin_mdio_irq, + Settings.ETH_Pin_power_rst, + SPI_host, + static_cast(Settings.SPI_SCLK_pin), + static_cast(Settings.SPI_MISO_pin), + static_cast(Settings.SPI_MOSI_pin)); + } + } else { +# if CONFIG_ETH_USE_ESP32_EMAC + ethResetGPIOpins(); EthEventData.ethInitSuccess = ETH.begin( - (eth_phy_type_t)Settings.ETH_Phy_Type, + to_ESP_phy_type(Settings.ETH_Phy_Type), Settings.ETH_Phy_Addr, - Settings.ETH_Pin_mdc, - Settings.ETH_Pin_mdio, - Settings.ETH_Pin_power, + Settings.ETH_Pin_mdc_cs, + Settings.ETH_Pin_mdio_irq, + Settings.ETH_Pin_power_rst, (eth_clock_mode_t)Settings.ETH_Clock_Mode); +#endif + } #endif } @@ -180,6 +214,27 @@ bool ETHConnectRelaxed() { // FIXME TD-er: Not sure if this is correctly set to false //EthEventData.ethConnectAttemptNeeded = false; + if (loglevelActiveFor(LOG_LEVEL_INFO)) { +#if ESP_IDF_VERSION_MAJOR < 5 + addLog(LOG_LEVEL_INFO, strformat( + F("ETH : MAC: %s speed: %dM %s Link: %s"), + ETH.macAddress().c_str(), + ETH.linkSpeed(), + String(ETH.fullDuplex() ? F("Full Duplex") : F("Half Duplex")).c_str(), + String(ETH.linkUp() ? F("Up") : F("Down")).c_str())); +#else + addLog(LOG_LEVEL_INFO, strformat( + F("ETH : MAC: %s phy addr: %d speed: %dM %s Link: %s"), + ETH.macAddress().c_str(), + ETH.phyAddr(), + ETH.linkSpeed(), + concat( + ETH.fullDuplex() ? F("Full Duplex") : F("Half Duplex"), + ETH.autoNegotiation() ? F("(auto)") : F("")).c_str(), + String(ETH.linkUp() ? F("Up") : F("Down")).c_str())); +#endif + } + if (EthLinkUp()) { // We might miss the connected event, since we are already connected. EthEventData.markConnected(); @@ -189,8 +244,10 @@ bool ETHConnectRelaxed() { } void ethPower(bool enable) { - if (Settings.ETH_Pin_power != -1) { - if (GPIO_Internal_Read(Settings.ETH_Pin_power) == enable) { + if (isSPI_EthernetType(Settings.ETH_Phy_Type)) + return; + if (Settings.ETH_Pin_power_rst != -1) { + if (GPIO_Internal_Read(Settings.ETH_Pin_power_rst) == enable) { // Already the desired state return; } @@ -211,9 +268,9 @@ void ethPower(bool enable) { if (enable) { // ethResetGPIOpins(); } -// gpio_reset_pin((gpio_num_t)Settings.ETH_Pin_power); +// gpio_reset_pin((gpio_num_t)Settings.ETH_Pin_power_rst); - GPIO_Write(PLUGIN_GPIO, Settings.ETH_Pin_power, enable ? 1 : 0); + GPIO_Write(PLUGIN_GPIO, Settings.ETH_Pin_power_rst, enable ? 1 : 0); if (!enable) { if (Settings.ETH_Clock_Mode == EthClockMode_t::Ext_crystal_osc) { delay(600); // Give some time to discharge any capacitors @@ -226,18 +283,23 @@ void ethPower(bool enable) { } void ethResetGPIOpins() { + if (isSPI_EthernetType(Settings.ETH_Phy_Type)) + return; + // fix an disconnection issue after rebooting Olimex POE - this forces a clean state for all GPIO involved in RMII // Thanks to @s-hadinger and @Jason2866 // Resetting state of power pin is done in ethPower() addLog(LOG_LEVEL_INFO, F("ethResetGPIOpins()")); - gpio_reset_pin((gpio_num_t)Settings.ETH_Pin_mdc); - gpio_reset_pin((gpio_num_t)Settings.ETH_Pin_mdio); + gpio_reset_pin((gpio_num_t)Settings.ETH_Pin_mdc_cs); + gpio_reset_pin((gpio_num_t)Settings.ETH_Pin_mdio_irq); +# if CONFIG_ETH_USE_ESP32_EMAC gpio_reset_pin(GPIO_NUM_19); // EMAC_TXD0 - hardcoded gpio_reset_pin(GPIO_NUM_21); // EMAC_TX_EN - hardcoded gpio_reset_pin(GPIO_NUM_22); // EMAC_TXD1 - hardcoded gpio_reset_pin(GPIO_NUM_25); // EMAC_RXD0 - hardcoded gpio_reset_pin(GPIO_NUM_26); // EMAC_RXD1 - hardcoded gpio_reset_pin(GPIO_NUM_27); // EMAC_RX_CRS_DV - hardcoded +#endif /* switch (Settings.ETH_Clock_Mode) { case EthClockMode_t::Ext_crystal_osc: // ETH_CLOCK_GPIO0_IN diff --git a/src/src/ESPEasyCore/ESPEasyEthEvent.cpp b/src/src/ESPEasyCore/ESPEasyEthEvent.cpp index 86f7008cc7..cb24ca007c 100644 --- a/src/src/ESPEasyCore/ESPEasyEthEvent.cpp +++ b/src/src/ESPEasyCore/ESPEasyEthEvent.cpp @@ -22,25 +22,25 @@ void EthEvent(WiFiEvent_t event, arduino_event_info_t info) { case ARDUINO_EVENT_ETH_START: if (ethPrepare()) { - addLog(LOG_LEVEL_INFO, F("ETH event: Started")); - } else { - addLog(LOG_LEVEL_ERROR, F("ETH event: Could not prepare ETH!")); +// addLog(LOG_LEVEL_INFO, F("ETH event: Started")); +// } else { +// addLog(LOG_LEVEL_ERROR, F("ETH event: Could not prepare ETH!")); } break; case ARDUINO_EVENT_ETH_CONNECTED: - addLog(LOG_LEVEL_INFO, F("ETH event: Connected")); +// addLog(LOG_LEVEL_INFO, F("ETH event: Connected")); EthEventData.markConnected(); break; case ARDUINO_EVENT_ETH_GOT_IP: EthEventData.markGotIP(); - addLog(LOG_LEVEL_INFO, F("ETH event: Got IP")); +// addLog(LOG_LEVEL_INFO, F("ETH event: Got IP")); break; case ARDUINO_EVENT_ETH_DISCONNECTED: - addLog(LOG_LEVEL_ERROR, F("ETH event: Disconnected")); +// addLog(LOG_LEVEL_ERROR, F("ETH event: Disconnected")); EthEventData.markDisconnect(); break; case ARDUINO_EVENT_ETH_STOP: - addLog(LOG_LEVEL_INFO, F("ETH event: Stopped")); +// addLog(LOG_LEVEL_INFO, F("ETH event: Stopped")); break; # if ESP_IDF_VERSION_MAJOR > 3 case ARDUINO_EVENT_ETH_GOT_IP6: @@ -52,10 +52,10 @@ void EthEvent(WiFiEvent_t event, arduino_event_info_t info) { ip_event_got_ip6_t * event = static_cast(&info.got_ip6); IPAddress ip(IPv6, (const uint8_t*)event->ip6_info.ip.addr, event->ip6_info.ip.zone); EthEventData.markGotIPv6(ip); - addLog(LOG_LEVEL_INFO, String(F("ETH event: Got IP6")) + ip.toString(true)); +// addLog(LOG_LEVEL_INFO, String(F("ETH event: Got IP6 ")) + ip.toString(true)); } #else - addLog(LOG_LEVEL_INFO, F("ETH event: Got IP6")); +// addLog(LOG_LEVEL_INFO, F("ETH event: Got IP6")); #endif break; default: diff --git a/src/src/ESPEasyCore/ESPEasyEth_ProcessEvent.cpp b/src/src/ESPEasyCore/ESPEasyEth_ProcessEvent.cpp index fe6fa5bd46..574c2aa879 100644 --- a/src/src/ESPEasyCore/ESPEasyEth_ProcessEvent.cpp +++ b/src/src/ESPEasyCore/ESPEasyEth_ProcessEvent.cpp @@ -29,10 +29,7 @@ void handle_unprocessedEthEvents() { // Process disconnect events before connect events. #if FEATURE_USE_IPV6 if (!EthEventData.processedGotIP6) { - EthEventData.processedGotIP6 = true; -#if FEATURE_ESPEASY_P2P - updateUDPport(true); -#endif + processEthernetGotIPv6(); } #endif @@ -251,4 +248,18 @@ void processEthernetGotIP() { CheckRunningServices(); } +#if FEATURE_USE_IPV6 +void processEthernetGotIPv6() { + if (!EthEventData.processedGotIP6) { + if (loglevelActiveFor(LOG_LEVEL_INFO)) + addLog(LOG_LEVEL_INFO, String(F("ETH event: Got IP6 ")) + EthEventData.unprocessed_IP6.toString(true)); + EthEventData.processedGotIP6 = true; +#if FEATURE_ESPEASY_P2P + updateUDPport(true); +#endif + + } +} +#endif + #endif // if FEATURE_ETHERNET diff --git a/src/src/ESPEasyCore/ESPEasyEth_ProcessEvent.h b/src/src/ESPEasyCore/ESPEasyEth_ProcessEvent.h index 5c6708f892..40c10dcf83 100644 --- a/src/src/ESPEasyCore/ESPEasyEth_ProcessEvent.h +++ b/src/src/ESPEasyCore/ESPEasyEth_ProcessEvent.h @@ -11,6 +11,9 @@ void check_Eth_DNS_valid(); void processEthernetConnected(); void processEthernetDisconnected(); void processEthernetGotIP(); +#if FEATURE_USE_IPV6 +void processEthernetGotIPv6(); +#endif #endif // if FEATURE_ETHERNET #endif // ifndef ESPEASYCORE_ESPEASYETH_PROCESSEVENT_H diff --git a/src/src/ESPEasyCore/ESPEasyNetwork.cpp b/src/src/ESPEasyCore/ESPEasyNetwork.cpp index 846cd128f7..8a3b05959f 100644 --- a/src/src/ESPEasyCore/ESPEasyNetwork.cpp +++ b/src/src/ESPEasyCore/ESPEasyNetwork.cpp @@ -398,7 +398,7 @@ bool EthFullDuplex() bool EthLinkUp() { if (EthEventData.ethInitSuccess) { - #ifdef ESP_IDF_VERSION_MAJOR + #if ESP_IDF_VERSION_MAJOR < 5 // FIXME TD-er: See: https://github.com/espressif/arduino-esp32/issues/6105 return EthEventData.EthConnected(); #else diff --git a/src/src/ESPEasyCore/ESPEasyWiFiEvent.cpp b/src/src/ESPEasyCore/ESPEasyWiFiEvent.cpp index 95fad54deb..dd70788ac3 100644 --- a/src/src/ESPEasyCore/ESPEasyWiFiEvent.cpp +++ b/src/src/ESPEasyCore/ESPEasyWiFiEvent.cpp @@ -134,9 +134,6 @@ void WiFiEvent(WiFiEvent_t event, arduino_event_info_t info) { ssid_copy[32] = 0; // Potentially add 0-termination if none present earlier WiFiEventData.markConnected((const char*) ssid_copy, info.connected.bssid, info.connected.channel); #endif - #if FEATURE_USE_IPV6 - WiFi.enableIPv6(true); - #endif break; } case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: @@ -167,9 +164,8 @@ void WiFiEvent(WiFiEvent_t event, arduino_event_info_t info) { case ARDUINO_EVENT_WIFI_STA_GOT_IP6: { ip_event_got_ip6_t * event = static_cast(&info.got_ip6); - IPAddress ip(IPv6, (const uint8_t*)event->ip6_info.ip.addr, event->ip6_info.ip.zone); + const IPAddress ip(IPv6, (const uint8_t*)event->ip6_info.ip.addr, event->ip6_info.ip.zone); WiFiEventData.markGotIPv6(ip); - addLog(LOG_LEVEL_INFO, String(F("WIFI : STA got IP6 ")) + ip.toString(true)); break; } case ARDUINO_EVENT_WIFI_AP_GOT_IP6: diff --git a/src/src/ESPEasyCore/ESPEasyWifi.cpp b/src/src/ESPEasyCore/ESPEasyWifi.cpp index d41160bd88..279485fcdb 100644 --- a/src/src/ESPEasyCore/ESPEasyWifi.cpp +++ b/src/src/ESPEasyCore/ESPEasyWifi.cpp @@ -231,10 +231,7 @@ bool WiFiConnected() { #if FEATURE_USE_IPV6 if (!WiFiEventData.processedGotIP6) { - WiFiEventData.processedGotIP6 = true; -#if FEATURE_ESPEASY_P2P - updateUDPport(true); -#endif + processGotIPv6(); } #endif diff --git a/src/src/ESPEasyCore/ESPEasyWifi_ProcessEvent.cpp b/src/src/ESPEasyCore/ESPEasyWifi_ProcessEvent.cpp index 2a54bf8f75..0130113cf6 100644 --- a/src/src/ESPEasyCore/ESPEasyWifi_ProcessEvent.cpp +++ b/src/src/ESPEasyCore/ESPEasyWifi_ProcessEvent.cpp @@ -459,6 +459,19 @@ void processGotIP() { logConnectionStatus(); } +#if FEATURE_USE_IPV6 +void processGotIPv6() { + if (!WiFiEventData.processedGotIP6) { + WiFiEventData.processedGotIP6 = true; + if (loglevelActiveFor(LOG_LEVEL_INFO)) + addLog(LOG_LEVEL_INFO, String(F("WIFI : STA got IP6 ")) + WiFiEventData.unprocessed_IP6.toString(true)); +#if FEATURE_ESPEASY_P2P + updateUDPport(true); +#endif + } +} +#endif + // A client disconnected from the AP on this node. void processDisconnectAPmode() { if (WiFiEventData.processedDisconnectAPmode) { return; } diff --git a/src/src/ESPEasyCore/ESPEasyWifi_ProcessEvent.h b/src/src/ESPEasyCore/ESPEasyWifi_ProcessEvent.h index 42fb965d68..ce26d4a73f 100644 --- a/src/src/ESPEasyCore/ESPEasyWifi_ProcessEvent.h +++ b/src/src/ESPEasyCore/ESPEasyWifi_ProcessEvent.h @@ -7,6 +7,9 @@ void handle_unprocessedNetworkEvents(); void processDisconnect(); void processConnect(); void processGotIP(); +#if FEATURE_USE_IPV6 +void processGotIPv6(); +#endif void processDisconnectAPmode(); void processConnectAPmode(); void processDisableAPmode(); diff --git a/src/src/ESPEasyCore/ESPEasy_Log.cpp b/src/src/ESPEasyCore/ESPEasy_Log.cpp index 0ffffd7462..eade2faa67 100644 --- a/src/src/ESPEasyCore/ESPEasy_Log.cpp +++ b/src/src/ESPEasyCore/ESPEasy_Log.cpp @@ -115,6 +115,15 @@ void updateLogLevelCache() { } bool loglevelActiveFor(uint8_t logLevel) { + #ifdef ESP32 + if (xPortInIsrContext()) { + // When called from an ISR, you should not send out logs. + // Allocating memory from within an ISR is a big no-no. + // Also long-time blocking like sending logs (especially to a syslog server) + // is also really not a good idea from an ISR call. + return false; + } + #endif return logLevel <= highest_active_log_level; } @@ -146,6 +155,16 @@ uint8_t getWebLogLevel() { } bool loglevelActiveFor(uint8_t destination, uint8_t logLevel) { + #ifdef ESP32 + if (xPortInIsrContext()) { + // When called from an ISR, you should not send out logs. + // Allocating memory from within an ISR is a big no-no. + // Also long-time blocking like sending logs (especially to a syslog server) + // is also really not a good idea from an ISR call. + return false; + } + #endif + uint8_t logLevelSettings = 0; switch (destination) { case LOG_TO_SERIAL: { @@ -293,6 +312,16 @@ void addToSDLog(uint8_t logLevel, const String& string) void addLog(uint8_t logLevel, const String& string) { + #ifdef ESP32 + if (xPortInIsrContext()) { + // When called from an ISR, you should not send out logs. + // Allocating memory from within an ISR is a big no-no. + // Also long-time blocking like sending logs (especially to a syslog server) + // is also really not a good idea from an ISR call. + return; + } + #endif + if (string.isEmpty()) return; addToSerialLog(logLevel, string); addToSysLog(logLevel, string); @@ -304,6 +333,16 @@ void addLog(uint8_t logLevel, const String& string) void addToLogMove(uint8_t logLevel, String&& string) { + #ifdef ESP32 + if (xPortInIsrContext()) { + // When called from an ISR, you should not send out logs. + // Allocating memory from within an ISR is a big no-no. + // Also long-time blocking like sending logs (especially to a syslog server) + // is also really not a good idea from an ISR call. + return; + } + #endif + if (string.isEmpty()) return; addToSerialLog(logLevel, string); addToSysLog(logLevel, string); diff --git a/src/src/ESPEasyCore/ESPEasy_setup.cpp b/src/src/ESPEasyCore/ESPEasy_setup.cpp index c3f3c41e66..a47dbfd215 100644 --- a/src/src/ESPEasyCore/ESPEasy_setup.cpp +++ b/src/src/ESPEasyCore/ESPEasy_setup.cpp @@ -581,8 +581,8 @@ void ESPEasy_setup() #endif #if FEATURE_ETHERNET - if (Settings.ETH_Pin_power != -1) { - GPIO_Write(PLUGIN_GPIO, Settings.ETH_Pin_power, 1); + if (Settings.ETH_Pin_power_rst != -1) { + GPIO_Write(PLUGIN_GPIO, Settings.ETH_Pin_power_rst, 1); } #endif diff --git a/src/src/Helpers/ESPEasy_FactoryDefault.cpp b/src/src/Helpers/ESPEasy_FactoryDefault.cpp index 3577ca3d6a..3bbcade1b1 100644 --- a/src/src/Helpers/ESPEasy_FactoryDefault.cpp +++ b/src/src/Helpers/ESPEasy_FactoryDefault.cpp @@ -306,9 +306,9 @@ void ResetFactory(bool formatFS) // Ethernet related settings are never used on ESP8266 Settings.ETH_Phy_Addr = gpio_settings.eth_phyaddr; - Settings.ETH_Pin_mdc = gpio_settings.eth_mdc; - Settings.ETH_Pin_mdio = gpio_settings.eth_mdio; - Settings.ETH_Pin_power = gpio_settings.eth_power; + Settings.ETH_Pin_mdc_cs = gpio_settings.eth_mdc; + Settings.ETH_Pin_mdio_irq = gpio_settings.eth_mdio; + Settings.ETH_Pin_power_rst = gpio_settings.eth_power; Settings.ETH_Phy_Type = gpio_settings.eth_phytype; Settings.ETH_Clock_Mode = gpio_settings.eth_clock_mode; #endif // ifdef ESP32 diff --git a/src/src/Helpers/ESPEasy_Storage.cpp b/src/src/Helpers/ESPEasy_Storage.cpp index 78fef1e533..e92675af49 100644 --- a/src/src/Helpers/ESPEasy_Storage.cpp +++ b/src/src/Helpers/ESPEasy_Storage.cpp @@ -338,9 +338,9 @@ bool BuildFixes() #ifdef ESP32 // Ethernet related settings are never used on ESP8266 Settings.ETH_Phy_Addr = DEFAULT_ETH_PHY_ADDR; - Settings.ETH_Pin_mdc = DEFAULT_ETH_PIN_MDC; - Settings.ETH_Pin_mdio = DEFAULT_ETH_PIN_MDIO; - Settings.ETH_Pin_power = DEFAULT_ETH_PIN_POWER; + Settings.ETH_Pin_mdc_cs = DEFAULT_ETH_PIN_MDC; + Settings.ETH_Pin_mdio_irq = DEFAULT_ETH_PIN_MDIO; + Settings.ETH_Pin_power_rst = DEFAULT_ETH_PIN_POWER; Settings.ETH_Phy_Type = DEFAULT_ETH_PHY_TYPE; Settings.ETH_Clock_Mode = DEFAULT_ETH_CLOCK_MODE; #endif diff --git a/src/src/Helpers/Hardware.cpp b/src/src/Helpers/Hardware.cpp index 45c2b9b398..8b0b60abdf 100644 --- a/src/src/Helpers/Hardware.cpp +++ b/src/src/Helpers/Hardware.cpp @@ -148,16 +148,16 @@ void hardwareInit() PinBootState bootState = Settings.getPinBootState(gpio); #if FEATURE_ETHERNET /* - if (Settings.ETH_Pin_power == gpio) + if (Settings.ETH_Pin_power_rst == gpio) { - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("ETH : Reset ETH module on pin "); - log += Settings.ETH_Pin_power; - addLog(LOG_LEVEL_INFO, log); - } - bootState = PinBootState::Output_low; - } -*/ + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("ETH : Reset ETH module on pin "); + log += Settings.ETH_Pin_power_rst; + addLog(LOG_LEVEL_INFO, log); + } + bootState = PinBootState::Output_low; + } + */ #endif // if FEATURE_ETHERNET #ifdef ESP32 @@ -228,8 +228,20 @@ void hardwareInit() PluginCall(PLUGIN_PRIORITY_INIT_ALL, nullptr, dummy); #endif // if FEATURE_PLUGIN_PRIORITY + bool tryInitSPI = true; +#if FEATURE_ETHERNET + if ((Settings.NetworkMedium == NetworkMedium_t::Ethernet) && + isValid(Settings.ETH_Phy_Type) && + isSPI_EthernetType(Settings.ETH_Phy_Type)) + { + tryInitSPI = false; + } +#endif + + // SPI Init - if (Settings.isSPI_valid()) + bool SPI_initialized = false; + if (tryInitSPI && Settings.isSPI_valid()) { SPI.setHwCs(false); @@ -237,55 +249,43 @@ void hardwareInit() #ifdef ESP32 const SPI_Options_e SPI_selection = static_cast(Settings.InitSPI); + int8_t spi_gpios[3] = {}; - switch (SPI_selection) { -#ifdef ESP32_CLASSIC - case SPI_Options_e::Hspi: - { - SPI.begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI); // HSPI - break; - } -#endif - case SPI_Options_e::UserDefined: - { - SPI.begin(Settings.SPI_SCLK_pin, - Settings.SPI_MISO_pin, - Settings.SPI_MOSI_pin); // User-defined SPI - break; - } - case SPI_Options_e::Vspi_Fspi: - { + if (Settings.getSPI_pins(spi_gpios)) { + if (SPI_selection == SPI_Options_e::Vspi_Fspi) { SPI.begin(); // Default SPI bus - break; + } else { + SPI.begin(spi_gpios[0], spi_gpios[1], spi_gpios[2]); } - case SPI_Options_e::None: - break; + SPI_initialized = true; } #else // ifdef ESP32 SPI.begin(); + SPI_initialized = true; #endif // ifdef ESP32 - addLog(LOG_LEVEL_INFO, F("INIT : SPI Init (without CS)")); - } - else - { - addLog(LOG_LEVEL_INFO, F("INIT : SPI not enabled")); } -#if FEATURE_SD - - if (Settings.Pin_sd_cs >= 0) + if (SPI_initialized) { - if (SD.begin(Settings.Pin_sd_cs)) - { - addLog(LOG_LEVEL_INFO, F("SD : Init OK")); - } - else + addLog(LOG_LEVEL_INFO, F("INIT : SPI Init (without CS)")); + #if FEATURE_SD + + if (Settings.Pin_sd_cs >= 0) { - SD.end(); - addLog(LOG_LEVEL_ERROR, F("SD : Init failed")); + if (SD.begin(Settings.Pin_sd_cs)) + { + addLog(LOG_LEVEL_INFO, F("SD : Init OK")); + } + else + { + SD.end(); + addLog(LOG_LEVEL_ERROR, F("SD : Init failed")); + } } - } #endif // if FEATURE_SD + } else { + addLog(LOG_LEVEL_INFO, F("INIT : SPI not enabled")); + } } @@ -759,6 +759,7 @@ const __FlashStringHelper* getDeviceModelBrandString(DeviceModel model) { case DeviceModel::DeviceModel_Sonoff_POWr2: return F("Sonoff"); case DeviceModel::DeviceModel_Shelly1: case DeviceModel::DeviceModel_ShellyPLUG_S: return F("Shelly"); +# if CONFIG_ETH_USE_ESP32_EMAC case DeviceModel::DeviceModel_Olimex_ESP32_PoE: case DeviceModel::DeviceModel_Olimex_ESP32_EVB: case DeviceModel::DeviceModel_Olimex_ESP32_GATEWAY: @@ -773,6 +774,7 @@ const __FlashStringHelper* getDeviceModelBrandString(DeviceModel model) { #ifdef ESP32_CLASSIC return F("WT32-ETH01"); #endif // ifdef ESP32_CLASSIC +#endif case DeviceModel::DeviceModel_default: case DeviceModel::DeviceModel_MAX: break; @@ -810,19 +812,13 @@ const __FlashStringHelper* getDeviceModelTypeString(DeviceModel model) case DeviceModel::DeviceModel_ShellyPLUG_S: return F("default"); #endif // if defined(ESP8266) && !defined(LIMIT_BUILD_SIZE) -#ifdef ESP32_CLASSIC +#if CONFIG_ETH_USE_ESP32_EMAC case DeviceModel::DeviceModel_Olimex_ESP32_PoE: return F(" ESP32-PoE"); case DeviceModel::DeviceModel_Olimex_ESP32_EVB: return F(" ESP32-EVB"); case DeviceModel::DeviceModel_Olimex_ESP32_GATEWAY: return F(" ESP32-GATEWAY"); case DeviceModel::DeviceModel_wESP32: break; case DeviceModel::DeviceModel_WT32_ETH01: return F(" add-on"); -#else // ifdef ESP32_CLASSIC - case DeviceModel::DeviceModel_Olimex_ESP32_PoE: - case DeviceModel::DeviceModel_Olimex_ESP32_EVB: - case DeviceModel::DeviceModel_Olimex_ESP32_GATEWAY: - case DeviceModel::DeviceModel_wESP32: - case DeviceModel::DeviceModel_WT32_ETH01: -#endif // ifdef ESP32_CLASSIC +#endif // if CONFIG_ETH_USE_ESP32_EMAC case DeviceModel::DeviceModel_default: case DeviceModel::DeviceModel_MAX: return F("default"); @@ -834,7 +830,7 @@ const __FlashStringHelper* getDeviceModelTypeString(DeviceModel model) String getDeviceModelString(DeviceModel model) { return concat( - getDeviceModelBrandString(model), + getDeviceModelBrandString(model), getDeviceModelTypeString(model)); } @@ -874,18 +870,19 @@ bool modelMatchingFlashSize(DeviceModel model) { return false; #endif // ifdef ESP8266 - // These Olimex boards all have Ethernet + // These Olimex boards all have Ethernet +#if CONFIG_ETH_USE_ESP32_EMAC case DeviceModel::DeviceModel_Olimex_ESP32_PoE: case DeviceModel::DeviceModel_Olimex_ESP32_EVB: case DeviceModel::DeviceModel_Olimex_ESP32_GATEWAY: case DeviceModel::DeviceModel_wESP32: case DeviceModel::DeviceModel_WT32_ETH01: -#if defined(ESP32_CLASSIC) && FEATURE_ETHERNET +# if defined(ESP32_CLASSIC) && FEATURE_ETHERNET return size_MB == 4; -#else // if defined(ESP32_CLASSIC) && FEATURE_ETHERNET +# else // if defined(ESP32_CLASSIC) && FEATURE_ETHERNET return false; -#endif // if defined(ESP32_CLASSIC) && FEATURE_ETHERNET - +# endif // if defined(ESP32_CLASSIC) && FEATURE_ETHERNET +#endif // if CONFIG_ETH_USE_ESP32_EMAC case DeviceModel::DeviceModel_default: case DeviceModel::DeviceModel_MAX: return true; @@ -966,7 +963,6 @@ void addPredefinedRules(const GpioFactorySettingsStruct& gpio_settings) { } } - // ******************************************************************************** // change of device: cleanup old device and reset default settings // ******************************************************************************** @@ -980,7 +976,8 @@ void setTaskDevice_to_TaskIndex(pluginID_t taskdevicenumber, taskIndex_t taskInd ClearCustomTaskSettings(taskIndex); Settings.TaskDeviceNumber[taskIndex] = taskdevicenumber.value; -// Settings.getPluginID_for_task(taskIndex) = taskdevicenumber; + + // Settings.getPluginID_for_task(taskIndex) = taskdevicenumber; if (validPluginID_fullcheck(taskdevicenumber)) // set default values if a new device has been selected { diff --git a/src/src/Helpers/StringGenerator_GPIO.cpp b/src/src/Helpers/StringGenerator_GPIO.cpp index 6c9763de4e..6ae416bf88 100644 --- a/src/src/Helpers/StringGenerator_GPIO.cpp +++ b/src/src/Helpers/StringGenerator_GPIO.cpp @@ -295,11 +295,11 @@ const __FlashStringHelper* getConflictingUse(int gpio, PinSelectPurpose purpose) if (includeEthernet && Settings.isEthernetPinOptional(gpio)) { if (isGpioUsedInETHClockMode(Settings.ETH_Clock_Mode, gpio)) { return F("Eth Clock"); } - if (Settings.ETH_Pin_mdc == gpio) { return F("Eth MDC"); } + if (Settings.ETH_Pin_mdc_cs == gpio) { return F("Eth MDC"); } - if (Settings.ETH_Pin_mdio == gpio) { return F("Eth MDIO"); } + if (Settings.ETH_Pin_mdio_irq == gpio) { return F("Eth MDIO"); } - if (Settings.ETH_Pin_power == gpio) { return F("Eth Pwr"); } + if (Settings.ETH_Pin_power_rst == gpio) { return F("Eth Pwr"); } return F("Eth"); } diff --git a/src/src/WebServer/HardwarePage.cpp b/src/src/WebServer/HardwarePage.cpp index 0029b93da4..c91e854462 100644 --- a/src/src/WebServer/HardwarePage.cpp +++ b/src/src/WebServer/HardwarePage.cpp @@ -72,11 +72,13 @@ void handle_hardware() { Settings.Pin_sd_cs = getFormItemInt(F("sd")); #if FEATURE_ETHERNET Settings.ETH_Phy_Addr = getFormItemInt(F("ethphy")); - Settings.ETH_Pin_mdc = getFormItemInt(F("ethmdc")); - Settings.ETH_Pin_mdio = getFormItemInt(F("ethmdio")); - Settings.ETH_Pin_power = getFormItemInt(F("ethpower")); + Settings.ETH_Pin_mdc_cs = getFormItemInt(F("ethmdc")); + Settings.ETH_Pin_mdio_irq = getFormItemInt(F("ethmdio")); + Settings.ETH_Pin_power_rst = getFormItemInt(F("ethpower")); Settings.ETH_Phy_Type = static_cast(getFormItemInt(F("ethtype"))); +#if CONFIG_ETH_USE_ESP32_EMAC Settings.ETH_Clock_Mode = static_cast(getFormItemInt(F("ethclock"))); +#endif Settings.NetworkMedium = static_cast(getFormItemInt(F("ethwifi"))); #endif // if FEATURE_ETHERNET int gpio = 0; @@ -242,41 +244,109 @@ void handle_hardware() { addSelector(F("ethwifi"), 2, ethWifiOptions, nullptr, nullptr, static_cast(Settings.NetworkMedium), false, true); } addFormNote(F("Change Switch between WiFi and Ethernet requires reboot to activate")); - addRowLabel_tr_id(F("Ethernet PHY type"), F("ethtype")); { - #if ESP_IDF_VERSION_MAJOR > 3 - const uint32_t nrItems = 5; - #else - const uint32_t nrItems = 2; - #endif - const __FlashStringHelper * ethPhyTypes[nrItems] = { - toString(EthPhyType_t::LAN8710), - toString(EthPhyType_t::TLK110) - #if ESP_IDF_VERSION_MAJOR > 3 - , - toString(EthPhyType_t::RTL8201), - toString(EthPhyType_t::DP83848), - toString(EthPhyType_t::DM9051) - #endif + const __FlashStringHelper * ethPhyTypes[] = { + toString(EthPhyType_t::notSet), + +# if CONFIG_ETH_USE_ESP32_EMAC + toString(EthPhyType_t::LAN8720), + toString(EthPhyType_t::TLK110), +#if ESP_IDF_VERSION_MAJOR > 3 + toString(EthPhyType_t::RTL8201), + toString(EthPhyType_t::JL1101), + toString(EthPhyType_t::DP83848), + toString(EthPhyType_t::KSZ8041), + toString(EthPhyType_t::KSZ8081), +#endif +# endif // if CONFIG_ETH_USE_ESP32_EMAC + +#if ESP_IDF_VERSION_MAJOR >= 5 +# if CONFIG_ETH_SPI_ETHERNET_DM9051 + toString(EthPhyType_t::DM9051), +# endif // if CONFIG_ETH_SPI_ETHERNET_DM9051 +# if CONFIG_ETH_SPI_ETHERNET_W5500 + toString(EthPhyType_t::W5500), +# endif // if CONFIG_ETH_SPI_ETHERNET_W5500 +# if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + toString(EthPhyType_t::KSZ8851), +# endif // if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL +#endif }; const int ethPhyTypes_index[] = { - static_cast(EthPhyType_t::LAN8710), - static_cast(EthPhyType_t::TLK110) - #if ESP_IDF_VERSION_MAJOR > 3 - , - static_cast(EthPhyType_t::RTL8201), - static_cast(EthPhyType_t::DP83848), - static_cast(EthPhyType_t::DM9051) - #endif + static_cast(EthPhyType_t::notSet), + +# if CONFIG_ETH_USE_ESP32_EMAC + static_cast(EthPhyType_t::LAN8720), + static_cast(EthPhyType_t::TLK110), +#if ESP_IDF_VERSION_MAJOR > 3 + static_cast(EthPhyType_t::RTL8201), + static_cast(EthPhyType_t::JL1101), + static_cast(EthPhyType_t::DP83848), + static_cast(EthPhyType_t::KSZ8041), + static_cast(EthPhyType_t::KSZ8081), +#endif +# endif // if CONFIG_ETH_USE_ESP32_EMAC + +#if ESP_IDF_VERSION_MAJOR >= 5 +# if CONFIG_ETH_SPI_ETHERNET_DM9051 + static_cast(EthPhyType_t::DM9051), +# endif // if CONFIG_ETH_SPI_ETHERNET_DM9051 +# if CONFIG_ETH_SPI_ETHERNET_W5500 + static_cast(EthPhyType_t::W5500), +# endif // if CONFIG_ETH_SPI_ETHERNET_W5500 +# if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL + static_cast(EthPhyType_t::KSZ8851), +# endif // if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL +#endif }; - addSelector(F("ethtype"), nrItems, ethPhyTypes, ethPhyTypes_index, nullptr, static_cast(Settings.ETH_Phy_Type), false, true); + constexpr unsigned nrItems = NR_ELEMENTS(ethPhyTypes_index); + + + const int choice = isValid(Settings.ETH_Phy_Type) + ? static_cast(Settings.ETH_Phy_Type) + : static_cast(EthPhyType_t::notSet); + + addFormSelector( + F("Ethernet PHY type"), + F("ethtype"), + nrItems, + ethPhyTypes, + ethPhyTypes_index, + choice, + false); } + +#if CONFIG_ETH_USE_SPI_ETHERNET && CONFIG_ETH_USE_ESP32_EMAC +#define MDC_CS_PIN_DESCR "Ethernet MDC/CS pin" +#define MIO_IRQ_PIN_DESCR "Ethernet MDIO/IRQ pin" +#define PWR_RST_PIN_DESCR "Ethernet Power/RST pin" +#elif CONFIG_ETH_USE_SPI_ETHERNET +#define MDC_CS_PIN_DESCR "Ethernet CS pin" +#define MIO_IRQ_PIN_DESCR "Ethernet IRQ pin" +#define PWR_RST_PIN_DESCR "Ethernet RST pin" +#else // #elif CONFIG_ETH_USE_ESP32_EMAC +#define MDC_CS_PIN_DESCR "Ethernet MDC pin" +#define MIO_IRQ_PIN_DESCR "Ethernet MIO pin" +#define PWR_RST_PIN_DESCR "Ethernet Power pin" +#endif + addFormNumericBox(F("Ethernet PHY Address"), F("ethphy"), Settings.ETH_Phy_Addr, -1, 127); - addFormNote(F("I²C-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110, -1 autodetect)")); - addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_output(F("Ethernet MDC pin")), F("ethmdc"), Settings.ETH_Pin_mdc); - addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_input(F("Ethernet MIO pin")), F("ethmdio"), Settings.ETH_Pin_mdio); - addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_output(F("Ethernet Power pin")), F("ethpower"), Settings.ETH_Pin_power); + addFormNote(F("I²C-address of Ethernet PHY" +#if CONFIG_ETH_USE_ESP32_EMAC + " (0 or 1 for LAN8720, 31 for TLK110, -1 autodetect)" +#endif + )); + addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_output( + F(MDC_CS_PIN_DESCR)), + F("ethmdc"), Settings.ETH_Pin_mdc_cs); + addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_input( + F(MIO_IRQ_PIN_DESCR)), + F("ethmdio"), Settings.ETH_Pin_mdio_irq); + addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_output( + F(PWR_RST_PIN_DESCR)), + F("ethpower"), Settings.ETH_Pin_power_rst); +#if CONFIG_ETH_USE_ESP32_EMAC addRowLabel_tr_id(F("Ethernet Clock"), F("ethclock")); { const __FlashStringHelper * ethClockOptions[4] = { @@ -287,6 +357,7 @@ void handle_hardware() { }; addSelector(F("ethclock"), 4, ethClockOptions, nullptr, nullptr, static_cast(Settings.ETH_Clock_Mode), false, true); } +#endif #endif // if FEATURE_ETHERNET addFormSubHeader(F("GPIO boot states"));