From c19cbd27bb979847a5a8cef3627e08bad8261a2c Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Fri, 19 Aug 2022 15:52:53 +0200 Subject: [PATCH 01/10] Added support for W5500 via. esp netif interface. --- libraries/Ethernet/src/ETH.cpp | 121 +++++++++++++++++++++++++++++++++ libraries/Ethernet/src/ETH.h | 10 ++- 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index db664473c67..8157833573c 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -402,6 +402,127 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ return true; } +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 +bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint8_t phy_addr, uint8_t spi_clock_mhz, spi_host_device_t spi_host, eth_phy_type_t type) { + if (type != ETH_PHY_W5500) { + log_e("Using this ETH.begin() method does not support other ethernet modules, besides the W5500."); + return false; + } + else if (mac_address == nullptr) { + log_e("Passed mac address needs to be a valid array the w5500 should be initalized with."); + return false; + } + else if (spi_clock_mhz > 80U) { + log_e("Using a higher spi clock speed than 80MHz is not possible."); + return false; + } + else if (spi_clock_mhz > 30U) { + log_w("Using a higher spi clock speed than 30MHz is possible, but not recommended as it might cause distortions."); + } + + // Initializes TCP/IP network interface (should be called only once in application) + // and create default event loop that is running in the background. + tcpipInit(); + esp_err_t error = tcpip_adapter_set_default_eth_handlers(); + if (error != ESP_OK) { + log_e("Method: (tcpip_adapter_set_default_eth_handlers) failed with error: (%s)", esp_err_to_name(error)); + return false; + } + + // Create instance of esp-netif for SPI Ethernet. + esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); + esp_netif_config_t cfg_spi = { + .base = &esp_netif_config, + .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH + }; + esp_netif_t *eth_netif = esp_netif_new(&cfg_spi); + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); + + // Install GPIO ISR handler to be able to service SPI Eth modlues interrupts. + error = gpio_install_isr_service(0); + if (error != ESP_OK) { + log_e("Method: (spi_bus_initialize) failed with error: (%s)", esp_err_to_name(error)); + return false; + } + + spi_device_handle_t spi_handle = nullptr; + spi_bus_config_t buscfg = { + .mosi_io_num = mosi_gpio, + .miso_io_num = miso_gpio, + .sclk_io_num = slck_gpio, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + }; + error = spi_bus_initialize(spi_host, &buscfg, 1); + if (error != ESP_OK) { + log_e("Method: (spi_bus_initialize) failed with error: (%s)", esp_err_to_name(error)); + return false; + } + spi_device_interface_config_t devcfg = { + .command_bits = 16, + .address_bits = 8, + .mode = 0, + .clock_speed_hz = spi_clock_mhz * 1000 * 1000, + .spics_io_num = cs_gpio, + .queue_size = 20 + }; + error = spi_bus_add_device(spi_host, &devcfg, &spi_handle); + if (error != ESP_OK) { + log_e("Method: (spi_bus_add_device) failed with error: (%s)", esp_err_to_name(error)); + return false; + } + + // W5500 ethernet driver is based on spi driver. + eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle); + w5500_config.int_gpio_num = int_gpio; + + esp_eth_mac_t* eth_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); + if (eth_mac == nullptr) { + log_e("Method: (esp_eth_mac_new_w5500) failed with error: (%s)", esp_err_to_name(ESP_FAIL)); + return false; + } + + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + phy_config.phy_addr = phy_addr; + phy_config.reset_gpio_num = phy_rst_gpio; + + esp_eth_phy_t *eth_phy = esp_eth_phy_new_w5500(&phy_config); + if (eth_phy == nullptr) { + log_e("Method: (esp_eth_phy_new) failed with error: (%s)", esp_err_to_name(ESP_FAIL)); + return false; + } + + esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(eth_mac, eth_phy); + eth_handle = nullptr; + + error = esp_eth_driver_install(ð_config, ð_handle); + if (error != ESP_OK || eth_handle == nullptr) { + log_e("Method: (esp_eth_driver_install) failed with error: (%s)", esp_err_to_name(error)); + return false; + } + + // Set the mac address. + esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, mac_address); + + // Attach Ethernet driver to TCP/IP stack. + error = esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)); + if (error != ESP_OK) { + log_e("Method: (esp_netif_attach) failed with error: (%s)", esp_err_to_name(error)); + return false; + } + + // Start Ethernet driver state machine. + error = esp_eth_start(eth_handle); + if (error != ESP_OK) { + log_e("Method: (esp_eth_start) failed with error: (%s)", esp_err_to_name(error)); + return false; + } + + return true; +} +#endif + bool ETHClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) { esp_err_t err = ESP_OK; diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index 647b59848d6..e39bab2e67b 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -25,6 +25,10 @@ #include "esp_system.h" #include "esp_eth.h" +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 + bool begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); +#endif + #ifndef ETH_PHY_ADDR #define ETH_PHY_ADDR 0 #endif @@ -53,7 +57,7 @@ typedef enum { ETH_CLOCK_GPIO0_IN, ETH_CLOCK_GPIO0_OUT, ETH_CLOCK_GPIO16_OUT, ETH_CLOCK_GPIO17_OUT } eth_clock_mode_t; #endif -typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_RTL8201, ETH_PHY_DP83848, ETH_PHY_DM9051, ETH_PHY_KSZ8041, ETH_PHY_KSZ8081, ETH_PHY_MAX } eth_phy_type_t; +typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_RTL8201, ETH_PHY_DP83848, ETH_PHY_DM9051, ETH_PHY_KSZ8041, ETH_PHY_KSZ8081, ETH_PHY_W5500, ETH_PHY_MAX } eth_phy_type_t; #define ETH_PHY_IP101 ETH_PHY_TLK110 class ETHClass { @@ -77,6 +81,10 @@ class ETHClass { bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE, bool use_mac_from_efuse=false); +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 + bool begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); +#endif + bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000); const char * getHostname(); From 64404bae8c7d8a5b82633c77d04ddf63b24c1d46 Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Fri, 19 Aug 2022 16:37:01 +0200 Subject: [PATCH 02/10] Added example for new begin method. --- .../Ethernet/examples/ETH_W5500/.skip.esp32c3 | 0 .../Ethernet/examples/ETH_W5500/.skip.esp32s2 | 0 .../Ethernet/examples/ETH_W5500/.skip.esp32s3 | 0 .../Ethernet/examples/ETH_W5500/ETH_W5500.ino | 91 +++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 libraries/Ethernet/examples/ETH_W5500/.skip.esp32c3 create mode 100644 libraries/Ethernet/examples/ETH_W5500/.skip.esp32s2 create mode 100644 libraries/Ethernet/examples/ETH_W5500/.skip.esp32s3 create mode 100644 libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino diff --git a/libraries/Ethernet/examples/ETH_W5500/.skip.esp32c3 b/libraries/Ethernet/examples/ETH_W5500/.skip.esp32c3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Ethernet/examples/ETH_W5500/.skip.esp32s2 b/libraries/Ethernet/examples/ETH_W5500/.skip.esp32s2 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Ethernet/examples/ETH_W5500/.skip.esp32s3 b/libraries/Ethernet/examples/ETH_W5500/.skip.esp32s3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino b/libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino new file mode 100644 index 00000000000..1f311195ce3 --- /dev/null +++ b/libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino @@ -0,0 +1,91 @@ +/* + This sketch shows the Ethernet event usage + +*/ + +#include + +#define MOSI_GPIO 23 +#define MISO_GPIO 38 +#define SCLK_GPIO 18 +#define CS_GPIO 26 +#define INT_GPIO 34 +#define PHY_RST_GPIO 19 + +static bool eth_connected = false; + +void WiFiEvent(WiFiEvent_t event) +{ + switch (event) { + case ARDUINO_EVENT_ETH_START: + Serial.println("ETH Started"); + //set eth hostname here + ETH.setHostname("esp32-ethernet"); + break; + case ARDUINO_EVENT_ETH_CONNECTED: + Serial.println("ETH Connected"); + break; + case ARDUINO_EVENT_ETH_GOT_IP: + Serial.print("ETH MAC: "); + Serial.print(ETH.macAddress()); + Serial.print(", IPv4: "); + Serial.print(ETH.localIP()); + if (ETH.fullDuplex()) { + Serial.print(", FULL_DUPLEX"); + } + Serial.print(", "); + Serial.print(ETH.linkSpeed()); + Serial.println("Mbps"); + eth_connected = true; + break; + case ARDUINO_EVENT_ETH_DISCONNECTED: + Serial.println("ETH Disconnected"); + eth_connected = false; + break; + case ARDUINO_EVENT_ETH_STOP: + Serial.println("ETH Stopped"); + eth_connected = false; + break; + default: + break; + } +} + +void testClient(const char * host, uint16_t port) +{ + Serial.print("\nconnecting to "); + Serial.println(host); + + WiFiClient client; + if (!client.connect(host, port)) { + Serial.println("connection failed"); + return; + } + client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host); + while (client.connected() && !client.available()); + while (client.available()) { + Serial.write(client.read()); + } + + Serial.println("closing connection\n"); + client.stop(); +} + +void setup() +{ + Serial.begin(115200); + WiFi.onEvent(WiFiEvent); + + std::array mac_address; + WiFi.macAddress(mac_address.data()); + ETH.begin_w5500(mac_address.data(), MOSI_GPIO, MISO_GPIO, SCLK_GPIO, CS_GPIO, INT_GPIO, PHY_RST_GPIO); +} + + +void loop() +{ + if (eth_connected) { + testClient("google.com", 80); + } + delay(10000); +} From d3e5932a0a4bc83ed66e3c78c713fc63824c29f0 Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Mon, 22 Aug 2022 12:27:31 +0200 Subject: [PATCH 03/10] Added HttpsOTAUpdate over Ethernet with example. --- .../HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino | 98 +++++++++++++++++++ ...A_Update.ino => HTTPS_OTA_Update_WiFi.ino} | 2 +- .../examples/HTTPS_OTA_Update/Readme.md | 11 ++- libraries/Update/src/HttpsOTAUpdate.cpp | 69 ++++++++++++- libraries/Update/src/HttpsOTAUpdate.h | 8 +- libraries/Update/src/UpdateNetworkInterface.h | 15 +++ 6 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino rename libraries/Update/examples/HTTPS_OTA_Update/{HTTPS_OTA_Update.ino => HTTPS_OTA_Update_WiFi.ino} (97%) create mode 100644 libraries/Update/src/UpdateNetworkInterface.h diff --git a/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino b/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino new file mode 100644 index 00000000000..2c021ef4f9a --- /dev/null +++ b/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino @@ -0,0 +1,98 @@ +// This sketch provide the functionality of OTA Firmware Upgrade +#include "ETH.h" +#include "HttpsOTAUpdate.h" +// This sketch shows how to implement HTTPS firmware update Over The Air. +// Please provide your WiFi credentials, https URL to the firmware image and the server certificate. + +static const char *url = "https://example.com/firmware.bin"; //state url of your firmware image + +static const char *server_certificate = "-----BEGIN CERTIFICATE-----\n" \ + "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n" \ + "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \ + "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n" \ + "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n" \ + "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" \ + "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n" \ + "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n" \ + "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n" \ + "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n" \ + "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n" \ + "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n" \ + "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n" \ + "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n" \ + "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n" \ + "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n" \ + "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n" \ + "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n" \ + "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n" \ + "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n" \ + "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n" \ + "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n" \ + "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n" \ + "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n" \ + "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n" \ + "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n" \ + "-----END CERTIFICATE-----"; + +// Replace GPIO pins with the GPIO pins of your W5500 +#define MOSI_GPIO 23 +#define MISO_GPIO 38 +#define SCLK_GPIO 18 +#define CS_GPIO 26 +#define INT_GPIO 34 +#define PHY_RST_GPIO 19 + +static HttpsOTAStatus_t otastatus; + +void HttpEvent(HttpEvent_t *event) +{ + switch(event->event_id) { + case HTTP_EVENT_ERROR: + Serial.println("Http Event Error"); + break; + case HTTP_EVENT_ON_CONNECTED: + Serial.println("Http Event On Connected"); + break; + case HTTP_EVENT_HEADER_SENT: + Serial.println("Http Event Header Sent"); + break; + case HTTP_EVENT_ON_HEADER: + Serial.printf("Http Event On Header, key=%s, value=%s\n", event->header_key, event->header_value); + break; + case HTTP_EVENT_ON_DATA: + break; + case HTTP_EVENT_ON_FINISH: + Serial.println("Http Event On Finish"); + break; + case HTTP_EVENT_DISCONNECTED: + Serial.println("Http Event Disconnected"); + break; + } +} + +void setup(){ + + Serial.begin(115200); + std::array mac_address; + WiFi.macAddress(mac_address.data()); + Serial.print("Attempting to connect to W5500"); + ETH.begin_w5500(mac_address.data(), MOSI_GPIO, MISO_GPIO, SCLK_GPIO, CS_GPIO, INT_GPIO, PHY_RST_GPIO); + + delay(3000); + + HttpsOTA.onHttpEvent(HttpEvent); + Serial.println("Starting OTA"); + HttpsOTA.begin(url, server_certificate, UpdateNetworkInterface::ETHERNET_IFC, false); + + Serial.println("Please Wait it takes some time ..."); +} + +void loop(){ + otastatus = HttpsOTA.status(); + if(otastatus == HTTPS_OTA_SUCCESS) { + Serial.println("Firmware written successfully. To reboot device, call API ESP.restart() or PUSH restart button on device"); + } else if(otastatus == HTTPS_OTA_FAIL) { + Serial.println("Firmware Upgrade Fail"); + } + delay(1000); +} diff --git a/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update.ino b/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_WiFi.ino similarity index 97% rename from libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update.ino rename to libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_WiFi.ino index 6e32ee5bd58..fb56c7b80ed 100644 --- a/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update.ino +++ b/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_WiFi.ino @@ -82,7 +82,7 @@ void setup(){ HttpsOTA.onHttpEvent(HttpEvent); Serial.println("Starting OTA"); - HttpsOTA.begin(url, server_certificate); + HttpsOTA.begin(url, server_certificate, UpdateNetworkInterface::WIFI_STA_IFC, false); Serial.println("Please Wait it takes some time ..."); } diff --git a/libraries/Update/examples/HTTPS_OTA_Update/Readme.md b/libraries/Update/examples/HTTPS_OTA_Update/Readme.md index 27fdb59612b..50ea54075b5 100644 --- a/libraries/Update/examples/HTTPS_OTA_Update/Readme.md +++ b/libraries/Update/examples/HTTPS_OTA_Update/Readme.md @@ -5,14 +5,15 @@ This sketch allows Arduino user to perform Over The Air (OTA) firmware upgrade. ## HttpsOTA.begin(const char * url, const char * server_certificate, bool skip_cert_common_name_check) -Main API which starts firmware upgrade +Begins the Https OTA update process in another task in the background, requires atleast 16KB of free heap space to use the array that will store the HTTPS packets that are downloaded. ### Parameters -* url : URL for the uploaded firmware image -* server_certificate : Provide the ota server certificate for authentication via HTTPS -* skip_cert_common_name_check : Skip any validation of server certificate CN field +* url : Url to the binary that should be downloaded and flashed onto the 2nd ota data partition +* server_certificate : Root server certificate of the website we are downloading the binary from +* update_network_interface : Underlying network interface we want to download the binary over (Ethernet, WLan, etc.). Ethernet requries using the ETH.h base class +* skip_cert_common_name_check : Wheter the certificate check should be skipped, generally not recommended if the update process needs to be secure, because this makes us vulnerable to man in the middle attacks where an attacker pretends to be the server and we might not download the actual binary we want too, but a binary sent by an attacker instead -The default value provided to skip_cert_common_name_check is true +The default value provided to update_network_interface is UpdateNetworkInterface::DEFAULT_INTERFACE and skip_cert_common_name_check is true ## HttpsOTA.onHttpEvent(function) diff --git a/libraries/Update/src/HttpsOTAUpdate.cpp b/libraries/Update/src/HttpsOTAUpdate.cpp index 106559bd3a4..5ecfba82548 100644 --- a/libraries/Update/src/HttpsOTAUpdate.cpp +++ b/libraries/Update/src/HttpsOTAUpdate.cpp @@ -8,6 +8,7 @@ */ #include #include +#include #include #include @@ -16,6 +17,7 @@ #include "esp32-hal-log.h" #include "esp_http_client.h" #include "esp_https_ota.h" +#include "esp_netif.h" #include "HttpsOTAUpdate.h" #define OTA_TASK_STACK_SIZE 9216 @@ -26,6 +28,7 @@ static esp_http_client_config_t config; static HttpEventCb cb; static EventGroupHandle_t ota_status = NULL;//check for ota status static EventBits_t set_bit; +static ifreq freq; const int OTA_IDLE_BIT = BIT0; const int OTA_UPDATING_BIT = BIT1; @@ -34,7 +37,11 @@ const int OTA_FAIL_BIT = BIT3; esp_err_t http_event_handler(esp_http_client_event_t *event) { - cb(event); + // OTA update will not be stopped if the callback wasn't set, + // because we return ESP_OK either way. + if (cb != nullptr) { + cb(event); + } return ESP_OK; } @@ -84,13 +91,18 @@ void HttpsOTAUpdateClass::onHttpEvent(HttpEventCb cbEvent) cb = cbEvent; } -void HttpsOTAUpdateClass::begin(const char *url, const char *cert_pem, bool skip_cert_common_name_check) +void HttpsOTAUpdateClass::begin(const char *url, const char *cert_pem, UpdateNetworkInterface network_interface, bool skip_cert_common_name_check) { config.url = url; config.cert_pem = cert_pem; config.skip_cert_common_name_check = skip_cert_common_name_check; config.event_handler = http_event_handler; + esp_netif_inherent_config_t network_interface_config; + get_netif_config_from_type(network_interface, network_interface_config); + const esp_err_t error = get_bound_interface_name(network_interface_config.if_key, freq); + config.if_name = error != ESP_OK ? nullptr : &freq; + if(!ota_status) { ota_status = xEventGroupCreate(); if(!ota_status) { @@ -104,4 +116,57 @@ void HttpsOTAUpdateClass::begin(const char *url, const char *cert_pem, bool skip } } +esp_err_t HttpsOTAUpdateClass::get_netif_config_from_type(UpdateNetworkInterface network_interface, esp_netif_inherent_config_t& netif_inherent_config) +{ + esp_err_t error = ESP_OK; + switch (network_interface) { + case UpdateNetworkInterface::DEFAULT_INTERFACE: + error = ESP_ERR_ESP_NETIF_IF_NOT_READY; + break; + case UpdateNetworkInterface::WIFI_STA: + netif_inherent_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA(); + break; + case UpdateNetworkInterface::WIFI_AP: + netif_inherent_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_AP(); + break; + case UpdateNetworkInterface::ETHERNET: + netif_inherent_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); + break; + case UpdateNetworkInterface::POINT_TO_POINT: + netif_inherent_config = ESP_NETIF_INHERENT_DEFAULT_PPP(); + break; + case UpdateNetworkInterface::SERIAL_LINE: + netif_inherent_config = ESP_NETIF_INHERENT_DEFAULT_SLIP(); + break; + default: + error = ESP_ERR_ESP_NETIF_IF_NOT_READY; + log_e("Unexpected UpdateNetworkInterface argument (%u).", static_cast::type>(network_interface)); + break; + } + return error; +} + +esp_err_t HttpsOTAUpdateClass::get_bound_interface_name(const char* is_key, ifreq& freq) +{ + if (is_key == nullptr) { + return ESP_ERR_INVALID_ARG; + } + log_d("Trying to get network interface with key (%s).", is_key); + + esp_netif_t* netif = esp_netif_get_handle_from_ifkey(is_key); + if (netif == nullptr) { + log_e("Attempting to get network interface returned NULL."); + return ESP_ERR_ESP_NETIF_IF_NOT_READY; + } + + const esp_err_t error = esp_netif_get_netif_impl_name(netif, freq.ifr_name); + if (error != ESP_OK) { + log_e("Error (%s) while getting bound interface name.", esp_err_to_name(error)); + return error; + } + + log_d("Bound interface name is (%s).", freq.ifr_name); + return error; +} + HttpsOTAUpdateClass HttpsOTA; diff --git a/libraries/Update/src/HttpsOTAUpdate.h b/libraries/Update/src/HttpsOTAUpdate.h index c2030a96477..fd18a4465be 100644 --- a/libraries/Update/src/HttpsOTAUpdate.h +++ b/libraries/Update/src/HttpsOTAUpdate.h @@ -1,6 +1,8 @@ #ifndef HTPSPOTUADATE_H #define HTPSPOTUADATE_H #include "esp_http_client.h" +#include "esp_netif_types.h" +#include "UpdateNetworkInterface.h" #define HttpEvent_t esp_http_client_event_t typedef enum @@ -15,9 +17,13 @@ typedef enum class HttpsOTAUpdateClass { public: - void begin(const char *url, const char *cert_pem, bool skip_cert_common_name_check = true); + void begin(const char *url, const char *cert_pem, UpdateNetworkInterface network_interface = UpdateNetworkInterface::DEFAULT_INTERFACE, bool skip_cert_common_name_check = false); void onHttpEvent(void (*http_event_cb_t)(HttpEvent_t *)); HttpsOTAStatus_t status(); + + private: + esp_err_t get_netif_config_from_type(UpdateNetworkInterface network_interface, esp_netif_inherent_config_t& netif_inherent_config); + esp_err_t get_bound_interface_name(const char* is_key, ifreq& freq); }; extern HttpsOTAUpdateClass HttpsOTA; diff --git a/libraries/Update/src/UpdateNetworkInterface.h b/libraries/Update/src/UpdateNetworkInterface.h new file mode 100644 index 00000000000..8b43b49ca35 --- /dev/null +++ b/libraries/Update/src/UpdateNetworkInterface.h @@ -0,0 +1,15 @@ +#ifndef UPDATE_NETWORK_INTERFACE +#define UPDATE_NETWORK_INTERFACE + +#include + +enum class UpdateNetworkInterface : const uint8_t { + DEFAULT_IFC, + WIFI_STA_IFC, + WIFI_AP_IFC, + ETHERNET_IFC, + POINT_TO_POINT_IFC, + SERIAL_LINE_IFC +}; + +#endif // UPDATE_NETWORK_INTERFACE From 3495e73d74c275f43036795a03da1f59a958b72d Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Mon, 22 Aug 2022 14:20:12 +0200 Subject: [PATCH 04/10] Fixed include statement. --- libraries/Ethernet/src/ETH.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index e39bab2e67b..138f4322603 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -26,7 +26,7 @@ #include "esp_eth.h" #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 - bool begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); +#include "driver/spi_master.h" #endif #ifndef ETH_PHY_ADDR From a6433413885a15206602c3645bb281d548e7ab1e Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Tue, 23 Aug 2022 15:49:43 +0200 Subject: [PATCH 05/10] Added another optional argument for stack size. --- libraries/Ethernet/src/ETH.cpp | 3 ++- libraries/Ethernet/src/ETH.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 8157833573c..52fa5a6c5e5 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -403,7 +403,7 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ } #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 -bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint8_t phy_addr, uint8_t spi_clock_mhz, spi_host_device_t spi_host, eth_phy_type_t type) { +bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size, uint8_t phy_addr, uint8_t spi_clock_mhz, spi_host_device_t spi_host, eth_phy_type_t type) { if (type != ETH_PHY_W5500) { log_e("Using this ETH.begin() method does not support other ethernet modules, besides the W5500."); return false; @@ -438,6 +438,7 @@ bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_g esp_netif_t *eth_netif = esp_netif_new(&cfg_spi); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); + mac_config.rx_task_stack_size = mac_stack_size; // Install GPIO ISR handler to be able to service SPI Eth modlues interrupts. error = gpio_install_isr_service(0); diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index 138f4322603..dc4fcee2dc5 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -82,7 +82,7 @@ class ETHClass { bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE, bool use_mac_from_efuse=false); #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 - bool begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); + bool begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size = 2048, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); #endif bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000); From d143ca2823a25adaf7c551c5398aab231145b1a3 Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Wed, 24 Aug 2022 10:00:23 +0200 Subject: [PATCH 06/10] Fixed incorrect comment. --- libraries/Ethernet/src/ETH.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 52fa5a6c5e5..9893533c598 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -443,7 +443,7 @@ bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_g // Install GPIO ISR handler to be able to service SPI Eth modlues interrupts. error = gpio_install_isr_service(0); if (error != ESP_OK) { - log_e("Method: (spi_bus_initialize) failed with error: (%s)", esp_err_to_name(error)); + log_e("Method: (gpio_install_isr_service) failed with error: (%s)", esp_err_to_name(error)); return false; } From 8f2a4b2fc88bb4a7dd2ce746780ff7ddac0d9c4b Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Wed, 24 Aug 2022 11:52:44 +0200 Subject: [PATCH 07/10] Added additional optional parameters. --- libraries/Ethernet/src/ETH.cpp | 5 +++-- libraries/Ethernet/src/ETH.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 9893533c598..6a609475ae5 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -403,7 +403,7 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ } #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 -bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size, uint8_t phy_addr, uint8_t spi_clock_mhz, spi_host_device_t spi_host, eth_phy_type_t type) { +bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size, int spi_max_transfer_size, spi_common_dma_t spi_dma_channel, uint8_t phy_addr, uint8_t spi_clock_mhz, spi_host_device_t spi_host, eth_phy_type_t type) { if (type != ETH_PHY_W5500) { log_e("Using this ETH.begin() method does not support other ethernet modules, besides the W5500."); return false; @@ -454,8 +454,9 @@ bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_g .sclk_io_num = slck_gpio, .quadwp_io_num = -1, .quadhd_io_num = -1, + .max_transfer_sz = spi_max_transfer_size }; - error = spi_bus_initialize(spi_host, &buscfg, 1); + error = spi_bus_initialize(spi_host, &buscfg, spi_dma_channel); if (error != ESP_OK) { log_e("Method: (spi_bus_initialize) failed with error: (%s)", esp_err_to_name(error)); return false; diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index dc4fcee2dc5..f1231a12a7b 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -82,7 +82,7 @@ class ETHClass { bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE, bool use_mac_from_efuse=false); #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 - bool begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size = 2048, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); + bool begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size = 2048, int spi_max_transfer_size = 0, spi_common_dma_t spi_dma_channel = spi_common_dma_t::SPI_DMA_CH_AUTO, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); #endif bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000); From 8a91e51286cbfc3db01d8e3d99fbb29da1b5e3ae Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Mon, 29 Aug 2022 16:39:19 +0200 Subject: [PATCH 08/10] Attempt to fix spi driver not blocking semaphore. --- cores/esp32/esp32-hal-spi.c | 42 ++++++++++++++++++++++++++++++++++ cores/esp32/esp32-hal-spi.h | 6 ++++- libraries/Ethernet/src/ETH.cpp | 22 ++++++++++++++---- libraries/Ethernet/src/ETH.h | 10 ++++++-- libraries/SPI/src/SPI.cpp | 7 ++++++ libraries/SPI/src/SPI.h | 15 +++++++++++- 6 files changed, 94 insertions(+), 8 deletions(-) diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index 39ad027be55..07245b87093 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -55,6 +55,10 @@ #include "esp_intr.h" #endif +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 +#include +#endif + struct spi_struct_t { spi_dev_t * dev; #if !CONFIG_DISABLE_HAL_LOCKS @@ -135,6 +139,29 @@ static spi_t _spi_bus_array[] = { {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3} #endif }; +#elif ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 +#define SPI_MUTEX_LOCK() if (spi_handle != NULL && spi->num == spi_host) { spi_lock_error = spi_device_acquire_bus(spi_handle, portMAX_DELAY); }\ + do {} while ((xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS)) +#define SPI_MUTEX_UNLOCK() if (spi_handle != NULL && spi_lock_error == ESP_OK) { spi_device_release_bus(spi_handle); }\ + xSemaphoreGive(spi->lock) + +static spi_t _spi_bus_array[] = { +#if CONFIG_IDF_TARGET_ESP32S2 + {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0}, + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2} +#elif CONFIG_IDF_TARGET_ESP32S3 + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 1} +#elif CONFIG_IDF_TARGET_ESP32C3 + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0} +#else + {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0}, + {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1}, + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3} +#endif +}; #else #define SPI_MUTEX_LOCK() do {} while (xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS) #define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock) @@ -158,6 +185,12 @@ static spi_t _spi_bus_array[] = { }; #endif +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 + spi_device_handle_t spi_handle = NULL; + uint8_t spi_host = 0; + esp_err_t spi_lock_error = ESP_FAIL; +#endif + void spiAttachSCK(spi_t * spi, int8_t sck) { if(!spi) { @@ -632,6 +665,15 @@ uint8_t spiGetBitOrder(spi_t * spi) return (spi->dev->ctrl.wr_bit_order | spi->dev->ctrl.rd_bit_order) == 0; } +void spiSetDeviceHandle(void * spi_device_handle, uint8_t spi_host_device) +{ +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 + spi_handle = spi_device_handle; + // Increase number by 1, because SPI_HOST_1 is 0, SPI_HOST_2 is 1 and SPI_HOST_3 is 2. + spi_host = spi_host_device + 1U; +#endif +} + void spiSetBitOrder(spi_t * spi, uint8_t bitOrder) { if(!spi) { diff --git a/cores/esp32/esp32-hal-spi.h b/cores/esp32/esp32-hal-spi.h index 89ceefccd60..5233b4e18c3 100644 --- a/cores/esp32/esp32-hal-spi.h +++ b/cores/esp32/esp32-hal-spi.h @@ -23,6 +23,10 @@ extern "C" { #include #include +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 +#include +#endif + #define SPI_HAS_TRANSACTION #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 @@ -95,7 +99,7 @@ void spiWaitReady(spi_t * spi); uint32_t spiGetClockDiv(spi_t * spi); uint8_t spiGetDataMode(spi_t * spi); uint8_t spiGetBitOrder(spi_t * spi); - +void spiSetDeviceHandle(void * spi_device_handle, uint8_t spi_host_device); /* * Non transaction based lock methods (each locks and unlocks when called) diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 6a609475ae5..f725f842bf9 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -40,6 +40,12 @@ #include "lwip/err.h" #include "lwip/dns.h" + +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 + #include + #include +#endif + extern void tcpipInit(); #if ESP_IDF_VERSION_MAJOR > 3 @@ -403,7 +409,7 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ } #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 -bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size, int spi_max_transfer_size, spi_common_dma_t spi_dma_channel, uint8_t phy_addr, uint8_t spi_clock_mhz, spi_host_device_t spi_host, eth_phy_type_t type) { +bool ETHClass::beginW5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size, int spi_max_transfer_size, spi_common_dma_t spi_dma_channel, uint8_t phy_addr, uint8_t spi_clock_mhz, spi_host_device_t spi_host, eth_phy_type_t type) { if (type != ETH_PHY_W5500) { log_e("Using this ETH.begin() method does not support other ethernet modules, besides the W5500."); return false; @@ -447,7 +453,7 @@ bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_g return false; } - spi_device_handle_t spi_handle = nullptr; + spi_device_handle = nullptr; spi_bus_config_t buscfg = { .mosi_io_num = mosi_gpio, .miso_io_num = miso_gpio, @@ -469,14 +475,14 @@ bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_g .spics_io_num = cs_gpio, .queue_size = 20 }; - error = spi_bus_add_device(spi_host, &devcfg, &spi_handle); + error = spi_bus_add_device(spi_host, &devcfg, &spi_device_handle); if (error != ESP_OK) { log_e("Method: (spi_bus_add_device) failed with error: (%s)", esp_err_to_name(error)); return false; } // W5500 ethernet driver is based on spi driver. - eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle); + eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_device_handle); w5500_config.int_gpio_num = int_gpio; esp_eth_mac_t* eth_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); @@ -523,6 +529,14 @@ bool ETHClass::begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_g return true; } + +spi_device_handle_t& ETHClass::getSpiDeviceHandle(void) { + return spi_device_handle; +} + +spi_host_device_t& ETHClass::getSpiHost(void) { + return spi_host_device; +} #endif bool ETHClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index f1231a12a7b..129e2bf725c 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -26,7 +26,7 @@ #include "esp_eth.h" #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 -#include "driver/spi_master.h" +#include #endif #ifndef ETH_PHY_ADDR @@ -66,6 +66,10 @@ class ETHClass { bool staticIP; #if ESP_IDF_VERSION_MAJOR > 3 esp_eth_handle_t eth_handle; +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 + spi_device_handle_t spi_device_handle = nullptr; + spi_host_device_t spi_host_device = spi_host_device_t::SPI3_HOST; +#endif protected: bool started; @@ -82,7 +86,9 @@ class ETHClass { bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE, bool use_mac_from_efuse=false); #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 - bool begin_w5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size = 2048, int spi_max_transfer_size = 0, spi_common_dma_t spi_dma_channel = spi_common_dma_t::SPI_DMA_CH_AUTO, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); + bool beginW5500(uint8_t* mac_address, int8_t mosi_gpio, int8_t miso_gpio, int8_t slck_gpio, int8_t cs_gpio, int8_t int_gpio, int8_t phy_rst_gpio, uint32_t mac_stack_size = 2048, int spi_max_transfer_size = 0, spi_common_dma_t spi_dma_channel = spi_common_dma_t::SPI_DMA_CH_AUTO, uint8_t phy_addr = 1, uint8_t spi_clock_mhz = 10, spi_host_device_t spi_host = SPI3_HOST, eth_phy_type_t type = ETH_PHY_W5500); + spi_device_handle_t& getSpiDeviceHandle(void); + spi_host_device_t& getSpiHost(void); #endif bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000); diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 23a35c0d357..d4dbf9c062e 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -158,6 +158,13 @@ void SPIClass::setClockDivider(uint32_t clockDiv) SPI_PARAM_UNLOCK(); } +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 +void SPIClass::setSpiDeviceHandle(spi_device_handle_t& spi_device_handle, spi_host_device_t& spi_host_device) +{ + spiSetDeviceHandle(spi_device_handle, spi_host_device); +} +#endif + uint32_t SPIClass::getClockDivider() { return spiGetClockDiv(_spi); diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 7f07e5beb0d..7b7c56770c5 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -27,6 +27,10 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 +#include +#endif + #define SPI_HAS_TRANSACTION class SPISettings @@ -68,7 +72,16 @@ class SPIClass void setDataMode(uint8_t dataMode); void setFrequency(uint32_t freq); void setClockDivider(uint32_t clockDiv); - + +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 + /** + * @brief Sets the spi device handle so that the underlying SPI driver, also respects when the esp-idf SPI driver attempts to use the SPI. + * @param spi_device_handle Spi device handle gettable via. ETH.getSpiDeviceHandle() + * @param spi_device_handle Spi host device gettable via. ETH.getSpiHost() + */ + void setSpiDeviceHandle(spi_device_handle_t& spi_device_handle, spi_host_device_t& spi_host_device); +#endif + uint32_t getClockDivider(); void beginTransaction(SPISettings settings); From 51c20deb94ff945abc8e9ebda8cb891c05b97f55 Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Tue, 6 Sep 2022 08:04:52 +0200 Subject: [PATCH 09/10] Removed not needed defines. --- cores/esp32/esp32-hal-spi.c | 46 ++++++++----------------------------- cores/esp32/esp32-hal-spi.h | 4 ---- libraries/SPI/src/SPI.cpp | 3 --- libraries/SPI/src/SPI.h | 5 ---- 4 files changed, 10 insertions(+), 48 deletions(-) diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index 07245b87093..211e12ae2b4 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -24,6 +24,7 @@ #include "soc/gpio_sig_map.h" #include "soc/rtc.h" #include "driver/periph_ctrl.h" +#include "driver/spi_master.h" #include "esp_system.h" #ifdef ESP_IDF_VERSION_MAJOR // IDF 4+ @@ -55,10 +56,6 @@ #include "esp_intr.h" #endif -#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 -#include -#endif - struct spi_struct_t { spi_dev_t * dev; #if !CONFIG_DISABLE_HAL_LOCKS @@ -139,32 +136,12 @@ static spi_t _spi_bus_array[] = { {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3} #endif }; -#elif ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 -#define SPI_MUTEX_LOCK() if (spi_handle != NULL && spi->num == spi_host) { spi_lock_error = spi_device_acquire_bus(spi_handle, portMAX_DELAY); }\ - do {} while ((xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS)) -#define SPI_MUTEX_UNLOCK() if (spi_handle != NULL && spi_lock_error == ESP_OK) { spi_device_release_bus(spi_handle); }\ - xSemaphoreGive(spi->lock) - -static spi_t _spi_bus_array[] = { -#if CONFIG_IDF_TARGET_ESP32S2 - {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0}, - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2} -#elif CONFIG_IDF_TARGET_ESP32S3 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 1} -#elif CONFIG_IDF_TARGET_ESP32C3 - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0} -#else - {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0}, - {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1}, - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3} -#endif -}; #else -#define SPI_MUTEX_LOCK() do {} while (xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS) -#define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock) +#define SPI_MUTEX_LOCK() if (spi_handle != NULL && spi->num == spi_host) { printf("Lock"); spi_lock_error = spi_device_acquire_bus(spi_handle, portMAX_DELAY); }\ + do {} while ((xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS));\ + locked_handle = xTaskGetCurrentTaskHandle(); +#define SPI_MUTEX_UNLOCK() if (spi_handle != NULL && spi_lock_error == ESP_OK) { printf("Unlock"); spi_device_release_bus(spi_handle); }\ + if (locked_handle == xTaskGetCurrentTaskHandle()) { xSemaphoreGive(spi->lock); } static spi_t _spi_bus_array[] = { #if CONFIG_IDF_TARGET_ESP32S2 @@ -185,11 +162,10 @@ static spi_t _spi_bus_array[] = { }; #endif -#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 - spi_device_handle_t spi_handle = NULL; - uint8_t spi_host = 0; - esp_err_t spi_lock_error = ESP_FAIL; -#endif +spi_device_handle_t spi_handle = NULL; +TaskHandle_t locked_handle = NULL; +uint8_t spi_host = 0; +esp_err_t spi_lock_error = ESP_FAIL; void spiAttachSCK(spi_t * spi, int8_t sck) { @@ -667,11 +643,9 @@ uint8_t spiGetBitOrder(spi_t * spi) void spiSetDeviceHandle(void * spi_device_handle, uint8_t spi_host_device) { -#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 spi_handle = spi_device_handle; // Increase number by 1, because SPI_HOST_1 is 0, SPI_HOST_2 is 1 and SPI_HOST_3 is 2. spi_host = spi_host_device + 1U; -#endif } void spiSetBitOrder(spi_t * spi, uint8_t bitOrder) diff --git a/cores/esp32/esp32-hal-spi.h b/cores/esp32/esp32-hal-spi.h index 5233b4e18c3..ca975c75143 100644 --- a/cores/esp32/esp32-hal-spi.h +++ b/cores/esp32/esp32-hal-spi.h @@ -23,10 +23,6 @@ extern "C" { #include #include -#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 -#include -#endif - #define SPI_HAS_TRANSACTION #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index d4dbf9c062e..282d8105c38 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -158,12 +158,10 @@ void SPIClass::setClockDivider(uint32_t clockDiv) SPI_PARAM_UNLOCK(); } -#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 void SPIClass::setSpiDeviceHandle(spi_device_handle_t& spi_device_handle, spi_host_device_t& spi_host_device) { spiSetDeviceHandle(spi_device_handle, spi_host_device); } -#endif uint32_t SPIClass::getClockDivider() { @@ -355,4 +353,3 @@ SPIClass SPI(VSPI); #else SPIClass SPI(FSPI); #endif - diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 7b7c56770c5..f167c6d0aba 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -26,10 +26,7 @@ #include "esp32-hal-spi.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" - -#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 #include -#endif #define SPI_HAS_TRANSACTION @@ -73,14 +70,12 @@ class SPIClass void setFrequency(uint32_t freq); void setClockDivider(uint32_t clockDiv); -#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 /** * @brief Sets the spi device handle so that the underlying SPI driver, also respects when the esp-idf SPI driver attempts to use the SPI. * @param spi_device_handle Spi device handle gettable via. ETH.getSpiDeviceHandle() * @param spi_device_handle Spi host device gettable via. ETH.getSpiHost() */ void setSpiDeviceHandle(spi_device_handle_t& spi_device_handle, spi_host_device_t& spi_host_device); -#endif uint32_t getClockDivider(); From f4d33145a11db4a4c8eb905c27e63e38975048a5 Mon Sep 17 00:00:00 2001 From: OekoSolveMG <94832869+OekoSolveMG@users.noreply.github.com> Date: Tue, 6 Sep 2022 08:10:19 +0200 Subject: [PATCH 10/10] Adjusted examples. --- cores/esp32/esp32-hal-spi.c | 4 ++-- libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino | 1 + .../Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index 211e12ae2b4..aa815d1b15c 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -137,10 +137,10 @@ static spi_t _spi_bus_array[] = { #endif }; #else -#define SPI_MUTEX_LOCK() if (spi_handle != NULL && spi->num == spi_host) { printf("Lock"); spi_lock_error = spi_device_acquire_bus(spi_handle, portMAX_DELAY); }\ +#define SPI_MUTEX_LOCK() if (spi_handle != NULL && spi->num == spi_host) { spi_lock_error = spi_device_acquire_bus(spi_handle, portMAX_DELAY); }\ do {} while ((xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS));\ locked_handle = xTaskGetCurrentTaskHandle(); -#define SPI_MUTEX_UNLOCK() if (spi_handle != NULL && spi_lock_error == ESP_OK) { printf("Unlock"); spi_device_release_bus(spi_handle); }\ +#define SPI_MUTEX_UNLOCK() if (spi_handle != NULL && spi_lock_error == ESP_OK) { spi_device_release_bus(spi_handle); }\ if (locked_handle == xTaskGetCurrentTaskHandle()) { xSemaphoreGive(spi->lock); } static spi_t _spi_bus_array[] = { diff --git a/libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino b/libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino index 1f311195ce3..2ab2cc44108 100644 --- a/libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino +++ b/libraries/Ethernet/examples/ETH_W5500/ETH_W5500.ino @@ -79,6 +79,7 @@ void setup() std::array mac_address; WiFi.macAddress(mac_address.data()); ETH.begin_w5500(mac_address.data(), MOSI_GPIO, MISO_GPIO, SCLK_GPIO, CS_GPIO, INT_GPIO, PHY_RST_GPIO); + SPI.setSpiDeviceHandle(ETH.getSpiDeviceHandle(), ETH.getSpiHost()); } diff --git a/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino b/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino index 2c021ef4f9a..7a723c8511b 100644 --- a/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino +++ b/libraries/Update/examples/HTTPS_OTA_Update/HTTPS_OTA_Update_ETH.ino @@ -77,6 +77,7 @@ void setup(){ WiFi.macAddress(mac_address.data()); Serial.print("Attempting to connect to W5500"); ETH.begin_w5500(mac_address.data(), MOSI_GPIO, MISO_GPIO, SCLK_GPIO, CS_GPIO, INT_GPIO, PHY_RST_GPIO); + SPI.setSpiDeviceHandle(ETH.getSpiDeviceHandle(), ETH.getSpiHost()); delay(3000);