diff --git a/.github/ISSUE_TEMPLATE/Issue-report.yml b/.github/ISSUE_TEMPLATE/Issue-report.yml index fb8d9c072..fc025f308 100644 --- a/.github/ISSUE_TEMPLATE/Issue-report.yml +++ b/.github/ISSUE_TEMPLATE/Issue-report.yml @@ -41,6 +41,7 @@ body: options: - latest master (checkout manually) - latest development Release Candidate (RC-X) + - v3.0.2 - v3.0.1 - v3.0.0 - v2.0.17 diff --git a/.github/workflows/tests_results.yml b/.github/workflows/tests_results.yml index 8269125a5..a51423179 100644 --- a/.github/workflows/tests_results.yml +++ b/.github/workflows/tests_results.yml @@ -22,7 +22,12 @@ jobs: statuses: write checks: write pull-requests: write + contents: write steps: + - uses: actions/checkout@v4 + with: + ref: gh-pages + - name: Download and Extract Artifacts uses: dawidd6/action-download-artifact@v6 with: @@ -102,7 +107,31 @@ jobs: repo: repo, sha: sha, state: '${{ job.status }}', - description: '${{ job.status }}' ? 'Runtime tests successful' : 'Runtime tests failed', + description: '${{ job.status }}' == 'success' ? 'Runtime tests successful' : 'Runtime tests failed', target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' })).data; core.info(`${name} is ${state}`); + + - name: Create output folder + if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} + run: | + rm -rf artifacts + mkdir -p runtime-tests-results + + - name: Generate badge + if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} + uses: jaywcjlove/generated-badges@main + with: + label: Runtime Tests + status: ${{ job.status }} + output: runtime-tests-results/badge.svg + color: ${{ job.status == 'success' && 'green' || 'red' }} + + - name: Push badge + if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add --all + git commit -m "Updated runtime tests badge" + git push origin HEAD:gh-pages diff --git a/README.md b/README.md index 52d13707d..fb459a717 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Arduino core for the ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2 -![Build Status](https://github.com/espressif/arduino-esp32/workflows/ESP32%20Arduino%20CI/badge.svg) [![External Libraries Test](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md) [![Hardware Tests](https://github.com/espressif/arduino-esp32/actions/workflows/tests.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/actions/workflows/tests.yml?query=event%3Aschedule) +![Build Status](https://github.com/espressif/arduino-esp32/workflows/ESP32%20Arduino%20CI/badge.svg) [![External Libraries Test](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md) [![Hardware Tests](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/badge.svg)](https://github.com/espressif/arduino-esp32/actions/workflows/tests_results.yml) ### Need help or have a question? Join the chat at [Gitter](https://gitter.im/espressif/arduino-esp32) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions) diff --git a/boards.txt b/boards.txt index 75f47c031..5b487c388 100644 --- a/boards.txt +++ b/boards.txt @@ -15447,7 +15447,7 @@ nodemcu-32s.build.target=esp32 nodemcu-32s.build.mcu=esp32 nodemcu-32s.build.core=esp32 nodemcu-32s.build.variant=nodemcu-32s -nodemcu-32s.build.board=NodeMCU_32S +nodemcu-32s.build.board=NODEMCU_32S nodemcu-32s.build.f_cpu=240000000L nodemcu-32s.build.flash_mode=dio @@ -15461,9 +15461,6 @@ nodemcu-32s.menu.FlashFreq.80.build.flash_freq=80m nodemcu-32s.menu.FlashFreq.40=40MHz nodemcu-32s.menu.FlashFreq.40.build.flash_freq=40m -nodemcu-32s.menu.UploadSpeed.460800.linux=460800 -nodemcu-32s.menu.UploadSpeed.460800.macosx=460800 -nodemcu-32s.menu.UploadSpeed.460800.upload.speed=460800 nodemcu-32s.menu.UploadSpeed.115200=115200 nodemcu-32s.menu.UploadSpeed.115200.upload.speed=115200 nodemcu-32s.menu.UploadSpeed.256000.windows=256000 @@ -15473,6 +15470,9 @@ nodemcu-32s.menu.UploadSpeed.230400=230400 nodemcu-32s.menu.UploadSpeed.230400.upload.speed=230400 nodemcu-32s.menu.UploadSpeed.512000.windows=512000 nodemcu-32s.menu.UploadSpeed.512000.upload.speed=512000 +nodemcu-32s.menu.UploadSpeed.460800.linux=460800 +nodemcu-32s.menu.UploadSpeed.460800.macosx=460800 +nodemcu-32s.menu.UploadSpeed.460800.upload.speed=460800 nodemcu-32s.menu.UploadSpeed.921600=921600 nodemcu-32s.menu.UploadSpeed.921600.upload.speed=921600 diff --git a/docs/en/esp-idf_component.rst b/docs/en/esp-idf_component.rst index aa946c617..350284e06 100644 --- a/docs/en/esp-idf_component.rst +++ b/docs/en/esp-idf_component.rst @@ -14,14 +14,36 @@ For a simplified method, see `Installing using Boards Manager `_. +.. note:: Latest Arduino Core ESP32 version (3.0.X) is now compatible with `ESP-IDF v5.1 `_. Please consider this compatibility when using Arduino as a component in ESP-IDF. + +For easiest use of Arduino framework as a ESP-IDF component, you can use the `IDF Component Manager `_ to add the Arduino component to your project. +This will automatically clone the repository and its submodules. You can find the Arduino component in the `ESP Registry `_ together with dependencies list and examples. + Installation ------------ -.. note:: Latest Arduino Core ESP32 version is now compatible with `ESP-IDF v4.4 `_. Please consider this compatibility when using Arduino as a component in ESP-IDF. - #. Download and install `ESP-IDF `_. * For more information see `Get Started `_. + +Installing using IDF Component Manager +************************************** + +To add the Arduino component to your project using the IDF Component Manager, run the following command in your project directory: + +.. code-block:: bash + + idf.py add-dependency "espressif/arduino-esp32^3.0.2" + +Or you can start a new project from a template with the Arduino component: + +.. code-block:: bash + + idf.py create-project-from-example "espressif/arduino-esp32^3.0.2:hello_world" + +Manual installation of Arduino framework +**************************************** + #. Create a blank ESP-IDF project (use sample_project from /examples/get-started) or choose one of the examples. #. In the project folder, create a new folder called ``components`` and clone this repository inside the newly created folder. diff --git a/docs/en/lib_builder.rst b/docs/en/lib_builder.rst index fb1a9b189..906188c80 100644 --- a/docs/en/lib_builder.rst +++ b/docs/en/lib_builder.rst @@ -181,6 +181,26 @@ Specify additional configs to be applied. ex. 'qio 80m' to compile for QIO Flash ./build.sh -t esp32 -b idf_libs qio 80m +User Interface +-------------- + +There is also a terminal user interface that can be used to configure the libraries to be compiled. +It allows the user to select the targets to compile, change the configuration options and compile the libraries. +It has mouse support and can be pre-configured using command line arguments. +For more information and troubleshooting, check `the documentation `_. + +To use the terminal user interface, make sure to have ``python>=3.9``, all the previous dependencies and install the ``textual`` library: + +.. code-block:: bash + + pip install --user textual + +You can then run the UI using the following command: + +.. code-block:: bash + + ./tools/config_editor/app.py + Docker Image ------------ diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 2480dd982..4d215d800 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -130,7 +130,8 @@ ETHClass::ETHClass(uint8_t eth_index) , _pin_mcd(-1), _pin_mdio(-1), _pin_power(-1), _pin_rmii_clock(-1) #endif /* CONFIG_ETH_USE_ESP32_EMAC */ -{ + , + _task_stack_size(4096) { } ETHClass::~ETHClass() {} @@ -141,6 +142,10 @@ bool ETHClass::ethDetachBus(void *bus_pointer) { return true; } +void ETHClass::setTaskStackSize(size_t size) { + _task_stack_size = size; +} + #if CONFIG_ETH_USE_ESP32_EMAC bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clock_mode) { esp_err_t ret = ESP_OK; @@ -214,6 +219,7 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i eth_mac_config_t eth_mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_mac_config.sw_reset_timeout_ms = 1000; + eth_mac_config.rx_task_stack_size = _task_stack_size; esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config, ð_mac_config); if (mac == NULL) { @@ -578,6 +584,9 @@ bool ETHClass::beginSPI( __unused eth_mac_config_t eth_mac_config = ETH_MAC_DEFAULT_CONFIG(); __unused eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + // Set RX Task Stack Size + eth_mac_config.rx_task_stack_size = _task_stack_size; + // Update PHY config based on board specific configuration phy_config.phy_addr = phy_addr; phy_config.reset_gpio_num = _pin_rst; diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index b481b9e36..14d2d0426 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -153,6 +153,9 @@ public: void end(); + // This function must be called before `begin()` + void setTaskStackSize(size_t size); + // ETH Handle APIs bool fullDuplex() const; uint8_t linkSpeed() const; @@ -203,6 +206,7 @@ private: int8_t _pin_power; int8_t _pin_rmii_clock; #endif /* CONFIG_ETH_USE_ESP32_EMAC */ + size_t _task_stack_size; static bool ethDetachBus(void *bus_pointer); bool beginSPI( diff --git a/libraries/FS/src/FS.cpp b/libraries/FS/src/FS.cpp index 8470ce1fe..252fc3e39 100644 --- a/libraries/FS/src/FS.cpp +++ b/libraries/FS/src/FS.cpp @@ -105,7 +105,7 @@ bool File::seek(uint32_t pos, SeekMode mode) { size_t File::position() const { if (!*this) { - return 0; + return (size_t)-1; } return _p->position(); diff --git a/libraries/FS/src/FS.h b/libraries/FS/src/FS.h index 5f2a91761..6572ad987 100644 --- a/libraries/FS/src/FS.h +++ b/libraries/FS/src/FS.h @@ -64,7 +64,7 @@ public: bool seek(uint32_t pos) { return seek(pos, SeekSet); } - size_t position() const; + size_t position() const; // returns (size_t)-1 on error size_t size() const; bool setBufferSize(size_t size); void close(); diff --git a/libraries/HTTPClient/src/HTTPClient.cpp b/libraries/HTTPClient/src/HTTPClient.cpp index 3dc3b7156..7881a8774 100644 --- a/libraries/HTTPClient/src/HTTPClient.cpp +++ b/libraries/HTTPClient/src/HTTPClient.cpp @@ -1362,7 +1362,7 @@ int HTTPClient::writeToStreamDataBlock(Stream *stream, int size) { // some time for the stream delay(1); - int leftBytes = (readBytes - bytesWrite); + int leftBytes = (bytesRead - bytesWrite); // retry to send the missed bytes bytesWrite = stream->write((buff + bytesWrite), leftBytes); @@ -1385,7 +1385,7 @@ int HTTPClient::writeToStreamDataBlock(Stream *stream, int size) { // count bytes to read left if (len > 0) { - len -= readBytes; + len -= bytesRead; } delay(0); diff --git a/libraries/WebServer/src/Parsing.cpp b/libraries/WebServer/src/Parsing.cpp index 200244e68..53f0962fe 100644 --- a/libraries/WebServer/src/Parsing.cpp +++ b/libraries/WebServer/src/Parsing.cpp @@ -347,11 +347,41 @@ int WebServer::_uploadReadByte(NetworkClient &client) { int res = client.read(); if (res < 0) { - while (!client.available() && client.connected()) { - delay(2); - } + // keep trying until you either read a valid byte or timeout + const unsigned long startMillis = millis(); + const long timeoutIntervalMillis = client.getTimeout(); + bool timedOut = false; + for (;;) { + if (!client.connected()) { + return -1; + } + // loosely modeled after blinkWithoutDelay pattern + while (!timedOut && !client.available() && client.connected()) { + delay(2); + timedOut = (millis() - startMillis) >= timeoutIntervalMillis; + } - res = client.read(); + res = client.read(); + if (res >= 0) { + return res; // exit on a valid read + } + // NOTE: it is possible to get here and have all of the following + // assertions hold true + // + // -- client.available() > 0 + // -- client.connected == true + // -- res == -1 + // + // a simple retry strategy overcomes this which is to say the + // assertion is not permanent, but the reason that this works + // is elusive, and possibly indicative of a more subtle underlying + // issue + + timedOut = (millis() - startMillis) >= timeoutIntervalMillis; + if (timedOut) { + return res; // exit on a timeout + } + } } return res; diff --git a/libraries/WebServer/src/WebServer.cpp b/libraries/WebServer/src/WebServer.cpp index 92623b79c..3996d3bdb 100644 --- a/libraries/WebServer/src/WebServer.cpp +++ b/libraries/WebServer/src/WebServer.cpp @@ -432,10 +432,8 @@ void WebServer::handleClient() { case HC_WAIT_READ: // Wait for data from client to become available if (_currentClient.available()) { + _currentClient.setTimeout(HTTP_MAX_SEND_WAIT); /* / 1000 removed, WifiClient setTimeout changed to ms */ if (_parseRequest(_currentClient)) { - // because HTTP_MAX_SEND_WAIT is expressed in milliseconds, - // it must be divided by 1000 - _currentClient.setTimeout(HTTP_MAX_SEND_WAIT); /* / 1000 removed, WifiClient setTimeout changed to ms */ _contentLength = CONTENT_LENGTH_NOT_SET; _handleRequest(); diff --git a/libraries/WebServer/src/WebServer.h b/libraries/WebServer/src/WebServer.h index c43dd4542..a107e223b 100644 --- a/libraries/WebServer/src/WebServer.h +++ b/libraries/WebServer/src/WebServer.h @@ -66,7 +66,7 @@ enum HTTPAuthMethod { #define HTTP_MAX_DATA_WAIT 5000 //ms to wait for the client to send the request #define HTTP_MAX_POST_WAIT 5000 //ms to wait for POST data to arrive #define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed -#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection +#define HTTP_MAX_CLOSE_WAIT 5000 //ms to wait for the client to close the connection #define HTTP_MAX_BASIC_AUTH_LEN 256 // maximum length of a basic Auth base64 encoded username:password string #define CONTENT_LENGTH_UNKNOWN ((size_t) - 1) @@ -88,7 +88,7 @@ typedef struct { HTTPRawStatus status; size_t totalSize; // content size size_t currentSize; // size of data currently in buf - uint8_t buf[HTTP_UPLOAD_BUFLEN]; + uint8_t buf[HTTP_RAW_BUFLEN]; void *data; // additional data } HTTPRaw; diff --git a/libraries/WiFi/examples/WPS/WPS.ino b/libraries/WiFi/examples/WPS/WPS.ino index 194aac011..1a6cc6114 100644 --- a/libraries/WiFi/examples/WPS/WPS.ino +++ b/libraries/WiFi/examples/WPS/WPS.ino @@ -20,35 +20,28 @@ Pranav Cherukupalli Change the definition of the WPS mode from WPS_TYPE_PBC to WPS_TYPE_PIN in the case that you are using pin type -WPS +WPS (pin is 00000000) */ -#define ESP_WPS_MODE WPS_TYPE_PBC -#define ESP_MANUFACTURER "ESPRESSIF" -#define ESP_MODEL_NUMBER "ESP32" -#define ESP_MODEL_NAME "ESPRESSIF IOT" -#define ESP_DEVICE_NAME "ESP STATION" - -static esp_wps_config_t config; - -void wpsInitConfig() { - config.wps_type = ESP_WPS_MODE; - strcpy(config.factory_info.manufacturer, ESP_MANUFACTURER); - strcpy(config.factory_info.model_number, ESP_MODEL_NUMBER); - strcpy(config.factory_info.model_name, ESP_MODEL_NAME); - strcpy(config.factory_info.device_name, ESP_DEVICE_NAME); -} +#define ESP_WPS_MODE WPS_TYPE_PBC void wpsStart() { - if (esp_wifi_wps_enable(&config)) { - Serial.println("WPS Enable Failed"); - } else if (esp_wifi_wps_start(0)) { - Serial.println("WPS Start Failed"); + esp_wps_config_t config = WPS_CONFIG_INIT_DEFAULT(ESP_WPS_MODE); + esp_err_t err = esp_wifi_wps_enable(&config); + if (err != ESP_OK) { + Serial.printf("WPS Enable Failed: 0x%x: %s\n", err, esp_err_to_name(err)); + return; + } + + err = esp_wifi_wps_start(0); + if (err != ESP_OK) { + Serial.printf("WPS Start Failed: 0x%x: %s\n", err, esp_err_to_name(err)); } } void wpsStop() { - if (esp_wifi_wps_disable()) { - Serial.println("WPS Disable Failed"); + esp_err_t err = esp_wifi_wps_disable(); + if (err != ESP_OK) { + Serial.printf("WPS Disable Failed: 0x%x: %s\n", err, esp_err_to_name(err)); } } @@ -102,7 +95,6 @@ void setup() { WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread. WiFi.mode(WIFI_MODE_STA); Serial.println("Starting WPS"); - wpsInitConfig(); wpsStart(); }