diff --git a/.github/ISSUE_TEMPLATE/Issue-report.yml b/.github/ISSUE_TEMPLATE/Issue-report.yml index 97834925020..79d8adb71bb 100644 --- a/.github/ISSUE_TEMPLATE/Issue-report.yml +++ b/.github/ISSUE_TEMPLATE/Issue-report.yml @@ -43,6 +43,9 @@ body: - latest stable Release (if not listed below) - latest development Release Candidate (RC-X) - latest master (checkout manually) + - v3.3.2 + - v3.3.2 + - v3.3.1 - v3.3.0 - v3.2.1 - v3.2.0 diff --git a/.github/scripts/find_new_boards.sh b/.github/scripts/find_new_boards.sh index 4482aa2b1da..96d50cecfeb 100755 --- a/.github/scripts/find_new_boards.sh +++ b/.github/scripts/find_new_boards.sh @@ -27,12 +27,25 @@ echo "$modified_lines" boards_array=() previous_board="" +# Define excluded entries that are not actual boards +excluded_entries=("" "+" "-" "esp32_family" "menu") + # Extract board names from the modified lines, and add them to the boards_array while read -r line; do board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1) # remove + or - from the board name at the beginning board_name=${board_name#[-+]} - if [ "$board_name" != "" ] && [ "$board_name" != "+" ] && [ "$board_name" != "-" ] && [ "$board_name" != "esp32_family" ]; then + + # Check if board_name is in excluded entries + is_excluded=false + for excluded in "${excluded_entries[@]}"; do + if [ "$board_name" = "$excluded" ]; then + is_excluded=true + break + fi + done + + if [ "$is_excluded" = false ]; then if [ "$board_name" != "$previous_board" ]; then boards_array+=("espressif:esp32:$board_name") previous_board="$board_name" diff --git a/.github/scripts/on-release.sh b/.github/scripts/on-release.sh index 275c74f8ea5..b65ab371640 100755 --- a/.github/scripts/on-release.sh +++ b/.github/scripts/on-release.sh @@ -54,6 +54,30 @@ if [ -n "${VENDOR}" ]; then echo "Setting packager: $VENDOR" fi +function update_version { + set -e + set -o pipefail + + local tag=$1 + local major + local minor + local patch + + # Extract major, minor, and patch from the tag + # We need to make sure to remove the "v" prefix from the tag and any characters after the patch version + tag=$(echo "$tag" | sed 's/^v//g' | sed 's/-.*//g') + major=$(echo "$tag" | cut -d. -f1) + minor=$(echo "$tag" | cut -d. -f2) + patch=$(echo "$tag" | cut -d. -f3 | sed 's/[^0-9].*//') # Remove non-numeric suffixes like RC1, alpha, beta + + echo "Major: $major, Minor: $minor, Patch: $patch" + + "${SCRIPTS_DIR}/update-version.sh" "$major" "$minor" "$patch" + + set +e + set +o pipefail +} + function get_file_size { local file="$1" if [[ "$OSTYPE" == "darwin"* ]]; then @@ -199,8 +223,31 @@ set -e ## mkdir -p "$OUTPUT_DIR" -PKG_DIR="$OUTPUT_DIR/$PACKAGE_NAME" +PKG_DIR="${OUTPUT_DIR:?}/$PACKAGE_NAME" PACKAGE_ZIP="$PACKAGE_NAME.zip" +PACKAGE_XZ="$PACKAGE_NAME.tar.xz" +LIBS_ZIP="$PACKAGE_NAME-libs.zip" +LIBS_XZ="$PACKAGE_NAME-libs.tar.xz" + +echo "Updating version..." +if ! update_version "$RELEASE_TAG"; then + echo "ERROR: update_version failed!" + exit 1 +fi +git config --global github.user "github-actions[bot]" +git config --global user.name "github-actions[bot]" +git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" +git add . + +# We should only commit if there are changes +need_update_commit=true +if git diff --cached --quiet; then + echo "Version already updated" + need_update_commit=false +else + echo "Creating version update commit..." + git commit -m "change(version): Update core version to $RELEASE_TAG" +fi echo "Updating submodules ..." git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1 @@ -283,7 +330,7 @@ echo \#define ARDUINO_ESP32_GIT_DESC "$(git -C "$GITHUB_WORKSPACE" describe --ta echo \#define ARDUINO_ESP32_RELEASE_"$ver_define" >> "$PKG_DIR/cores/esp32/core_version.h" echo \#define ARDUINO_ESP32_RELEASE \""$ver_define"\" >> "$PKG_DIR/cores/esp32/core_version.h" -# Compress package folder +# Compress ZIP package folder echo "Creating ZIP ..." pushd "$OUTPUT_DIR" >/dev/null zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME" @@ -293,22 +340,112 @@ if [ $? -ne 0 ]; then fi # Calculate SHA-256 -echo "Calculating SHA sum ..." -PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP" +echo "Calculating ZIP SHA sum ..." +PACKAGE_PATH="${OUTPUT_DIR:?}/$PACKAGE_ZIP" PACKAGE_SHA=$(shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' ') PACKAGE_SIZE=$(get_file_size "$PACKAGE_ZIP") popd >/dev/null -rm -rf "$PKG_DIR" echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA" echo -# Upload package to release page -echo "Uploading package to release page ..." +# Compress XZ package folder +echo "Creating XZ ..." +pushd "$OUTPUT_DIR" >/dev/null +tar -cJf "$PACKAGE_XZ" "$PACKAGE_NAME" +if [ $? -ne 0 ]; then + echo "ERROR: Failed to create $PACKAGE_XZ ($?)" + exit 1 +fi + +# Calculate SHA-256 +echo "Calculating XZ SHA sum ..." +PACKAGE_XZ_PATH="${OUTPUT_DIR:?}/$PACKAGE_XZ" +PACKAGE_XZ_SHA=$(shasum -a 256 "$PACKAGE_XZ" | cut -f 1 -d ' ') +PACKAGE_XZ_SIZE=$(get_file_size "$PACKAGE_XZ") +popd >/dev/null +echo "'$PACKAGE_XZ' Created! Size: $PACKAGE_XZ_SIZE, SHA-256: $PACKAGE_XZ_SHA" +echo + +# Upload ZIP package to release page +echo "Uploading ZIP package to release page ..." PACKAGE_URL=$(git_safe_upload_asset "$PACKAGE_PATH") echo "Package Uploaded" echo "Download URL: $PACKAGE_URL" echo +# Upload XZ package to release page +echo "Uploading XZ package to release page ..." +PACKAGE_XZ_URL=$(git_safe_upload_asset "$PACKAGE_XZ_PATH") +echo "Package Uploaded" +echo "Download URL: $PACKAGE_XZ_URL" +echo + +# Remove package folder +rm -rf "$PKG_DIR" + +# Copy Libs from lib-builder to release in ZIP and XZ + +libs_url=$(cat "$PACKAGE_JSON_TEMPLATE" | jq -r ".packages[0].tools[] | select(.name == \"esp32-arduino-libs\") | .systems[0].url") +libs_sha=$(cat "$PACKAGE_JSON_TEMPLATE" | jq -r ".packages[0].tools[] | select(.name == \"esp32-arduino-libs\") | .systems[0].checksum" | sed 's/^SHA-256://') +libs_size=$(cat "$PACKAGE_JSON_TEMPLATE" | jq -r ".packages[0].tools[] | select(.name == \"esp32-arduino-libs\") | .systems[0].size") +echo "Downloading libs from lib-builder ..." +echo "URL: $libs_url" +echo "Expected SHA: $libs_sha" +echo "Expected Size: $libs_size" +echo + +echo "Downloading libs from lib-builder ..." +curl -L -o "$OUTPUT_DIR/$LIBS_ZIP" "$libs_url" + +# Check SHA and Size +zip_sha=$(sha256sum "$OUTPUT_DIR/$LIBS_ZIP" | awk '{print $1}') +zip_size=$(stat -c%s "$OUTPUT_DIR/$LIBS_ZIP") +echo "Downloaded SHA: $zip_sha" +echo "Downloaded Size: $zip_size" +if [ "$zip_sha" != "$libs_sha" ] || [ "$zip_size" != "$libs_size" ]; then + echo "ERROR: ZIP SHA and Size do not match" + exit 1 +fi + +# Extract ZIP + +echo "Repacking libs to XZ ..." +unzip -q "$OUTPUT_DIR/$LIBS_ZIP" -d "$OUTPUT_DIR" +pushd "$OUTPUT_DIR" >/dev/null +tar -cJf "$LIBS_XZ" "esp32-arduino-libs" +popd >/dev/null + +# Upload ZIP and XZ libs to release page + +echo "Uploading ZIP libs to release page ..." +LIBS_ZIP_URL=$(git_safe_upload_asset "$OUTPUT_DIR/$LIBS_ZIP") +echo "ZIP libs Uploaded" +echo "Download URL: $LIBS_ZIP_URL" +echo + +echo "Uploading XZ libs to release page ..." +LIBS_XZ_URL=$(git_safe_upload_asset "$OUTPUT_DIR/$LIBS_XZ") +echo "XZ libs Uploaded" +echo "Download URL: $LIBS_XZ_URL" +echo + +# Update libs URLs in JSON template +echo "Updating libs URLs in JSON template ..." + +# Update all libs URLs in the JSON template +libs_jq_arg="(.packages[0].tools[] | select(.name == \"esp32-arduino-libs\") | .systems[].url) = \"$LIBS_ZIP_URL\"" + +cat "$PACKAGE_JSON_TEMPLATE" | jq "$libs_jq_arg" > "$OUTPUT_DIR/package-libs-updated.json" +PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-libs-updated.json" + +echo "Libs URLs updated in JSON template" +echo + +# Clean up +rm -rf "${OUTPUT_DIR:?}/esp32-arduino-libs" +rm -rf "${OUTPUT_DIR:?}/$LIBS_ZIP" +rm -rf "${OUTPUT_DIR:?}/$LIBS_XZ" + ## ## TEMP WORKAROUND FOR RV32 LONG PATH ON WINDOWS ## @@ -469,6 +606,17 @@ if [ "$RELEASE_PRE" == "false" ]; then echo fi +if [ "$need_update_commit" == "true" ]; then + echo "Pushing version update commit..." + git push + new_tag_commit=$(git rev-parse HEAD) + echo "New commit: $new_tag_commit" + + echo "Moving tag $RELEASE_TAG to $new_tag_commit..." + git tag -f "$RELEASE_TAG" "$new_tag_commit" + git push --force origin "$RELEASE_TAG" +fi + set +e ## diff --git a/.github/scripts/tests_matrix.sh b/.github/scripts/tests_matrix.sh index a8baf2ce275..01cc122753c 100644 --- a/.github/scripts/tests_matrix.sh +++ b/.github/scripts/tests_matrix.sh @@ -17,6 +17,7 @@ targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c6','esp32h2','esp32p4'" mkdir -p info echo "[$wokwi_types]" > info/wokwi_types.txt +echo "[$hw_types]" > info/hw_types.txt echo "[$targets]" > info/targets.txt { diff --git a/.github/scripts/tests_run.sh b/.github/scripts/tests_run.sh index c85db2e984a..26ec1a10d43 100755 --- a/.github/scripts/tests_run.sh +++ b/.github/scripts/tests_run.sh @@ -88,10 +88,7 @@ function run_test { fi if [ $platform == "wokwi" ]; then - extra_args=("--target" "$target" "--embedded-services" "arduino,wokwi" "--wokwi-timeout=$wokwi_timeout") - if [[ -f "$sketchdir/scenario.yaml" ]]; then - extra_args+=("--wokwi-scenario" "$sketchdir/scenario.yaml") - fi + extra_args=("--target" "$target" "--embedded-services" "arduino,wokwi") if [[ -f "$sketchdir/diagram.$target.json" ]]; then extra_args+=("--wokwi-diagram" "$sketchdir/diagram.$target.json") fi @@ -137,7 +134,6 @@ SCRIPTS_DIR="./.github/scripts" COUNT_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh count" platform="hardware" -wokwi_timeout=60000 chunk_run=0 options=0 erase=0 @@ -156,7 +152,6 @@ while [ -n "$1" ]; do ;; -W ) shift - wokwi_timeout=$1 if [[ -z $WOKWI_CLI_TOKEN ]]; then echo "Wokwi CLI token is not set" exit 1 diff --git a/.github/scripts/update-version.sh b/.github/scripts/update-version.sh index 59a95d01105..ea680a6d801 100755 --- a/.github/scripts/update-version.sh +++ b/.github/scripts/update-version.sh @@ -2,6 +2,10 @@ # Disable shellcheck warning about using 'cat' to read a file. # shellcheck disable=SC2002 +# Exit on any error and make pipelines fail if any command fails +set -e +set -o pipefail + # For reference: add tools for all boards by replacing one line in each board # "[board].upload.tool=esptool_py" to "[board].upload.tool=esptool_py\n[board].upload.tool.default=esptool_py\n[board].upload.tool.network=esp_ota" #cat boards.txt | sed "s/\([a-zA-Z0-9_\-]*\)\.upload\.tool\=esptool_py/\1\.upload\.tool\=esptool_py\\n\1\.upload\.tool\.default\=esptool_py\\n\1\.upload\.tool\.network\=esp_ota/" @@ -24,16 +28,25 @@ ESP_ARDUINO_VERSION_MINOR="$2" ESP_ARDUINO_VERSION_PATCH="$3" ESP_ARDUINO_VERSION="$ESP_ARDUINO_VERSION_MAJOR.$ESP_ARDUINO_VERSION_MINOR.$ESP_ARDUINO_VERSION_PATCH" -# Get ESP-IDF version from push.yml (this way we can ensure that the version is correct even if the local libs are not up to date) -ESP_IDF_VERSION=$(grep "idf_ver:" .github/workflows/push.yml | sed 's/.*release-v\([^"]*\).*/\1/') +# Get ESP-IDF version from build_component.yml (this way we can ensure that the version is correct even if the local libs are not up to date) +ESP_IDF_VERSION=$(grep -m 1 "default:" .github/workflows/build_component.yml | sed 's/.*release-v\([^"]*\).*/\1/') if [ -z "$ESP_IDF_VERSION" ]; then - echo "Error: ESP-IDF version not found in push.yml" >&2 + echo "Error: ESP-IDF version not found in build_component.yml" >&2 exit 1 fi echo "New Arduino Version: $ESP_ARDUINO_VERSION" echo "ESP-IDF Version: $ESP_IDF_VERSION" +echo "Updating issue template..." +cat .github/ISSUE_TEMPLATE/Issue-report.yml | \ +sed "s/.*\- latest master .*/ - latest master \(checkout manually\)\\n - v$ESP_ARDUINO_VERSION/g" > __issue-report.yml && mv __issue-report.yml .github/ISSUE_TEMPLATE/Issue-report.yml + +echo "Updating GitLab variables..." +cat .gitlab/workflows/common.yml | \ +sed "s/ESP_IDF_VERSION:.*/ESP_IDF_VERSION: \"$ESP_IDF_VERSION\"/g" | \ +sed "s/ESP_ARDUINO_VERSION:.*/ESP_ARDUINO_VERSION: \"$ESP_ARDUINO_VERSION\"/g" > .gitlab/workflows/__common.yml && mv .gitlab/workflows/__common.yml .gitlab/workflows/common.yml + echo "Updating platform.txt..." cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platform.txt && mv __platform.txt platform.txt diff --git a/.github/scripts/validate_board.sh b/.github/scripts/validate_board.sh new file mode 100755 index 00000000000..5c142ca8c19 --- /dev/null +++ b/.github/scripts/validate_board.sh @@ -0,0 +1,596 @@ +#!/bin/bash + +# Board validation script for ESP32 Arduino Core +# This script validates board definitions in boards.txt + +set -e + +# Required properties for all boards +REQUIRED_PROPERTIES=("upload.flags" "upload.extra_flags") + +# Function to print output +print_error() { + echo "Error: $1" +} + +print_success() { + echo "✓ $1" +} + +# Function to validate a single board +validate_board() { + local board_name="$1" + local boards_file="boards.txt" + + echo "Validating board: $board_name" + echo "" + + # Rule 1: Check build.board format + echo "Rule 1: Build Board Format Validation" + echo "=====================================" + validate_build_board_format "$board_name" "$boards_file" + echo "" + + # Rule 2: Check for required board properties + echo "Rule 2: Required Properties Validation" + echo "======================================" + validate_required_properties "$board_name" "$boards_file" + echo "" + + # Rule 3: Check for valid partition schemes for available flash sizes + echo "Rule 3: Partition Scheme Validation" + echo "===================================" + validate_partition_schemes "$board_name" "$boards_file" + echo "" + + # Rule 4: Check for VID and PID consistency + echo "Rule 4: VID/PID Consistency Validation" + echo "=====================================" + validate_vid_pid_consistency "$board_name" "$boards_file" + echo "" + + # Rule 5: Check for DebugLevel menu + echo "Rule 5: DebugLevel Menu Validation" + echo "==================================" + validate_debug_level_menu "$board_name" "$boards_file" + echo "" + + # Rule 6: Check for duplicate lines + echo "Rule 6: Duplicate Lines Validation" + echo "==================================" + validate_no_duplicates "$board_name" "$boards_file" + echo "" + + # Add more validation rules here as needed + echo "==========================================" + print_success "ALL VALIDATION RULES PASSED for board '$board_name'" + echo "==========================================" +} + +# Rule 1: Check build.board format +validate_build_board_format() { + local board_name="$1" + local boards_file="$2" + + # Get the build.board value + local build_board_value + build_board_value=$(grep "^$board_name.build.board=" "$boards_file" | cut -d'=' -f2) + + if [ -z "$build_board_value" ]; then + print_error "build.board property not found for '$board_name'" + exit 1 + fi + + # Check for invalid characters (anything that's not uppercase letter, number, or underscore) + if echo "$build_board_value" | grep -q '[^A-Z0-9_]'; then + local invalid_chars + invalid_chars=$(echo "$build_board_value" | grep -o '[^A-Z0-9_]' | sort -u | tr -d '\n') + print_error "$board_name.build.board contains invalid characters: '$invalid_chars' (only A-Z, 0-9, and _ are allowed)" + exit 1 + fi + + # Check if it's all uppercase + if echo "$build_board_value" | grep -q '[a-z]'; then + print_error "build.board must be uppercase: '$build_board_value' (found lowercase letters)" + exit 1 + fi + + echo " ✓ build.board is valid: '$build_board_value'" +} + +# Rule 2: Check for required board properties +validate_required_properties() { + local board_name="$1" + local boards_file="$2" + + local missing_props=() + + for prop in "${REQUIRED_PROPERTIES[@]}"; do + if ! grep -q "^$board_name.$prop=" "$boards_file"; then + missing_props+=("$prop") + fi + done + + if [ ${#missing_props[@]} -gt 0 ]; then + print_error "Missing required properties for board '$board_name':" + printf ' - %s\n' "${missing_props[@]}" + exit 1 + fi + + echo " ✓ Required properties validation completed" +} + + +# Rule 3: Check for valid partition schemes for available flash sizes +validate_partition_schemes() { + local board_name="$1" + local boards_file="$2" + + # Get all available flash sizes for this board + local flash_sizes + flash_sizes=$(grep "^$board_name.menu.FlashSize\." "$boards_file" | grep "\.build\.flash_size=" | cut -d'=' -f2 | sort -V) + + # Check if board has menu.FlashSize entries + if [ -z "$flash_sizes" ]; then + # If no menu.FlashSize entries, check if board has build.flash_size entry at least + local has_flash_size + has_flash_size=$(grep "^$board_name\." "$boards_file" | grep "\.build\.flash_size=" | head -1) + + if [ -z "$has_flash_size" ]; then + print_error "No flash size options found for board '$board_name' (needs build.flash_size entry at least)" + exit 1 + else + # Extract flash size from build.flash_size entry + local flash_size_value + flash_size_value=$(echo "$has_flash_size" | cut -d'=' -f2) + flash_sizes="$flash_size_value" + fi + fi + + # Convert flash sizes to MB for comparison + local flash_sizes_mb=() + while IFS= read -r size; do + if [[ "$size" =~ ^([0-9]+)MB$ ]]; then + flash_sizes_mb+=("${BASH_REMATCH[1]}") + fi + done <<< "$flash_sizes" + + # Find the maximum flash size available + local max_flash_mb=0 + for size_mb in "${flash_sizes_mb[@]}"; do + if [ "$size_mb" -gt "$max_flash_mb" ]; then + max_flash_mb="$size_mb" + fi + done + + echo " ✓ Flash configuration found - maximum size: ${max_flash_mb}MB" + + # Find all partition schemes for this board + local partition_schemes + partition_schemes=$(grep "^$board_name.menu.PartitionScheme\." "$boards_file" | grep -v "\.build\." | grep -v "\.upload\." | sed 's/.*\.PartitionScheme\.\([^=]*\)=.*/\1/' | sort -u) + + if [ -n "$partition_schemes" ]; then + # Validate each partition scheme against the maximum flash size + while IFS= read -r scheme; do + validate_partition_scheme_size "$scheme" "$max_flash_mb" "$board_name" "$boards_file" + done <<< "$partition_schemes" + fi + + + echo " ✓ Partition scheme validation completed" +} + +# Helper function to validate individual partition scheme +validate_partition_scheme_size() { + local scheme="$1" + local max_flash_mb="$2" + local board_name="$3" + local boards_file="$4" + + # Extract size from partition scheme name (e.g., "default_8MB" -> 8) + if [[ "$scheme" =~ _([0-9]+)MB$ ]]; then + local scheme_size_mb="${BASH_REMATCH[1]}" + + if [ "$scheme_size_mb" -gt "$max_flash_mb" ]; then + print_error "Partition scheme '$scheme' (${scheme_size_mb}MB) exceeds available flash size (${max_flash_mb}MB) for board '$board_name'" + exit 1 + else + echo " ✓ Partition scheme '$scheme' is valid for ${max_flash_mb}MB flash (size indicator: ${scheme_size_mb}MB)" + fi + elif [[ "$scheme" =~ _([0-9]+)M$ ]]; then + # Handle cases like "default_8M" (without B) + local scheme_size_mb="${BASH_REMATCH[1]}" + + if [ "$scheme_size_mb" -gt "$max_flash_mb" ]; then + print_error "Partition scheme '$scheme' (${scheme_size_mb}MB) exceeds available flash size (${max_flash_mb}MB) for board '$board_name'" + exit 1 + else + echo " ✓ Partition scheme '$scheme' is valid for ${max_flash_mb}MB flash (size indicator: ${scheme_size_mb}MB)" + fi + elif [[ "$scheme" =~ _([0-9]+)$ ]]; then + # Handle cases like "esp_sr_16" (just number at end) + local scheme_size_mb="${BASH_REMATCH[1]}" + + if [ "$scheme_size_mb" -gt "$max_flash_mb" ]; then + print_error "Partition scheme '$scheme' (${scheme_size_mb}MB) exceeds available flash size (${max_flash_mb}MB) for board '$board_name'" + exit 1 + else + echo " ✓ Partition scheme '$scheme' is valid for ${max_flash_mb}MB flash (size indicator: ${scheme_size_mb}MB)" + fi + else + # For schemes without size in name, check description for size indicators + local description_text + description_text=$(grep "^$board_name.menu.PartitionScheme\.$scheme=" "$boards_file" | cut -d'=' -f2) + + # First check main description for size indicators (before brackets) + # Look for the largest size indicator in the main description + local main_description_size_mb=0 + local main_description_size_text="" + + # Check for MB and M values in main description (before brackets) + local main_part=$(echo "$description_text" | sed 's/(.*//') # Remove bracket content + + # Extract M values (not followed by B) and MB values + local m_values=$(echo "$main_part" | grep -oE '([0-9]+\.?[0-9]*)M' | grep -v 'MB' | sed 's/M$//') + local mb_values=$(echo "$main_part" | grep -oE '([0-9]+\.?[0-9]*)MB' | sed 's/MB//') + + # Combine both M and MB values + local all_mb_values=$(echo -e "$m_values\n$mb_values" | grep -v '^$') + + # Find the largest MB value in main description + local largest_mb_int=0 + while IFS= read -r value; do + if [[ "$value" =~ ^([0-9]+)\.([0-9]+)$ ]]; then + local whole="${BASH_REMATCH[1]}" + local decimal="${BASH_REMATCH[2]}" + local value_int=$((whole * 10 + decimal)) + elif [[ "$value" =~ ^([0-9]+)$ ]]; then + local value_int=$((value * 10)) + else + continue + fi + + if [ "$value_int" -gt "$largest_mb_int" ]; then + largest_mb_int=$value_int + main_description_size_text="${value}M" + fi + done <<< "$all_mb_values" + + if [ "$largest_mb_int" -gt 0 ]; then + # Found size in main description + if [ "$largest_mb_int" -gt $((max_flash_mb * 10)) ]; then + print_error "Partition scheme '$scheme' (${main_description_size_text} from description) exceeds available flash size (${max_flash_mb}MB) for board '$board_name'" + exit 1 + else + echo " ✓ Partition scheme '$scheme' is valid for ${max_flash_mb}MB flash (size from description: ${main_description_size_text})" + fi + else + # No size in main description, check bracket content + local bracket_content + bracket_content=$(echo "$description_text" | grep -oE '\([^)]+\)' | head -1) + + if [ -n "$bracket_content" ]; then + # Calculate total size from all components in brackets + local total_size_mb=0 + + # Extract and sum MB values + local mb_sum=0 + while IFS= read -r value; do + if [[ "$value" =~ ^([0-9]+)\.([0-9]+)$ ]]; then + local whole="${BASH_REMATCH[1]}" + local decimal="${BASH_REMATCH[2]}" + # Convert decimal to integer (e.g., 1.3 -> 13, 6.93 -> 69) + # Handle multi-digit decimals: 6.93 -> 6*10 + 9 = 69 (round down) + local decimal_int=$((decimal / 10)) + mb_sum=$((mb_sum + whole * 10 + decimal_int)) + elif [[ "$value" =~ ^([0-9]+)$ ]]; then + mb_sum=$((mb_sum + value * 10)) + fi + done < <(echo "$bracket_content" | grep -oE '([0-9]+\.?[0-9]*)MB' | sed 's/MB//') + + # Extract and sum KB values (convert to MB tenths) + local kb_sum=0 + while IFS= read -r value; do + if [[ "$value" =~ ^([0-9]+)\.([0-9]+)$ ]]; then + local whole="${BASH_REMATCH[1]}" + local decimal="${BASH_REMATCH[2]}" + # Convert KB to MB tenths: (whole.decimal * 10) / 1024, rounded + local kb_tenths=$((whole * 10 + decimal)) + kb_sum=$((kb_sum + (kb_tenths * 10 + 512) / 1024)) + elif [[ "$value" =~ ^([0-9]+)$ ]]; then + # Convert KB to MB tenths: value * 10 / 1024, rounded + kb_sum=$((kb_sum + (value * 10 + 512) / 1024)) + fi + done < <(echo "$bracket_content" | grep -oE '([0-9]+\.?[0-9]*)KB' | sed 's/KB//') + + # Sum all values and convert back to MB (divide by 10, rounded) + total_size_mb=$(( (mb_sum + kb_sum + 5) / 10 )) + + if [ "$total_size_mb" -gt 0 ]; then + # Found size in description + if [ "$total_size_mb" -gt "$max_flash_mb" ]; then + print_error "Partition scheme '$scheme' (${total_size_mb}MB from description) exceeds available flash size (${max_flash_mb}MB) for board '$board_name'" + exit 1 + else + echo " ✓ Partition scheme '$scheme' is valid for ${max_flash_mb}MB flash (size from description: ${total_size_mb}MB)" + fi + else + # No size indicator found in brackets, check upload maximum size + validate_scheme_upload_size "$scheme" "$board_name" "$boards_file" "$max_flash_mb" + fi + else + # No brackets found, check upload maximum size + validate_scheme_upload_size "$scheme" "$board_name" "$boards_file" "$max_flash_mb" + fi + fi + fi +} + +# Helper function to validate upload maximum size for a specific partition scheme +validate_scheme_upload_size() { + local scheme="$1" + local board_name="$2" + local boards_file="$3" + local max_flash_mb="$4" + + # Get upload maximum size for this specific scheme + local upload_size + upload_size=$(grep "^$board_name.menu.PartitionScheme\.$scheme\." "$boards_file" | grep "\.upload\.maximum_size=" | head -1 | cut -d'=' -f2) + + if [ -z "$upload_size" ]; then + echo " ✓ Partition scheme '$scheme' is valid for ${max_flash_mb}MB flash (no upload size limit)" + return 0 + fi + + # Convert flash size to bytes for comparison + local max_flash_bytes=$((max_flash_mb * 1024 * 1024)) + + # Check upload size against maximum flash size + if [ "$upload_size" -gt "$max_flash_bytes" ]; then + local upload_mb=$(( (upload_size + 524288) / 1048576 )) + print_error "Partition scheme '$scheme' upload size (${upload_mb}MB, ${upload_size} bytes) exceeds available flash size (${max_flash_mb}MB) for board '$board_name'" + exit 1 + fi + + local upload_mb=$(( (upload_size + 524288) / 1048576 )) + echo " ✓ Partition scheme '$scheme' is valid for ${max_flash_mb}MB flash (upload size: ${upload_mb}MB)" +} + +# Rule 4: Check for VID and PID consistency +validate_vid_pid_consistency() { + local board_name="$1" + local boards_file="$2" + + # Get all VID and PID entries for this board (including upload_port entries) + local vid_entries + local pid_entries + + vid_entries=$(grep "^$board_name\.vid\." "$boards_file" | sort) + pid_entries=$(grep "^$board_name\.pid\." "$boards_file" | sort) + + # Also get upload_port VID and PID entries + local upload_port_vid_entries + local upload_port_pid_entries + + upload_port_vid_entries=$(grep "^$board_name\.upload_port\..*\.vid=" "$boards_file" | sort) + upload_port_pid_entries=$(grep "^$board_name\.upload_port\..*\.pid=" "$boards_file" | sort) + + # Check for duplicate VID entries with same index but different values + local all_vid_entries="$vid_entries" + if [ -n "$upload_port_vid_entries" ]; then + all_vid_entries="$all_vid_entries +$upload_port_vid_entries" + fi + + local vid_duplicates + vid_duplicates=$(echo "$all_vid_entries" | cut -d'=' -f1 | sort | uniq -d) + + if [ -n "$vid_duplicates" ]; then + print_error "Found duplicate VID entries with different values for board '$board_name':" + echo "$vid_duplicates" + exit 1 + fi + + # Check for duplicate PID entries with same index but different values + local all_pid_entries="$pid_entries" + if [ -n "$upload_port_pid_entries" ]; then + all_pid_entries="$all_pid_entries +$upload_port_pid_entries" + fi + + local pid_duplicates + pid_duplicates=$(echo "$all_pid_entries" | cut -d'=' -f1 | sort | uniq -d) + + if [ -n "$pid_duplicates" ]; then + print_error "Found duplicate PID entries with different values for board '$board_name':" + echo "$pid_duplicates" + exit 1 + fi + + # Check for missing corresponding PID for each VID (and vice versa) + local vid_indices + local pid_indices + + # Get indices from regular vid/pid entries + local regular_vid_indices=$(echo "$vid_entries" | cut -d'=' -f1 | sed "s/^$board_name\.vid\.//" | sort -n) + local regular_pid_indices=$(echo "$pid_entries" | cut -d'=' -f1 | sed "s/^$board_name\.pid\.//" | sort -n) + + # Get indices from upload_port entries + local upload_vid_indices=$(echo "$upload_port_vid_entries" | cut -d'=' -f1 | sed "s/^$board_name\.upload_port\.//" | sed "s/\.vid$//" | sort -n) + local upload_pid_indices=$(echo "$upload_port_pid_entries" | cut -d'=' -f1 | sed "s/^$board_name\.upload_port\.//" | sed "s/\.pid$//" | sort -n) + + # Combine indices + vid_indices="$regular_vid_indices" + if [ -n "$upload_vid_indices" ]; then + vid_indices="$vid_indices +$upload_vid_indices" + fi + + pid_indices="$regular_pid_indices" + if [ -n "$upload_pid_indices" ]; then + pid_indices="$pid_indices +$upload_pid_indices" + fi + + # Check if VID and PID indices match + if [ "$vid_indices" != "$pid_indices" ]; then + print_error "VID and PID indices don't match for board '$board_name'" + echo "VID indices: $vid_indices" + echo "PID indices: $pid_indices" + exit 1 + fi + + # Check that no VID/PID combination matches esp32_family (0x303a/0x1001) + local esp32_family_vid="0x303a" + local esp32_family_pid="0x1001" + + # Check regular vid/pid entries + if [ -n "$vid_entries" ] && [ -n "$pid_entries" ]; then + while IFS= read -r vid_line; do + if [ -n "$vid_line" ]; then + local vid_index=$(echo "$vid_line" | cut -d'=' -f1 | sed "s/^$board_name\.vid\.//") + local vid_value=$(echo "$vid_line" | cut -d'=' -f2) + + # Find corresponding PID + local pid_value + pid_value=$(grep "^$board_name\.pid\.$vid_index=" "$boards_file" | cut -d'=' -f2) + + if [ "$vid_value" = "$esp32_family_vid" ] && [ "$pid_value" = "$esp32_family_pid" ]; then + print_error "Board '$board_name' VID/PID combination ($vid_value/$pid_value) matches esp32_family VID/PID (0x303a/0x1001) - this is not allowed" + exit 1 + fi + fi + done <<< "$vid_entries" + fi + + # Check upload_port vid/pid entries + if [ -n "$upload_port_vid_entries" ] && [ -n "$upload_port_pid_entries" ]; then + while IFS= read -r vid_line; do + if [ -n "$vid_line" ]; then + local vid_index=$(echo "$vid_line" | cut -d'=' -f1 | sed "s/^$board_name\.upload_port\.//" | sed "s/\.vid$//") + local vid_value=$(echo "$vid_line" | cut -d'=' -f2) + + # Find corresponding PID + local pid_value + pid_value=$(grep "^$board_name\.upload_port\.$vid_index\.pid=" "$boards_file" | cut -d'=' -f2) + + if [ "$vid_value" = "$esp32_family_vid" ] && [ "$pid_value" = "$esp32_family_pid" ]; then + print_error "Board '$board_name' upload_port VID/PID combination ($vid_value/$pid_value) matches esp32_family VID/PID (0x303a/0x1001) - this is not allowed" + exit 1 + fi + fi + done <<< "$upload_port_vid_entries" + fi + + echo " ✓ VID and PID consistency check passed" +} + +# Rule 5: Check for DebugLevel menu +validate_debug_level_menu() { + local board_name="$1" + local boards_file="$2" + + # Required DebugLevel menu options + local required_debug_levels=("none" "error" "warn" "info" "debug" "verbose") + local missing_levels=() + + # Check if DebugLevel menu exists + if ! grep -q "^$board_name.menu.DebugLevel\." "$boards_file"; then + print_error "Missing DebugLevel menu for board '$board_name'" + exit 1 + fi + + # Check each required debug level + for level in "${required_debug_levels[@]}"; do + if ! grep -q "^$board_name.menu.DebugLevel.$level=" "$boards_file"; then + missing_levels+=("$level") + fi + done + + if [ ${#missing_levels[@]} -gt 0 ]; then + print_error "Missing DebugLevel menu options for board '$board_name':" + printf ' - %s\n' "${missing_levels[@]}" + exit 1 + fi + + # Check that each debug level has the correct build.code_debug value + local code_debug_values=("0" "1" "2" "3" "4" "5") + local debug_level_index=0 + + for level in "${required_debug_levels[@]}"; do + local expected_value="${code_debug_values[$debug_level_index]}" + local actual_value + actual_value=$(grep "^$board_name.menu.DebugLevel.$level.build.code_debug=" "$boards_file" | cut -d'=' -f2) + + if [ "$actual_value" != "$expected_value" ]; then + print_error "Invalid code_debug value for DebugLevel '$level' in board '$board_name': expected '$expected_value', found '$actual_value'" + exit 1 + fi + + debug_level_index=$((debug_level_index + 1)) + done + + echo " ✓ DebugLevel menu validation completed" +} + +# Rule 6: Check for duplicate lines +validate_no_duplicates() { + local board_name="$1" + local boards_file="$2" + + # Get all lines for this board + local board_lines + board_lines=$(grep "^$board_name\." "$boards_file") + + # Extract just the property names (before =) + local property_names + property_names=$(echo "$board_lines" | cut -d'=' -f1) + + # Find duplicates + local duplicate_lines + duplicate_lines=$(echo "$property_names" | sort | uniq -d) + + if [ -n "$duplicate_lines" ]; then + print_error "Found duplicate lines for board '$board_name':" + echo "Duplicate line keys:" + echo "$duplicate_lines" + + echo "Duplicate content details:" + while IFS= read -r line_key; do + if [ -n "$line_key" ]; then + echo " Key: $line_key" + echo " Content with line numbers:" + local key_only=$(echo "$line_key" | cut -d'=' -f1) + grep -n "^$key_only=" "$boards_file" | while IFS=':' read -r line_num full_line; do + echo " Line $line_num: $full_line" + done + echo "" + fi + done <<< "$duplicate_lines" + exit 1 + fi + + echo " ✓ No duplicate lines found" +} + +# Main execution +main() { + if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 esp32s3" + exit 1 + fi + + local board_name="$1" + local boards_file="boards.txt" + + if [ ! -f "$boards_file" ]; then + print_error "Boards file '$boards_file' not found" + exit 1 + fi + + validate_board "$board_name" +} + +# Run main function with all arguments +main "$@" diff --git a/.github/workflows/allboards.yml b/.github/workflows/allboards.yml index 31eee587ca9..5d834f6abbe 100644 --- a/.github/workflows/allboards.yml +++ b/.github/workflows/allboards.yml @@ -72,6 +72,36 @@ jobs: env: FQBN: ${{ toJSON(matrix.chunk) }} + - name: Make validation script executable + run: chmod +x ./.github/scripts/validate_board.sh + + - name: Validate boards in chunk + run: | + echo "Starting board validation for chunk..." + failed_boards=() + + # Extract board names from FQBNs (remove espressif:esp32: prefix) + boards_json=$(cat fqbns.json) + board_names=$(echo "$boards_json" | jq -r '.[]' | sed 's/espressif:esp32://') + + for board in $board_names; do + echo "Validating board: $board" + if ! ./.github/scripts/validate_board.sh "$board"; then + echo "❌ Validation failed for board: $board" + failed_boards+=("$board") + else + echo "✅ Validation passed for board: $board" + fi + done + + if [ ${#failed_boards[@]} -gt 0 ]; then + echo "❌ Board validation failed for the following boards:" + printf ' - %s\n' "${failed_boards[@]}" + exit 1 + else + echo "✅ All board validations in chunk passed!" + fi + - name: Compile sketch uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main with: diff --git a/.github/workflows/boards.yml b/.github/workflows/boards.yml index 4ddb1443746..d40ba4824ea 100644 --- a/.github/workflows/boards.yml +++ b/.github/workflows/boards.yml @@ -49,15 +49,10 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Check if build.board is uppercase + - name: Validate board definition run: | board_name=$(echo ${{ matrix.fqbn }} | awk -F':' '{print $NF}') - if grep -q "^$board_name.build.board=[A-Z0-9_]*$" boards.txt; then - echo "$board_name.build.board is valid."; - else - echo "Error: $board_name.build.board is not uppercase!"; - exit 1; - fi + ./.github/scripts/validate_board.sh "$board_name" - name: Get libs cache uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ddefdf69258..acba6c54e68 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,6 +17,8 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: + token: ${{ secrets.TOOLS_UPLOAD_PAT }} + ref: ${{ github.event.release.target_commitish }} fetch-depth: 0 - name: Set up Python @@ -32,5 +34,5 @@ jobs: - name: Build Release env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.TOOLS_UPLOAD_PAT }} run: bash ./.github/scripts/on-release.sh diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 557de11b509..8c46ef07661 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -89,23 +89,6 @@ jobs: type: ${{ matrix.type }} chip: ${{ matrix.chip }} - call-hardware-tests: - name: Hardware - uses: ./.github/workflows/tests_hw.yml - needs: [gen-matrix, call-build-tests] - if: | - github.repository == 'espressif/arduino-esp32' && - (github.event_name != 'pull_request' || - contains(github.event.pull_request.labels.*.name, 'hil_test')) - strategy: - fail-fast: false - matrix: - type: ${{ fromJson(needs.gen-matrix.outputs.hw-types) }} - chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }} - with: - type: ${{ matrix.type }} - chip: ${{ matrix.chip }} - # This job is disabled for now call-qemu-tests: name: QEMU @@ -121,4 +104,4 @@ jobs: type: ${{ matrix.type }} chip: ${{ matrix.chip }} - # Wokwi tests are run after this workflow as it needs access to secrets + # Hardware and Wokwi tests are run after this workflow as they need access to secrets diff --git a/.github/workflows/tests_hw.yml b/.github/workflows/tests_hw.yml deleted file mode 100644 index d3b2ef79301..00000000000 --- a/.github/workflows/tests_hw.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: Hardware tests - -on: - workflow_call: - inputs: - type: - type: string - description: "Type of tests to run" - required: true - chip: - type: string - description: "Chip to run tests for" - required: true - -permissions: - contents: read - -env: - DEBIAN_FRONTEND: noninteractive - -defaults: - run: - shell: bash - -jobs: - hardware-test: - name: Hardware ${{ inputs.chip }} ${{ inputs.type }} tests - runs-on: ["arduino", "${{ inputs.chip }}"] - env: - id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }} - container: - image: python:3.10.1-bullseye - options: --privileged --device-cgroup-rule="c 188:* rmw" --device-cgroup-rule="c 166:* rmw" - steps: - - name: Clean workspace - run: | - rm -rf ./* - rm -rf ~/.arduino/tests - - - name: Check if already passed - id: cache-results - if: github.event.pull_request.number != null - uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - with: - key: test-${{ env.id }}-results-hw - path: | - tests/**/*.xml - tests/**/result_*.json - - - name: Evaluate if tests should be run - id: check-tests - run: | - cache_exists=${{ steps.cache-results.outputs.cache-hit == 'true' }} - enabled=true - - if [[ $cache_exists == 'true' ]]; then - echo "Already ran, skipping" - enabled=false - fi - - echo "enabled=$enabled" >> $GITHUB_OUTPUT - - - name: Checkout user repository - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - # Workaround for missing files in checkout - sparse-checkout: | - * - - # setup-python currently only works on ubuntu images - # - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 - # if: ${{ steps.check-tests.outputs.enabled == 'true' }} - # with: - # cache-dependency-path: tests/requirements.txt - # cache: 'pip' - # python-version: '3.10.1' - - - name: Install dependencies - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: | - pip install -U pip - pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi - apt update - apt install -y jq - - - name: Get binaries - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 - with: - name: test-bin-${{ inputs.chip }}-${{ inputs.type }} - path: | - ~/.arduino/tests/${{ inputs.chip }} - - - name: List binaries - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: | - ls -laR ~/.arduino/tests - - - name: Run Tests - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: | - bash .github/scripts/tests_run.sh -c -type ${{ inputs.type }} -t ${{ inputs.chip }} -i 0 -m 1 -e - - - name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as cache - uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null - with: - key: test-${{ env.id }}-results-hw - path: | - tests/**/*.xml - tests/**/result_*.json - - - name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: always() - with: - name: test-results-hw-${{ inputs.chip }}-${{ inputs.type }} - overwrite: true - path: | - tests/**/*.xml - tests/**/result_*.json diff --git a/.github/workflows/tests_wokwi.yml b/.github/workflows/tests_hw_wokwi.yml similarity index 55% rename from .github/workflows/tests_wokwi.yml rename to .github/workflows/tests_hw_wokwi.yml index cfea30a501d..14e7085eabb 100644 --- a/.github/workflows/tests_wokwi.yml +++ b/.github/workflows/tests_hw_wokwi.yml @@ -1,4 +1,4 @@ -name: Wokwi tests +name: Hardware and Wokwi tests on: workflow_run: @@ -11,7 +11,7 @@ permissions: contents: read env: - WOKWI_TIMEOUT: 600000 # Milliseconds + TESTS_BRANCH: "master" # Branch that will be checked out to run the tests jobs: get-artifacts: @@ -25,7 +25,10 @@ jobs: ref: ${{ steps.set-ref.outputs.ref }} base: ${{ steps.set-ref.outputs.base }} targets: ${{ steps.set-ref.outputs.targets }} - types: ${{ steps.set-ref.outputs.types }} + wokwi_types: ${{ steps.set-ref.outputs.wokwi_types }} + hw_types: ${{ steps.set-ref.outputs.hw_types }} + hw_tests_enabled: ${{ steps.set-ref.outputs.hw_tests_enabled }} + push_time: ${{ steps.set-ref.outputs.push_time }} steps: - name: Report pending uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 @@ -63,7 +66,7 @@ jobs: name: matrix_info path: artifacts/matrix_info - - name: Try to read PR number + - name: Get info id: set-ref run: | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json | tr -cd "[:digit:]") @@ -86,13 +89,34 @@ jobs: base=${{ github.ref }} fi - types=$(cat artifacts/matrix_info/wokwi_types.txt | tr -cd "[:alpha:],[]'") + hw_tests_enabled="true" + if [[ -n "$pr_num" ]]; then + # This is a PR, check for hil_test label + has_hil_label=$(jq -r '.pull_request.labels[]?.name' artifacts/event_file/event.json 2>/dev/null | grep -q "hil_test" && echo "true" || echo "false") + echo "Has hil_test label: $has_hil_label" + + if [[ "$has_hil_label" != "true" ]]; then + echo "PR does not have hil_test label, hardware tests will be disabled" + hw_tests_enabled="false" + fi + fi + + push_time=$(jq -r '.repository.pushed_at' artifacts/event_file/event.json | tr -cd "[:alnum:]:-") + if [ -z "$push_time" ] || [ "$push_time" == "null" ]; then + push_time="" + fi + + wokwi_types=$(cat artifacts/matrix_info/wokwi_types.txt | tr -cd "[:alpha:],[]'") + hw_types=$(cat artifacts/matrix_info/hw_types.txt | tr -cd "[:alpha:],[]'") targets=$(cat artifacts/matrix_info/targets.txt | tr -cd "[:alnum:],[]'") echo "base = $base" echo "targets = $targets" - echo "types = $types" + echo "wokwi_types = $wokwi_types" + echo "hw_types = $hw_types" echo "pr_num = $pr_num" + echo "hw_tests_enabled = $hw_tests_enabled" + echo "push_time = $push_time" printf "$ref" >> artifacts/ref.txt printf "Ref = " @@ -127,28 +151,11 @@ jobs: echo "pr_num=$pr_num" >> $GITHUB_OUTPUT echo "base=$base" >> $GITHUB_OUTPUT echo "targets=$targets" >> $GITHUB_OUTPUT - echo "types=$types" >> $GITHUB_OUTPUT + echo "wokwi_types=$wokwi_types" >> $GITHUB_OUTPUT + echo "hw_types=$hw_types" >> $GITHUB_OUTPUT echo "ref=$ref" >> $GITHUB_OUTPUT - - - name: Download and extract parent hardware results - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 - continue-on-error: true - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ github.event.workflow_run.id }} - pattern: test-results-hw-* - merge-multiple: true - path: artifacts/results/hw - - - name: Download and extract parent GitLab results - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 - continue-on-error: true - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ github.event.workflow_run.id }} - pattern: test-results-gitlab - merge-multiple: true - path: artifacts/results/gitlab + echo "hw_tests_enabled=$hw_tests_enabled" >> $GITHUB_OUTPUT + echo "push_time=$push_time" >> $GITHUB_OUTPUT - name: Download and extract parent QEMU results uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 @@ -188,6 +195,196 @@ jobs: })).data; core.info(`${name} is ${state}`); + hardware-test: + name: Internal Hardware Tests + if: | + (github.event.workflow_run.conclusion == 'success' || + github.event.workflow_run.conclusion == 'failure' || + github.event.workflow_run.conclusion == 'timed_out') && + needs.get-artifacts.outputs.hw_tests_enabled == 'true' + runs-on: ubuntu-latest + needs: get-artifacts + env: + id: ${{ needs.get-artifacts.outputs.ref }}-${{ github.event.workflow_run.head_sha || github.sha }} + permissions: + actions: read + statuses: write + steps: + - name: Report pending + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const owner = '${{ github.repository_owner }}'; + const repo = '${{ github.repository }}'.split('/')[1]; + const sha = '${{ github.event.workflow_run.head_sha }}'; + core.debug(`owner: ${owner}`); + core.debug(`repo: ${repo}`); + core.debug(`sha: ${sha}`); + const { context: name, state } = (await github.rest.repos.createCommitStatus({ + context: 'Runtime Tests / Internal Hardware Tests (${{ github.event.workflow_run.event }} -> workflow_run)', + owner: owner, + repo: repo, + sha: sha, + state: 'pending', + target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + })).data; + core.info(`${name} is ${state}`); + + - name: Check if already passed + id: get-cache-results + if: needs.get-artifacts.outputs.pr_num + uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + key: test-${{ env.id }}-results-hw + path: | + tests/**/*.xml + tests/**/result_*.json + + - name: Evaluate if tests should be run + id: check-tests + run: | + cache_exists=${{ steps.get-cache-results.outputs.cache-hit == 'true' }} + enabled=true + + # Check cache first + if [[ $cache_exists == 'true' ]]; then + echo "Already ran, skipping GitLab pipeline trigger" + enabled=false + else + echo "Cache miss, hardware tests will run" + fi + + echo "enabled=$enabled" >> $GITHUB_OUTPUT + + - name: Wait for GitLab sync + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + env: + PUSH_TIME: ${{ needs.get-artifacts.outputs.push_time }} + run: | + # A webhook to sync the repository is sent to GitLab when a commit is pushed to GitHub + # We wait for 10 minutes after the push to GitHub to be safe + + echo "Ensuring GitLab sync has completed before triggering pipeline..." + + # Use push time determined in get-artifacts job + push_time="$PUSH_TIME" + + if [ -n "$push_time" ]; then + echo "Push time: $push_time" + + # Convert push time to epoch + push_epoch=$(date -d "$push_time" +%s 2>/dev/null || echo "") + + if [ -n "$push_epoch" ]; then + current_epoch=$(date +%s) + elapsed_minutes=$(( (current_epoch - push_epoch) / 60 )) + + echo "Elapsed time since push: ${elapsed_minutes} minutes" + + if [ $elapsed_minutes -lt 10 ]; then + wait_time=$(( (10 - elapsed_minutes) * 60 )) + echo "Waiting ${wait_time} seconds for GitLab sync to complete..." + sleep $wait_time + else + echo "GitLab sync should be complete (${elapsed_minutes} minutes elapsed)" + fi + else + echo "Could not parse push timestamp, waiting 60 seconds as fallback..." + sleep 60 + fi + else + echo "Could not determine push time, waiting 60 seconds as fallback..." + sleep 60 + fi + + echo "Proceeding with GitLab pipeline trigger..." + + - name: Trigger GitLab Pipeline and Download Artifacts + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + uses: digital-blueprint/gitlab-pipeline-trigger-action@20e77989b24af658ba138a0aa5291bdc657f1505 # v1.3.0 + id: gitlab-trigger + with: + host: ${{ secrets.GITLAB_URL }} + id: ${{ secrets.GITLAB_PROJECT_ID }} + ref: ${{ env.TESTS_BRANCH }} + trigger_token: ${{ secrets.GITLAB_TRIGGER_TOKEN }} + access_token: ${{ secrets.GITLAB_ACCESS_TOKEN }} + download_artifacts: 'true' + download_artifacts_on_failure: 'true' + download_path: './gitlab-artifacts' + variables: '{"TEST_TYPES":"${{ needs.get-artifacts.outputs.hw_types }}","TEST_CHIPS":"${{ needs.get-artifacts.outputs.targets }}","PIPELINE_ID":"${{ env.id }}","BINARIES_RUN_ID":"${{ github.event.workflow_run.id }}","GITHUB_REPOSITORY":"${{ github.repository }}"}' + + - name: Process Downloaded Artifacts + if: ${{ always() && steps.check-tests.outputs.enabled == 'true' }} + run: | + echo "GitLab Pipeline Status: ${{ steps.gitlab-trigger.outputs.status }}" + echo "Artifacts Downloaded: ${{ steps.gitlab-trigger.outputs.artifacts_downloaded }}" + + # Create tests directory structure expected by GitHub caching + mkdir -p tests + + # Process downloaded GitLab artifacts + if [ "${{ steps.gitlab-trigger.outputs.artifacts_downloaded }}" = "true" ]; then + echo "Processing downloaded GitLab artifacts..." + + # Find and copy test result files while preserving directory structure + # The GitLab artifacts have the structure: gitlab-artifacts/job_*/artifacts/tests/... + # We want to preserve the tests/... part of the structure + + for job_dir in ./gitlab-artifacts/job_*; do + if [ -d "$job_dir/artifacts/tests" ]; then + # Merge results into tests/ without failing on non-empty directories + echo "Merging $job_dir/artifacts/tests/ into tests/" + cp -a "$job_dir/artifacts/tests/." tests/ + fi + done + + echo "Test results found:" + ls -laR tests/ || echo "No test results found" + else + echo "No artifacts were downloaded from GitLab" + fi + + - name: Upload hardware results as cache + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + if: steps.check-tests.outputs.enabled == 'true' && needs.get-artifacts.outputs.pr_num + with: + key: test-${{ env.id }}-results-hw + path: | + tests/**/*.xml + tests/**/result_*.json + + - name: Upload hardware results as artifacts + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: always() + with: + name: test-results-hw + overwrite: true + path: | + tests/**/*.xml + tests/**/result_*.json + + - name: Report conclusion + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + if: always() + with: + script: | + const owner = '${{ github.repository_owner }}'; + const repo = '${{ github.repository }}'.split('/')[1]; + const sha = '${{ github.event.workflow_run.head_sha }}'; + core.debug(`owner: ${owner}`); + core.debug(`repo: ${repo}`); + core.debug(`sha: ${sha}`); + const { context: name, state } = (await github.rest.repos.createCommitStatus({ + context: 'Runtime Tests / Internal Hardware Tests (${{ github.event.workflow_run.event }} -> workflow_run)', + owner: owner, + repo: repo, + sha: sha, + state: '${{ job.status }}', + target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + })).data; + core.info(`${name} is ${state}`); + wokwi-test: name: Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests if: | @@ -204,7 +401,7 @@ jobs: strategy: fail-fast: false matrix: - type: ${{ fromJson(needs.get-artifacts.outputs.types) }} + type: ${{ fromJson(needs.get-artifacts.outputs.wokwi_types) }} chip: ${{ fromJson(needs.get-artifacts.outputs.targets) }} steps: - name: Report pending @@ -271,10 +468,6 @@ jobs: pip install -U pip pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi - - name: Install Wokwi CLI - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: curl -L https://wokwi.com/ci/install.sh | sh - - name: Wokwi CI Server if: ${{ steps.check-tests.outputs.enabled == 'true' }} uses: wokwi/wokwi-ci-server-action@a6fabb5a49e080158c7a1d121ea5b789536a82c3 # v1 @@ -294,7 +487,7 @@ jobs: env: WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }} run: | - bash .github/scripts/tests_run.sh -c -type ${{ matrix.type }} -t ${{ matrix.chip }} -i 0 -m 1 -W ${{ env.WOKWI_TIMEOUT }} + bash .github/scripts/tests_run.sh -c -type ${{ matrix.type }} -t ${{ matrix.chip }} -i 0 -m 1 -W - name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as cache uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 diff --git a/.github/workflows/tests_results.yml b/.github/workflows/tests_results.yml index ab4bb31fca5..525b303e486 100644 --- a/.github/workflows/tests_results.yml +++ b/.github/workflows/tests_results.yml @@ -2,7 +2,7 @@ name: Publish and clean test results on: workflow_run: - workflows: ["Wokwi tests"] + workflows: ["Hardware and Wokwi tests"] types: - completed @@ -11,24 +11,17 @@ permissions: contents: read jobs: - unit-test-results: - name: Unit Test Results - if: | - github.event.workflow_run.conclusion == 'success' || - github.event.workflow_run.conclusion == 'failure' || - github.event.workflow_run.conclusion == 'timed_out' + get-artifacts: + name: Get artifacts runs-on: ubuntu-latest - permissions: - actions: write - statuses: write - checks: write - pull-requests: write - contents: write + outputs: + original_event: ${{ steps.get-info.outputs.original_event }} + original_action: ${{ steps.get-info.outputs.original_action }} + original_sha: ${{ steps.get-info.outputs.original_sha }} + original_ref: ${{ steps.get-info.outputs.original_ref }} + original_conclusion: ${{ steps.get-info.outputs.original_conclusion }} + original_run_id: ${{ steps.get-info.outputs.original_run_id }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - ref: gh-pages - - name: Download and Extract Artifacts uses: dawidd6/action-download-artifact@07ab29fd4a977ae4d2b275087cf67563dfdf0295 # v9 with: @@ -36,7 +29,11 @@ jobs: path: ./artifacts - name: Get original info + id: get-info run: | + echo "Artifacts:" + ls -laR ./artifacts + original_event=$(cat ./artifacts/parent-artifacts/event.txt) original_action=$(cat ./artifacts/parent-artifacts/action.txt) original_sha=$(cat ./artifacts/parent-artifacts/sha.txt) @@ -64,12 +61,12 @@ jobs: # Run ID: Allow numeric characters original_run_id=$(echo "$original_run_id" | tr -cd '[:digit:]') - echo "original_event=$original_event" >> $GITHUB_ENV - echo "original_action=$original_action" >> $GITHUB_ENV - echo "original_sha=$original_sha" >> $GITHUB_ENV - echo "original_ref=$original_ref" >> $GITHUB_ENV - echo "original_conclusion=$original_conclusion" >> $GITHUB_ENV - echo "original_run_id=$original_run_id" >> $GITHUB_ENV + echo "original_event=$original_event" >> $GITHUB_OUTPUT + echo "original_action=$original_action" >> $GITHUB_OUTPUT + echo "original_sha=$original_sha" >> $GITHUB_OUTPUT + echo "original_ref=$original_ref" >> $GITHUB_OUTPUT + echo "original_conclusion=$original_conclusion" >> $GITHUB_OUTPUT + echo "original_run_id=$original_run_id" >> $GITHUB_OUTPUT echo "original_event = $original_event" echo "original_action = $original_action" @@ -79,44 +76,81 @@ jobs: echo "original_run_id = $original_run_id" - name: Print links to other runs + env: + ORIGINAL_RUN_ID: ${{ steps.get-info.outputs.original_run_id }} run: | - echo "Build, Hardware and QEMU tests: https://github.com/${{ github.repository }}/actions/runs/${{ env.original_run_id }}" - echo "Wokwi tests: https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}" + echo "Build and QEMU tests: https://github.com/${{ github.repository }}/actions/runs/$ORIGINAL_RUN_ID" + echo "Hardware and Wokwi tests: https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}" + + unit-test-results: + name: Unit Test Results + needs: get-artifacts + if: | + github.event.workflow_run.conclusion == 'success' || + github.event.workflow_run.conclusion == 'failure' || + github.event.workflow_run.conclusion == 'timed_out' + runs-on: ubuntu-latest + permissions: + actions: write + statuses: write + checks: write + pull-requests: write + contents: write + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: gh-pages + + - name: Download and Extract Artifacts + uses: dawidd6/action-download-artifact@07ab29fd4a977ae4d2b275087cf67563dfdf0295 # v9 + with: + run_id: ${{ github.event.workflow_run.id }} + path: ./artifacts - name: Publish Unit Test Results uses: EnricoMi/publish-unit-test-result-action@170bf24d20d201b842d7a52403b73ed297e6645b # v2.18.0 with: - commit: ${{ env.original_sha }} + commit: ${{ needs.get-artifacts.outputs.original_sha }} event_file: ./artifacts/parent-artifacts/event_file/event.json - event_name: ${{ env.original_event }} + event_name: ${{ needs.get-artifacts.outputs.original_event }} files: ./artifacts/**/*.xml action_fail: true + action_fail_on_inconclusive: true compare_to_earlier_commit: false json_file: ./unity_results.json json_suite_details: true - name: Upload JSON uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: ${{ always() }} + if: always() with: name: unity_results overwrite: true - path: | - ./unity_results.json + path: ./unity_results.json - name: Fail if tests failed - if: ${{ env.original_conclusion == 'failure' || env.original_conclusion == 'timed_out' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' }} + if: | + needs.get-artifacts.outputs.original_conclusion == 'failure' || + needs.get-artifacts.outputs.original_conclusion == 'cancelled' || + needs.get-artifacts.outputs.original_conclusion == 'timed_out' || + github.event.workflow_run.conclusion == 'failure' || + github.event.workflow_run.conclusion == 'cancelled' || + github.event.workflow_run.conclusion == 'timed_out' run: exit 1 - name: Clean up caches if: always() uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + env: + ORIGINAL_REF: ${{ needs.get-artifacts.outputs.original_ref }} + ORIGINAL_EVENT: ${{ needs.get-artifacts.outputs.original_event }} + ORIGINAL_ACTION: ${{ needs.get-artifacts.outputs.original_action }} with: script: | - const ref = process.env.original_ref; + const ref = process.env.ORIGINAL_REF; const key_prefix = 'test-' + ref + '-'; - if (process.env.original_event == 'pull_request' && process.env.original_action != 'closed') { + if (process.env.ORIGINAL_EVENT == 'pull_request' && process.env.ORIGINAL_ACTION != 'closed') { console.log('Skipping cache cleanup for open PR'); return; } @@ -142,16 +176,19 @@ jobs: - name: Report conclusion uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 if: always() + env: + ORIGINAL_EVENT: ${{ needs.get-artifacts.outputs.original_event }} + ORIGINAL_SHA: ${{ needs.get-artifacts.outputs.original_sha }} with: script: | const owner = '${{ github.repository_owner }}'; const repo = '${{ github.repository }}'.split('/')[1]; - const sha = process.env.original_sha; + const sha = process.env.ORIGINAL_SHA; core.debug(`owner: ${owner}`); core.debug(`repo: ${repo}`); core.debug(`sha: ${sha}`); const { context: name, state } = (await github.rest.repos.createCommitStatus({ - context: `Runtime Tests / Report results (${process.env.original_event} -> workflow_run -> workflow_run)`, + context: `Runtime Tests / Report results (${process.env.ORIGINAL_EVENT} -> workflow_run -> workflow_run)`, owner: owner, repo: repo, sha: sha, @@ -162,12 +199,24 @@ jobs: core.info(`${name} is ${state}`); - name: Generate report - if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled + if: | + (!cancelled() && + needs.get-artifacts.outputs.original_conclusion != 'cancelled' && + github.event.workflow_run.conclusion != 'cancelled') && + (needs.get-artifacts.outputs.original_event == 'schedule' || + needs.get-artifacts.outputs.original_event == 'workflow_dispatch') env: REPORT_FILE: ./runtime-test-results/RUNTIME_TEST_RESULTS.md WOKWI_RUN_ID: ${{ github.event.workflow_run.id }} - BUILD_RUN_ID: ${{ env.original_run_id }} - IS_FAILING: ${{ env.original_conclusion == 'failure' || env.original_conclusion == 'timed_out' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' || job.status == 'failure' }} + BUILD_RUN_ID: ${{ needs.get-artifacts.outputs.original_run_id }} + IS_FAILING: | + needs.get-artifacts.outputs.original_conclusion == 'failure' || + needs.get-artifacts.outputs.original_conclusion == 'cancelled' || + needs.get-artifacts.outputs.original_conclusion == 'timed_out' || + github.event.workflow_run.conclusion == 'failure' || + github.event.workflow_run.conclusion == 'cancelled' || + github.event.workflow_run.conclusion == 'timed_out' || + job.status == 'failure' run: | rm -rf artifacts $REPORT_FILE mv -f ./unity_results.json ./runtime-test-results/unity_results.json @@ -176,7 +225,12 @@ jobs: mv -f ./test_results.json ./runtime-test-results/test_results.json - name: Generate badge - if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled + if: | + (!cancelled() && + needs.get-artifacts.outputs.original_conclusion != 'cancelled' && + github.event.workflow_run.conclusion != 'cancelled') && + (needs.get-artifacts.outputs.original_event == 'schedule' || + needs.get-artifacts.outputs.original_event == 'workflow_dispatch') uses: jaywcjlove/generated-badges@0e078ae4d4bab3777ea4f137de496ab44688f5ad # v1.0.13 with: label: Runtime Tests @@ -186,7 +240,12 @@ jobs: style: flat - name: Push badge - if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled + if: | + (!cancelled() && + needs.get-artifacts.outputs.original_conclusion != 'cancelled' && + github.event.workflow_run.conclusion != 'cancelled') && + (needs.get-artifacts.outputs.original_event == 'schedule' || + needs.get-artifacts.outputs.original_event == 'workflow_dispatch') run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 89a45022bc2..3d0ecd0cb34 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,25 +1,13 @@ workflow: rules: - # Disable those non-protected push triggered pipelines - - if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^\d+\.\d+(\.\d+)?($|-)/ && $CI_PIPELINE_SOURCE == "push"' - when: never - # when running merged result pipelines, CI_COMMIT_SHA represents the temp commit it created. - # Please use PIPELINE_COMMIT_SHA at all places that require a commit sha of the original commit. - - if: $CI_OPEN_MERGE_REQUESTS != null - variables: - PIPELINE_COMMIT_SHA: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA - IS_MR_PIPELINE: 1 - - if: $CI_OPEN_MERGE_REQUESTS == null - variables: - PIPELINE_COMMIT_SHA: $CI_COMMIT_SHA - IS_MR_PIPELINE: 0 - - if: '$CI_PIPELINE_SOURCE == "schedule"' - variables: - IS_SCHEDULED_RUN: "true" - - when: always + # Allow only when triggered manually (web), via API, or by a trigger token + - if: "$CI_PIPELINE_SOURCE =~ /^(trigger|api|web)$/" + when: always + # Deny all other sources + - when: never # Place the default settings in `.gitlab/workflows/common.yml` instead include: - ".gitlab/workflows/common.yml" - - ".gitlab/workflows/sample.yml" + - ".gitlab/workflows/hardware_tests_dynamic.yml" diff --git a/.gitlab/scripts/gen_hw_jobs.py b/.gitlab/scripts/gen_hw_jobs.py new file mode 100644 index 00000000000..804e245c18f --- /dev/null +++ b/.gitlab/scripts/gen_hw_jobs.py @@ -0,0 +1,318 @@ +#!/usr/bin/env python3 + +import argparse +import json +import yaml +import os +import sys +import copy +import traceback +from pathlib import Path + +# Resolve repository root from this script location +SCRIPT_DIR = Path(__file__).resolve().parent +REPO_ROOT = SCRIPT_DIR.parent.parent +TESTS_ROOT = REPO_ROOT / "tests" + +# Ensure we run from repo root so relative paths work consistently +try: + os.chdir(REPO_ROOT) +except Exception as e: + sys.stderr.write(f"[WARN] Failed to chdir to repo root '{REPO_ROOT}': {e}\n") + sys.stderr.write(traceback.format_exc() + "\n") + + +class PrettyDumper(yaml.SafeDumper): + def increase_indent(self, flow=False, indentless=False): + return super().increase_indent(flow, False) + + +def str_representer(dumper, data): + style = "|" if "\n" in data else None + return dumper.represent_scalar("tag:yaml.org,2002:str", data, style=style) + + +def read_json(p: Path): + try: + with p.open("r", encoding="utf-8") as f: + return json.load(f) + except Exception as e: + sys.stderr.write(f"[WARN] Failed to parse JSON file '{p}': {e}\n") + sys.stderr.write(traceback.format_exc() + "\n") + return {} + + +def find_tests() -> list[Path]: + tests = [] + if not TESTS_ROOT.exists(): + return tests + for ci in TESTS_ROOT.rglob("ci.json"): + if ci.is_file(): + tests.append(ci) + return tests + + +def find_sketch_test_dirs(types_filter: list[str]) -> list[tuple[str, Path]]: + """ + Return list of (test_type, test_dir) where test_dir contains a sketch named /.ino + If types_filter provided, only include those types. + """ + results: list[tuple[str, Path]] = [] + if not TESTS_ROOT.exists(): + return results + for type_dir in TESTS_ROOT.iterdir(): + if not type_dir.is_dir(): + continue + test_type = type_dir.name + if types_filter and test_type not in types_filter: + continue + for candidate in type_dir.iterdir(): + if not candidate.is_dir(): + continue + sketch = candidate.name + ino = candidate / f"{sketch}.ino" + if ino.exists(): + results.append((test_type, candidate)) + return results + + +def load_tags_for_test(ci_json: dict, chip: str) -> set[str]: + tags = set() + # Global tags + for key in "tags": + v = ci_json.get(key) + if isinstance(v, list): + for e in v: + if isinstance(e, str) and e.strip(): + tags.add(e.strip()) + # Per-SoC tags + soc_tags = ci_json.get("soc_tags") + if isinstance(soc_tags, dict): + v = soc_tags.get(chip) + if isinstance(v, list): + for e in v: + if isinstance(e, str) and e.strip(): + tags.add(e.strip()) + return tags + + +def test_enabled_for_target(ci_json: dict, chip: str) -> bool: + targets = ci_json.get("targets") + if isinstance(targets, dict): + v = targets.get(chip) + if v is False: + return False + return True + + +def platform_allowed(ci_json: dict, platform: str = "hardware") -> bool: + platforms = ci_json.get("platforms") + if isinstance(platforms, dict): + v = platforms.get(platform) + if v is False: + return False + return True + + +def sketch_name_from_ci(ci_path: Path) -> str: + # The sketch directory holds .ino named as the directory + sketch_dir = ci_path.parent + return sketch_dir.name + + +def sdkconfig_path_for(chip: str, sketch: str, ci_json: dict) -> Path: + # Match logic from tests_run.sh: if multiple FQBN entries -> build0.tmp + fqbn = ci_json.get("fqbn", {}) if isinstance(ci_json, dict) else {} + length = 0 + if isinstance(fqbn, dict): + v = fqbn.get(chip) + if isinstance(v, list): + length = len(v) + if length <= 1: + return Path.home() / f".arduino/tests/{chip}/{sketch}/build.tmp/sdkconfig" + return Path.home() / f".arduino/tests/{chip}/{sketch}/build0.tmp/sdkconfig" + + +def sdk_meets_requirements(sdkconfig: Path, ci_json: dict) -> bool: + # Mirror check_requirements in sketch_utils.sh + if not sdkconfig.exists(): + # Build might have been skipped or failed; allow parent to skip scheduling + return False + try: + requires = ci_json.get("requires") or [] + requires_any = ci_json.get("requires_any") or [] + content = sdkconfig.read_text(encoding="utf-8", errors="ignore") + # AND requirements + for req in requires: + if not isinstance(req, str): + continue + if not any(line.startswith(req) for line in content.splitlines()): + return False + # OR requirements + if requires_any: + ok = any( + any(line.startswith(req) for line in content.splitlines()) + for req in requires_any + if isinstance(req, str) + ) + if not ok: + return False + return True + except Exception as e: + sys.stderr.write(f"[WARN] Failed to evaluate requirements against '{sdkconfig}': {e}\n") + sys.stderr.write(traceback.format_exc() + "\n") + return False + + +def parse_list_arg(s: str) -> list[str]: + if not s: + return [] + txt = s.strip() + if txt.startswith("[") and txt.endswith("]"): + try: + return [str(x).strip() for x in json.loads(txt)] + except Exception as e: + sys.stderr.write(f"[WARN] Failed to parse JSON list '{txt}': {e}. Retrying with quote normalization.\n") + try: + fixed = txt.replace("'", '"') + return [str(x).strip() for x in json.loads(fixed)] + except Exception as e2: + sys.stderr.write( + f"[WARN] Failed to parse JSON list after normalization: {e2}. Falling back to CSV parsing.\n" + ) + # Fallback: comma-separated + return [part.strip() for part in txt.split(",") if part.strip()] + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--chips", required=True, help="Comma-separated or JSON array list of SoCs") + ap.add_argument( + "--types", + required=False, + default="validation", + help="Comma-separated or JSON array of test type directories under tests/", + ) + ap.add_argument("--out", required=True, help="Output YAML path for child pipeline") + ap.add_argument( + "--dry-run", action="store_true", help="Print planned groups/jobs and skip sdkconfig requirement checks" + ) + args = ap.parse_args() + + chips = parse_list_arg(args.chips) + types = parse_list_arg(args.types) + + print(f"Inputs: chips={chips or '[]'}, types={types or '[]'}") + print(f"Repo root: {REPO_ROOT}") + print(f"Tests root: {TESTS_ROOT}") + + # Aggregate mapping: (chip, frozenset(tags or generic), test_type) -> list of test paths + group_map: dict[tuple[str, frozenset[str], str], list[str]] = {} + all_ci = find_tests() + print(f"Discovered {len(all_ci)} ci.json files under tests/") + + matched_count = 0 + for test_type, test_path in find_sketch_test_dirs(types): + ci_path = test_path / "ci.json" + ci = read_json(ci_path) if ci_path.exists() else {} + test_dir = str(test_path) + sketch = test_path.name + for chip in chips: + tags = load_tags_for_test(ci, chip) + if not test_enabled_for_target(ci, chip): + continue + # Skip tests that explicitly disable the hardware platform + if not platform_allowed(ci, "hardware"): + continue + sdk = sdkconfig_path_for(chip, sketch, ci) + if not args.dry_run and not sdk_meets_requirements(sdk, ci): + continue + key_tags = tags.copy() + # SOC must always be one runner tag + key_tags.add(chip) + if len(key_tags) == 1: + # Only SOC present, add generic + key_tags.add("generic") + key = (chip, frozenset(sorted(key_tags)), test_type) + group_map.setdefault(key, []).append(test_dir) + matched_count += 1 + + print(f"Matched {matched_count} test entries into {len(group_map)} groups") + + # Load template job + template_path = REPO_ROOT / ".gitlab/workflows/hw_test_template.yml" + template = yaml.safe_load(template_path.read_text(encoding="utf-8")) + if not isinstance(template, dict) or "hw-test-template" not in template: + print("ERROR: hw_test_template.yml missing hw-test-template") + sys.exit(2) + base_job = template["hw-test-template"] + + # Build child pipeline YAML in deterministic order + jobs_entries = [] # list of (sort_key, job_name, job_dict) + for (chip, tagset, test_type), test_dirs in group_map.items(): + tag_list = sorted(tagset) + # Build name suffix excluding the SOC itself to avoid duplication + non_soc_tags = [t for t in tag_list if t != chip] + tag_suffix = "-".join(non_soc_tags) if non_soc_tags else "generic" + job_name = f"hw-{chip}-{test_type}-{tag_suffix}"[:255] + + # Clone base job and adjust (preserve key order using deepcopy) + job = copy.deepcopy(base_job) + # Ensure tags include SOC+extras + job["tags"] = tag_list + vars_block = job.get("variables", {}) + vars_block["TEST_CHIP"] = chip + vars_block["TEST_TYPE"] = test_type + # Provide list of test directories for this job + vars_block["TEST_LIST"] = "\n".join(sorted(test_dirs)) + job["variables"] = vars_block + + sort_key = (chip, test_type, tag_suffix) + jobs_entries.append((sort_key, job_name, job)) + + # Order jobs by (chip, type, tag_suffix) + jobs = {} + for _, name, job in sorted(jobs_entries, key=lambda x: x[0]): + jobs[name] = job + + if args.dry_run: + print("Planned hardware test jobs:") + for name, job in jobs.items(): + tags = job.get("tags", []) + soc = job.get("variables", {}).get("TEST_CHIP") + ttype = job.get("variables", {}).get("TEST_TYPE") + tlist = job.get("variables", {}).get("TEST_LIST", "") + tests = [p for p in tlist.split("\n") if p] + print(f"- {name} tags={tags} soc={soc} type={ttype} tests={len(tests)}") + for t in tests: + print(f" * {t}") + + # If no jobs matched, create a no-op job to avoid failing trigger + if not jobs: + jobs["no-op"] = { + "stage": "test", + "script": ["echo No matching hardware tests to run"], + "rules": [{"when": "on_success"}], + } + + # Ensure child pipeline defines stages + child = {"stages": ["test"]} + + for name, job in jobs.items(): + child[name] = job + + if args.dry_run: + print("\n--- Generated child pipeline YAML (dry run) ---") + PrettyDumper.add_representer(str, str_representer) + sys.stdout.write(yaml.dump(child, Dumper=PrettyDumper, sort_keys=False, width=4096)) + return 0 + + out = Path(args.out) + + PrettyDumper.add_representer(str, str_representer) + out.write_text(yaml.dump(child, Dumper=PrettyDumper, sort_keys=False, width=4096), encoding="utf-8") + print(f"Wrote child pipeline with {len(jobs)} job(s) to {out}") + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.gitlab/scripts/get_artifacts.sh b/.gitlab/scripts/get_artifacts.sh new file mode 100644 index 00000000000..a29e76a9ba1 --- /dev/null +++ b/.gitlab/scripts/get_artifacts.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# Disable shellcheck warning about $? uses. +# shellcheck disable=SC2181 + +set -e +set -o pipefail + +echo "Downloading test binaries for $TEST_CHIP from GitHub repository $GITHUB_REPOSITORY" +echo "Binaries run ID: $BINARIES_RUN_ID" +echo "Looking for artifact: test-bin-$TEST_CHIP-$TEST_TYPE" + +# Check if GitHub token is available +if [ -z "$GITHUB_DOWNLOAD_PAT" ]; then + echo "ERROR: GITHUB_DOWNLOAD_PAT not available in GitLab environment" + echo "Please set up GITHUB_DOWNLOAD_PAT in GitLab CI/CD variables" + exit 1 +fi + +# First, get the artifacts list and save it for debugging +echo "Fetching artifacts list from GitHub API..." +artifacts_response=$(curl -s -H "Authorization: token $GITHUB_DOWNLOAD_PAT" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/$GITHUB_REPOSITORY/actions/runs/$BINARIES_RUN_ID/artifacts") + +# Check if we got a valid response +if [ -z "$artifacts_response" ]; then + echo "ERROR: Empty response from GitHub API" + exit 1 +fi + +# Check for API errors +error_message=$(echo "$artifacts_response" | jq -r '.message // empty' 2>/dev/null) +if [ -n "$error_message" ]; then + echo "ERROR: GitHub API returned error: $error_message" + exit 1 +fi + +# List all available artifacts for debugging +echo "Available artifacts:" +echo "$artifacts_response" | jq -r '.artifacts[]?.name // "No artifacts found"' 2>/dev/null || echo "Could not parse artifacts" + +# Find the download URL for our specific artifact +download_url=$(echo "$artifacts_response" | jq -r ".artifacts[] | select(.name==\"test-bin-$TEST_CHIP-$TEST_TYPE\") | .archive_download_url" 2>/dev/null) + +if [ "$download_url" = "null" ] || [ -z "$download_url" ]; then + echo "ERROR: Could not find artifact 'test-bin-$TEST_CHIP-$TEST_TYPE'" + echo "This could mean:" + echo "1. The artifact name doesn't match exactly" + echo "2. The artifacts haven't been uploaded yet" + echo "3. The GitHub run ID is incorrect" + exit 1 +fi + +echo "Found download URL: $download_url" + +# Download the artifact +echo "Downloading artifact..." +curl -H "Authorization: token $GITHUB_DOWNLOAD_PAT" -L "$download_url" -o test-binaries.zip + +if [ $? -ne 0 ] || [ ! -f test-binaries.zip ]; then + echo "ERROR: Failed to download artifact" + exit 1 +fi + +echo "Extracting binaries..." +unzip -q -o test-binaries.zip -d ~/.arduino/tests/"$TEST_CHIP"/ + +if [ $? -ne 0 ]; then + echo "ERROR: Failed to extract binaries" + exit 1 +fi + +rm -f test-binaries.zip +echo "Successfully downloaded and extracted test binaries" diff --git a/.gitlab/scripts/get_results.sh b/.gitlab/scripts/get_results.sh new file mode 100644 index 00000000000..cdfe2e64f96 --- /dev/null +++ b/.gitlab/scripts/get_results.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +set -euo pipefail + +echo "Collecting artifacts from child pipeline(s)" + +api="$CI_API_V4_URL" +proj="$CI_PROJECT_ID" +parent="$CI_PIPELINE_ID" + +# Choose auth header (prefer PRIVATE-TOKEN if provided) +AUTH_HEADER="JOB-TOKEN: $CI_JOB_TOKEN" +if [ -n "${GITLAB_API_TOKEN:-}" ]; then + AUTH_HEADER="PRIVATE-TOKEN: $GITLAB_API_TOKEN" +fi + +# Verify project is reachable +if ! curl -sf --header "$AUTH_HEADER" "$api/projects/$proj" >/dev/null; then + echo "WARNING: Unable to access project $proj via API (token scope?)" + exit 1 +fi + +bridges=$(curl -s --header "$AUTH_HEADER" "$api/projects/$proj/pipelines/$parent/bridges") +# Ensure we got a JSON array +if ! echo "$bridges" | jq -e 'type=="array"' >/dev/null 2>&1; then + echo "WARNING: Unexpected bridges response:"; echo "$bridges" + exit 1 +fi + +child_ids=$(echo "$bridges" | jq -r '.[] | select(.name=="trigger-hw-tests") | .downstream_pipeline.id') +mkdir -p aggregated + +for cid in $child_ids; do + echo "Child pipeline: $cid" + + jobs=$(curl -s --header "$AUTH_HEADER" "$api/projects/$proj/pipelines/$cid/jobs?per_page=100") + if ! echo "$jobs" | jq -e 'type=="array"' >/dev/null 2>&1; then + echo "WARNING: Unable to list jobs for child $cid"; echo "$jobs" + exit 1 + fi + + ids=$(echo "$jobs" | jq -r '.[] | select(.artifacts_file!=null) | .id') + failed=false + for jid in $ids; do + echo "Downloading artifacts from job $jid" + curl --header "$AUTH_HEADER" -L -s "$api/projects/$proj/jobs/$jid/artifacts" -o artifact.zip || true + if [ -f artifact.zip ]; then + unzip -q -o artifact.zip -d . >/dev/null 2>&1 || true + else + echo "Job $jid has no artifacts" + failed=true + fi + rm -f artifact.zip + done +done + +if $failed; then + echo "Some jobs failed to download artifacts" + exit 1 +fi diff --git a/.gitlab/workflows/common.yml b/.gitlab/workflows/common.yml index 611e1d974f4..5702954e9e9 100644 --- a/.gitlab/workflows/common.yml +++ b/.gitlab/workflows/common.yml @@ -4,13 +4,16 @@ stages: - pre_check + - generate - build - test + - trigger + - collect - result variables: ESP_IDF_VERSION: "5.5" - ESP_ARDUINO_VERSION: "3.3.0" + ESP_ARDUINO_VERSION: "3.3.2" ############# # `default` # diff --git a/.gitlab/workflows/hardware_tests_dynamic.yml b/.gitlab/workflows/hardware_tests_dynamic.yml new file mode 100644 index 00000000000..2c137f092ab --- /dev/null +++ b/.gitlab/workflows/hardware_tests_dynamic.yml @@ -0,0 +1,79 @@ +############################### +# Dynamic Hardware Tests Parent +############################### + +# This parent workflow generates a dynamic child pipeline with jobs grouped +# by SOC + runner tags derived from tests' ci.json, then triggers it and waits. + +generate-hw-tests: + stage: generate + image: python:3.12-bookworm + rules: + - if: $CI_PIPELINE_SOURCE == "trigger" + when: on_success + variables: + DEBIAN_FRONTEND: "noninteractive" + TEST_TYPES: $TEST_TYPES + TEST_CHIPS: $TEST_CHIPS + before_script: + - pip install PyYAML + - apt-get update + - apt-get install -y jq unzip curl + script: + - mkdir -p ~/.arduino/tests + - | + # Download artifacts for all requested chips/types so sdkconfig exists for grouping + CHIPS=$(echo "$TEST_CHIPS" | tr -d "[]' " | tr ',' ' ') + TYPES=$(echo "$TEST_TYPES" | tr -d "[]' " | tr ',' ' ') + for chip in $CHIPS; do + for t in $TYPES; do + export TEST_CHIP="$chip" + export TEST_TYPE="$t" + echo "Fetching artifacts for chip=$chip type=$t" + bash .gitlab/scripts/get_artifacts.sh + done + done + - python3 .gitlab/scripts/gen_hw_jobs.py --chips "$TEST_CHIPS" --types "$TEST_TYPES" --out child-hw-jobs.yml + artifacts: + when: always + expire_in: 7 days + paths: + - child-hw-jobs.yml + +trigger-hw-tests: + stage: trigger + needs: ["generate-hw-tests"] + rules: + - if: $CI_PIPELINE_SOURCE == "trigger" + when: on_success + variables: + # Forward common context to children + BINARIES_RUN_ID: $BINARIES_RUN_ID + GITHUB_REPOSITORY: $GITHUB_REPOSITORY + PIPELINE_ID: $PIPELINE_ID + trigger: + include: + - artifact: child-hw-jobs.yml + job: generate-hw-tests + strategy: depend + +collect-hw-results: + stage: result + image: python:3.12-bookworm + needs: ["trigger-hw-tests"] + rules: + - if: $CI_PIPELINE_SOURCE == "trigger" + when: always + before_script: + - apt-get update && apt-get install -y jq curl unzip + script: + - bash .gitlab/scripts/get_results.sh + artifacts: + name: "hw-test-results-aggregated" + expire_in: 7 days + when: always + paths: + - "tests/**/*.xml" + - "tests/**/result_*.json" + reports: + junit: "tests/**/*.xml" diff --git a/.gitlab/workflows/hw_test_template.yml b/.gitlab/workflows/hw_test_template.yml new file mode 100644 index 00000000000..1b09c2cb7eb --- /dev/null +++ b/.gitlab/workflows/hw_test_template.yml @@ -0,0 +1,65 @@ +######################## +# HW Test Job Template # +######################## + +# This template is used to generate the pipeline for each hardware test. +# It is triggered in hardware_tests_dynamic.yml after being generated by gen_hw_jobs.py. + +include: + - local: ".gitlab/workflows/common.yml" + +# Single job template to be cloned by the dynamic generator +hw-test-template: + stage: test + image: python:3.12-bookworm + + rules: + - when: on_success + + variables: + RUNNER_SCRIPT_TIMEOUT: 4h + RUNNER_AFTER_SCRIPT_TIMEOUT: 2h + DEBIAN_FRONTEND: "noninteractive" + TEST_TYPE: $TEST_TYPE + TEST_CHIP: $TEST_CHIP + PIPELINE_ID: $PIPELINE_ID + BINARIES_RUN_ID: $BINARIES_RUN_ID + GITHUB_REPOSITORY: $GITHUB_REPOSITORY + + tags: + - $TEST_CHIP + + before_script: + - echo "Running hardware tests for chip:$TEST_CHIP type:$TEST_TYPE" + - echo "Pipeline ID:$PIPELINE_ID" + - echo "Running hardware tests for chip:$TEST_CHIP" + - apt-get update + - apt-get install -y jq unzip curl + - rm -rf ~/.arduino/tests + - mkdir -p ~/.arduino/tests/$TEST_CHIP + - echo Fetching binaries for $TEST_CHIP $TEST_TYPE + - bash .gitlab/scripts/get_artifacts.sh + - pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi + + script: + - echo "Using binaries for $TEST_CHIP" + - ls -laR ~/.arduino/tests || true + - | + set -e + rc=0 + while IFS= read -r d; do + [ -z "$d" ] && continue; + sketch=$(basename "$d"); + echo Running $sketch in $d; + bash .github/scripts/tests_run.sh -t $TEST_CHIP -s $sketch -e || rc=$?; + done <<< "$TEST_LIST"; exit $rc + + artifacts: + name: "hw-test-results-$TEST_CHIP-$TEST_TYPE" + expire_in: 7 days + when: always + paths: + - "tests/**/*.xml" + - "tests/**/result_*.json" + reports: + junit: "tests/**/*.xml" diff --git a/.gitlab/workflows/sample.yml b/.gitlab/workflows/sample.yml deleted file mode 100644 index e20cecf9e9e..00000000000 --- a/.gitlab/workflows/sample.yml +++ /dev/null @@ -1,16 +0,0 @@ -hello-world: - stage: test - rules: - - if: $CI_PIPELINE_SOURCE == "push" - - if: $CI_PIPELINE_SOURCE == "web" - - if: $CI_PIPELINE_SOURCE == "trigger" - variables: - PIPELINE_TRIGGER_TOKEN: $CI_PIPELINE_TRIGGER_TOKEN - script: - - echo "Hello, World from GitLab CI!" - - echo "Hello World!" > sample_artifact.txt - artifacts: - name: "sample-artifact" - paths: - - sample_artifact.txt - expire_in: 1 day diff --git a/Kconfig.projbuild b/Kconfig.projbuild index 9966463f8c1..705d0e66d5a 100644 --- a/Kconfig.projbuild +++ b/Kconfig.projbuild @@ -341,9 +341,15 @@ config ARDUINO_SELECTIVE_PPP depends on ARDUINO_SELECTIVE_COMPILATION default y +config ARDUINO_SELECTIVE_Hash + bool "Enable Hash" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + config ARDUINO_SELECTIVE_ArduinoOTA bool "Enable ArduinoOTA" depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network + select ARDUINO_SELECTIVE_Hash select ARDUINO_SELECTIVE_ESPmDNS default y @@ -383,6 +389,7 @@ config ARDUINO_SELECTIVE_WebServer depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network default y select ARDUINO_SELECTIVE_FS + select ARDUINO_SELECTIVE_Hash config ARDUINO_SELECTIVE_WiFi bool "Enable WiFi" diff --git a/README.md b/README.md index f8ff1f28eaa..51ab98e0af1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Arduino core for the ESP32, ESP32-C3, ESP32-C6, ESP32-H2, ESP32-P4, ESP32-S2 and ESP32-S3. +# Arduino core for the ESP32, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-H2, ESP32-P4, ESP32-S2 and ESP32-S3. [![Build Status](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/push.yml?branch=master&event=push&label=Compilation%20Tests)](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml?query=branch%3Amaster+event%3Apush) [![Verbose Build Status](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/push.yml?branch=master&event=schedule&label=Compilation%20Tests%20(Verbose))](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml?query=branch%3Amaster+event%3Aschedule) @@ -68,6 +68,7 @@ Here are the ESP32 series supported by the Arduino-ESP32 project: |----------|:----------:|:---------------:|:-------------------------------------------------------------------------------------------------:| | ESP32 | Yes | Yes | [ESP32](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) | | ESP32-C3 | Yes | Yes | [ESP32-C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) | +| ESP32-C5 | Yes | Yes | [ESP32-C5](https://www.espressif.com/sites/default/files/documentation/esp32-c5_datasheet_en.pdf) | | ESP32-C6 | Yes | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) | | ESP32-H2 | Yes | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) | | ESP32-P4 | Yes | Yes | [ESP32-P4](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf) | diff --git a/boards.txt b/boards.txt index 876ef761c94..038b9727f84 100644 --- a/boards.txt +++ b/boards.txt @@ -2033,9 +2033,6 @@ esp32wrover.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5M esp32wrover.menu.PartitionScheme.default.build.partitions=default esp32wrover.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) esp32wrover.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -esp32wrover.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -esp32wrover.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -esp32wrover.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 esp32wrover.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) esp32wrover.menu.PartitionScheme.minimal.build.partitions=minimal esp32wrover.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -2056,9 +2053,6 @@ esp32wrover.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 esp32wrover.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) esp32wrover.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs esp32wrover.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -esp32wrover.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -esp32wrover.menu.PartitionScheme.fatflash.build.partitions=ffat -esp32wrover.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 esp32wrover.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32wrover.menu.PartitionScheme.rainmaker.build.partitions=rainmaker esp32wrover.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -2067,7 +2061,7 @@ esp32wrover.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no esp32wrover.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 esp32wrover.menu.PartitionScheme.custom=Custom esp32wrover.menu.PartitionScheme.custom.build.partitions= -esp32wrover.menu.PartitionScheme.custom.upload.maximum_size=16777216 +esp32wrover.menu.PartitionScheme.custom.upload.maximum_size=4194304 esp32wrover.menu.FlashMode.qio=QIO esp32wrover.menu.FlashMode.qio.build.flash_mode=dio @@ -2159,7 +2153,7 @@ pico32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs pico32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 pico32.menu.PartitionScheme.custom=Custom pico32.menu.PartitionScheme.custom.build.partitions= -pico32.menu.PartitionScheme.custom.upload.maximum_size=16777216 +pico32.menu.PartitionScheme.custom.upload.maximum_size=4194304 pico32.menu.UploadSpeed.921600=921600 pico32.menu.UploadSpeed.921600.upload.speed=921600 @@ -2284,12 +2278,11 @@ esp32s3-octal.menu.FlashMode.dio.build.boot_freq=80m esp32s3-octal.menu.FlashMode.dio.build.flash_freq=80m esp32s3-octal.menu.FlashSize.16M=16MB (128Mb) +esp32s3-octal.menu.FlashSize.16M.build.flash_size=16MB esp32s3-octal.menu.FlashSize.4M=4MB (32Mb) esp32s3-octal.menu.FlashSize.4M.build.flash_size=4MB esp32s3-octal.menu.FlashSize.8M=8MB (64Mb) esp32s3-octal.menu.FlashSize.8M.build.flash_size=8MB -esp32s3-octal.menu.FlashSize.16M=16MB (128Mb) -esp32s3-octal.menu.FlashSize.16M.build.flash_size=16MB esp32s3-octal.menu.FlashSize.32M=32MB (256Mb) esp32s3-octal.menu.FlashSize.32M.build.flash_size=32MB @@ -2331,6 +2324,8 @@ esp32s3-octal.menu.UploadMode.cdc.upload.use_1200bps_touch=true esp32s3-octal.menu.UploadMode.cdc.upload.wait_for_upload_port=true esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 esp32s3-octal.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) esp32s3-octal.menu.PartitionScheme.default.build.partitions=default esp32s3-octal.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -2361,9 +2356,6 @@ esp32s3-octal.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 esp32s3-octal.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) esp32s3-octal.menu.PartitionScheme.fatflash.build.partitions=ffat esp32s3-octal.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -esp32s3-octal.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 esp32s3-octal.menu.PartitionScheme.rainmaker=RainMaker 4MB esp32s3-octal.menu.PartitionScheme.rainmaker.build.partitions=rainmaker esp32s3-octal.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -2612,15 +2604,9 @@ esp32s3usbotg.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 esp32s3usbotg.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) esp32s3usbotg.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs esp32s3usbotg.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -esp32s3usbotg.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -esp32s3usbotg.menu.PartitionScheme.fatflash.build.partitions=ffat -esp32s3usbotg.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -esp32s3usbotg.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -esp32s3usbotg.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -esp32s3usbotg.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 esp32s3usbotg.menu.PartitionScheme.custom=Custom esp32s3usbotg.menu.PartitionScheme.custom.build.partitions= -esp32s3usbotg.menu.PartitionScheme.custom.upload.maximum_size=16777216 +esp32s3usbotg.menu.PartitionScheme.custom.upload.maximum_size=8388608 esp32s3usbotg.menu.DebugLevel.none=None esp32s3usbotg.menu.DebugLevel.none.build.code_debug=0 @@ -2698,9 +2684,6 @@ esp32s3camlcd.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1. esp32s3camlcd.menu.PartitionScheme.default.build.partitions=default esp32s3camlcd.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) esp32s3camlcd.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -esp32s3camlcd.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -esp32s3camlcd.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -esp32s3camlcd.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 esp32s3camlcd.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) esp32s3camlcd.menu.PartitionScheme.minimal.build.partitions=minimal esp32s3camlcd.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -2721,12 +2704,6 @@ esp32s3camlcd.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 esp32s3camlcd.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) esp32s3camlcd.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs esp32s3camlcd.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -esp32s3camlcd.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -esp32s3camlcd.menu.PartitionScheme.fatflash.build.partitions=ffat -esp32s3camlcd.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -esp32s3camlcd.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -esp32s3camlcd.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -esp32s3camlcd.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 esp32s3camlcd.menu.UploadSpeed.921600=921600 esp32s3camlcd.menu.UploadSpeed.921600.upload.speed=921600 @@ -5394,7 +5371,7 @@ um_tinyc6.build.bootloader_addr=0x0 um_tinyc6.build.cdc_on_boot=1 um_tinyc6.build.f_cpu=160000000L -um_tinyc6.build.flash_size=4MB +um_tinyc6.build.flash_size=8MB um_tinyc6.build.flash_freq=80m um_tinyc6.build.flash_mode=qio um_tinyc6.build.boot=qio @@ -5439,7 +5416,7 @@ um_tinyc6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr um_tinyc6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 um_tinyc6.menu.PartitionScheme.custom=Custom um_tinyc6.menu.PartitionScheme.custom.build.partitions= -um_tinyc6.menu.PartitionScheme.custom.upload.maximum_size=16777216 +um_tinyc6.menu.PartitionScheme.custom.upload.maximum_size=8388608 um_tinyc6.menu.CPUFreq.160=160MHz (WiFi) um_tinyc6.menu.CPUFreq.160.build.f_cpu=160000000L @@ -5867,6 +5844,8 @@ S_ODI_Ultra.menu.DebugLevel.info=Info S_ODI_Ultra.menu.DebugLevel.info.build.code_debug=3 S_ODI_Ultra.menu.DebugLevel.debug=Debug S_ODI_Ultra.menu.DebugLevel.debug.build.code_debug=4 +S_ODI_Ultra.menu.DebugLevel.verbose=Verbose +S_ODI_Ultra.menu.DebugLevel.verbose.build.code_debug=5 S_ODI_Ultra.menu.EraseFlash.none=Disabled S_ODI_Ultra.menu.EraseFlash.none.upload.erase_cmd= @@ -8450,7 +8429,7 @@ sparkfun_esp32s3_thing_plus.menu.PartitionScheme.zigbee_zczr.build.partitions=zi sparkfun_esp32s3_thing_plus.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 sparkfun_esp32s3_thing_plus.menu.PartitionScheme.custom=Custom sparkfun_esp32s3_thing_plus.menu.PartitionScheme.custom.build.partitions= -sparkfun_esp32s3_thing_plus.menu.PartitionScheme.custom.upload.maximum_size=16777216 +sparkfun_esp32s3_thing_plus.menu.PartitionScheme.custom.upload.maximum_size=4194304 sparkfun_esp32s3_thing_plus.menu.CPUFreq.240=240MHz (WiFi) sparkfun_esp32s3_thing_plus.menu.CPUFreq.240.build.f_cpu=240000000L @@ -10446,8 +10425,6 @@ lolin_s2_mini.build.flash_freq=80m lolin_s2_mini.build.flash_mode=dio lolin_s2_mini.build.boot=qio lolin_s2_mini.build.partitions=default -lolin_s2_mini.build.defines= - lolin_s2_mini.build.defines=-DBOARD_HAS_PSRAM lolin_s2_mini.menu.CDCOnBoot.default=Enabled @@ -10544,8 +10521,6 @@ lolin_s2_pico.build.flash_freq=80m lolin_s2_pico.build.flash_mode=dio lolin_s2_pico.build.boot=qio lolin_s2_pico.build.partitions=default -lolin_s2_pico.build.defines= - lolin_s2_pico.build.defines=-DBOARD_HAS_PSRAM lolin_s2_pico.menu.CDCOnBoot.default=Enabled @@ -12249,9 +12224,6 @@ dfrobot_beetle_esp32c3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2 dfrobot_beetle_esp32c3.menu.PartitionScheme.default.build.partitions=default dfrobot_beetle_esp32c3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) dfrobot_beetle_esp32c3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -dfrobot_beetle_esp32c3.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -dfrobot_beetle_esp32c3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -dfrobot_beetle_esp32c3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 dfrobot_beetle_esp32c3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) dfrobot_beetle_esp32c3.menu.PartitionScheme.minimal.build.partitions=minimal dfrobot_beetle_esp32c3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -12272,12 +12244,6 @@ dfrobot_beetle_esp32c3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 dfrobot_beetle_esp32c3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) dfrobot_beetle_esp32c3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs dfrobot_beetle_esp32c3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -dfrobot_beetle_esp32c3.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -dfrobot_beetle_esp32c3.menu.PartitionScheme.fatflash.build.partitions=ffat -dfrobot_beetle_esp32c3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -dfrobot_beetle_esp32c3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -dfrobot_beetle_esp32c3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -dfrobot_beetle_esp32c3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker=RainMaker 4MB dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker dfrobot_beetle_esp32c3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -12438,7 +12404,7 @@ dfrobot_beetle_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_ dfrobot_beetle_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 dfrobot_beetle_esp32c6.menu.PartitionScheme.custom=Custom dfrobot_beetle_esp32c6.menu.PartitionScheme.custom.build.partitions= -dfrobot_beetle_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 +dfrobot_beetle_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=4194304 dfrobot_beetle_esp32c6.menu.CPUFreq.160=160MHz (WiFi) dfrobot_beetle_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L @@ -12984,7 +12950,7 @@ dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zi dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.custom=Custom dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.custom.build.partitions= -dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 +dfrobot_firebeetle2_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=4194304 dfrobot_firebeetle2_esp32c6.menu.CPUFreq.160=160MHz (WiFi) dfrobot_firebeetle2_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L @@ -16132,9 +16098,6 @@ adafruit_feather_esp32c6.menu.PartitionScheme.default=Default 4MB with spiffs (1 adafruit_feather_esp32c6.menu.PartitionScheme.default.build.partitions=default adafruit_feather_esp32c6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) adafruit_feather_esp32c6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -adafruit_feather_esp32c6.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -adafruit_feather_esp32c6.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -adafruit_feather_esp32c6.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 adafruit_feather_esp32c6.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) adafruit_feather_esp32c6.menu.PartitionScheme.minimal.build.partitions=minimal adafruit_feather_esp32c6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -16155,12 +16118,6 @@ adafruit_feather_esp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=31457 adafruit_feather_esp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) adafruit_feather_esp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs adafruit_feather_esp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -adafruit_feather_esp32c6.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -adafruit_feather_esp32c6.menu.PartitionScheme.fatflash.build.partitions=ffat -adafruit_feather_esp32c6.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -adafruit_feather_esp32c6.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -adafruit_feather_esp32c6.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -adafruit_feather_esp32c6.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker adafruit_feather_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -16175,7 +16132,7 @@ adafruit_feather_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbe adafruit_feather_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 adafruit_feather_esp32c6.menu.PartitionScheme.custom=Custom adafruit_feather_esp32c6.menu.PartitionScheme.custom.build.partitions= -adafruit_feather_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 +adafruit_feather_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=4194304 adafruit_feather_esp32c6.menu.CPUFreq.160=160MHz (WiFi) adafruit_feather_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L @@ -18360,9 +18317,6 @@ nologo_esp32c3_super_mini.menu.PartitionScheme.default=Default 4MB with spiffs ( nologo_esp32c3_super_mini.menu.PartitionScheme.default.build.partitions=default nologo_esp32c3_super_mini.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) nologo_esp32c3_super_mini.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -nologo_esp32c3_super_mini.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -nologo_esp32c3_super_mini.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -nologo_esp32c3_super_mini.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 nologo_esp32c3_super_mini.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) nologo_esp32c3_super_mini.menu.PartitionScheme.minimal.build.partitions=minimal nologo_esp32c3_super_mini.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -18611,12 +18565,6 @@ nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=40386 nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB nologo_esp32s3_pico.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4096000 -nologo_esp32s3_pico.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) -nologo_esp32s3_pico.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB -nologo_esp32s3_pico.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 -nologo_esp32s3_pico.menu.PartitionScheme.app5M_little24M_32MB=32M Flash (4.8MB APP/22MB LittleFS) -nologo_esp32s3_pico.menu.PartitionScheme.app5M_little24M_32MB.build.partitions=large_littlefs_32MB -nologo_esp32s3_pico.menu.PartitionScheme.app5M_little24M_32MB.upload.maximum_size=4718592 nologo_esp32s3_pico.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) nologo_esp32s3_pico.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 nologo_esp32s3_pico.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin @@ -18981,6 +18929,8 @@ esp32doit-devkit-v1.menu.DebugLevel.info=Info esp32doit-devkit-v1.menu.DebugLevel.info.build.code_debug=3 esp32doit-devkit-v1.menu.DebugLevel.debug=Debug esp32doit-devkit-v1.menu.DebugLevel.debug.build.code_debug=4 +esp32doit-devkit-v1.menu.DebugLevel.verbose=Verbose +esp32doit-devkit-v1.menu.DebugLevel.verbose.build.code_debug=5 esp32doit-devkit-v1.menu.EraseFlash.none=Disabled esp32doit-devkit-v1.menu.EraseFlash.none.upload.erase_cmd= @@ -19585,8 +19535,6 @@ esp32-devkitlipo.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 esp32-devkitlipo.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) esp32-devkitlipo.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs esp32-devkitlipo.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -esp32-devkitlipo.menu.PartitionScheme.fatflash=16M Fat -esp32-devkitlipo.menu.PartitionScheme.fatflash.build.partitions=ffat esp32-devkitlipo.menu.FlashMode.qio=QIO esp32-devkitlipo.menu.FlashMode.qio.build.flash_mode=dio @@ -21955,9 +21903,6 @@ m5stack_stickc.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1 m5stack_stickc.menu.PartitionScheme.default.build.partitions=default m5stack_stickc.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) m5stack_stickc.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -m5stack_stickc.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -m5stack_stickc.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -m5stack_stickc.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 m5stack_stickc.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) m5stack_stickc.menu.PartitionScheme.minimal.build.partitions=minimal m5stack_stickc.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -21975,9 +21920,6 @@ m5stack_stickc.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 m5stack_stickc.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) m5stack_stickc.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs m5stack_stickc.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -m5stack_stickc.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -m5stack_stickc.menu.PartitionScheme.fatflash.build.partitions=ffat -m5stack_stickc.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_stickc.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stickc.menu.PartitionScheme.rainmaker.build.partitions=rainmaker m5stack_stickc.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -21986,7 +21928,7 @@ m5stack_stickc.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB m5stack_stickc.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_stickc.menu.PartitionScheme.custom=Custom m5stack_stickc.menu.PartitionScheme.custom.build.partitions= -m5stack_stickc.menu.PartitionScheme.custom.upload.maximum_size=16777216 +m5stack_stickc.menu.PartitionScheme.custom.upload.maximum_size=4194304 m5stack_stickc.menu.CPUFreq.240=240MHz (WiFi/BT) m5stack_stickc.menu.CPUFreq.240.build.f_cpu=240000000L @@ -22110,9 +22052,6 @@ m5stack_stickc_plus.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB m5stack_stickc_plus.menu.PartitionScheme.default.build.partitions=default m5stack_stickc_plus.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) m5stack_stickc_plus.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -m5stack_stickc_plus.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -m5stack_stickc_plus.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -m5stack_stickc_plus.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 m5stack_stickc_plus.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) m5stack_stickc_plus.menu.PartitionScheme.minimal.build.partitions=minimal m5stack_stickc_plus.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -22130,9 +22069,6 @@ m5stack_stickc_plus.menu.PartitionScheme.noota_3gffat.upload.maximum_size=104857 m5stack_stickc_plus.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) m5stack_stickc_plus.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs m5stack_stickc_plus.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -m5stack_stickc_plus.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -m5stack_stickc_plus.menu.PartitionScheme.fatflash.build.partitions=ffat -m5stack_stickc_plus.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_stickc_plus.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stickc_plus.menu.PartitionScheme.rainmaker.build.partitions=rainmaker m5stack_stickc_plus.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -22141,7 +22077,7 @@ m5stack_stickc_plus.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmake m5stack_stickc_plus.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_stickc_plus.menu.PartitionScheme.custom=Custom m5stack_stickc_plus.menu.PartitionScheme.custom.build.partitions= -m5stack_stickc_plus.menu.PartitionScheme.custom.upload.maximum_size=16777216 +m5stack_stickc_plus.menu.PartitionScheme.custom.upload.maximum_size=4194304 m5stack_stickc_plus.menu.CPUFreq.240=240MHz (WiFi/BT) m5stack_stickc_plus.menu.CPUFreq.240.build.f_cpu=240000000L @@ -22291,9 +22227,6 @@ m5stack_stickc_plus2.menu.PartitionScheme.noota_3gffat.upload.maximum_size=10485 m5stack_stickc_plus2.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) m5stack_stickc_plus2.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs m5stack_stickc_plus2.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -m5stack_stickc_plus2.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -m5stack_stickc_plus2.menu.PartitionScheme.fatflash.build.partitions=ffat -m5stack_stickc_plus2.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_stickc_plus2.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stickc_plus2.menu.PartitionScheme.rainmaker.build.partitions=rainmaker m5stack_stickc_plus2.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -22305,7 +22238,7 @@ m5stack_stickc_plus2.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmak m5stack_stickc_plus2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4096000 m5stack_stickc_plus2.menu.PartitionScheme.custom=Custom m5stack_stickc_plus2.menu.PartitionScheme.custom.build.partitions= -m5stack_stickc_plus2.menu.PartitionScheme.custom.upload.maximum_size=16777216 +m5stack_stickc_plus2.menu.PartitionScheme.custom.upload.maximum_size=8388608 m5stack_stickc_plus2.menu.CPUFreq.240=240MHz (WiFi/BT) m5stack_stickc_plus2.menu.CPUFreq.240.build.f_cpu=240000000L @@ -22428,9 +22361,6 @@ m5stack_atom.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5 m5stack_atom.menu.PartitionScheme.default.build.partitions=default m5stack_atom.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) m5stack_atom.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -m5stack_atom.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -m5stack_atom.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -m5stack_atom.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 m5stack_atom.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) m5stack_atom.menu.PartitionScheme.minimal.build.partitions=minimal m5stack_atom.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -22448,9 +22378,6 @@ m5stack_atom.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 m5stack_atom.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) m5stack_atom.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs m5stack_atom.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -m5stack_atom.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -m5stack_atom.menu.PartitionScheme.fatflash.build.partitions=ffat -m5stack_atom.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_atom.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_atom.menu.PartitionScheme.rainmaker.build.partitions=rainmaker m5stack_atom.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -22459,7 +22386,7 @@ m5stack_atom.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_n m5stack_atom.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_atom.menu.PartitionScheme.custom=Custom m5stack_atom.menu.PartitionScheme.custom.build.partitions= -m5stack_atom.menu.PartitionScheme.custom.upload.maximum_size=16777216 +m5stack_atom.menu.PartitionScheme.custom.upload.maximum_size=4194304 m5stack_atom.menu.CPUFreq.240=240MHz (WiFi/BT) m5stack_atom.menu.CPUFreq.240.build.f_cpu=240000000L @@ -22695,12 +22622,6 @@ m5stack_atoms3.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 m5stack_atoms3.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) m5stack_atoms3.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs m5stack_atoms3.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -m5stack_atoms3.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -m5stack_atoms3.menu.PartitionScheme.fatflash.build.partitions=ffat -m5stack_atoms3.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -m5stack_atoms3.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -m5stack_atoms3.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -m5stack_atoms3.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 m5stack_atoms3.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_atoms3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker m5stack_atoms3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -22710,19 +22631,9 @@ m5stack_atoms3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_atoms3.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB m5stack_atoms3.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB m5stack_atoms3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4096000 -m5stack_atoms3.menu.PartitionScheme.app5M_fat24M_32MB=32M Flash (4.8MB APP/22MB FATFS) -m5stack_atoms3.menu.PartitionScheme.app5M_fat24M_32MB.build.partitions=large_fat_32MB -m5stack_atoms3.menu.PartitionScheme.app5M_fat24M_32MB.upload.maximum_size=4718592 -m5stack_atoms3.menu.PartitionScheme.app5M_little24M_32MB=32M Flash (4.8MB APP/22MB LittleFS) -m5stack_atoms3.menu.PartitionScheme.app5M_little24M_32MB.build.partitions=large_littlefs_32MB -m5stack_atoms3.menu.PartitionScheme.app5M_little24M_32MB.upload.maximum_size=4718592 -m5stack_atoms3.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL) -m5stack_atoms3.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728 -m5stack_atoms3.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin -m5stack_atoms3.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16 m5stack_atoms3.menu.PartitionScheme.custom=Custom m5stack_atoms3.menu.PartitionScheme.custom.build.partitions= -m5stack_atoms3.menu.PartitionScheme.custom.upload.maximum_size=16777216 +m5stack_atoms3.menu.PartitionScheme.custom.upload.maximum_size=8388608 m5stack_atoms3.menu.CPUFreq.240=240MHz (WiFi) m5stack_atoms3.menu.CPUFreq.240.build.f_cpu=240000000L @@ -23240,9 +23151,6 @@ m5stack_timer_cam.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB AP m5stack_timer_cam.menu.PartitionScheme.default.build.partitions=default m5stack_timer_cam.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) m5stack_timer_cam.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -m5stack_timer_cam.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -m5stack_timer_cam.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -m5stack_timer_cam.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 m5stack_timer_cam.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) m5stack_timer_cam.menu.PartitionScheme.minimal.build.partitions=minimal m5stack_timer_cam.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -23391,9 +23299,6 @@ m5stack_unit_cam.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP m5stack_unit_cam.menu.PartitionScheme.default.build.partitions=default m5stack_unit_cam.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) m5stack_unit_cam.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -m5stack_unit_cam.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -m5stack_unit_cam.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -m5stack_unit_cam.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 m5stack_unit_cam.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) m5stack_unit_cam.menu.PartitionScheme.minimal.build.partitions=minimal m5stack_unit_cam.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -23775,9 +23680,6 @@ m5stack_poe_cam.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/ m5stack_poe_cam.menu.PartitionScheme.default.build.partitions=default m5stack_poe_cam.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) m5stack_poe_cam.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -m5stack_poe_cam.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -m5stack_poe_cam.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -m5stack_poe_cam.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 m5stack_poe_cam.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) m5stack_poe_cam.menu.PartitionScheme.minimal.build.partitions=minimal m5stack_poe_cam.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -24091,9 +23993,6 @@ m5stack_coreink.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/ m5stack_coreink.menu.PartitionScheme.default.build.partitions=default m5stack_coreink.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) m5stack_coreink.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -m5stack_coreink.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -m5stack_coreink.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -m5stack_coreink.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 m5stack_coreink.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) m5stack_coreink.menu.PartitionScheme.minimal.build.partitions=minimal m5stack_coreink.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -24114,9 +24013,6 @@ m5stack_coreink.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 m5stack_coreink.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) m5stack_coreink.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs m5stack_coreink.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -m5stack_coreink.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -m5stack_coreink.menu.PartitionScheme.fatflash.build.partitions=ffat -m5stack_coreink.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_coreink.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_coreink.menu.PartitionScheme.rainmaker.build.partitions=rainmaker m5stack_coreink.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -24125,7 +24021,7 @@ m5stack_coreink.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4M m5stack_coreink.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_coreink.menu.PartitionScheme.custom=Custom m5stack_coreink.menu.PartitionScheme.custom.build.partitions= -m5stack_coreink.menu.PartitionScheme.custom.upload.maximum_size=16777216 +m5stack_coreink.menu.PartitionScheme.custom.upload.maximum_size=4194304 m5stack_coreink.menu.CPUFreq.240=240MHz (WiFi/BT) m5stack_coreink.menu.CPUFreq.240.build.f_cpu=240000000L @@ -24245,9 +24141,6 @@ m5stack_stamp_pico.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB A m5stack_stamp_pico.menu.PartitionScheme.default.build.partitions=default m5stack_stamp_pico.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) m5stack_stamp_pico.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -m5stack_stamp_pico.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -m5stack_stamp_pico.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -m5stack_stamp_pico.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 m5stack_stamp_pico.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) m5stack_stamp_pico.menu.PartitionScheme.minimal.build.partitions=minimal m5stack_stamp_pico.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -24268,9 +24161,6 @@ m5stack_stamp_pico.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 m5stack_stamp_pico.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) m5stack_stamp_pico.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs m5stack_stamp_pico.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -m5stack_stamp_pico.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -m5stack_stamp_pico.menu.PartitionScheme.fatflash.build.partitions=ffat -m5stack_stamp_pico.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 m5stack_stamp_pico.menu.PartitionScheme.rainmaker=RainMaker 4MB m5stack_stamp_pico.menu.PartitionScheme.rainmaker.build.partitions=rainmaker m5stack_stamp_pico.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -24279,7 +24169,7 @@ m5stack_stamp_pico.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker m5stack_stamp_pico.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 m5stack_stamp_pico.menu.PartitionScheme.custom=Custom m5stack_stamp_pico.menu.PartitionScheme.custom.build.partitions= -m5stack_stamp_pico.menu.PartitionScheme.custom.upload.maximum_size=16777216 +m5stack_stamp_pico.menu.PartitionScheme.custom.upload.maximum_size=4194304 m5stack_stamp_pico.menu.CPUFreq.240=240MHz (WiFi/BT) m5stack_stamp_pico.menu.CPUFreq.240.build.f_cpu=240000000L @@ -26191,7 +26081,7 @@ heltec_wifi_lora_32.menu.CPUFreq.240.build.f_cpu=240000000L heltec_wifi_lora_32.menu.CPUFreq.160=160MHz (WiFi/BT) heltec_wifi_lora_32.menu.CPUFreq.160.build.f_cpu=160000000L heltec_wifi_lora_32.menu.CPUFreq.80=80MHz (WiFi/BT) -heltec_wifi_lora_32.menu.CPUFreq.160.build.f_cpu=80000000L +heltec_wifi_lora_32.menu.CPUFreq.80.build.f_cpu=80000000L heltec_wifi_lora_32.menu.UploadSpeed.921600=921600 heltec_wifi_lora_32.menu.UploadSpeed.921600.upload.speed=921600 @@ -29533,7 +29423,7 @@ wesp32.build.board=WESP32 wesp32.build.f_cpu=240000000L wesp32.build.flash_mode=dio -wesp32.build.flash_size=4MB +wesp32.build.flash_size=16MB wesp32.build.boot=dio wesp32.build.partitions=default wesp32.build.defines= @@ -29543,6 +29433,23 @@ wesp32.menu.FlashFreq.80.build.flash_freq=80m wesp32.menu.FlashFreq.40=40MHz wesp32.menu.FlashFreq.40.build.flash_freq=40m +wesp32.menu.FlashSize.default=16MB (128Mb) rev 7+ +wesp32.menu.FlashSize.default.build.flash_size=16MB +wesp32.menu.FlashSize.default_4m_flash=4MB (32Mb) rev 5 and below +wesp32.menu.FlashSize.default_4m_flash.build.flash_size=4MB + +wesp32.menu.PartitionScheme.default=16M OTA with large SPIFFS (4.5MB APP/6.8MB SPIFFS) +wesp32.menu.PartitionScheme.default.build.partitions=large_spiffs_16MB +wesp32.menu.PartitionScheme.default.upload.maximum_size=4718592 +wesp32.menu.PartitionScheme.default_large_app=16M large OTA app with SPIFFS (6.2MB APP/3.3MB SPIFFS) +wesp32.menu.PartitionScheme.default_large_app.build.partitions=default_16MB +wesp32.menu.PartitionScheme.default_large_app.upload.maximum_size=6553600 +wesp32.menu.PartitionScheme.default_fatfs=16M OTA with large FATFS (3MB APP/9.8MB FATFS) +wesp32.menu.PartitionScheme.default_fatfs.build.partitions=app3M_fat9M_16MB +wesp32.menu.PartitionScheme.default_fatfs.upload.maximum_size=3145728 +wesp32.menu.PartitionScheme.default_4m_flash=4M OTA app with SPIFFS (1.25MB APP/1.3MB SPIFFS) +wesp32.menu.PartitionScheme.default_4m_flash.build.partitions=default + wesp32.menu.UploadSpeed.921600=921600 wesp32.menu.UploadSpeed.921600.upload.speed=921600 wesp32.menu.UploadSpeed.115200=115200 @@ -31028,6 +30935,8 @@ vintlabs-devkit-v1.menu.DebugLevel.info=Info vintlabs-devkit-v1.menu.DebugLevel.info.build.code_debug=3 vintlabs-devkit-v1.menu.DebugLevel.debug=Debug vintlabs-devkit-v1.menu.DebugLevel.debug.build.code_debug=4 +vintlabs-devkit-v1.menu.DebugLevel.verbose=Verbose +vintlabs-devkit-v1.menu.DebugLevel.verbose.build.code_debug=5 vintlabs-devkit-v1.menu.EraseFlash.none=Disabled vintlabs-devkit-v1.menu.EraseFlash.none.upload.erase_cmd= @@ -31777,8 +31686,6 @@ mPython.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 mPython.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) mPython.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs mPython.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -mPython.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -mPython.menu.PartitionScheme.fatflash.build.partitions=ffat mPython.menu.CPUFreq.240=240MHz (WiFi/BT) mPython.menu.CPUFreq.240.build.f_cpu=240000000L @@ -33941,7 +33848,7 @@ deneyapkartv2.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr deneyapkartv2.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 deneyapkartv2.menu.PartitionScheme.custom=Custom deneyapkartv2.menu.PartitionScheme.custom.build.partitions= -deneyapkartv2.menu.PartitionScheme.custom.upload.maximum_size=16777216 +deneyapkartv2.menu.PartitionScheme.custom.upload.maximum_size=4194304 deneyapkartv2.menu.CPUFreq.240=240MHz (WiFi) deneyapkartv2.menu.CPUFreq.240.build.f_cpu=240000000L @@ -35744,8 +35651,6 @@ dpu_esp32.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 dpu_esp32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) dpu_esp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs dpu_esp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -dpu_esp32.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -dpu_esp32.menu.PartitionScheme.fatflash.build.partitions=ffat dpu_esp32.menu.FlashMode.qio=QIO dpu_esp32.menu.FlashMode.qio.build.flash_mode=dio @@ -36487,9 +36392,6 @@ XIAO_ESP32C5.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 XIAO_ESP32C5.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) XIAO_ESP32C5.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs XIAO_ESP32C5.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -XIAO_ESP32C5.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -XIAO_ESP32C5.menu.PartitionScheme.fatflash.build.partitions=ffat -XIAO_ESP32C5.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 XIAO_ESP32C5.menu.PartitionScheme.rainmaker=RainMaker 4MB XIAO_ESP32C5.menu.PartitionScheme.rainmaker.build.partitions=rainmaker XIAO_ESP32C5.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -37514,8 +37416,6 @@ Bee_Data_Logger.build.f_cpu=240000000L Bee_Data_Logger.build.flash_size=8MB Bee_Data_Logger.build.flash_freq=80m Bee_Data_Logger.build.flash_mode=dio -Bee_Data_Logger.build.partitions=default_8MB -Bee_Data_Logger.build.defines= Bee_Data_Logger.build.loop_core=-DARDUINO_RUNNING_CORE=1 Bee_Data_Logger.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 Bee_Data_Logger.build.boot=qio @@ -41003,7 +40903,7 @@ ioxesp32.build.board=IOXESP32 ioxesp32.build.f_cpu=240000000L ioxesp32.build.flash_mode=dio ioxesp32.build.flash_size=4MB -ioxesp32ps.build.flash_freq=40m +ioxesp32.build.flash_freq=40m ioxesp32.build.boot=dio ioxesp32.build.partitions=default ioxesp32.build.defines= @@ -41013,9 +40913,6 @@ ioxesp32.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB S ioxesp32.menu.PartitionScheme.default.build.partitions=default ioxesp32.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) ioxesp32.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -ioxesp32.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -ioxesp32.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -ioxesp32.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 ioxesp32.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) ioxesp32.menu.PartitionScheme.minimal.build.partitions=minimal ioxesp32.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -41036,9 +40933,6 @@ ioxesp32.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 ioxesp32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) ioxesp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs ioxesp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -ioxesp32.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -ioxesp32.menu.PartitionScheme.fatflash.build.partitions=ffat -ioxesp32.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 ioxesp32.menu.PartitionScheme.rainmaker=RainMaker 4MB ioxesp32.menu.PartitionScheme.rainmaker.build.partitions=rainmaker ioxesp32.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -41125,9 +41019,6 @@ ioxesp32ps.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB ioxesp32ps.menu.PartitionScheme.default.build.partitions=default ioxesp32ps.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) ioxesp32ps.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -ioxesp32ps.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -ioxesp32ps.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -ioxesp32ps.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 ioxesp32ps.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) ioxesp32ps.menu.PartitionScheme.minimal.build.partitions=minimal ioxesp32ps.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -41148,9 +41039,6 @@ ioxesp32ps.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 ioxesp32ps.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) ioxesp32ps.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs ioxesp32ps.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -ioxesp32ps.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -ioxesp32ps.menu.PartitionScheme.fatflash.build.partitions=ffat -ioxesp32ps.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 ioxesp32ps.menu.PartitionScheme.rainmaker=RainMaker 4MB ioxesp32ps.menu.PartitionScheme.rainmaker.build.partitions=rainmaker ioxesp32ps.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 @@ -41294,7 +41182,7 @@ ioxesp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr ioxesp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 ioxesp32c6.menu.PartitionScheme.custom=Custom ioxesp32c6.menu.PartitionScheme.custom.build.partitions= -ioxesp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 +ioxesp32c6.menu.PartitionScheme.custom.upload.maximum_size=4194304 ioxesp32c6.menu.CPUFreq.160=160MHz (WiFi) ioxesp32c6.menu.CPUFreq.160.build.f_cpu=160000000L @@ -42280,6 +42168,8 @@ nano_nora.upload.tool.network=esp_ota nano_nora.upload.protocol=serial nano_nora.upload.maximum_size=3145728 nano_nora.upload.maximum_data_size=327680 +nano_nora.upload.flags= +nano_nora.upload.extra_flags= nano_nora.upload.use_1200bps_touch=false nano_nora.upload.wait_for_upload_port=false @@ -42341,6 +42231,19 @@ nano_nora.menu.USBMode.hwcdc=Debug mode (Hardware CDC) nano_nora.menu.USBMode.hwcdc.build.usb_mode=1 nano_nora.menu.USBMode.hwcdc.debug.executable={build.path}/{build.project_name}.elf +nano_nora.menu.DebugLevel.none=None +nano_nora.menu.DebugLevel.none.build.code_debug=0 +nano_nora.menu.DebugLevel.error=Error +nano_nora.menu.DebugLevel.error.build.code_debug=1 +nano_nora.menu.DebugLevel.warn=Warn +nano_nora.menu.DebugLevel.warn.build.code_debug=2 +nano_nora.menu.DebugLevel.info=Info +nano_nora.menu.DebugLevel.info.build.code_debug=3 +nano_nora.menu.DebugLevel.debug=Debug +nano_nora.menu.DebugLevel.debug.build.code_debug=4 +nano_nora.menu.DebugLevel.verbose=Verbose +nano_nora.menu.DebugLevel.verbose.build.code_debug=5 + ############################################################## makergo_c3_supermini.name=MakerGO ESP32 C3 SuperMini @@ -42660,7 +42563,7 @@ epulse_feather_c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr epulse_feather_c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 epulse_feather_c6.menu.PartitionScheme.custom=Custom epulse_feather_c6.menu.PartitionScheme.custom.build.partitions= -epulse_feather_c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 +epulse_feather_c6.menu.PartitionScheme.custom.upload.maximum_size=4194304 epulse_feather_c6.menu.CPUFreq.160=160MHz (WiFi) epulse_feather_c6.menu.CPUFreq.160.build.f_cpu=160000000L @@ -42922,7 +42825,7 @@ Geekble_Nano_ESP32S3.menu.PartitionScheme.all_app.build.custom_partitions=max_ap Geekble_Nano_ESP32S3.menu.PartitionScheme.all_app.upload.maximum_size=4063232 Geekble_Nano_ESP32S3.menu.PartitionScheme.custom=Custom Geekble_Nano_ESP32S3.menu.PartitionScheme.custom.build.partitions= -Geekble_Nano_ESP32S3.menu.PartitionScheme.custom.upload.maximum_size=16777216 +Geekble_Nano_ESP32S3.menu.PartitionScheme.custom.upload.maximum_size=4194304 Geekble_Nano_ESP32S3.menu.PSRAM.disabled=Disabled Geekble_Nano_ESP32S3.menu.PSRAM.disabled.build.defines= @@ -43083,17 +42986,15 @@ waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker.upload.maximum_size=19660 waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota waveshare_esp32_s3_zero.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 - waveshare_esp32_s3_zero.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_zero.menu.PartitionScheme.otanofs.build.custom_partitions=ota_nofs_4MB waveshare_esp32_s3_zero.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_zero.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_zero.menu.PartitionScheme.all_app.build.custom_partitions=max_app_4MB waveshare_esp32_s3_zero.menu.PartitionScheme.all_app.upload.maximum_size=4063232 - waveshare_esp32_s3_zero.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_zero.menu.PartitionScheme.custom.build.partitions= -waveshare_esp32_s3_zero.menu.PartitionScheme.custom.upload.maximum_size=16777216 +waveshare_esp32_s3_zero.menu.PartitionScheme.custom.upload.maximum_size=4194304 waveshare_esp32_s3_zero.menu.CPUFreq.240=240MHz (WiFi) waveshare_esp32_s3_zero.menu.CPUFreq.240.build.f_cpu=240000000L @@ -43278,17 +43179,15 @@ ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota ws_esp32_s3_matrix.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 - ws_esp32_s3_matrix.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) ws_esp32_s3_matrix.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB ws_esp32_s3_matrix.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 ws_esp32_s3_matrix.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) ws_esp32_s3_matrix.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB ws_esp32_s3_matrix.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - ws_esp32_s3_matrix.menu.PartitionScheme.custom=Custom ws_esp32_s3_matrix.menu.PartitionScheme.custom.build.partitions= -ws_esp32_s3_matrix.menu.PartitionScheme.custom.upload.maximum_size=16777216 +ws_esp32_s3_matrix.menu.PartitionScheme.custom.upload.maximum_size=4194304 ws_esp32_s3_matrix.menu.CPUFreq.240=240MHz (WiFi) ws_esp32_s3_matrix.menu.CPUFreq.240.build.f_cpu=240000000L @@ -43443,6 +43342,8 @@ waveshare_esp32_s3_touch_lcd_169.menu.UploadMode.cdc.upload.use_1200bps_touch=tr waveshare_esp32_s3_touch_lcd_169.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -43474,17 +43375,12 @@ waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.rainmaker_8MB.upload.maxim waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_lcd_169.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -43642,6 +43538,8 @@ waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.cdc.upload.use_1200bps_touch= waveshare_esp32_s3_touch_amoled_18.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -43673,17 +43571,12 @@ waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.rainmaker_8MB.upload.max waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_amoled_18.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -43841,6 +43734,8 @@ waveshare_esp32_s3_lcd_169.menu.UploadMode.cdc.upload.use_1200bps_touch=true waveshare_esp32_s3_lcd_169.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_lcd_169.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_lcd_169.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_lcd_169.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -43872,17 +43767,12 @@ waveshare_esp32_s3_lcd_169.menu.PartitionScheme.rainmaker_8MB.upload.maximum_siz waveshare_esp32_s3_lcd_169.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_lcd_169.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_lcd_169.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_lcd_169.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_lcd_169.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_lcd_169.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_lcd_169.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_lcd_169.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_lcd_169.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_lcd_169.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_lcd_169.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_lcd_169.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_lcd_169.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -44146,9 +44036,6 @@ weact_studio_esp32c3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB weact_studio_esp32c3.menu.PartitionScheme.default.build.partitions=default weact_studio_esp32c3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) weact_studio_esp32c3.menu.PartitionScheme.defaultffat.build.partitions=default_ffat -weact_studio_esp32c3.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) -weact_studio_esp32c3.menu.PartitionScheme.default_8MB.build.partitions=default_8MB -weact_studio_esp32c3.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 weact_studio_esp32c3.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) weact_studio_esp32c3.menu.PartitionScheme.minimal.build.partitions=minimal weact_studio_esp32c3.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) @@ -45157,30 +45044,18 @@ codecell.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 codecell.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) codecell.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs codecell.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 -codecell.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) -codecell.menu.PartitionScheme.fatflash.build.partitions=ffat -codecell.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -codecell.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -codecell.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -codecell.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 codecell.menu.PartitionScheme.rainmaker=RainMaker 4MB codecell.menu.PartitionScheme.rainmaker.build.partitions=rainmaker codecell.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 codecell.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA codecell.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota codecell.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 -codecell.menu.PartitionScheme.rainmaker_8MB=RainMaker 8MB -codecell.menu.PartitionScheme.rainmaker_8MB.build.partitions=rainmaker_8MB -codecell.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4096000 codecell.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs codecell.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr codecell.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 -codecell.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs -codecell.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB -codecell.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872 codecell.menu.PartitionScheme.custom=Custom codecell.menu.PartitionScheme.custom.build.partitions= -codecell.menu.PartitionScheme.custom.upload.maximum_size=16777216 +codecell.menu.PartitionScheme.custom.upload.maximum_size=4194304 codecell.menu.CPUFreq.160=160MHz (WiFi) codecell.menu.CPUFreq.160.build.f_cpu=160000000L @@ -45520,10 +45395,11 @@ waveshare_esp32_s3_touch_amoled_241.menu.UploadMode.cdc.upload.use_1200bps_touch waveshare_esp32_s3_touch_amoled_241.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) - waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.defaultffat.build.partitions=default_ffat waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.no_ota.build.partitions=no_ota @@ -45552,18 +45428,12 @@ waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.rainmaker_8MB.upload.ma waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 - -waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_amoled_241.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -45726,6 +45596,8 @@ waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.cdc.upload.use_1200bps_touch=tru waveshare_esp32_s3_touch_lcd_43.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -45757,17 +45629,12 @@ waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.rainmaker_8MB.upload.maximu waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_lcd_43.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -45925,6 +45792,8 @@ waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.cdc.upload.use_1200bps_touch=tr waveshare_esp32_s3_touch_lcd_43B.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -45956,17 +45825,12 @@ waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.rainmaker_8MB.upload.maxim waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_lcd_43B.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -46129,6 +45993,8 @@ waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.cdc.upload.use_1200bps_touch=true waveshare_esp32_s3_touch_lcd_7.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -46160,17 +46026,12 @@ waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.rainmaker_8MB.upload.maximum waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_lcd_7.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -46328,6 +46189,8 @@ waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.cdc.upload.use_1200bps_touch=true waveshare_esp32_s3_touch_lcd_5.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -46359,17 +46222,12 @@ waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.rainmaker_8MB.upload.maximum waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_lcd_5.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -46527,6 +46385,8 @@ waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.cdc.upload.use_1200bps_touch=tru waveshare_esp32_s3_touch_lcd_5B.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -46558,17 +46418,12 @@ waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.rainmaker_8MB.upload.maximu waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_lcd_5B.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -46726,6 +46581,8 @@ waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.cdc.upload.use_1200bps_touch=true waveshare_esp32_s3_touch_lcd_4.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) @@ -46757,17 +46614,12 @@ waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.rainmaker_8MB.upload.maximum waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 -waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_lcd_4.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -47152,7 +47004,7 @@ cezerio_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zcz cezerio_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 cezerio_dev_esp32c6.menu.PartitionScheme.custom=Custom cezerio_dev_esp32c6.menu.PartitionScheme.custom.build.partitions= -cezerio_dev_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 +cezerio_dev_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=4194304 cezerio_dev_esp32c6.menu.CPUFreq.160=160MHz (WiFi) cezerio_dev_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L @@ -47322,7 +47174,7 @@ cezerio_mini_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbe cezerio_mini_dev_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 cezerio_mini_dev_esp32c6.menu.PartitionScheme.custom=Custom cezerio_mini_dev_esp32c6.menu.PartitionScheme.custom.build.partitions= -cezerio_mini_dev_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=16777216 +cezerio_mini_dev_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=4194304 cezerio_mini_dev_esp32c6.menu.CPUFreq.160=160MHz (WiFi) cezerio_mini_dev_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L @@ -49402,10 +49254,11 @@ waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.cdc.upload.use_1200bps_touch waveshare_esp32_s3_touch_amoled_164.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) - waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.defaultffat.build.partitions=default_ffat waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.no_ota.build.partitions=no_ota @@ -49434,18 +49287,12 @@ waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.rainmaker_8MB.upload.ma waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 - -waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_amoled_164.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -49604,10 +49451,11 @@ waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.cdc.upload.use_1200bps_touch waveshare_esp32_s3_touch_amoled_143.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) - waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.defaultffat.build.partitions=default_ffat waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.no_ota.build.partitions=no_ota @@ -49636,18 +49484,12 @@ waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.rainmaker_8MB.upload.ma waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 - -waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_amoled_143.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -49806,10 +49648,11 @@ waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.cdc.upload.use_1200bps_touch waveshare_esp32_s3_touch_amoled_191.menu.UploadMode.cdc.upload.wait_for_upload_port=true waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB +waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.default.build.partitions=default waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) - waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.defaultffat.build.partitions=default_ffat waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.no_ota.build.partitions=no_ota @@ -49838,18 +49681,12 @@ waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.rainmaker_8MB.upload.ma waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash.build.partitions=ffat waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 - -waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS) -waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB -waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 - waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA) waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs.build.custom_partitions=partitions_otanofs_4MB waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.otanofs.upload.maximum_size=2031616 waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA) waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app.build.custom_partitions=partitions_all_app_4MB waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.all_app.upload.maximum_size=4128768 - waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom=Custom waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom.build.partitions= waveshare_esp32_s3_touch_amoled_191.menu.PartitionScheme.custom.upload.maximum_size=16777216 @@ -50129,7 +49966,7 @@ Pcbcupid_GLYPH_H2.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr Pcbcupid_GLYPH_H2.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 Pcbcupid_GLYPH_H2.menu.PartitionScheme.custom=Custom Pcbcupid_GLYPH_H2.menu.PartitionScheme.custom.build.partitions= -Pcbcupid_GLYPH_H2.menu.PartitionScheme.custom.upload.maximum_size=16777216 +Pcbcupid_GLYPH_H2.menu.PartitionScheme.custom.upload.maximum_size=4194304 Pcbcupid_GLYPH_H2.menu.FlashMode.qio=QIO Pcbcupid_GLYPH_H2.menu.FlashMode.qio.build.flash_mode=dio @@ -51940,6 +51777,19 @@ kodedot.recipe.hooks.objcopy.postobjcopy.3.pattern_args= kodedot.recipe.output.save_file={build.project_name}.ino.bin +kodedot.menu.DebugLevel.none=None +kodedot.menu.DebugLevel.none.build.code_debug=0 +kodedot.menu.DebugLevel.error=Error +kodedot.menu.DebugLevel.error.build.code_debug=1 +kodedot.menu.DebugLevel.warn=Warn +kodedot.menu.DebugLevel.warn.build.code_debug=2 +kodedot.menu.DebugLevel.info=Info +kodedot.menu.DebugLevel.info.build.code_debug=3 +kodedot.menu.DebugLevel.debug=Debug +kodedot.menu.DebugLevel.debug.build.code_debug=4 +kodedot.menu.DebugLevel.verbose=Verbose +kodedot.menu.DebugLevel.verbose.build.code_debug=5 + ############################################################## # FED4 Board @@ -52133,7 +51983,7 @@ fobe_quill_esp32s3_mesh.name=FoBE Quill ESP32S3 Mesh fobe_quill_esp32s3_mesh.vid.0=0x303a fobe_quill_esp32s3_mesh.pid.0=0x82f4 fobe_quill_esp32s3_mesh.vid.1=0x303a -fobe_quill_esp32s3_mesh.vid.1=0x82f5 +fobe_quill_esp32s3_mesh.pid.1=0x82f5 fobe_quill_esp32s3_mesh.vid.2=0x303a fobe_quill_esp32s3_mesh.pid.2=0x82f6 @@ -52353,6 +52203,8 @@ twinaiot.upload.tool.network=esp_ota twinaiot.upload.maximum_size=1310720 twinaiot.upload.maximum_data_size=327680 +twinaiot.upload.flags= +twinaiot.upload.extra_flags= twinaiot.upload.use_1200bps_touch=false twinaiot.upload.wait_for_upload_port=false @@ -52487,7 +52339,7 @@ twinaiot.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr twinaiot.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 twinaiot.menu.PartitionScheme.custom=Custom twinaiot.menu.PartitionScheme.custom.build.partitions= -twinaiot.menu.PartitionScheme.custom.upload.maximum_size=16777216 +twinaiot.menu.PartitionScheme.custom.upload.maximum_size=4194304 twinaiot.menu.LoopCore.1=Core 1 twinaiot.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 @@ -52648,11 +52500,6 @@ esp32p4_4ds_mipi.menu.CPUFreq.360.build.f_cpu=360000000L esp32p4_4ds_mipi.menu.CPUFreq.40=40MHz esp32p4_4ds_mipi.menu.CPUFreq.40.build.f_cpu=40000000L -esp32p4_4ds_mipi.menu.FlashSize.16M=16MB (128Mb) -esp32p4_4ds_mipi.menu.FlashSize.16M.build.flash_size=16MB -esp32p4_4ds_mipi.menu.FlashSize.32M=32MB (256Mb) -esp32p4_4ds_mipi.menu.FlashSize.32M.build.flash_size=32MB - esp32p4_4ds_mipi.menu.UploadSpeed.921600=921600 esp32p4_4ds_mipi.menu.UploadSpeed.921600.upload.speed=921600 esp32p4_4ds_mipi.menu.UploadSpeed.115200=115200 @@ -52944,3 +52791,167 @@ axiometa_pixie_m1.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR axiometa_pixie_m1.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote ############################################################## + +soldered_nula_mini_esp32c6.name=Soldered NULA Mini ESP32C6 + +soldered_nula_mini_esp32c6.bootloader.tool=esptool_py +soldered_nula_mini_esp32c6.bootloader.tool.default=esptool_py + +soldered_nula_mini_esp32c6.upload.tool=esptool_py +soldered_nula_mini_esp32c6.upload.tool.default=esptool_py +soldered_nula_mini_esp32c6.upload.tool.network=esp_ota + +soldered_nula_mini_esp32c6.upload.maximum_size=1310720 +soldered_nula_mini_esp32c6.upload.maximum_data_size=327680 +soldered_nula_mini_esp32c6.upload.flags= +soldered_nula_mini_esp32c6.upload.extra_flags= +soldered_nula_mini_esp32c6.upload.use_1200bps_touch=false +soldered_nula_mini_esp32c6.upload.wait_for_upload_port=false + +soldered_nula_mini_esp32c6.serial.disableDTR=true +soldered_nula_mini_esp32c6.serial.disableRTS=true + +soldered_nula_mini_esp32c6.build.tarch=riscv32 +soldered_nula_mini_esp32c6.build.target=esp +soldered_nula_mini_esp32c6.build.mcu=esp32c6 +soldered_nula_mini_esp32c6.build.core=esp32 +soldered_nula_mini_esp32c6.build.variant=soldered_nula_mini_esp32c6 +soldered_nula_mini_esp32c6.build.board=SOLDERED_NULA_MINI_ESP32C6 +soldered_nula_mini_esp32c6.build.bootloader_addr=0x0 + +soldered_nula_mini_esp32c6.build.f_cpu=160000000L +soldered_nula_mini_esp32c6.build.flash_size=4MB +soldered_nula_mini_esp32c6.build.flash_freq=80m +soldered_nula_mini_esp32c6.build.flash_mode=qio +soldered_nula_mini_esp32c6.build.boot=qio +soldered_nula_mini_esp32c6.build.partitions=default +soldered_nula_mini_esp32c6.build.defines= + +## IDE 2.0 Seems to not update the value +soldered_nula_mini_esp32c6.menu.JTAGAdapter.default=Disabled +soldered_nula_mini_esp32c6.menu.JTAGAdapter.default.build.copy_jtag_files=0 +soldered_nula_mini_esp32c6.menu.JTAGAdapter.builtin=Integrated USB JTAG +soldered_nula_mini_esp32c6.menu.JTAGAdapter.builtin.build.openocdscript=esp32c6-builtin.cfg +soldered_nula_mini_esp32c6.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +soldered_nula_mini_esp32c6.menu.JTAGAdapter.external=FTDI Adapter +soldered_nula_mini_esp32c6.menu.JTAGAdapter.external.build.openocdscript=esp32c6-ftdi.cfg +soldered_nula_mini_esp32c6.menu.JTAGAdapter.external.build.copy_jtag_files=1 +soldered_nula_mini_esp32c6.menu.JTAGAdapter.bridge=ESP USB Bridge +soldered_nula_mini_esp32c6.menu.JTAGAdapter.bridge.build.openocdscript=esp32c6-bridge.cfg +soldered_nula_mini_esp32c6.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +soldered_nula_mini_esp32c6.menu.CDCOnBoot.default=Disabled +soldered_nula_mini_esp32c6.menu.CDCOnBoot.default.build.cdc_on_boot=0 +soldered_nula_mini_esp32c6.menu.CDCOnBoot.cdc=Enabled +soldered_nula_mini_esp32c6.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +soldered_nula_mini_esp32c6.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.default.build.partitions=default +soldered_nula_mini_esp32c6.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +soldered_nula_mini_esp32c6.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.minimal.build.partitions=minimal +soldered_nula_mini_esp32c6.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.no_ota.build.partitions=no_ota +soldered_nula_mini_esp32c6.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +soldered_nula_mini_esp32c6.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +soldered_nula_mini_esp32c6.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.huge_app.build.partitions=huge_app +soldered_nula_mini_esp32c6.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +soldered_nula_mini_esp32c6.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +soldered_nula_mini_esp32c6.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +soldered_nula_mini_esp32c6.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +soldered_nula_mini_esp32c6.menu.PartitionScheme.rainmaker=RainMaker 4MB +soldered_nula_mini_esp32c6.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +soldered_nula_mini_esp32c6.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080 +soldered_nula_mini_esp32c6.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA +soldered_nula_mini_esp32c6.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota +soldered_nula_mini_esp32c6.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656 +soldered_nula_mini_esp32c6.menu.PartitionScheme.zigbee=Zigbee 4MB with spiffs +soldered_nula_mini_esp32c6.menu.PartitionScheme.zigbee.build.partitions=zigbee +soldered_nula_mini_esp32c6.menu.PartitionScheme.zigbee.upload.maximum_size=1310720 +soldered_nula_mini_esp32c6.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs +soldered_nula_mini_esp32c6.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr +soldered_nula_mini_esp32c6.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720 +soldered_nula_mini_esp32c6.menu.PartitionScheme.custom=Custom +soldered_nula_mini_esp32c6.menu.PartitionScheme.custom.build.partitions= +soldered_nula_mini_esp32c6.menu.PartitionScheme.custom.upload.maximum_size=4194304 + +soldered_nula_mini_esp32c6.menu.CPUFreq.160=160MHz (WiFi) +soldered_nula_mini_esp32c6.menu.CPUFreq.160.build.f_cpu=160000000L +soldered_nula_mini_esp32c6.menu.CPUFreq.80=80MHz (WiFi) +soldered_nula_mini_esp32c6.menu.CPUFreq.80.build.f_cpu=80000000L +soldered_nula_mini_esp32c6.menu.CPUFreq.40=40MHz +soldered_nula_mini_esp32c6.menu.CPUFreq.40.build.f_cpu=40000000L +soldered_nula_mini_esp32c6.menu.CPUFreq.20=20MHz +soldered_nula_mini_esp32c6.menu.CPUFreq.20.build.f_cpu=20000000L +soldered_nula_mini_esp32c6.menu.CPUFreq.10=10MHz +soldered_nula_mini_esp32c6.menu.CPUFreq.10.build.f_cpu=10000000L + +soldered_nula_mini_esp32c6.menu.FlashMode.qio=QIO +soldered_nula_mini_esp32c6.menu.FlashMode.qio.build.flash_mode=dio +soldered_nula_mini_esp32c6.menu.FlashMode.qio.build.boot=qio +soldered_nula_mini_esp32c6.menu.FlashMode.dio=DIO +soldered_nula_mini_esp32c6.menu.FlashMode.dio.build.flash_mode=dio +soldered_nula_mini_esp32c6.menu.FlashMode.dio.build.boot=dio + +soldered_nula_mini_esp32c6.menu.FlashFreq.80=80MHz +soldered_nula_mini_esp32c6.menu.FlashFreq.80.build.flash_freq=80m +soldered_nula_mini_esp32c6.menu.FlashFreq.40=40MHz +soldered_nula_mini_esp32c6.menu.FlashFreq.40.build.flash_freq=40m + +soldered_nula_mini_esp32c6.menu.FlashSize.4M=4MB (32Mb) +soldered_nula_mini_esp32c6.menu.FlashSize.4M.build.flash_size=4MB + +soldered_nula_mini_esp32c6.menu.UploadSpeed.921600=921600 +soldered_nula_mini_esp32c6.menu.UploadSpeed.921600.upload.speed=921600 +soldered_nula_mini_esp32c6.menu.UploadSpeed.115200=115200 +soldered_nula_mini_esp32c6.menu.UploadSpeed.115200.upload.speed=115200 +soldered_nula_mini_esp32c6.menu.UploadSpeed.256000.windows=256000 +soldered_nula_mini_esp32c6.menu.UploadSpeed.256000.upload.speed=256000 +soldered_nula_mini_esp32c6.menu.UploadSpeed.230400.windows.upload.speed=256000 +soldered_nula_mini_esp32c6.menu.UploadSpeed.230400=230400 +soldered_nula_mini_esp32c6.menu.UploadSpeed.230400.upload.speed=230400 +soldered_nula_mini_esp32c6.menu.UploadSpeed.460800.linux=460800 +soldered_nula_mini_esp32c6.menu.UploadSpeed.460800.macosx=460800 +soldered_nula_mini_esp32c6.menu.UploadSpeed.460800.upload.speed=460800 +soldered_nula_mini_esp32c6.menu.UploadSpeed.512000.windows=512000 +soldered_nula_mini_esp32c6.menu.UploadSpeed.512000.upload.speed=512000 + +soldered_nula_mini_esp32c6.menu.DebugLevel.none=None +soldered_nula_mini_esp32c6.menu.DebugLevel.none.build.code_debug=0 +soldered_nula_mini_esp32c6.menu.DebugLevel.error=Error +soldered_nula_mini_esp32c6.menu.DebugLevel.error.build.code_debug=1 +soldered_nula_mini_esp32c6.menu.DebugLevel.warn=Warn +soldered_nula_mini_esp32c6.menu.DebugLevel.warn.build.code_debug=2 +soldered_nula_mini_esp32c6.menu.DebugLevel.info=Info +soldered_nula_mini_esp32c6.menu.DebugLevel.info.build.code_debug=3 +soldered_nula_mini_esp32c6.menu.DebugLevel.debug=Debug +soldered_nula_mini_esp32c6.menu.DebugLevel.debug.build.code_debug=4 +soldered_nula_mini_esp32c6.menu.DebugLevel.verbose=Verbose +soldered_nula_mini_esp32c6.menu.DebugLevel.verbose.build.code_debug=5 + +soldered_nula_mini_esp32c6.menu.EraseFlash.none=Disabled +soldered_nula_mini_esp32c6.menu.EraseFlash.none.upload.erase_cmd= +soldered_nula_mini_esp32c6.menu.EraseFlash.all=Enabled +soldered_nula_mini_esp32c6.menu.EraseFlash.all.upload.erase_cmd=-e + +soldered_nula_mini_esp32c6.menu.ZigbeeMode.default=Disabled +soldered_nula_mini_esp32c6.menu.ZigbeeMode.default.build.zigbee_mode= +soldered_nula_mini_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= +soldered_nula_mini_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) +soldered_nula_mini_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED +soldered_nula_mini_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native +soldered_nula_mini_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) +soldered_nula_mini_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR +soldered_nula_mini_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.native + +############################################################## diff --git a/cores/esp32/Esp.cpp b/cores/esp32/Esp.cpp index 061404977f9..5f5a7a353e8 100644 --- a/cores/esp32/Esp.cpp +++ b/cores/esp32/Esp.cpp @@ -36,6 +36,22 @@ extern "C" { #include "esp_chip_info.h" #include "esp_mac.h" #include "esp_flash.h" + +// Include HAL layer for flash clock access +#include "hal/spi_flash_ll.h" +#if CONFIG_IDF_TARGET_ESP32 +#include "soc/spi_struct.h" +#else +// All modern chips (S2, S3, C2, C3, C5, C6, H2, P4) use spimem +#include "hal/spimem_flash_ll.h" +// Try to include the newer c_struct header first, fall back to regular struct +#if __has_include("soc/spi_mem_c_struct.h") +#include "soc/spi_mem_c_struct.h" +#else +#include "soc/spi_mem_struct.h" +#endif +#endif + #ifdef ESP_IDF_VERSION_MAJOR // IDF 4+ #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 #include "esp32/rom/spi_flash.h" @@ -348,17 +364,13 @@ uint32_t EspClass::getFlashChipSpeed(void) { return magicFlashChipSpeed(fhdr.spi_speed); } -// FIXME for P4 -#if !defined(CONFIG_IDF_TARGET_ESP32P4) FlashMode_t EspClass::getFlashChipMode(void) { -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL); -#else -#if CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 +#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 uint32_t spi_ctrl = REG_READ(DR_REG_SPI0_BASE + 0x8); #else uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0)); -#endif #endif /* Not all of the following constants are already defined in older versions of spi_reg.h, so do it manually for now*/ if (spi_ctrl & BIT(24)) { //SPI_FREAD_QIO @@ -374,9 +386,7 @@ FlashMode_t EspClass::getFlashChipMode(void) { } else { return (FM_SLOW_READ); } - return (FM_DOUT); } -#endif // if !defined(CONFIG_IDF_TARGET_ESP32P4) uint32_t EspClass::magicFlashChipSize(uint8_t flashByte) { /* @@ -516,3 +526,63 @@ uint64_t EspClass::getEfuseMac(void) { esp_efuse_mac_get_default((uint8_t *)(&_chipmacid)); return _chipmacid; } + +// ============================================================================ +// Flash Frequency Runtime Detection +// ============================================================================ + +/** + * @brief Read the source clock frequency using ESP-IDF HAL functions + * @return Source clock frequency in MHz (80, 120, 160, or 240) + */ +uint8_t EspClass::getFlashSourceFrequencyMHz(void) { +#if CONFIG_IDF_TARGET_ESP32 + // ESP32: Use HAL function + return spi_flash_ll_get_source_clock_freq_mhz(0); // host_id = 0 for SPI0 +#else + // All modern MCUs: Use spimem HAL function + return spimem_flash_ll_get_source_freq_mhz(); +#endif +} + +/** + * @brief Read the clock divider from hardware using HAL structures + * Based on ESP-IDF HAL implementation: + * - ESP32: Uses SPI1.clock (typedef in spi_flash_ll.h) + * - All newer MCUs: Use SPIMEM1.clock (typedef in spimem_flash_ll.h) + * @return Clock divider value (1 = no division, 2 = divide by 2, etc.) + */ +uint8_t EspClass::getFlashClockDivider(void) { +#if CONFIG_IDF_TARGET_ESP32 + // ESP32: Flash uses SPI1 + // See: line 52: esp-idf/components/hal/esp32/include/hal/spi_flash_ll.h + if (SPI1.clock.clk_equ_sysclk) { + return 1; // 1:1 clock + } + return SPI1.clock.clkcnt_n + 1; +#else + // All newer MCUs: Flash uses SPIMEM1 + // See: esp-idf/components/hal/esp32*/include/hal/spimem_flash_ll.h + // Example S3: line 38: typedef typeof(SPIMEM1.clock.val) spimem_flash_ll_clock_reg_t; + // Example C5: lines 97-99: esp-idf/components/soc/esp32c5/mp/include/soc/spi_mem_struct.h + if (SPIMEM1.clock.clk_equ_sysclk) { + return 1; // 1:1 clock + } + return SPIMEM1.clock.clkcnt_n + 1; +#endif +} + +/** + * @brief Get the actual flash frequency in MHz + * @return Flash frequency in MHz (80, 120, 160, or 240) + */ +uint32_t EspClass::getFlashFrequencyMHz(void) { + uint8_t source = getFlashSourceFrequencyMHz(); + uint8_t divider = getFlashClockDivider(); + + if (divider == 0) { + divider = 1; // Safety check + } + + return source / divider; +} diff --git a/cores/esp32/Esp.h b/cores/esp32/Esp.h index 0b496c91c1b..7d5266f7b1a 100644 --- a/cores/esp32/Esp.h +++ b/cores/esp32/Esp.h @@ -92,6 +92,11 @@ class EspClass { uint32_t getFlashChipSpeed(); FlashMode_t getFlashChipMode(); + // Flash frequency runtime detection + uint32_t getFlashFrequencyMHz(); + uint8_t getFlashSourceFrequencyMHz(); + uint8_t getFlashClockDivider(); + uint32_t magicFlashChipSize(uint8_t flashByte); uint32_t magicFlashChipSpeed(uint8_t flashByte); FlashMode_t magicFlashChipMode(uint8_t flashByte); diff --git a/cores/esp32/HEXBuilder.cpp b/cores/esp32/HEXBuilder.cpp index 4298ad65d6a..52c53feafa8 100644 --- a/cores/esp32/HEXBuilder.cpp +++ b/cores/esp32/HEXBuilder.cpp @@ -18,6 +18,7 @@ */ #include "HEXBuilder.h" +#include static uint8_t hex_char_to_byte(uint8_t c) { return (c >= 'a' && c <= 'f') ? (c - ((uint8_t)'a' - 0xa)) @@ -26,6 +27,19 @@ static uint8_t hex_char_to_byte(uint8_t c) { : 0x10; // unknown char is 16 } +bool HEXBuilder::isHexString(const char *str, size_t len) { + for (size_t i = 0; i < len; i++) { + if (isxdigit(str[i]) == 0) { + return false; + } + } + return true; +} + +bool HEXBuilder::isHexString(String str) { + return isHexString(str.c_str(), str.length()); +} + size_t HEXBuilder::hex2bytes(unsigned char *out, size_t maxlen, String &in) { return hex2bytes(out, maxlen, in.c_str()); } diff --git a/cores/esp32/HEXBuilder.h b/cores/esp32/HEXBuilder.h index c5b8a8a88f4..dc977c938c3 100644 --- a/cores/esp32/HEXBuilder.h +++ b/cores/esp32/HEXBuilder.h @@ -32,5 +32,8 @@ class HEXBuilder { static String bytes2hex(const unsigned char *in, size_t len); static size_t bytes2hex(char *out, size_t maxlen, const unsigned char *in, size_t len); + + static bool isHexString(const char *str, size_t len); + static bool isHexString(String str); }; #endif diff --git a/cores/esp32/HWCDC.cpp b/cores/esp32/HWCDC.cpp index 062317d9f53..87df44b5247 100644 --- a/cores/esp32/HWCDC.cpp +++ b/cores/esp32/HWCDC.cpp @@ -14,6 +14,7 @@ #include "USB.h" #if SOC_USB_SERIAL_JTAG_SUPPORTED +#include "Arduino.h" // defines ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE and ARDUINO_SERIAL_EVENT_TASK_PRIORITY #include "esp32-hal.h" #include "esp32-hal-periman.h" #include "HWCDC.h" @@ -60,7 +61,11 @@ static esp_err_t arduino_hw_cdc_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg) { if (!arduino_hw_cdc_event_loop_handle) { esp_event_loop_args_t event_task_args = { - .queue_size = 5, .task_name = "arduino_hw_cdc_events", .task_priority = 5, .task_stack_size = 2048, .task_core_id = tskNO_AFFINITY + .queue_size = 5, + .task_name = "arduino_hw_cdc_events", + .task_priority = ARDUINO_SERIAL_EVENT_TASK_PRIORITY, + .task_stack_size = ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE, + .task_core_id = tskNO_AFFINITY }; if (esp_event_loop_create(&event_task_args, &arduino_hw_cdc_event_loop_handle) != ESP_OK) { log_e("esp_event_loop_create failed"); @@ -253,8 +258,6 @@ static void ARDUINO_ISR_ATTR cdc0_write_char(char c) { } HWCDC::HWCDC() { - perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DM, HWCDC::deinit); - perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DP, HWCDC::deinit); // SOF in ISR causes problems for uploading firmware // lastSOF_ms = 0; // SOF_TIMEOUT = 5; @@ -324,14 +327,19 @@ void HWCDC::begin(unsigned long baud) { // Peripheral Manager setting for USB D+ D- pins uint8_t pin = USB_INT_PHY0_DM_GPIO_NUM; + if (perimanGetBusDeinit(ESP32_BUS_TYPE_USB_DM) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DM, HWCDC::deinit); + } if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DM, (void *)this, -1, -1)) { goto err; } pin = USB_INT_PHY0_DP_GPIO_NUM; + if (perimanGetBusDeinit(ESP32_BUS_TYPE_USB_DP) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DP, HWCDC::deinit); + } if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DP, (void *)this, -1, -1)) { goto err; } - // Configure PHY // USB_Serial_JTAG use internal PHY USB_SERIAL_JTAG.conf0.phy_sel = 0; diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 6d762da21fb..3651667fe07 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -136,8 +136,6 @@ HardwareSerial::HardwareSerial(uint8_t uart_nr) } } #endif - // set deinit function in the Peripheral Manager - uart_init_PeriMan(); } HardwareSerial::~HardwareSerial() { diff --git a/cores/esp32/USB.h b/cores/esp32/USB.h index 6d284937e00..782121e6d50 100644 --- a/cores/esp32/USB.h +++ b/cores/esp32/USB.h @@ -21,6 +21,7 @@ #include "esp_event.h" #include "USBCDC.h" +#include "Arduino.h" // defines ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE and ARDUINO_SERIAL_EVENT_TASK_PRIORITY #define ARDUINO_USB_ON_BOOT (ARDUINO_USB_CDC_ON_BOOT | ARDUINO_USB_MSC_ON_BOOT | ARDUINO_USB_DFU_ON_BOOT) @@ -43,7 +44,7 @@ typedef union { class ESPUSB { public: - ESPUSB(size_t event_task_stack_size = 2048, uint8_t event_task_priority = 5); + ESPUSB(size_t event_task_stack_size = ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE, uint8_t event_task_priority = ARDUINO_SERIAL_EVENT_TASK_PRIORITY); ~ESPUSB(); void onEvent(esp_event_handler_t callback); diff --git a/cores/esp32/USBCDC.cpp b/cores/esp32/USBCDC.cpp index c7bb4582d4f..4eea8845b35 100644 --- a/cores/esp32/USBCDC.cpp +++ b/cores/esp32/USBCDC.cpp @@ -405,8 +405,11 @@ size_t USBCDC::write(const uint8_t *buffer, size_t size) { return 0; } size_t to_send = size, so_far = 0; + // writeTimeout will prevent that TinyUSB failure locks the while(to_send) loop + uint32_t writeTimeout = millis() + tx_timeout_ms; while (to_send) { - if (!tud_cdc_n_connected(itf)) { + if (!tud_cdc_n_connected(itf) || (int32_t)(millis() - writeTimeout) >= 0) { + log_e("USB is disconnected or CDC writing has timed out."); size = so_far; break; } diff --git a/cores/esp32/chip-debug-report.cpp b/cores/esp32/chip-debug-report.cpp index 8592031ee3f..753e7346775 100644 --- a/cores/esp32/chip-debug-report.cpp +++ b/cores/esp32/chip-debug-report.cpp @@ -9,6 +9,7 @@ #include "soc/efuse_reg.h" #include "soc/rtc.h" #include "soc/spi_reg.h" +#include "soc/soc.h" #if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/spi_flash.h" #endif @@ -16,6 +17,7 @@ #include "Arduino.h" #include "esp32-hal-periman.h" +#include "chip-debug-report.h" #define chip_report_printf log_printf @@ -138,25 +140,15 @@ static void printFlashInfo(void) { chip_report_printf(" Block Size : %8lu B (%6.1f KB)\n", g_rom_flashchip.block_size, b2kb(g_rom_flashchip.block_size)); chip_report_printf(" Sector Size : %8lu B (%6.1f KB)\n", g_rom_flashchip.sector_size, b2kb(g_rom_flashchip.sector_size)); chip_report_printf(" Page Size : %8lu B (%6.1f KB)\n", g_rom_flashchip.page_size, b2kb(g_rom_flashchip.page_size)); - esp_image_header_t fhdr; - esp_flash_read(esp_flash_default_chip, (void *)&fhdr, ESP_FLASH_IMAGE_BASE, sizeof(esp_image_header_t)); - if (fhdr.magic == ESP_IMAGE_HEADER_MAGIC) { - uint32_t f_freq = 0; - switch (fhdr.spi_speed) { -#if CONFIG_IDF_TARGET_ESP32H2 - case 0x0: f_freq = 32; break; - case 0x2: f_freq = 16; break; - case 0xf: f_freq = 64; break; -#else - case 0x0: f_freq = 40; break; - case 0x1: f_freq = 26; break; - case 0x2: f_freq = 20; break; - case 0xf: f_freq = 80; break; -#endif - default: f_freq = fhdr.spi_speed; break; - } - chip_report_printf(" Bus Speed : %lu MHz\n", f_freq); - } + + // Runtime flash frequency detection from hardware registers + uint32_t actual_freq = ESP.getFlashFrequencyMHz(); + uint8_t source_freq = ESP.getFlashSourceFrequencyMHz(); + uint8_t divider = ESP.getFlashClockDivider(); + + chip_report_printf(" Bus Speed : %lu MHz\n", actual_freq); + chip_report_printf(" Flash Frequency : %lu MHz (source: %u MHz, divider: %u)\n", actual_freq, source_freq, divider); + chip_report_printf(" Bus Mode : "); #if CONFIG_ESPTOOLPY_OCT_FLASH chip_report_printf("OPI\n"); diff --git a/cores/esp32/esp32-hal-gpio.c b/cores/esp32/esp32-hal-gpio.c index 90ad1e7f36d..197f789d94d 100644 --- a/cores/esp32/esp32-hal-gpio.c +++ b/cores/esp32/esp32-hal-gpio.c @@ -33,20 +33,21 @@ #include "soc/touch_sensor_periph.h" int8_t digitalPinToTouchChannel(uint8_t pin) { - int8_t ret = -1; if (pin < SOC_GPIO_PIN_COUNT) { for (uint8_t i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) { if (touch_sensor_channel_io_map[i] == pin) { - ret = i; - break; + return i; } } } - return ret; + + log_e("No touch pad on selected pin(%u)!", pin); + return -1; } #else // No Touch Sensor available int8_t digitalPinToTouchChannel(uint8_t pin) { + log_e("Touch sensor not available on this chip"); return -1; } #endif diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c index 98f9052d18c..44bde091be8 100644 --- a/cores/esp32/esp32-hal-touch-ng.c +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -332,7 +332,6 @@ static void __touchChannelInit(int pad) { static touch_value_t __touchRead(uint8_t pin) { int8_t pad = digitalPinToTouchChannel(pin); if (pad < 0) { - log_e(" No touch pad on selected pin!"); return 0; } @@ -360,7 +359,6 @@ static touch_value_t __touchRead(uint8_t pin) { static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, bool callWithArgs, touch_value_t threshold) { int8_t pad = digitalPinToTouchChannel(pin); if (pad < 0) { - log_e(" No touch pad on selected pin!"); return; } @@ -446,7 +444,6 @@ bool touchInterruptGetLastStatus(uint8_t pin) { void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { int8_t pad = digitalPinToTouchChannel(pin); if (pad < 0) { - log_e(" No touch pad on selected pin!"); return; } diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c index 10482234de0..e27064d20e1 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -206,7 +206,6 @@ static void __touchChannelInit(int pad) { static touch_value_t __touchRead(uint8_t pin) { int8_t pad = digitalPinToTouchChannel(pin); if (pad < 0) { - log_e(" No touch pad on selected pin!"); return 0; } @@ -233,7 +232,6 @@ static touch_value_t __touchRead(uint8_t pin) { static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, touch_value_t threshold, bool callWithArgs) { int8_t pad = digitalPinToTouchChannel(pin); if (pad < 0) { - log_e(" No touch pad on selected pin!"); return; } @@ -295,7 +293,6 @@ bool touchInterruptGetLastStatus(uint8_t pin) { void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { int8_t pad = digitalPinToTouchChannel(pin); if (pad < 0) { - log_e(" No touch pad on selected pin!"); return; } diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 7b194679caa..3b88dae5901 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -479,6 +479,10 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ret &= perimanSetPinBus(rxPin, ESP32_BUS_TYPE_UART_RX, (void *)uart, uart_num, -1); if (ret) { uart->_rxPin = rxPin; + // set Peripheral Manager deInit Callback for this UART pin + if (perimanGetBusDeinit(ESP32_BUS_TYPE_UART_RX) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_UART_RX, _uartDetachBus_RX); + } } } if (!ret) { @@ -502,6 +506,10 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ret &= perimanSetPinBus(txPin, ESP32_BUS_TYPE_UART_TX, (void *)uart, uart_num, -1); if (ret) { uart->_txPin = txPin; + // set Peripheral Manager deInit Callback for this UART pin + if (perimanGetBusDeinit(ESP32_BUS_TYPE_UART_TX) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_UART_TX, _uartDetachBus_TX); + } } } if (!ret) { @@ -525,6 +533,10 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ret &= perimanSetPinBus(ctsPin, ESP32_BUS_TYPE_UART_CTS, (void *)uart, uart_num, -1); if (ret) { uart->_ctsPin = ctsPin; + // set Peripheral Manager deInit Callback for this UART pin + if (perimanGetBusDeinit(ESP32_BUS_TYPE_UART_CTS) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_UART_CTS, _uartDetachBus_CTS); + } } } if (!ret) { @@ -548,6 +560,10 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ret &= perimanSetPinBus(rtsPin, ESP32_BUS_TYPE_UART_RTS, (void *)uart, uart_num, -1); if (ret) { uart->_rtsPin = rtsPin; + // set Peripheral Manager deInit Callback for this UART pin + if (perimanGetBusDeinit(ESP32_BUS_TYPE_UART_RTS) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_UART_RTS, _uartDetachBus_RTS); + } } } if (!ret) { @@ -567,14 +583,6 @@ int8_t uart_get_TxPin(uint8_t uart_num) { return _uart_bus_array[uart_num]._txPin; } -void uart_init_PeriMan(void) { - // set Peripheral Manager deInit Callback for each UART pin - perimanSetBusDeinit(ESP32_BUS_TYPE_UART_RX, _uartDetachBus_RX); - perimanSetBusDeinit(ESP32_BUS_TYPE_UART_TX, _uartDetachBus_TX); - perimanSetBusDeinit(ESP32_BUS_TYPE_UART_CTS, _uartDetachBus_CTS); - perimanSetBusDeinit(ESP32_BUS_TYPE_UART_RTS, _uartDetachBus_RTS); -} - // Routines that take care of UART events will be in the HardwareSerial Class code void uartGetEventQueue(uart_t *uart, QueueHandle_t *q) { // passing back NULL for the Queue pointer when UART is not initialized yet diff --git a/cores/esp32/esp32-hal-uart.h b/cores/esp32/esp32-hal-uart.h index 41b005aa151..3af0d7ab96c 100644 --- a/cores/esp32/esp32-hal-uart.h +++ b/cores/esp32/esp32-hal-uart.h @@ -79,7 +79,6 @@ bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, in // helper functions int8_t uart_get_RxPin(uint8_t uart_num); int8_t uart_get_TxPin(uint8_t uart_num); -void uart_init_PeriMan(void); // Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins // UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control diff --git a/cores/esp32/esp_arduino_version.h b/cores/esp32/esp_arduino_version.h index 120377c61f7..20cb911956d 100644 --- a/cores/esp32/esp_arduino_version.h +++ b/cores/esp32/esp_arduino_version.h @@ -23,7 +23,7 @@ extern "C" { /** Minor version number (x.X.x) */ #define ESP_ARDUINO_VERSION_MINOR 3 /** Patch version number (x.x.X) */ -#define ESP_ARDUINO_VERSION_PATCH 0 +#define ESP_ARDUINO_VERSION_PATCH 2 /** * Macro to convert ARDUINO version number into an integer diff --git a/cores/esp32/main.cpp b/cores/esp32/main.cpp index fb11ff4a5c7..4d1ec770c07 100644 --- a/cores/esp32/main.cpp +++ b/cores/esp32/main.cpp @@ -50,19 +50,19 @@ __attribute__((weak)) uint64_t getArduinoSetupWaitTime_ms(void) { } void loopTask(void *pvParameters) { -#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) - // sets UART0 (default console) RX/TX pins as already configured in boot or as defined in variants/pins_arduino.h - Serial0.setPins(gpioNumberToDigitalPin(SOC_RX0), gpioNumberToDigitalPin(SOC_TX0)); - // time in ms that the sketch may wait before starting its execution - default is zero - // usually done for opening the Serial Monitor and seeing all debug messages delay(getArduinoSetupWaitTime_ms()); -#endif #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG printBeforeSetupInfo(); #else if (shouldPrintChipDebugReport()) { printBeforeSetupInfo(); } +#endif +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) + // sets UART0 (default console) RX/TX pins as already configured in boot or as defined in variants/pins_arduino.h + Serial0.setPins(gpioNumberToDigitalPin(SOC_RX0), gpioNumberToDigitalPin(SOC_TX0)); + // time in ms that the sketch may wait before starting its execution - default is zero + // usually done for opening the Serial Monitor and seeing all debug messages #endif setup(); #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG diff --git a/docs/conf_common.py b/docs/conf_common.py index 10d4bd715b2..1ef2e5ee2e6 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -4,7 +4,7 @@ # Used for substituting variables in the documentation rst_prolog = """ -.. |version| replace:: 3.3.0 +.. |version| replace:: 3.3.2 .. |idf_version| replace:: 5.5 """ diff --git a/docs/en/contributing.rst b/docs/en/contributing.rst index ae07bb57706..0a2ff38b95f 100644 --- a/docs/en/contributing.rst +++ b/docs/en/contributing.rst @@ -365,7 +365,7 @@ After the test is finished, you can check the output in the terminal and the gen Additionally, for performance tests, you can check the generated JSON file in the same folder. You can also run the tests in `Wokwi `_ or `Espressif's QEMU `_ -by using the ``-W `` and ``-Q`` flags respectively. You will need to have the Wokwi and/or QEMU installed in your system +by using the ``-W`` and ``-Q`` flags respectively. You will need to have the Wokwi and/or QEMU installed in your system and set the ``WOKWI_CLI_TOKEN`` and/or ``QEMU_PATH`` environment variables. The ``WOKWI_CLI_TOKEN`` is the CI token that can be obtained from the `Wokwi website `_ and the ``QEMU_PATH`` is the path to the QEMU binary. @@ -373,7 +373,7 @@ For example, to run the ``uart`` test using Wokwi, you would run: .. code-block:: bash - WOKWI_CLI_TOKEN= ./.github/scripts/tests_run.sh -s uart -t esp32c3 -W + WOKWI_CLI_TOKEN= ./.github/scripts/tests_run.sh -s uart -t esp32c3 -W And to run the ``uart`` test using QEMU, you would run: @@ -398,7 +398,6 @@ A test suite contains the following files: * ``.ino``: The sketch that will be tested. Required. * ``ci.json``: The file that specifies how the test suite will be run in the CI system. Optional. * ``diagram..json``: The diagram file that specifies the connections between the components in Wokwi. Optional. -* ``scenario.yaml``: The scenario file that specifies how Wokwi will interact with the components. Optional. * Any other files that are needed for the test suite. You can read more about the test python API in the `pytest-embedded documentation `_. diff --git a/libraries/ArduinoOTA/library.properties b/libraries/ArduinoOTA/library.properties index 3a3f7e111e0..c4e5ff88a65 100644 --- a/libraries/ArduinoOTA/library.properties +++ b/libraries/ArduinoOTA/library.properties @@ -1,5 +1,5 @@ name=ArduinoOTA -version=3.3.0 +version=3.3.2 author=Ivan Grokhotkov and Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables Over The Air upgrades, via wifi and espota.py UDP request/TCP download. diff --git a/libraries/ArduinoOTA/src/ArduinoOTA.cpp b/libraries/ArduinoOTA/src/ArduinoOTA.cpp index 308660c3ce7..a5b0d09de58 100644 --- a/libraries/ArduinoOTA/src/ArduinoOTA.cpp +++ b/libraries/ArduinoOTA/src/ArduinoOTA.cpp @@ -19,6 +19,7 @@ #include "ArduinoOTA.h" #include "NetworkClient.h" #include "ESPmDNS.h" +#include "HEXBuilder.h" #include "SHA2Builder.h" #include "PBKDF2_HMACBuilder.h" #include "Update.h" @@ -86,6 +87,26 @@ ArduinoOTAClass &ArduinoOTAClass::setPassword(const char *password) { ArduinoOTAClass &ArduinoOTAClass::setPasswordHash(const char *password) { if (_state == OTA_IDLE && password) { + size_t len = strlen(password); + bool is_hex = HEXBuilder::isHexString(password, len); + + if (!is_hex) { + log_e("Invalid password hash. Expected hex string (0-9, a-f, A-F)."); + return *this; + } + + if (len == 32) { + // Warn if MD5 hash is detected (32 hex characters) + log_w("MD5 password hash detected. MD5 is deprecated and insecure."); + log_w("Please use setPassword() with plain text or setPasswordHash() with SHA256 hash (64 chars)."); + log_w("To generate SHA256: echo -n 'yourpassword' | sha256sum"); + } else if (len == 64) { + log_i("Using SHA256 password hash."); + } else { + log_e("Invalid password hash length. Expected 32 (deprecated MD5) or 64 (SHA256) characters."); + return *this; + } + // Store the pre-hashed password directly _password.clear(); _password = password; @@ -182,7 +203,7 @@ String ArduinoOTAClass::readStringUntil(char end) { void ArduinoOTAClass::_onRx() { if (_state == OTA_IDLE) { int cmd = parseInt(); - if (cmd != U_FLASH && cmd != U_SPIFFS) { + if (cmd != U_FLASH && cmd != U_FLASHFS) { return; } _cmd = cmd; diff --git a/libraries/AsyncUDP/library.properties b/libraries/AsyncUDP/library.properties index ddf9f79b6d9..24b48d2e4de 100644 --- a/libraries/AsyncUDP/library.properties +++ b/libraries/AsyncUDP/library.properties @@ -1,5 +1,5 @@ name=ESP32 Async UDP -version=3.3.0 +version=3.3.2 author=Me-No-Dev maintainer=Me-No-Dev sentence=Async UDP Library for ESP32 diff --git a/libraries/BLE/library.properties b/libraries/BLE/library.properties index c6fae19a4a1..730ab0ea315 100644 --- a/libraries/BLE/library.properties +++ b/libraries/BLE/library.properties @@ -1,5 +1,5 @@ name=BLE -version=3.3.0 +version=3.3.2 author=Neil Kolban maintainer=lucasssvaz sentence=BLE functions for ESP32 diff --git a/libraries/BluetoothSerial/library.properties b/libraries/BluetoothSerial/library.properties index 49211bf3b63..3ced43c52ea 100644 --- a/libraries/BluetoothSerial/library.properties +++ b/libraries/BluetoothSerial/library.properties @@ -1,5 +1,5 @@ name=BluetoothSerial -version=3.3.0 +version=3.3.2 author=Evandro Copercini maintainer=Evandro Copercini sentence=Simple UART to Classical Bluetooth bridge for ESP32 diff --git a/libraries/DNSServer/library.properties b/libraries/DNSServer/library.properties index c193b919d02..e30f5a39555 100644 --- a/libraries/DNSServer/library.properties +++ b/libraries/DNSServer/library.properties @@ -1,5 +1,5 @@ name=DNSServer -version=3.3.0 +version=3.3.2 author=Kristijan Novoselić maintainer=Kristijan Novoselić, sentence=A simple DNS server for ESP32. diff --git a/libraries/EEPROM/library.properties b/libraries/EEPROM/library.properties index 6d69f52a085..e6728c5d808 100644 --- a/libraries/EEPROM/library.properties +++ b/libraries/EEPROM/library.properties @@ -1,5 +1,5 @@ name=EEPROM -version=3.3.0 +version=3.3.2 author=Ivan Grokhotkov maintainer=Paolo Becchi sentence=Enables reading and writing data a sequential, addressable FLASH storage diff --git a/libraries/ESP32/library.properties b/libraries/ESP32/library.properties index e664022388d..864c315224b 100644 --- a/libraries/ESP32/library.properties +++ b/libraries/ESP32/library.properties @@ -1,5 +1,5 @@ name=ESP32 -version=3.3.0 +version=3.3.2 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 sketches examples diff --git a/libraries/ESP_I2S/library.properties b/libraries/ESP_I2S/library.properties index 18c48c095a8..7145fb7dccd 100644 --- a/libraries/ESP_I2S/library.properties +++ b/libraries/ESP_I2S/library.properties @@ -1,5 +1,5 @@ name=ESP_I2S -version=3.3.0 +version=3.3.2 author=me-no-dev maintainer=me-no-dev sentence=Library for ESP I2S communication diff --git a/libraries/ESP_NOW/library.properties b/libraries/ESP_NOW/library.properties index dd61bf0d4c2..a1868930307 100644 --- a/libraries/ESP_NOW/library.properties +++ b/libraries/ESP_NOW/library.properties @@ -1,5 +1,5 @@ name=ESP_NOW -version=3.3.0 +version=3.3.2 author=me-no-dev maintainer=P-R-O-C-H-Y sentence=Library for ESP_NOW diff --git a/libraries/ESP_SR/library.properties b/libraries/ESP_SR/library.properties index 9d9787b7931..b39120f015d 100644 --- a/libraries/ESP_SR/library.properties +++ b/libraries/ESP_SR/library.properties @@ -1,5 +1,5 @@ name=ESP_SR -version=3.3.0 +version=3.3.2 author=me-no-dev maintainer=me-no-dev sentence=Library for ESP Sound Recognition diff --git a/libraries/ESP_SR/src/esp32-hal-sr.c b/libraries/ESP_SR/src/esp32-hal-sr.c index 1ae96d616eb..68cfb6a7a01 100644 --- a/libraries/ESP_SR/src/esp32-hal-sr.c +++ b/libraries/ESP_SR/src/esp32-hal-sr.c @@ -343,7 +343,7 @@ esp_err_t sr_start( // Load WakeWord Detection afe_config_t *afe_config = afe_config_init(input_format, models, AFE_TYPE_SR, AFE_MODE_LOW_COST); g_sr_data->afe_handle = esp_afe_handle_from_config(afe_config); - log_d("load wakenet '%s'", afe_config.wakenet_model_name); + log_d("load wakenet '%s'", afe_config->wakenet_model_name); g_sr_data->afe_data = g_sr_data->afe_handle->create_from_config(afe_config); afe_config_free(afe_config); diff --git a/libraries/ESPmDNS/library.properties b/libraries/ESPmDNS/library.properties index 062d3b90b51..4d0f1d4eef9 100644 --- a/libraries/ESPmDNS/library.properties +++ b/libraries/ESPmDNS/library.properties @@ -1,5 +1,5 @@ name=ESPmDNS -version=3.3.0 +version=3.3.2 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 mDNS Library diff --git a/libraries/Ethernet/library.properties b/libraries/Ethernet/library.properties index 28f2a8697d9..a9bff23f7f1 100644 --- a/libraries/Ethernet/library.properties +++ b/libraries/Ethernet/library.properties @@ -1,5 +1,5 @@ name=Ethernet -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection (local and Internet) using the ESP32 Ethernet. diff --git a/libraries/FFat/library.properties b/libraries/FFat/library.properties index 25b8c4e8acd..a94339dc87e 100644 --- a/libraries/FFat/library.properties +++ b/libraries/FFat/library.properties @@ -1,5 +1,5 @@ name=FFat -version=3.3.0 +version=3.3.2 author=Hristo Gochkov, Ivan Grokhtkov, Larry Bernstone maintainer=Hristo Gochkov sentence=ESP32 FAT on Flash File System diff --git a/libraries/FS/library.properties b/libraries/FS/library.properties index 0f05f1134d5..8dac5fc3235 100644 --- a/libraries/FS/library.properties +++ b/libraries/FS/library.properties @@ -1,5 +1,5 @@ name=FS -version=3.3.0 +version=3.3.2 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 File System diff --git a/libraries/HTTPClient/library.properties b/libraries/HTTPClient/library.properties index bb5b0936255..79717c13b37 100644 --- a/libraries/HTTPClient/library.properties +++ b/libraries/HTTPClient/library.properties @@ -1,5 +1,5 @@ name=HTTPClient -version=3.3.0 +version=3.3.2 author=Markus Sattler maintainer=Markus Sattler sentence=HTTP Client for ESP32 diff --git a/libraries/HTTPUpdate/library.properties b/libraries/HTTPUpdate/library.properties index 88466a3a72e..c61ceee9fac 100644 --- a/libraries/HTTPUpdate/library.properties +++ b/libraries/HTTPUpdate/library.properties @@ -1,5 +1,5 @@ name=HTTPUpdate -version=3.3.0 +version=3.3.2 author=Markus Sattler maintainer=Markus Sattler sentence=Http Update for ESP32 diff --git a/libraries/HTTPUpdate/src/HTTPUpdate.cpp b/libraries/HTTPUpdate/src/HTTPUpdate.cpp index b463ffe2e83..5183afac017 100644 --- a/libraries/HTTPUpdate/src/HTTPUpdate.cpp +++ b/libraries/HTTPUpdate/src/HTTPUpdate.cpp @@ -52,11 +52,31 @@ HTTPUpdateResult HTTPUpdate::update(NetworkClient &client, const String &url, co if (!http.begin(client, url)) { return HTTP_UPDATE_FAILED; } - return handleUpdate(http, currentVersion, false, requestCB); + return handleUpdate(http, currentVersion, U_FLASH, requestCB); +} + +HTTPUpdateResult HTTPUpdate::updateFs(HTTPClient &httpClient, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { + return handleUpdate(httpClient, currentVersion, U_FLASHFS, requestCB); } HTTPUpdateResult HTTPUpdate::updateSpiffs(HTTPClient &httpClient, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { - return handleUpdate(httpClient, currentVersion, true, requestCB); + return handleUpdate(httpClient, currentVersion, U_SPIFFS, requestCB); +} + +HTTPUpdateResult HTTPUpdate::updateFatfs(HTTPClient &httpClient, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { + return handleUpdate(httpClient, currentVersion, U_FATFS, requestCB); +} + +HTTPUpdateResult HTTPUpdate::updateLittlefs(HTTPClient &httpClient, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { + return handleUpdate(httpClient, currentVersion, U_LITTLEFS, requestCB); +} + +HTTPUpdateResult HTTPUpdate::updateFs(NetworkClient &client, const String &url, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { + HTTPClient http; + if (!http.begin(client, url)) { + return HTTP_UPDATE_FAILED; + } + return handleUpdate(http, currentVersion, U_FLASHFS, requestCB); } HTTPUpdateResult HTTPUpdate::updateSpiffs(NetworkClient &client, const String &url, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { @@ -64,11 +84,27 @@ HTTPUpdateResult HTTPUpdate::updateSpiffs(NetworkClient &client, const String &u if (!http.begin(client, url)) { return HTTP_UPDATE_FAILED; } - return handleUpdate(http, currentVersion, true, requestCB); + return handleUpdate(http, currentVersion, U_SPIFFS, requestCB); +} + +HTTPUpdateResult HTTPUpdate::updateFatfs(NetworkClient &client, const String &url, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { + HTTPClient http; + if (!http.begin(client, url)) { + return HTTP_UPDATE_FAILED; + } + return handleUpdate(http, currentVersion, U_FATFS, requestCB); +} + +HTTPUpdateResult HTTPUpdate::updateLittlefs(NetworkClient &client, const String &url, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { + HTTPClient http; + if (!http.begin(client, url)) { + return HTTP_UPDATE_FAILED; + } + return handleUpdate(http, currentVersion, U_LITTLEFS, requestCB); } HTTPUpdateResult HTTPUpdate::update(HTTPClient &httpClient, const String ¤tVersion, HTTPUpdateRequestCB requestCB) { - return handleUpdate(httpClient, currentVersion, false, requestCB); + return handleUpdate(httpClient, currentVersion, U_FLASH, requestCB); } HTTPUpdateResult @@ -77,7 +113,7 @@ HTTPUpdateResult if (!http.begin(client, host, port, uri)) { return HTTP_UPDATE_FAILED; } - return handleUpdate(http, currentVersion, false, requestCB); + return handleUpdate(http, currentVersion, U_FLASH, requestCB); } /** @@ -158,7 +194,7 @@ String getSketchSHA256() { * @param currentVersion const char * * @return HTTPUpdateResult */ -HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient &http, const String ¤tVersion, bool spiffs, HTTPUpdateRequestCB requestCB) { +HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient &http, const String ¤tVersion, uint8_t type, HTTPUpdateRequestCB requestCB) { HTTPUpdateResult ret = HTTP_UPDATE_FAILED; @@ -187,8 +223,14 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient &http, const String ¤ http.addHeader("x-ESP32-chip-size", String(ESP.getFlashChipSize())); http.addHeader("x-ESP32-sdk-version", ESP.getSdkVersion()); - if (spiffs) { + if (type == U_SPIFFS) { http.addHeader("x-ESP32-mode", "spiffs"); + } else if (type == U_FATFS) { + http.addHeader("x-ESP32-mode", "fatfs"); + } else if (type == U_LITTLEFS) { + http.addHeader("x-ESP32-mode", "littlefs"); + } else if (type == U_FLASHFS) { + http.addHeader("x-ESP32-mode", "flashfs"); } else { http.addHeader("x-ESP32-mode", "sketch"); } @@ -251,8 +293,24 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient &http, const String ¤ case HTTP_CODE_OK: ///< OK (Start Update) if (len > 0) { bool startUpdate = true; - if (spiffs) { - const esp_partition_t *_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); + if (type != U_FLASH) { + const esp_partition_t *_partition = NULL; + if (type == U_SPIFFS) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); + } else if (type == U_FATFS) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); + } else if (type == U_LITTLEFS) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_LITTLEFS, NULL); + } else if (type == U_FLASHFS) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); + if (!_partition) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); + } + if (!_partition) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_LITTLEFS, NULL); + } + } + if (!_partition) { _lastError = HTTP_UE_NO_PARTITION; return HTTP_UPDATE_FAILED; @@ -291,17 +349,15 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient &http, const String ¤ delay(100); - int command; + int command = type; - if (spiffs) { - command = U_SPIFFS; - log_d("runUpdate spiffs...\n"); - } else { - command = U_FLASH; + if (type == U_FLASH) { log_d("runUpdate flash...\n"); + } else { + log_d("runUpdate file system...\n"); } - if (!spiffs) { + if (type == U_FLASH) { /* To do uint8_t buf[4]; if(tcp->peekBytes(&buf[0], 4) != 4) { @@ -341,7 +397,7 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient &http, const String ¤ _cbEnd(); } - if (_rebootOnUpdate && !spiffs) { + if (_rebootOnUpdate && type == U_FLASH) { ESP.restart(); } diff --git a/libraries/HTTPUpdate/src/HTTPUpdate.h b/libraries/HTTPUpdate/src/HTTPUpdate.h index a48d1a89a3e..ad38701b948 100644 --- a/libraries/HTTPUpdate/src/HTTPUpdate.h +++ b/libraries/HTTPUpdate/src/HTTPUpdate.h @@ -98,11 +98,17 @@ class HTTPUpdate { NetworkClient &client, const String &host, uint16_t port, const String &uri = "/", const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL ); + t_httpUpdate_return updateFs(NetworkClient &client, const String &url, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); t_httpUpdate_return updateSpiffs(NetworkClient &client, const String &url, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); + t_httpUpdate_return updateFatfs(NetworkClient &client, const String &url, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); + t_httpUpdate_return updateLittlefs(NetworkClient &client, const String &url, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); t_httpUpdate_return update(HTTPClient &httpClient, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); + t_httpUpdate_return updateFs(HTTPClient &httpClient, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); t_httpUpdate_return updateSpiffs(HTTPClient &httpClient, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); + t_httpUpdate_return updateFatfs(HTTPClient &httpClient, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); + t_httpUpdate_return updateLittlefs(HTTPClient &httpClient, const String ¤tVersion = "", HTTPUpdateRequestCB requestCB = NULL); // Notification callbacks void onStart(HTTPUpdateStartCB cbOnStart) { @@ -122,7 +128,7 @@ class HTTPUpdate { String getLastErrorString(void); protected: - t_httpUpdate_return handleUpdate(HTTPClient &http, const String ¤tVersion, bool spiffs = false, HTTPUpdateRequestCB requestCB = NULL); + t_httpUpdate_return handleUpdate(HTTPClient &http, const String ¤tVersion, uint8_t type = U_FLASH, HTTPUpdateRequestCB requestCB = NULL); bool runUpdate(Stream &in, uint32_t size, String md5, int command = U_FLASH); // Set the error and potentially use a CB to notify the application diff --git a/libraries/HTTPUpdateServer/library.properties b/libraries/HTTPUpdateServer/library.properties index c182eeb8d7f..e391d05ae91 100644 --- a/libraries/HTTPUpdateServer/library.properties +++ b/libraries/HTTPUpdateServer/library.properties @@ -1,5 +1,5 @@ name=HTTPUpdateServer -version=3.3.0 +version=3.3.2 author=Hristo Kapanakov maintainer= sentence=Simple HTTP Update server based on the WebServer diff --git a/libraries/HTTPUpdateServer/src/HTTPUpdateServer.h b/libraries/HTTPUpdateServer/src/HTTPUpdateServer.h index 952711bef66..d9e9b9ea2d5 100644 --- a/libraries/HTTPUpdateServer/src/HTTPUpdateServer.h +++ b/libraries/HTTPUpdateServer/src/HTTPUpdateServer.h @@ -122,7 +122,7 @@ class HTTPUpdateServer { Serial.printf("Update: %s\n", upload.filename.c_str()); } if (upload.name == "filesystem") { - if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) { //Instead of SPIFFS.totalBytes(). Fix https://github.com/espressif/arduino-esp32/issues/9967 + if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASHFS)) { //Instead of SPIFFS.totalBytes(). Fix https://github.com/espressif/arduino-esp32/issues/9967 if (_serial_output) { Update.printError(Serial); } diff --git a/libraries/Hash/library.properties b/libraries/Hash/library.properties index 5db4df17c2d..6e7ed56919c 100644 --- a/libraries/Hash/library.properties +++ b/libraries/Hash/library.properties @@ -1,5 +1,5 @@ name=Hash -version=3.3.0 +version=3.3.2 author=lucasssvaz maintainer=lucasssvaz sentence=Bundle of hashing functions for the ESP32 diff --git a/libraries/Insights/library.properties b/libraries/Insights/library.properties index 3ef98d25be6..24904296fe8 100644 --- a/libraries/Insights/library.properties +++ b/libraries/Insights/library.properties @@ -1,5 +1,5 @@ name=ESP Insights -version=3.3.0 +version=3.3.2 author=Sanket Wadekar maintainer=Sanket Wadekar sentence=ESP Insights diff --git a/libraries/LittleFS/library.properties b/libraries/LittleFS/library.properties index 202d8ad4a6d..e94daaa9602 100644 --- a/libraries/LittleFS/library.properties +++ b/libraries/LittleFS/library.properties @@ -1,5 +1,5 @@ name=LittleFS -version=3.3.0 +version=3.3.2 author= maintainer= sentence=LittleFS for esp32 diff --git a/libraries/Matter/library.properties b/libraries/Matter/library.properties index 0b140bfa169..522e777f852 100644 --- a/libraries/Matter/library.properties +++ b/libraries/Matter/library.properties @@ -1,5 +1,5 @@ name=Matter -version=3.3.0 +version=3.3.2 author=Rodrigo Garcia | GitHub @SuGlider maintainer=Rodrigo Garcia sentence=Library for supporting Matter environment on ESP32. diff --git a/libraries/NetBIOS/library.properties b/libraries/NetBIOS/library.properties index 71d22d6f363..7a28a36e016 100644 --- a/libraries/NetBIOS/library.properties +++ b/libraries/NetBIOS/library.properties @@ -1,5 +1,5 @@ name=NetBIOS -version=3.3.0 +version=3.3.2 author=Pablo@xpablo.cz maintainer=Hristo Gochkov sentence=Enables NBNS (NetBIOS) name resolution. diff --git a/libraries/Network/library.properties b/libraries/Network/library.properties index f7e04f4de3b..5c848a0fcc1 100644 --- a/libraries/Network/library.properties +++ b/libraries/Network/library.properties @@ -1,5 +1,5 @@ name=Networking -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=General network management library. diff --git a/libraries/NetworkClientSecure/library.properties b/libraries/NetworkClientSecure/library.properties index 6ebf4c0ec70..8d74c2b8f37 100644 --- a/libraries/NetworkClientSecure/library.properties +++ b/libraries/NetworkClientSecure/library.properties @@ -1,5 +1,5 @@ name=NetworkClientSecure -version=3.3.0 +version=3.3.2 author=Evandro Luis Copercini maintainer=Github Community sentence=Enables secure network connection (local and Internet) using the ESP32 built-in WiFi. diff --git a/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp b/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp index b24c9f1adc3..08da928668e 100644 --- a/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp +++ b/libraries/NetworkClientSecure/src/NetworkClientSecure.cpp @@ -227,6 +227,10 @@ size_t NetworkClientSecure::write(const uint8_t *buf, size_t size) { return 0; } + if (size == 0) { + return 0; + } + if (_stillinPlainStart) { return send_net_data(sslclient.get(), buf, size); } diff --git a/libraries/NetworkClientSecure/src/ssl_client.cpp b/libraries/NetworkClientSecure/src/ssl_client.cpp index 19f75673133..f70aefec034 100644 --- a/libraries/NetworkClientSecure/src/ssl_client.cpp +++ b/libraries/NetworkClientSecure/src/ssl_client.cpp @@ -409,25 +409,41 @@ int data_to_read(sslclient_context *ssl_client) { } int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, size_t len) { - unsigned long write_start_time = millis(); - int ret = -1; + if (len == 0) { + return 0; // Skipping zero-length write + } + + static constexpr size_t max_write_chunk_size = 4096; + unsigned long last_progress = millis(); // Timeout since last progress + size_t sent = 0; + + while (sent < len) { + size_t to_send = len - sent; + if (to_send > max_write_chunk_size) { + to_send = max_write_chunk_size; + } - while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0) { - if ((millis() - write_start_time) > ssl_client->socket_timeout) { + int ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data + sent, to_send); + if (ret > 0) { + sent += ret; + last_progress = millis(); // refresh timeout window + continue; + } + + if ((millis() - last_progress) > ssl_client->socket_timeout) { log_v("SSL write timed out."); return -1; } if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0) { - log_v("Handling error %d", ret); //for low level debug + log_v("Handling error %d", ret); return handle_error(ret); } - //wait for space to become available vTaskDelay(2); } - return ret; + return (int)sent; } // Some protocols, such as SMTP, XMPP, MySQL/Posgress and various others diff --git a/libraries/OpenThread/library.properties b/libraries/OpenThread/library.properties index 550d4eb1627..147793e59d6 100644 --- a/libraries/OpenThread/library.properties +++ b/libraries/OpenThread/library.properties @@ -1,5 +1,5 @@ name=OpenThread -version=3.3.0 +version=3.3.2 author=Rodrigo Garcia | GitHub @SuGlider maintainer=Rodrigo Garcia sentence=Library for OpenThread Network on ESP32. diff --git a/libraries/PPP/library.properties b/libraries/PPP/library.properties index 537708b1261..eaaf349d847 100644 --- a/libraries/PPP/library.properties +++ b/libraries/PPP/library.properties @@ -1,5 +1,5 @@ name=PPP -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection using GSM Modem. diff --git a/libraries/Preferences/library.properties b/libraries/Preferences/library.properties index 0a7e678aa6c..aa64864c7bd 100644 --- a/libraries/Preferences/library.properties +++ b/libraries/Preferences/library.properties @@ -1,5 +1,5 @@ name=Preferences -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Provides friendly access to ESP32's Non-Volatile Storage diff --git a/libraries/RainMaker/library.properties b/libraries/RainMaker/library.properties index 1d72a8faff5..580c9115cfb 100644 --- a/libraries/RainMaker/library.properties +++ b/libraries/RainMaker/library.properties @@ -1,5 +1,5 @@ name=ESP RainMaker -version=3.3.0 +version=3.3.2 author=Sweety Mhaiske maintainer=Hristo Gochkov sentence=ESP RainMaker Support diff --git a/libraries/SD/library.properties b/libraries/SD/library.properties index 9d868dce799..2c5a2b6a16c 100644 --- a/libraries/SD/library.properties +++ b/libraries/SD/library.properties @@ -1,5 +1,5 @@ name=SD -version=3.3.0 +version=3.3.2 author=Arduino, SparkFun maintainer=Arduino sentence=Enables reading and writing on SD cards. For all Arduino boards. diff --git a/libraries/SD_MMC/library.properties b/libraries/SD_MMC/library.properties index f96ee4377c2..f7fe194e586 100644 --- a/libraries/SD_MMC/library.properties +++ b/libraries/SD_MMC/library.properties @@ -1,5 +1,5 @@ name=SD_MMC -version=3.3.0 +version=3.3.2 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 SDMMC File System diff --git a/libraries/SPI/library.properties b/libraries/SPI/library.properties index 3403d1c5d4f..1e9b1aa5a5b 100644 --- a/libraries/SPI/library.properties +++ b/libraries/SPI/library.properties @@ -1,5 +1,5 @@ name=SPI -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE. diff --git a/libraries/SPIFFS/library.properties b/libraries/SPIFFS/library.properties index 486ec1b4ce6..f516aed2ee2 100644 --- a/libraries/SPIFFS/library.properties +++ b/libraries/SPIFFS/library.properties @@ -1,5 +1,5 @@ name=SPIFFS -version=3.3.0 +version=3.3.2 author=Hristo Gochkov, Ivan Grokhtkov maintainer=Hristo Gochkov sentence=ESP32 SPIFFS File System diff --git a/libraries/SimpleBLE/library.properties b/libraries/SimpleBLE/library.properties index a7f12207afe..b6f189bb7f0 100644 --- a/libraries/SimpleBLE/library.properties +++ b/libraries/SimpleBLE/library.properties @@ -1,5 +1,5 @@ name=SimpleBLE -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Provides really simple BLE advertizer with just on and off diff --git a/libraries/TFLiteMicro/library.properties b/libraries/TFLiteMicro/library.properties index d2dc127f5ab..8e5f6d95718 100644 --- a/libraries/TFLiteMicro/library.properties +++ b/libraries/TFLiteMicro/library.properties @@ -1,5 +1,5 @@ name=TFLite Micro -version=3.3.0 +version=3.3.2 author=Sanket Wadekar maintainer=Sanket Wadekar sentence=TensorFlow Lite for Microcontrollers diff --git a/libraries/Ticker/library.properties b/libraries/Ticker/library.properties index 8795deb22ce..b978f9a805e 100644 --- a/libraries/Ticker/library.properties +++ b/libraries/Ticker/library.properties @@ -1,5 +1,5 @@ name=Ticker -version=3.3.0 +version=3.3.2 author=Bert Melis maintainer=Hristo Gochkov sentence=Allows to call functions with a given interval. diff --git a/libraries/USB/library.properties b/libraries/USB/library.properties index 4c2c032545e..d9229c9d7b9 100644 --- a/libraries/USB/library.properties +++ b/libraries/USB/library.properties @@ -1,5 +1,5 @@ name=USB -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=ESP32S2 USB Library diff --git a/libraries/Update/examples/HTTP_Server_AES_OTA_Update/HTTP_Server_AES_OTA_Update.ino b/libraries/Update/examples/HTTP_Server_AES_OTA_Update/HTTP_Server_AES_OTA_Update.ino index 5af4f1bf9f4..f9216f678a5 100644 --- a/libraries/Update/examples/HTTP_Server_AES_OTA_Update/HTTP_Server_AES_OTA_Update.ino +++ b/libraries/Update/examples/HTTP_Server_AES_OTA_Update/HTTP_Server_AES_OTA_Update.ino @@ -18,7 +18,7 @@ defaults:- {if not set ie. "Update.setupCrypt();" } OTA_MODE options:- U_AES_DECRYPT_NONE decryption disabled, loads OTA image files as sent(plain) - U_AES_DECRYPT_AUTO auto loads both plain & encrypted OTA FLASH image files, and plain OTA SPIFFS image files + U_AES_DECRYPT_AUTO auto loads both plain & encrypted OTA FLASH image files, and plain OTA File System image files U_AES_DECRYPT_ON decrypts OTA image files https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/ @@ -36,7 +36,6 @@ espsecure.py encrypt_flash_data = runs the idf encryption function to make a en #include #include -#include #include #include #include @@ -145,7 +144,7 @@ void setupHttpUpdateServer() { if (upload.status == UPLOAD_FILE_START) { Serial.printf("Update: %s\n", upload.filename.c_str()); if (upload.name == "filesystem") { - if (!Update.begin(SPIFFS.totalBytes(), U_SPIFFS)) { //start with max available size + if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASHFS)) { //start with max available size Update.printError(Serial); } } else { diff --git a/libraries/Update/library.properties b/libraries/Update/library.properties index 5fd633ec358..a192318bb73 100644 --- a/libraries/Update/library.properties +++ b/libraries/Update/library.properties @@ -1,5 +1,5 @@ name=Update -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=ESP32 Sketch Update Library diff --git a/libraries/Update/src/Update.h b/libraries/Update/src/Update.h index 9a4d3e02489..5f52e6b3b73 100644 --- a/libraries/Update/src/Update.h +++ b/libraries/Update/src/Update.h @@ -29,9 +29,12 @@ #define UPDATE_SIZE_UNKNOWN 0xFFFFFFFF -#define U_FLASH 0 -#define U_SPIFFS 100 -#define U_AUTH 200 +#define U_FLASH 0 +#define U_FLASHFS 100 +#define U_SPIFFS 101 +#define U_FATFS 102 +#define U_LITTLEFS 103 +#define U_AUTH 200 #define ENCRYPTED_BLOCK_SIZE 16 #define ENCRYPTED_TWEAK_BLOCK_SIZE 32 @@ -267,7 +270,6 @@ class UpdateClass { size_t _size; THandlerFunction_Progress _progress_callback; uint32_t _progress; - uint32_t _paroffset; uint32_t _command; const esp_partition_t *_partition; diff --git a/libraries/Update/src/Updater.cpp b/libraries/Update/src/Updater.cpp index 3b0c517431d..e9f39f729d3 100644 --- a/libraries/Update/src/Updater.cpp +++ b/libraries/Update/src/Updater.cpp @@ -75,7 +75,7 @@ UpdateClass::UpdateClass() #ifndef UPDATE_NOCRYPT _cryptKey(0), _cryptBuffer(0), #endif /* UPDATE_NOCRYPT */ - _buffer(0), _skipBuffer(0), _bufferLen(0), _size(0), _progress_callback(NULL), _progress(0), _paroffset(0), _command(U_FLASH), _partition(NULL) + _buffer(0), _skipBuffer(0), _bufferLen(0), _size(0), _progress_callback(NULL), _progress(0), _command(U_FLASH), _partition(NULL) #ifndef UPDATE_NOCRYPT , _cryptMode(U_AES_DECRYPT_AUTO), _cryptAddress(0), _cryptCfg(0xf) @@ -154,16 +154,39 @@ bool UpdateClass::begin(size_t size, int command, int ledPin, uint8_t ledOn, con } log_d("OTA Partition: %s", _partition->label); } else if (command == U_SPIFFS) { - _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, label); - _paroffset = 0; + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); + if (!_partition) { + _error = UPDATE_ERROR_NO_PARTITION; + return false; + } + log_d("SPIFFS Partition: %s", _partition->label); + } else if (command == U_FATFS) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); + if (!_partition) { + _error = UPDATE_ERROR_NO_PARTITION; + return false; + } + log_d("FATFS Partition: %s", _partition->label); + } else if (command == U_LITTLEFS) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_LITTLEFS, NULL); + if (!_partition) { + _error = UPDATE_ERROR_NO_PARTITION; + return false; + } + log_d("LittleFS Partition: %s", _partition->label); + } else if (command == U_FLASHFS) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); if (!_partition) { _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); - _paroffset = 0x1000; //Offset for ffat, assuming size is already corrected - if (!_partition) { - _error = UPDATE_ERROR_NO_PARTITION; - return false; - } } + if (!_partition) { + _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_LITTLEFS, NULL); + } + if (!_partition) { + _error = UPDATE_ERROR_NO_PARTITION; + return false; + } + log_d("FS Partition: %s", _partition->label); } else { _error = UPDATE_ERROR_BAD_ARGUMENT; log_e("bad command %u", command); @@ -452,7 +475,7 @@ bool UpdateClass::_verifyHeader(uint8_t data) { return false; } return true; - } else if (_command == U_SPIFFS) { + } else { return true; } return false; @@ -471,7 +494,7 @@ bool UpdateClass::_verifyEnd() { } _reset(); return true; - } else if (_command == U_SPIFFS) { + } else { _reset(); return true; } diff --git a/libraries/WebServer/examples/ChunkWriting/ChunkWriting.ino b/libraries/WebServer/examples/ChunkWriting/ChunkWriting.ino new file mode 100644 index 00000000000..50c29322302 --- /dev/null +++ b/libraries/WebServer/examples/ChunkWriting/ChunkWriting.ino @@ -0,0 +1,75 @@ +/* + * This example demonstrates how to send an HTTP response using chunks + * It will create an HTTP Server (port 80) associated with an a MDNS service + * Access the HTTP server using a Web Browser: + * URL can be composed using the MDNS name "esp32_chunk_resp.local" + * http://esp32_chunk_resp.local/ + * or the IP Address that will be printed out, such as for instance 192.168.1.10 + * http://192.168.1.10/ + * + * ESP32 Server response can also be viewed using the curl command: + * curl -i esp32_chunk_resp.local:80 + * curl -i --raw esp32_chunk_resp.local:80 + */ + +#include +#include +#include +#include + +const char *ssid = "........"; +const char *password = "........"; + +WebServer server(80); + +void handleChunks() { + uint8_t countDown = 10; + server.chunkResponseBegin(); + char countContent[8]; + while (countDown) { + sprintf(countContent, "%d...\r\n", countDown--); + server.chunkWrite(countContent, strlen(countContent)); + // count down shall show up in the browser only after about 5 seconds when finishing the whole transmission + // using "curl -i esp32_chunk_resp.local:80", it will show the count down as it sends each chunk + delay(500); + } + server.chunkWrite("DONE!", 5); + server.chunkResponseEnd(); +} + +void setup(void) { + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + // Use the URL: http://esp32_chunk_resp.local/ + if (MDNS.begin("esp32_chunk_resp")) { + Serial.println("MDNS responder started"); + } + + server.on("/", handleChunks); + + server.onNotFound([]() { + server.send(404, "text/plain", "Page not found"); + }); + + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); + delay(2); //allow the cpu to switch to other tasks +} diff --git a/libraries/WebServer/examples/ChunkWriting/ci.json b/libraries/WebServer/examples/ChunkWriting/ci.json new file mode 100644 index 00000000000..618e46bd244 --- /dev/null +++ b/libraries/WebServer/examples/ChunkWriting/ci.json @@ -0,0 +1,6 @@ +{ + "requires_any": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_WIFI_REMOTE_ENABLED=y" + ] +} diff --git a/libraries/WebServer/library.properties b/libraries/WebServer/library.properties index 913dd00e036..e89eb90221c 100644 --- a/libraries/WebServer/library.properties +++ b/libraries/WebServer/library.properties @@ -1,5 +1,5 @@ name=WebServer -version=3.3.0 +version=3.3.2 author=Ivan Grokhotkov maintainer=Ivan Grokhtkov sentence=Simple web server library diff --git a/libraries/WebServer/src/WebServer.cpp b/libraries/WebServer/src/WebServer.cpp index 7523e40259b..e67fcec05e4 100644 --- a/libraries/WebServer/src/WebServer.cpp +++ b/libraries/WebServer/src/WebServer.cpp @@ -551,6 +551,76 @@ void WebServer::enableETag(bool enable, ETagFunction fn) { _eTagFunction = fn; } +void WebServer::chunkResponseBegin(const char *contentType) { + if (_chunkedResponseActive) { + log_e("Already in chunked response mode"); + return; + } + + if (strchr(contentType, '\r') || strchr(contentType, '\n')) { + log_e("Invalid character in content type"); + return; + } + + _chunkedResponseActive = true; + _chunkedClient = _currentClient; + + _contentLength = CONTENT_LENGTH_UNKNOWN; + + String header; + _prepareHeader(header, 200, contentType, 0); + _currentClientWrite(header.c_str(), header.length()); + + _chunkedResponseActive = true; + _chunkedClient = _currentClient; +} + +void WebServer::chunkWrite(const char *data, size_t length) { + if (!_chunkedResponseActive) { + log_e("Chunked response has not been started"); + return; + } + + char chunkSize[11]; + snprintf(chunkSize, sizeof(chunkSize), "%zx\r\n", length); + + if (_chunkedClient.write(chunkSize) != strlen(chunkSize)) { + log_e("Failed to write chunk size"); + _chunkedResponseActive = false; + return; + } + + if (_chunkedClient.write((const uint8_t *)data, length) != length) { + log_e("Failed to write chunk data"); + _chunkedResponseActive = false; + return; + } + + if (_chunkedClient.write("\r\n") != 2) { + log_e("Failed to write chunk terminator"); + _chunkedResponseActive = false; + return; + } +} + +void WebServer::chunkResponseEnd() { + if (!_chunkedResponseActive) { + log_e("Chunked response has not been started"); + return; + } + + if (_chunkedClient.write("0\r\n\r\n", 5) != 5) { + log_e("Failed to write terminating chunk"); + } + + _chunkedClient.flush(); + _chunkedResponseActive = false; + _chunked = false; + _chunkedClient = NetworkClient(); + + _clearResponseHeaders(); +} + void WebServer::_prepareHeader(String &response, int code, const char *content_type, size_t contentLength) { _responseCode = code; diff --git a/libraries/WebServer/src/WebServer.h b/libraries/WebServer/src/WebServer.h index 8daf12c5c30..498bcb5806c 100644 --- a/libraries/WebServer/src/WebServer.h +++ b/libraries/WebServer/src/WebServer.h @@ -115,6 +115,10 @@ class WebServer { const String AuthTypeDigest = F("Digest"); const String AuthTypeBasic = F("Basic"); + void chunkResponseBegin(const char *contentType = "text/plain"); + void chunkWrite(const char *data, size_t length); + void chunkResponseEnd(); + /* Callbackhandler for authentication. The extra parameters depend on the * HTTPAuthMethod mode: * @@ -241,6 +245,10 @@ class WebServer { static String responseCodeToString(int code); +private: + bool _chunkedResponseActive = false; + NetworkClient _chunkedClient; // Store by value, no dangling pointer + protected: virtual size_t _currentClientWrite(const char *b, size_t l) { return _currentClient.write(b, l); diff --git a/libraries/WiFi/library.properties b/libraries/WiFi/library.properties index 82ccb32b702..9c9a267361b 100644 --- a/libraries/WiFi/library.properties +++ b/libraries/WiFi/library.properties @@ -1,5 +1,5 @@ name=WiFi -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Enables network connection (local and Internet) using the ESP32 built-in WiFi. diff --git a/libraries/WiFiProv/library.properties b/libraries/WiFiProv/library.properties index 1b19186c40b..87bc5691201 100644 --- a/libraries/WiFiProv/library.properties +++ b/libraries/WiFiProv/library.properties @@ -1,5 +1,5 @@ name=WiFiProv -version=3.3.0 +version=3.3.2 author=Switi Mhaiske maintainer=Hristo Gochkov sentence=Enables provisioning. diff --git a/libraries/Wire/library.properties b/libraries/Wire/library.properties index 182e98790bc..c4abd55152d 100644 --- a/libraries/Wire/library.properties +++ b/libraries/Wire/library.properties @@ -1,5 +1,5 @@ name=Wire -version=3.3.0 +version=3.3.2 author=Hristo Gochkov maintainer=Hristo Gochkov sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For esp8266 boards. diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index 0721371ce0e..d4a71bbed89 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -66,6 +66,8 @@ static SwitchData buttonFunctionPair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_O ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); +static bool light_state = false; + /********************* Zigbee functions **************************/ static void onZbButton(SwitchData *button_func_pair) { if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { @@ -75,6 +77,33 @@ static void onZbButton(SwitchData *button_func_pair) { } } +static void onLightStateChange(bool state) { + if (state != light_state) { + light_state = state; + Serial.printf("Light state changed to %d\r\n", state); + } +} + +/********************* Periodic task ***************************/ +void periodicTask(void *arg) { + while (true) { + // print the bound lights every 10 seconds + static uint32_t lastPrint = 0; + if (millis() - lastPrint > 10000) { + lastPrint = millis(); + zbSwitch.printBoundDevices(Serial); + } + + // Poll light state every second + static uint32_t lastPoll = 0; + if (millis() - lastPoll > 1000) { + lastPoll = millis(); + zbSwitch.getLightState(); + } + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + /********************* GPIO functions **************************/ static QueueHandle_t gpio_evt_queue = NULL; @@ -102,6 +131,8 @@ void setup() { //Optional to allow multiple light to bind to the switch zbSwitch.allowMultipleBinding(true); + zbSwitch.onLightStateChange(onLightStateChange); + //Add endpoint to Zigbee Core Serial.println("Adding ZigbeeSwitch endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbSwitch); @@ -154,6 +185,8 @@ void setup() { } Serial.println(); + + xTaskCreate(periodicTask, "periodicTask", 1024 * 4, NULL, 10, NULL); } void loop() { @@ -188,11 +221,4 @@ void loop() { } vTaskDelay(10 / portTICK_PERIOD_MS); } - - // print the bound lights every 10 seconds - static uint32_t lastPrint = 0; - if (millis() - lastPrint > 10000) { - lastPrint = millis(); - zbSwitch.printBoundDevices(Serial); - } } diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt index 67cb47ee319..f203de96da6 100644 --- a/libraries/Zigbee/keywords.txt +++ b/libraries/Zigbee/keywords.txt @@ -104,7 +104,6 @@ clearBoundDevices KEYWORD2 onDefaultResponse KEYWORD2 # ZigbeeLight + ZigbeeColorDimmableLight -onLightChange KEYWORD2 restoreLight KEYWORD2 setLight KEYWORD2 setLightState KEYWORD2 @@ -115,6 +114,12 @@ getLightLevel KEYWORD2 getLightRed KEYWORD2 getLightGreen KEYWORD2 getLightBlue KEYWORD2 +onLightChange KEYWORD2 +onLightColorChangeWithSource KEYWORD2 +onLightLevelChange KEYWORD2 +onLightLevelChangeWithSource KEYWORD2 +onLightStateChange KEYWORD2 +onLightStateChangeWithSource KEYWORD2 # ZigbeeSwitch + ZigbeeColorDimmerSwitch lightToggle KEYWORD2 @@ -125,6 +130,15 @@ lightOnWithTimedOff KEYWORD2 lightOnWithSceneRecall KEYWORD2 setLightLevel KEYWORD2 setLightColor KEYWORD2 +getLightState KEYWORD2 +getLightLevel KEYWORD2 +getLightColor KEYWORD2 +onLightStateChange KEYWORD2 +onLightStateChangeWithSource KEYWORD2 +onLightLevelChange KEYWORD2 +onLightLevelChangeWithSource KEYWORD2 +onLightColorChange KEYWORD2 +onLightColorChangeWithSource KEYWORD2 # ZigbeeThermostat onTempRecieve KEYWORD2 diff --git a/libraries/Zigbee/library.properties b/libraries/Zigbee/library.properties index dab96b82a61..8cb401d713a 100644 --- a/libraries/Zigbee/library.properties +++ b/libraries/Zigbee/library.properties @@ -1,5 +1,5 @@ name=Zigbee -version=3.3.0 +version=3.3.2 author=P-R-O-C-H-Y maintainer=Jan Procházka sentence=Enables zigbee connection with the ESP32 diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index b857eb5e7a5..48a083748f4 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -160,7 +160,8 @@ bool ZigbeeEP::setBatteryVoltage(uint8_t voltage) { bool ZigbeeEP::reportBatteryPercentage() { /* Send report attributes command */ - esp_zb_zcl_report_attr_cmd_t report_attr_cmd = {0}; + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + memset(&report_attr_cmd, 0, sizeof(report_attr_cmd)); report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID; report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; @@ -181,7 +182,8 @@ bool ZigbeeEP::reportBatteryPercentage() { char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) { /* Read peer Manufacture Name & Model Identifier */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); if (short_addr != 0) { read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -219,7 +221,8 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) { /* Read peer Manufacture Name & Model Identifier */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); if (short_addr != 0) { read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -396,7 +399,8 @@ bool ZigbeeEP::setTimezone(int32_t gmt_offset) { tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) { /* Read peer time */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); if (short_addr >= 0) { read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -448,7 +452,8 @@ tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ie int32_t ZigbeeEP::getTimezone(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) { /* Read peer timezone */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); if (short_addr >= 0) { read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -564,7 +569,8 @@ static void findOTAServer(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t } void ZigbeeEP::requestOTAUpdate() { - esp_zb_zdo_match_desc_req_param_t req = {0}; + esp_zb_zdo_match_desc_req_param_t req; + memset(&req, 0, sizeof(req)); uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_OTA_UPGRADE}; /* Match the OTA server of coordinator */ diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 1d18d3c10e8..18465104dfa 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -23,6 +23,16 @@ ZigbeeColorDimmerSwitch::ZigbeeColorDimmerSwitch(uint8_t endpoint) : ZigbeeEP(en _instance = this; // Set the static pointer to this instance _device = nullptr; // Initialize light pointer to null + _light_color_rgb = {0, 0, 0}; + _light_color_hsv = {0, 0, 255}; + _light_color_xy = {0, 0}; + _on_light_state_change = nullptr; + _on_light_state_change_with_source = nullptr; + _on_light_level_change = nullptr; + _on_light_level_change_with_source = nullptr; + _on_light_color_change = nullptr; + _on_light_color_change_with_source = nullptr; + esp_zb_color_dimmable_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_SWITCH_CONFIG(); _cluster_list = esp_zb_color_dimmable_switch_clusters_create(&switch_cfg); @@ -67,7 +77,8 @@ void ZigbeeColorDimmerSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t ad ZigbeeColorDimmerSwitch *instance = static_cast(user_ctx); if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_d("Found light endpoint"); - esp_zb_zdo_bind_req_param_t bind_req = {0}; + esp_zb_zdo_bind_req_param_t bind_req; + memset(&bind_req, 0, sizeof(bind_req)); zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); light->endpoint = endpoint; light->short_addr = addr; @@ -111,7 +122,8 @@ void ZigbeeColorDimmerSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cm // Methods to control the light void ZigbeeColorDimmerSwitch::lightToggle() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; @@ -126,7 +138,8 @@ void ZigbeeColorDimmerSwitch::lightToggle() { void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -142,7 +155,8 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) { void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -159,7 +173,8 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -179,7 +194,8 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t i void ZigbeeColorDimmerSwitch::lightOn() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; @@ -194,7 +210,8 @@ void ZigbeeColorDimmerSwitch::lightOn() { void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -210,7 +227,8 @@ void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) { void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -227,7 +245,8 @@ void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -247,7 +266,8 @@ void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_ void ZigbeeColorDimmerSwitch::lightOff() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; @@ -262,7 +282,8 @@ void ZigbeeColorDimmerSwitch::lightOff() { void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -278,7 +299,8 @@ void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) { void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -295,7 +317,8 @@ void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -315,7 +338,8 @@ void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee void ZigbeeColorDimmerSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) { if (_is_bound) { - esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.effect_id = effect_id; @@ -331,7 +355,8 @@ void ZigbeeColorDimmerSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effe void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() { if (_is_bound) { - esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; log_v("Sending 'light on with scene recall' command"); @@ -345,7 +370,8 @@ void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() { void ZigbeeColorDimmerSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off) { if (_is_bound) { - esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_control = on_off_control; //TODO: Test how it works, then maybe change API @@ -362,7 +388,8 @@ void ZigbeeColorDimmerSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16 void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) { if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req = {0}; + esp_zb_zcl_move_to_level_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.level = level; @@ -378,7 +405,8 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) { void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req = {0}; + esp_zb_zcl_move_to_level_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -395,7 +423,8 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req = {0}; + esp_zb_zcl_move_to_level_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -413,7 +442,8 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, uin void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req = {0}; + esp_zb_zcl_move_to_level_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -436,7 +466,8 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t if (_is_bound) { espXyColor_t xy_color = espRgbToXYColor(red, green, blue); - esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0}; + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.color_x = xy_color.x; @@ -455,7 +486,8 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t if (_is_bound) { espXyColor_t xy_color = espRgbToXYColor(red, green, blue); - esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0}; + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -475,7 +507,8 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t if (_is_bound) { espXyColor_t xy_color = espRgbToXYColor(red, green, blue); - esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0}; + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -496,7 +529,8 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t if (_is_bound) { espXyColor_t xy_color = espRgbToXYColor(red, green, blue); - esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0}; + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -516,4 +550,356 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t } } +void ZigbeeColorDimmerSwitch::getLightState() { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightState(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightState(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightState(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightLevel() { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightLevel(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightLevel(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightLevel(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightColor() { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + read_req.attr_number = 2; + uint16_t attr_id[] = {ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID}; + read_req.attr_field = attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightColor(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + read_req.attr_number = 2; + uint16_t attr_id[] = {ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID}; + read_req.attr_field = attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightColor(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + read_req.attr_number = 2; + uint16_t attr_id[] = {ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID}; + read_req.attr_field = attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightColor(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + read_req.attr_number = 2; + uint16_t attr_id[] = {ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID}; + read_req.attr_field = attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightColorHS() { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + read_req.attr_number = 2; + uint16_t attr_id[] = {ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID}; + read_req.attr_field = attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightColorHS(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + read_req.attr_number = 2; + uint16_t attr_id[] = {ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID}; + read_req.attr_field = attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightColorHS(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + read_req.attr_number = 2; + uint16_t attr_id[] = {ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID}; + read_req.attr_field = attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::getLightColorHS(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + read_req.attr_number = 2; + uint16_t attr_id[] = {ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID}; + read_req.attr_field = attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeColorDimmerSwitch::zbAttributeRead( + uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address +) { + if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (attribute->id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + bool light_state = attribute->data.value ? *(bool *)attribute->data.value : false; + if (_on_light_state_change) { + _on_light_state_change(light_state); + } + if (_on_light_state_change_with_source) { + _on_light_state_change_with_source(light_state, src_endpoint, src_address); + } + } + } + if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { + if (attribute->id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + uint8_t light_level = attribute->data.value ? *(uint8_t *)attribute->data.value : 0; + if (_on_light_level_change) { + _on_light_level_change(light_level); + } + if (_on_light_level_change_with_source) { + _on_light_level_change_with_source(light_level, src_endpoint, src_address); + } + } + } + if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) { + static bool x_received = false; + static bool y_received = false; + static bool h_received = false; + static bool s_received = false; + + if (attribute->id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + _light_color_xy.x = attribute->data.value ? *(uint16_t *)attribute->data.value : 0; + x_received = true; + } + if (attribute->id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + _light_color_xy.y = attribute->data.value ? *(uint16_t *)attribute->data.value : 0; + y_received = true; + } + + if (attribute->id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + _light_color_hsv.h = attribute->data.value ? *(uint8_t *)attribute->data.value : 0; + h_received = true; + } + if (attribute->id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + _light_color_hsv.s = attribute->data.value ? *(uint8_t *)attribute->data.value : 0; + s_received = true; + } + + // Process XY color if both X and Y have been received + if (x_received && y_received) { + _light_color_rgb = espXYToRgbColor(255, _light_color_xy.x, _light_color_xy.y, false); + if (_on_light_color_change) { + _on_light_color_change(_light_color_rgb.r, _light_color_rgb.g, _light_color_rgb.b); + } + if (_on_light_color_change_with_source) { + _on_light_color_change_with_source(_light_color_rgb.r, _light_color_rgb.g, _light_color_rgb.b, src_endpoint, src_address); + } + x_received = false; // Reset flags after processing + y_received = false; + } + + // Process HS color if both H and S have been received + if (h_received && s_received) { + _light_color_rgb = espHsvColorToRgbColor(_light_color_hsv); + if (_on_light_color_change) { + _on_light_color_change(_light_color_rgb.r, _light_color_rgb.g, _light_color_rgb.b); + } + if (_on_light_color_change_with_source) { + _on_light_color_change_with_source(_light_color_rgb.r, _light_color_rgb.g, _light_color_rgb.b, src_endpoint, src_address); + } + h_received = false; // Reset flags after processing + s_received = false; + } + } +} #endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h index 9d813c47651..10484a6867f 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h @@ -58,18 +58,68 @@ class ZigbeeColorDimmerSwitch : public ZigbeeEP { void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr); void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + void getLightState(); + void getLightState(uint16_t group_addr); + void getLightState(uint8_t endpoint, uint16_t short_addr); + void getLightState(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void getLightLevel(); + void getLightLevel(uint16_t group_addr); + void getLightLevel(uint8_t endpoint, uint16_t short_addr); + void getLightLevel(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void getLightColor(); + void getLightColor(uint16_t group_addr); + void getLightColor(uint8_t endpoint, uint16_t short_addr); + void getLightColor(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void getLightColorHS(); + void getLightColorHS(uint16_t group_addr); + void getLightColorHS(uint8_t endpoint, uint16_t short_addr); + void getLightColorHS(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void onLightStateChange(void (*callback)(bool)) { + _on_light_state_change = callback; + } + void onLightStateChangeWithSource(void (*callback)(bool, uint8_t, esp_zb_zcl_addr_t)) { + _on_light_state_change_with_source = callback; + } + void onLightLevelChange(void (*callback)(uint8_t)) { + _on_light_level_change = callback; + } + void onLightLevelChangeWithSource(void (*callback)(uint8_t, uint8_t, esp_zb_zcl_addr_t)) { + _on_light_level_change_with_source = callback; + } + void onLightColorChange(void (*callback)(uint8_t, uint8_t, uint8_t)) { + _on_light_color_change = callback; + } + void onLightColorChangeWithSource(void (*callback)(uint8_t, uint8_t, uint8_t, uint8_t, esp_zb_zcl_addr_t)) { + _on_light_color_change_with_source = callback; + } + private: // save instance of the class in order to use it in static functions static ZigbeeColorDimmerSwitch *_instance; zb_device_params_t *_device; + espHsvColor_t _light_color_hsv; + espXyColor_t _light_color_xy; + espRgbColor_t _light_color_rgb; + + void (*_on_light_state_change)(bool); + void (*_on_light_state_change_with_source)(bool, uint8_t, esp_zb_zcl_addr_t); + void (*_on_light_level_change)(uint8_t); + void (*_on_light_level_change_with_source)(uint8_t, uint8_t, esp_zb_zcl_addr_t); + void (*_on_light_color_change)(uint8_t, uint8_t, uint8_t); + void (*_on_light_color_change_with_source)(uint8_t, uint8_t, uint8_t, uint8_t, esp_zb_zcl_addr_t); + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); static void bindCbWrapper(esp_zb_zdp_status_t zdo_status, void *user_ctx); static void findCbWrapper(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); - void calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y); + void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) override; }; #endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index d3e3aae4cf7..a81c63aed06 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -66,7 +66,8 @@ void ZigbeeSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t ZigbeeSwitch *instance = static_cast(user_ctx); if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_d("Found light endpoint"); - esp_zb_zdo_bind_req_param_t bind_req = {0}; + esp_zb_zdo_bind_req_param_t bind_req; + memset(&bind_req, 0, sizeof(bind_req)); zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); light->endpoint = endpoint; light->short_addr = addr; @@ -108,7 +109,8 @@ void ZigbeeSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { // Methods to control the light void ZigbeeSwitch::lightToggle() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; @@ -123,7 +125,8 @@ void ZigbeeSwitch::lightToggle() { void ZigbeeSwitch::lightToggle(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -139,7 +142,8 @@ void ZigbeeSwitch::lightToggle(uint16_t group_addr) { void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -156,7 +160,8 @@ void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { void ZigbeeSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -176,7 +181,8 @@ void ZigbeeSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { void ZigbeeSwitch::lightOn() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; @@ -191,7 +197,8 @@ void ZigbeeSwitch::lightOn() { void ZigbeeSwitch::lightOn(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -207,7 +214,8 @@ void ZigbeeSwitch::lightOn(uint16_t group_addr) { void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -224,7 +232,8 @@ void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { void ZigbeeSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -244,7 +253,8 @@ void ZigbeeSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { void ZigbeeSwitch::lightOff() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; @@ -259,7 +269,8 @@ void ZigbeeSwitch::lightOff() { void ZigbeeSwitch::lightOff(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -275,7 +286,8 @@ void ZigbeeSwitch::lightOff(uint16_t group_addr) { void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -292,7 +304,8 @@ void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { void ZigbeeSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -312,7 +325,8 @@ void ZigbeeSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { void ZigbeeSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) { if (_is_bound) { - esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.effect_id = effect_id; @@ -328,7 +342,8 @@ void ZigbeeSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) void ZigbeeSwitch::lightOnWithSceneRecall() { if (_is_bound) { - esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; log_v("Sending 'light on with scene recall' command"); @@ -339,9 +354,11 @@ void ZigbeeSwitch::lightOnWithSceneRecall() { log_e("Light not bound"); } } + void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off) { if (_is_bound) { - esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req = {0}; + esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req; + memset(&cmd_req, 0, sizeof(cmd_req)); cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_control = on_off_control; //TODO: Test how it works, then maybe change API @@ -356,4 +373,86 @@ void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, } } +void ZigbeeSwitch::getLightState() { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeSwitch::getLightState(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeSwitch::getLightState(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeSwitch::getLightState(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + read_req.attr_number = 1; + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; + read_req.attr_field = &attr_id; + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + } +} + +void ZigbeeSwitch::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) { + if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (attribute->id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + bool light_state = attribute->data.value ? *(bool *)attribute->data.value : false; + if (_on_light_state_change) { + _on_light_state_change(light_state); + } + if (_on_light_state_change_with_source) { + _on_light_state_change_with_source(light_state, src_endpoint, src_address); + } + } + } +} #endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.h b/libraries/Zigbee/src/ep/ZigbeeSwitch.h index f449843d85c..09c17355763 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.h @@ -48,15 +48,32 @@ class ZigbeeSwitch : public ZigbeeEP { void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); void lightOnWithSceneRecall(); + void getLightState(); + void getLightState(uint16_t group_addr); + void getLightState(uint8_t endpoint, uint16_t short_addr); + void getLightState(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + + void onLightStateChange(void (*callback)(bool)) { + _on_light_state_change = callback; + } + void onLightStateChangeWithSource(void (*callback)(bool, uint8_t, esp_zb_zcl_addr_t)) { + _on_light_state_change_with_source = callback; + } + private: // save instance of the class in order to use it in static functions static ZigbeeSwitch *_instance; zb_device_params_t *_device; + + void (*_on_light_state_change)(bool); + void (*_on_light_state_change_with_source)(bool, uint8_t, esp_zb_zcl_addr_t); + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); static void findCbWrapper(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); static void bindCbWrapper(esp_zb_zdp_status_t zdo_status, void *user_ctx); + void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) override; }; #endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp index b08c256ab6b..e076aff79f0 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -79,7 +79,8 @@ void ZigbeeThermostat::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uin ZigbeeThermostat *instance = static_cast(user_ctx); if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Found temperature sensor"); - esp_zb_zdo_bind_req_param_t bind_req = {0}; + esp_zb_zdo_bind_req_param_t bind_req; + memset(&bind_req, 0, sizeof(bind_req)); /* Store the information of the remote device */ zb_device_params_t *sensor = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); sensor->endpoint = endpoint; @@ -169,7 +170,8 @@ void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_att void ZigbeeThermostat::getTemperature() { /* Send "read attributes" command to all bound sensors */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; @@ -186,7 +188,8 @@ void ZigbeeThermostat::getTemperature() { void ZigbeeThermostat::getTemperature(uint16_t group_addr) { /* Send "read attributes" command to the group */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; @@ -204,7 +207,8 @@ void ZigbeeThermostat::getTemperature(uint16_t group_addr) { void ZigbeeThermostat::getTemperature(uint8_t endpoint, uint16_t short_addr) { /* Send "read attributes" command to specific endpoint */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.zcl_basic_cmd.dst_endpoint = endpoint; @@ -223,7 +227,8 @@ void ZigbeeThermostat::getTemperature(uint8_t endpoint, uint16_t short_addr) { void ZigbeeThermostat::getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { /* Send "read attributes" command to specific endpoint */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.zcl_basic_cmd.dst_endpoint = endpoint; @@ -245,7 +250,8 @@ void ZigbeeThermostat::getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_ void ZigbeeThermostat::getSensorSettings() { /* Send "read attributes" command to all bound sensors */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; @@ -273,7 +279,8 @@ void ZigbeeThermostat::getSensorSettings() { void ZigbeeThermostat::getSensorSettings(uint16_t group_addr) { /* Send "read attributes" command to the group */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; @@ -302,7 +309,8 @@ void ZigbeeThermostat::getSensorSettings(uint16_t group_addr) { void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, uint16_t short_addr) { /* Send "read attributes" command to specific endpoint */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.zcl_basic_cmd.dst_endpoint = endpoint; @@ -332,7 +340,8 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, uint16_t short_addr) void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { /* Send "read attributes" command to specific endpoint */ - esp_zb_zcl_read_attr_cmd_t read_req = {0}; + esp_zb_zcl_read_attr_cmd_t read_req; + memset(&read_req, 0, sizeof(read_req)); read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.zcl_basic_cmd.dst_endpoint = endpoint; @@ -365,7 +374,8 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ie void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta) { /* Send "configure report attribute" command to all bound sensors */ - esp_zb_zcl_config_report_cmd_t report_cmd = {0}; + esp_zb_zcl_config_report_cmd_t report_cmd; + memset(&report_cmd, 0, sizeof(report_cmd)); report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; @@ -392,7 +402,8 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min_interval, uint16_t max_interval, float delta) { /* Send "configure report attribute" command to the group */ - esp_zb_zcl_config_report_cmd_t report_cmd = {0}; + esp_zb_zcl_config_report_cmd_t report_cmd; + memset(&report_cmd, 0, sizeof(report_cmd)); report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; report_cmd.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; @@ -420,7 +431,8 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_addr, uint16_t min_interval, uint16_t max_interval, float delta) { /* Send "configure report attribute" command to specific endpoint */ - esp_zb_zcl_config_report_cmd_t report_cmd = {0}; + esp_zb_zcl_config_report_cmd_t report_cmd; + memset(&report_cmd, 0, sizeof(report_cmd)); report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; report_cmd.zcl_basic_cmd.dst_endpoint = endpoint; @@ -449,7 +461,8 @@ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr, uint16_t min_interval, uint16_t max_interval, float delta) { /* Send "configure report attribute" command to specific endpoint */ - esp_zb_zcl_config_report_cmd_t report_cmd = {0}; + esp_zb_zcl_config_report_cmd_t report_cmd; + memset(&report_cmd, 0, sizeof(report_cmd)); report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; report_cmd.zcl_basic_cmd.dst_endpoint = endpoint; diff --git a/package.json b/package.json index 4c3e4725a9d..f4b8a6824da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "framework-arduinoespressif32", - "version": "3.3.0", + "version": "3.3.2", "description": "Arduino Wiring-based Framework for the Espressif ESP32, ESP32-P4, ESP32-S and ESP32-C series of SoCs", "keywords": [ "framework", diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 7382af86779..77b203fc056 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -51,27 +51,27 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.5-129cd0d2-v4" + "version": "idf-release_v5.5-07e9bf49-v1" }, { "packager": "esp32", "name": "xtensa-esp-elf-gcc", - "version": "esp-14.2.0_20241119" + "version": "esp-14.2.0_20250730" }, { "packager": "esp32", "name": "xtensa-esp-elf-gdb", - "version": "16.2_20250324" + "version": "16.3_20250913" }, { "packager": "esp32", "name": "riscv32-esp-elf-gcc", - "version": "esp-14.2.0_20241119" + "version": "esp-14.2.0_20250730" }, { "packager": "esp32", "name": "riscv32-esp-elf-gdb", - "version": "16.2_20250324" + "version": "16.3_20250913" }, { "packager": "esp32", @@ -104,311 +104,311 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.5-129cd0d2-v4", + "version": "idf-release_v5.5-07e9bf49-v1", "systems": [ { "host": "i686-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "checksum": "SHA-256:be9402929176a556007fea48db7bb79da431614a2e153c54f92c8314f6ccd099", - "size": "446164326" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "checksum": "SHA-256:e5ae9e62d781df941128a526e653bb82decde844604b5ccee62efd12c6b2eaa6", + "size": "448900656" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "checksum": "SHA-256:be9402929176a556007fea48db7bb79da431614a2e153c54f92c8314f6ccd099", - "size": "446164326" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "checksum": "SHA-256:e5ae9e62d781df941128a526e653bb82decde844604b5ccee62efd12c6b2eaa6", + "size": "448900656" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "checksum": "SHA-256:be9402929176a556007fea48db7bb79da431614a2e153c54f92c8314f6ccd099", - "size": "446164326" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "checksum": "SHA-256:e5ae9e62d781df941128a526e653bb82decde844604b5ccee62efd12c6b2eaa6", + "size": "448900656" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "checksum": "SHA-256:be9402929176a556007fea48db7bb79da431614a2e153c54f92c8314f6ccd099", - "size": "446164326" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "checksum": "SHA-256:e5ae9e62d781df941128a526e653bb82decde844604b5ccee62efd12c6b2eaa6", + "size": "448900656" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "checksum": "SHA-256:be9402929176a556007fea48db7bb79da431614a2e153c54f92c8314f6ccd099", - "size": "446164326" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "checksum": "SHA-256:e5ae9e62d781df941128a526e653bb82decde844604b5ccee62efd12c6b2eaa6", + "size": "448900656" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "checksum": "SHA-256:be9402929176a556007fea48db7bb79da431614a2e153c54f92c8314f6ccd099", - "size": "446164326" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "checksum": "SHA-256:e5ae9e62d781df941128a526e653bb82decde844604b5ccee62efd12c6b2eaa6", + "size": "448900656" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "checksum": "SHA-256:be9402929176a556007fea48db7bb79da431614a2e153c54f92c8314f6ccd099", - "size": "446164326" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "checksum": "SHA-256:e5ae9e62d781df941128a526e653bb82decde844604b5ccee62efd12c6b2eaa6", + "size": "448900656" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-129cd0d2-v4.zip", - "checksum": "SHA-256:be9402929176a556007fea48db7bb79da431614a2e153c54f92c8314f6ccd099", - "size": "446164326" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.5-07e9bf49-v1.zip", + "checksum": "SHA-256:e5ae9e62d781df941128a526e653bb82decde844604b5ccee62efd12c6b2eaa6", + "size": "448900656" } ] }, { "name": "xtensa-esp-elf-gcc", - "version": "esp-14.2.0_20241119", + "version": "esp-14.2.0_20250730", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:b1859df334a85541ae746e1b86439f59180d87f8cf1cc04c2e770fadf9f006e9", - "size": "323678089" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/xtensa-esp-elf-14.2.0_20250730-x86_64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20250730-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:2031cbec81edf5f863afcaba44ce8d05d2a570c48ad514f0d43be7f9419198d8", + "size": "326342823" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:7ff023033a5c00e55b9fc0a0b26d18fb0e476c24e24c5b0459bcb2e05a3729f1", - "size": "320064691" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/xtensa-esp-elf-14.2.0_20250730-aarch64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20250730-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:0ac7087a07b554477f66043b6cd81189b3b15d89d51dc08767b1af469f3dd532", + "size": "322745855" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:bb11dbf3ed25d4e0cc9e938749519e8236cfa2609e85742d311f1d869111805a", - "size": "319454139" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/xtensa-esp-elf-14.2.0_20250730-arm-linux-gnueabi.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20250730-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:8a64d968832a3ede4481fcec8140968384942c52f817c4af347401ef024b52a5", + "size": "322129706" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-i586-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-i586-linux-gnu.tar.gz", - "checksum": "SHA-256:5ac611dca62ec791d413d1f417d566c444b006d2a4f97bd749b15f782d87249b", - "size": "328335914" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/xtensa-esp-elf-14.2.0_20250730-i586-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20250730-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:a9e3b5f516a00b6b580c7c7bb983e536ea76fb39cac1cbc3d0e632c9f790c71c", + "size": "330989568" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-x86_64-apple-darwin_signed.tar.gz", - "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-x86_64-apple-darwin_signed.tar.gz", - "checksum": "SHA-256:15b3e60362028eaeff9156dc82dac3f1436b4aeef3920b28d7650974d8c34751", - "size": "336215844" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/xtensa-esp-elf-14.2.0_20250730-x86_64-apple-darwin.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20250730-x86_64-apple-darwin.tar.gz", + "checksum": "SHA-256:7f6e9273b0c2330869f847dd6a12c7a95eda572de5f58bd5dc4550869395e01f", + "size": "338869041" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-aarch64-apple-darwin_signed.tar.gz", - "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-aarch64-apple-darwin_signed.tar.gz", - "checksum": "SHA-256:45c475518735133789bacccad31f872318b7ecc0b31cc9b7924aad880034f0bf", - "size": "318797396" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/xtensa-esp-elf-14.2.0_20250730-aarch64-apple-darwin.tar.gz", + "archiveFileName": "xtensa-esp-elf-14.2.0_20250730-aarch64-apple-darwin.tar.gz", + "checksum": "SHA-256:8ce30a1b662dc0d57266146c2a144cb8238761fe8b118c0610ff19533dd35d78", + "size": "321443711" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-i686-w64-mingw32.zip", - "checksum": "SHA-256:b30e450e0af279783c54a9ae77c3b367dd556b78eda930a92ec7b784a74c28c8", - "size": "382457717" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/xtensa-esp-elf-14.2.0_20250730-i686-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-14.2.0_20250730-i686-w64-mingw32.zip", + "checksum": "SHA-256:77020244927a0deaabb650ea1c56ee1d355ca9fdad78d0f53b1a80075ecabcba", + "size": "391479409" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/xtensa-esp-elf-14.2.0_20241119-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp-elf-14.2.0_20241119-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:62ae704777d73c30689efff6e81178632a1ca44d1a2d60f4621eb997e040e028", - "size": "386316009" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/xtensa-esp-elf-14.2.0_20250730-x86_64-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-14.2.0_20250730-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:9ce39218884cfbf428f9f6b1cb6afd9341e327f5e1a8d1d0369c21ae6e3b0828", + "size": "396050234" } ] }, { "name": "xtensa-esp-elf-gdb", - "version": "16.2_20250324", + "version": "16.3_20250913", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/xtensa-esp-elf-gdb-16.2_20250324-x86_64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-16.2_20250324-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:27b58ab12248e04277c4fdc74038cf0a001d5142df091ab94939ad35053738fd", - "size": "36361058" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/xtensa-esp-elf-gdb-16.3_20250913-x86_64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-16.3_20250913-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:16d05c9104ff84529ac3799abb04d5666c193131ab461f153040721728b48730", + "size": "36396804" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/xtensa-esp-elf-gdb-16.2_20250324-aarch64-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-16.2_20250324-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:24f85aa778e1605098a13ff7bd29d5760767faf012705c8915cb08b32cad0206", - "size": "35442104" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/xtensa-esp-elf-gdb-16.3_20250913-aarch64-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-16.3_20250913-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:ecbd53ba28cf24301be8260249bfcfb60567f938f4402797617c8a0fc170dc7d", + "size": "35457879" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/xtensa-esp-elf-gdb-16.2_20250324-arm-linux-gnueabi.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-16.2_20250324-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:c73e43038b6d50374cd0ee714370ce748189e0b00404d581babd2bb0115c4785", - "size": "31260410" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/xtensa-esp-elf-gdb-16.3_20250913-arm-linux-gnueabi.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-16.3_20250913-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:c0895e88797089fd6b16e1cb986c5c85a880e0e8dc03bde1016c7771bc10ddba", + "size": "31288407" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/xtensa-esp-elf-gdb-16.2_20250324-i586-linux-gnu.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-16.2_20250324-i586-linux-gnu.tar.gz", - "checksum": "SHA-256:dc7b8aad0fb1c6a1abfdb8dff4f08221ea08a0f28fb837f181969ac1174d4dc6", - "size": "35067894" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/xtensa-esp-elf-gdb-16.3_20250913-i586-linux-gnu.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-16.3_20250913-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:64ffefb7625edae77a03a13fd9bd07db088dec9d145eb1124de66f11510f7558", + "size": "35094067" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/xtensa-esp-elf-gdb-16.2_20250324-x86_64-apple-darwin21.1.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-16.2_20250324-x86_64-apple-darwin21.1.tar.gz", - "checksum": "SHA-256:398c429cfe696bad01d636c5488cadc87b20471c1b5ed02c60eee5ef2a775c93", - "size": "54992785" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/xtensa-esp-elf-gdb-16.3_20250913-x86_64-apple-darwin24.5.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-16.3_20250913-x86_64-apple-darwin24.5.tar.gz", + "checksum": "SHA-256:8341493abc87e6ae468f4eda16c768b2ddb20c98336e1c491a3801ad823680ae", + "size": "45646032" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/xtensa-esp-elf-gdb-16.2_20250324-aarch64-apple-darwin21.1.tar.gz", - "archiveFileName": "xtensa-esp-elf-gdb-16.2_20250324-aarch64-apple-darwin21.1.tar.gz", - "checksum": "SHA-256:b6d85c0d76d653bb55f9d06b0cd509eab7e99db541c88b8c849c64827e9d74a9", - "size": "43538967" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/xtensa-esp-elf-gdb-16.3_20250913-aarch64-apple-darwin24.5.tar.gz", + "archiveFileName": "xtensa-esp-elf-gdb-16.3_20250913-aarch64-apple-darwin24.5.tar.gz", + "checksum": "SHA-256:251e3be9c9436d9ab7fee6c05519fd816a05e63bd47495e24ea4e354881a851c", + "size": "39809369" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/xtensa-esp-elf-gdb-16.2_20250324-i686-w64-mingw32.zip", - "archiveFileName": "xtensa-esp-elf-gdb-16.2_20250324-i686-w64-mingw32.zip", - "checksum": "SHA-256:f748d6b65fdf66733b82e12d0d85a05e3134122416280379df129cfebe2aa4b2", - "size": "32189419" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/xtensa-esp-elf-gdb-16.3_20250913-i686-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-gdb-16.3_20250913-i686-w64-mingw32.zip", + "checksum": "SHA-256:8fc9fa6a934523b6ad6e787cf1664d48496bae456fd85ea7589e3684ce3bbbe5", + "size": "32824604" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/xtensa-esp-elf-gdb-16.2_20250324-x86_64-w64-mingw32.zip", - "archiveFileName": "xtensa-esp-elf-gdb-16.2_20250324-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:e970fc3ec8a1d0acee2432e91e0a01b348613a0425aacfa981b2fc505fe920cc", - "size": "32290997" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/xtensa-esp-elf-gdb-16.3_20250913-x86_64-w64-mingw32.zip", + "archiveFileName": "xtensa-esp-elf-gdb-16.3_20250913-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:99a2243b9a75bbac95a672cc3ab4b36013429ab5b4583e7a28339e3015a3fdfa", + "size": "33835839" } ] }, { "name": "riscv32-esp-elf-gcc", - "version": "esp-14.2.0_20241119", + "version": "esp-14.2.0_20250730", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:a16942465d33c7f0334c16e83bc6feb62e06eeb79cf19099293480bb8d48c0cd", - "size": "593721156" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/riscv32-esp-elf-14.2.0_20250730-x86_64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20250730-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:05b3fe041866c2bee400c3a5bc591beb710795aee3bab63b7c95e2e47f1f4cf4", + "size": "596288860" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-aarch64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:22486233d0e0fd58a54ae453b701f195f1432fc6f2e17085b9d6c8d5d9acefb7", - "size": "587879927" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/riscv32-esp-elf-14.2.0_20250730-aarch64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20250730-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:e1c63b7dc9348af0a642b1694a7f5b83fdb08ad1fb4ec0742f52864eddfe0573", + "size": "590413157" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-arm-linux-gnueabi.tar.gz", - "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:27a72d5d96cdb56dae2a1da5dfde1717c18a8c1f9a1454c8e34a8bd34abe662d", - "size": "586531522" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/riscv32-esp-elf-14.2.0_20250730-arm-linux-gnueabi.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20250730-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:433a232e515a75f9155ab50900cfeb25f6522f40faf9e24a0126d67448e31784", + "size": "589108924" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-i586-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-i586-linux-gnu.tar.gz", - "checksum": "SHA-256:b7bd6e4cd53a4c55831d48e96a3d500bfffb091bec84a30bc8c3ad687e3eb3a2", - "size": "597070471" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/riscv32-esp-elf-14.2.0_20250730-i586-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20250730-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:b28e95b39f64e485da4cb9e2c93904cefeb46ce17390cfe8844cbd96354921d4", + "size": "599653621" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-x86_64-apple-darwin_signed.tar.gz", - "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-x86_64-apple-darwin_signed.tar.gz", - "checksum": "SHA-256:5f8b571e1aedbe9f856f3bdeca6600cd5510ccff1ca102c4f001421eda560585", - "size": "602343061" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/riscv32-esp-elf-14.2.0_20250730-x86_64-apple-darwin.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20250730-x86_64-apple-darwin.tar.gz", + "checksum": "SHA-256:07fc04efb5ee40c75f526761424d1e8cd1b486393b8edc1dc558a5eaa6524120", + "size": "604869144" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-aarch64-apple-darwin_signed.tar.gz", - "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-aarch64-apple-darwin_signed.tar.gz", - "checksum": "SHA-256:a7276042a7eb2d33c2dff7167539e445c32c07d43a2c6827e86d035642503e0b", - "size": "578521565" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/riscv32-esp-elf-14.2.0_20250730-aarch64-apple-darwin.tar.gz", + "archiveFileName": "riscv32-esp-elf-14.2.0_20250730-aarch64-apple-darwin.tar.gz", + "checksum": "SHA-256:654e2c0d14e8c8955a166a800af9081bd2fdad41a89c20659a20eeff6c0f287b", + "size": "581049206" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-i686-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-i686-w64-mingw32.zip", - "checksum": "SHA-256:54193a97bd75205678ead8d11f00b351cfa3c2a6e5ab5d966341358b9f9422d7", - "size": "672055172" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/riscv32-esp-elf-14.2.0_20250730-i686-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-14.2.0_20250730-i686-w64-mingw32.zip", + "checksum": "SHA-256:ac8816920e0bc6c4032abc27f4962b2b2f59b231ed86e0002476196f9f1f0d35", + "size": "686131875" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20241119/riscv32-esp-elf-14.2.0_20241119-x86_64-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-14.2.0_20241119-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:24c8407fa467448d394e0639436a5ede31caf1838e35e8435e19df58ebed438c", - "size": "677812937" + "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20250730/riscv32-esp-elf-14.2.0_20250730-x86_64-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-14.2.0_20250730-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:a41e5219f0ff66cde3da3ac096b55d60fef4a1fb746590893c4c47f5437f192a", + "size": "692761883" } ] }, { "name": "riscv32-esp-elf-gdb", - "version": "16.2_20250324", + "version": "16.3_20250913", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/riscv32-esp-elf-gdb-16.2_20250324-x86_64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-16.2_20250324-x86_64-linux-gnu.tar.gz", - "checksum": "SHA-256:f9b172d8d72d0a1e2b0b80127df29263a0cb0d0c4e998e09c27031bfac09f3ec", - "size": "36528201" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/riscv32-esp-elf-gdb-16.3_20250913-x86_64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-16.3_20250913-x86_64-linux-gnu.tar.gz", + "checksum": "SHA-256:4e3cf8b7d11c7a2d1b50f40b1c50c0671dfe7eb13782c27c8a8cfdc8548bcdd4", + "size": "36557187" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/riscv32-esp-elf-gdb-16.2_20250324-aarch64-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-16.2_20250324-aarch64-linux-gnu.tar.gz", - "checksum": "SHA-256:68bb6a85fb58b8a738f799e8fb4fa1f56cfeffc4de803ceb03c8a33cb2cd919d", - "size": "35643464" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/riscv32-esp-elf-gdb-16.3_20250913-aarch64-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-16.3_20250913-aarch64-linux-gnu.tar.gz", + "checksum": "SHA-256:8f1f4f24fa534c76ed9d71efffbf728cc30169e911742d7bd67dd0fdcf5f3ae3", + "size": "35664185" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/riscv32-esp-elf-gdb-16.2_20250324-arm-linux-gnueabi.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-16.2_20250324-arm-linux-gnueabi.tar.gz", - "checksum": "SHA-256:673038ab9fb2b7391ff9252824194e3b9e40668efe9ce54d1e582a9d6c51f04a", - "size": "32154574" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/riscv32-esp-elf-gdb-16.3_20250913-arm-linux-gnueabi.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-16.3_20250913-arm-linux-gnueabi.tar.gz", + "checksum": "SHA-256:ac4fc85e3daf190b21598ec468933dc2659033580715560f45827da25e15b285", + "size": "32183532" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/riscv32-esp-elf-gdb-16.2_20250324-i586-linux-gnu.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-16.2_20250324-i586-linux-gnu.tar.gz", - "checksum": "SHA-256:62f05d5fe08145b25e423dd0b3f1ae260be99abf5462b8cfd918bf2231e26e30", - "size": "35410891" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/riscv32-esp-elf-gdb-16.3_20250913-i586-linux-gnu.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-16.3_20250913-i586-linux-gnu.tar.gz", + "checksum": "SHA-256:905dcd78558d7d559a95dc1eacc4572ea908be4ae6b1c937ea63a98df4482ca9", + "size": "35438945" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/riscv32-esp-elf-gdb-16.2_20250324-x86_64-apple-darwin21.1.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-16.2_20250324-x86_64-apple-darwin21.1.tar.gz", - "checksum": "SHA-256:63ae12cfbab648e2d2ca7a700a0c615c4f36a6fbe6876c11ba108115ee0d60f2", - "size": "55359246" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/riscv32-esp-elf-gdb-16.3_20250913-x86_64-apple-darwin24.5.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-16.3_20250913-x86_64-apple-darwin24.5.tar.gz", + "checksum": "SHA-256:2d5e5efead0b189e13cfe2670ca9d6d5965378ef3632d0b163a14f2f0536c274", + "size": "45892529" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/riscv32-esp-elf-gdb-16.2_20250324-aarch64-apple-darwin21.1.tar.gz", - "archiveFileName": "riscv32-esp-elf-gdb-16.2_20250324-aarch64-apple-darwin21.1.tar.gz", - "checksum": "SHA-256:bfbe49774f839020cef988537da0a06896dfe4a382674c62285361ed9bd4aee3", - "size": "43926592" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/riscv32-esp-elf-gdb-16.3_20250913-aarch64-apple-darwin24.5.tar.gz", + "archiveFileName": "riscv32-esp-elf-gdb-16.3_20250913-aarch64-apple-darwin24.5.tar.gz", + "checksum": "SHA-256:92771492084746fd22521c7c5b52bf1ed6dd86ef3cafe60e771bbdb4f0943f5a", + "size": "40145407" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/riscv32-esp-elf-gdb-16.2_20250324-i686-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-gdb-16.2_20250324-i686-w64-mingw32.zip", - "checksum": "SHA-256:e8b84eec990ff514729b3770edf2b543f36670f43663ce0c3b624fb4884812ca", - "size": "32914955" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/riscv32-esp-elf-gdb-16.3_20250913-i686-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-gdb-16.3_20250913-i686-w64-mingw32.zip", + "checksum": "SHA-256:c6a36c469d3b76e2b442be207814f7c3f71f21faf6faab4dd33fdedd56d89c01", + "size": "33531234" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.2_20250324/riscv32-esp-elf-gdb-16.2_20250324-x86_64-w64-mingw32.zip", - "archiveFileName": "riscv32-esp-elf-gdb-16.2_20250324-x86_64-w64-mingw32.zip", - "checksum": "SHA-256:37c79178900c19ca7487c26af4b5ad6b0d3f34683bd0e9c2ddd39038c999e429", - "size": "32667353" + "url": "https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v16.3_20250913/riscv32-esp-elf-gdb-16.3_20250913-x86_64-w64-mingw32.zip", + "archiveFileName": "riscv32-esp-elf-gdb-16.3_20250913-x86_64-w64-mingw32.zip", + "checksum": "SHA-256:32e79cb43b40f3b256193139b1fefd2782e3eaf82ee317b757ec8ba18b35159d", + "size": "34196400" } ] }, diff --git a/platform.txt b/platform.txt index 82560190c8f..a9258e8d7a5 100644 --- a/platform.txt +++ b/platform.txt @@ -1,5 +1,5 @@ name=ESP32 Arduino -version=3.3.0 +version=3.3.2 tools.esp32-arduino-libs.path={runtime.platform.path}/tools/esp32-arduino-libs tools.esp32-arduino-libs.path.windows={runtime.platform.path}\tools\esp32-arduino-libs diff --git a/tests/performance/coremark/test_coremark.py b/tests/performance/coremark/test_coremark.py index befd7c3a1c9..f314ebcfdfa 100644 --- a/tests/performance/coremark/test_coremark.py +++ b/tests/performance/coremark/test_coremark.py @@ -46,7 +46,7 @@ def test_coremark(dut, request): current_folder = os.path.dirname(request.path) file_index = 0 - report_file = os.path.join(current_folder, "result_coremark" + str(file_index) + ".json") + report_file = os.path.join(current_folder, dut.app.target, "result_coremark" + str(file_index) + ".json") while os.path.exists(report_file): report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") file_index += 1 diff --git a/tests/performance/fibonacci/test_fibonacci.py b/tests/performance/fibonacci/test_fibonacci.py index cf560d9691c..c7df59bb3aa 100644 --- a/tests/performance/fibonacci/test_fibonacci.py +++ b/tests/performance/fibonacci/test_fibonacci.py @@ -68,7 +68,7 @@ def test_fibonacci(dut, request): current_folder = os.path.dirname(request.path) file_index = 0 - report_file = os.path.join(current_folder, "result_fibonacci" + str(file_index) + ".json") + report_file = os.path.join(current_folder, dut.app.target, "result_fibonacci" + str(file_index) + ".json") while os.path.exists(report_file): report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") file_index += 1 diff --git a/tests/performance/linpack_double/test_linpack_double.py b/tests/performance/linpack_double/test_linpack_double.py index 0a6e2f90ef3..bd6c52cac17 100644 --- a/tests/performance/linpack_double/test_linpack_double.py +++ b/tests/performance/linpack_double/test_linpack_double.py @@ -49,7 +49,7 @@ def test_linpack_double(dut, request): current_folder = os.path.dirname(request.path) file_index = 0 - report_file = os.path.join(current_folder, "result_linpack_double" + str(file_index) + ".json") + report_file = os.path.join(current_folder, dut.app.target, "result_linpack_double" + str(file_index) + ".json") while os.path.exists(report_file): report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") file_index += 1 diff --git a/tests/performance/linpack_float/test_linpack_float.py b/tests/performance/linpack_float/test_linpack_float.py index d11f6c74136..d4c333d8e70 100644 --- a/tests/performance/linpack_float/test_linpack_float.py +++ b/tests/performance/linpack_float/test_linpack_float.py @@ -49,7 +49,7 @@ def test_linpack_float(dut, request): current_folder = os.path.dirname(request.path) file_index = 0 - report_file = os.path.join(current_folder, "result_linpack_float" + str(file_index) + ".json") + report_file = os.path.join(current_folder, dut.app.target, "result_linpack_float" + str(file_index) + ".json") while os.path.exists(report_file): report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") file_index += 1 diff --git a/tests/performance/psramspeed/ci.json b/tests/performance/psramspeed/ci.json index 341df103671..e981565f0ca 100644 --- a/tests/performance/psramspeed/ci.json +++ b/tests/performance/psramspeed/ci.json @@ -1,4 +1,18 @@ { + "soc_tags": { + "esp32": [ + "psram" + ], + "esp32s2": [ + "psram" + ], + "esp32s3": [ + "octal_psram" + ], + "esp32c5": [ + "psram" + ] + }, "platforms": { "qemu": false, "wokwi": false diff --git a/tests/performance/psramspeed/test_psramspeed.py b/tests/performance/psramspeed/test_psramspeed.py index 9e96e158504..68467478eba 100644 --- a/tests/performance/psramspeed/test_psramspeed.py +++ b/tests/performance/psramspeed/test_psramspeed.py @@ -93,7 +93,7 @@ def test_psramspeed(dut, request): current_folder = os.path.dirname(request.path) file_index = 0 - report_file = os.path.join(current_folder, "result_psramspeed" + str(file_index) + ".json") + report_file = os.path.join(current_folder, dut.app.target, "result_psramspeed" + str(file_index) + ".json") while os.path.exists(report_file): report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") file_index += 1 diff --git a/tests/performance/ramspeed/test_ramspeed.py b/tests/performance/ramspeed/test_ramspeed.py index dbe1670d329..987b6c00066 100644 --- a/tests/performance/ramspeed/test_ramspeed.py +++ b/tests/performance/ramspeed/test_ramspeed.py @@ -93,7 +93,7 @@ def test_ramspeed(dut, request): current_folder = os.path.dirname(request.path) file_index = 0 - report_file = os.path.join(current_folder, "result_ramspeed" + str(file_index) + ".json") + report_file = os.path.join(current_folder, dut.app.target, "result_ramspeed" + str(file_index) + ".json") while os.path.exists(report_file): report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") file_index += 1 diff --git a/tests/performance/superpi/test_superpi.py b/tests/performance/superpi/test_superpi.py index 0bd7a3477b6..4e99bbb1c1b 100644 --- a/tests/performance/superpi/test_superpi.py +++ b/tests/performance/superpi/test_superpi.py @@ -41,7 +41,7 @@ def test_superpi(dut, request): current_folder = os.path.dirname(request.path) file_index = 0 - report_file = os.path.join(current_folder, "result_superpi" + str(file_index) + ".json") + report_file = os.path.join(current_folder, dut.app.target, "result_superpi" + str(file_index) + ".json") while os.path.exists(report_file): report_file = report_file.replace(str(file_index) + ".json", str(file_index + 1) + ".json") file_index += 1 diff --git a/tests/requirements.txt b/tests/requirements.txt index b2bae3b86d0..29b7d531bd4 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,8 +1,8 @@ cryptography==44.0.1 --only-binary cryptography pytest-cov==5.0.0 -pytest-embedded-serial-esp==1.12.0 -pytest-embedded-arduino==1.12.0 -pytest-embedded-wokwi==1.12.0 -pytest-embedded-qemu==1.12.0 -esptool==4.8.1 +pytest-embedded-serial-esp==2.1.0 +pytest-embedded-arduino==2.1.0 +pytest-embedded-wokwi==2.1.0 +pytest-embedded-qemu==2.1.0 +esptool==5.1.0 diff --git a/tests/validation/gpio/test_gpio.py b/tests/validation/gpio/test_gpio.py index 8aa3a42dcc6..42010ab520b 100644 --- a/tests/validation/gpio/test_gpio.py +++ b/tests/validation/gpio/test_gpio.py @@ -1,16 +1,17 @@ import logging +from pytest_embedded_wokwi import Wokwi +from pytest_embedded import Dut -def test_gpio(dut): +def test_gpio(dut: Dut, wokwi: Wokwi): LOGGER = logging.getLogger(__name__) + LOGGER.info("Waiting for Button test begin...") dut.expect_exact("Button test") - LOGGER.info("Expecting button press 1") - dut.expect_exact("Button pressed 1 times") + for i in range(3): + LOGGER.info(f"Setting button pressed for {i + 1} seconds") + wokwi.client.set_control("btn1", "pressed", 1) - LOGGER.info("Expecting button press 2") - dut.expect_exact("Button pressed 2 times") - - LOGGER.info("Expecting button press 3") - dut.expect_exact("Button pressed 3 times") + dut.expect_exact(f"Button pressed {i + 1} times") + wokwi.client.set_control("btn1", "pressed", 0) diff --git a/tests/validation/psram/ci.json b/tests/validation/psram/ci.json index 999d3be953e..4d426d38c30 100644 --- a/tests/validation/psram/ci.json +++ b/tests/validation/psram/ci.json @@ -1,4 +1,18 @@ { + "soc_tags": { + "esp32": [ + "psram" + ], + "esp32s2": [ + "psram" + ], + "esp32s3": [ + "octal_psram" + ], + "esp32c5": [ + "psram" + ] + }, "platforms": { "qemu": false }, diff --git a/tests/validation/wifi/ci.json b/tests/validation/wifi/ci.json index 36e91b221cb..54dd47ae9a9 100644 --- a/tests/validation/wifi/ci.json +++ b/tests/validation/wifi/ci.json @@ -1,5 +1,5 @@ { - "extra_tags": [ + "tags": [ "wifi" ], "fqbn": { diff --git a/tools/espota.exe b/tools/espota.exe index 6b132d5b950..2748d038100 100644 Binary files a/tools/espota.exe and b/tools/espota.exe differ diff --git a/tools/espota.py b/tools/espota.py index e474aeffe3b..bc06cec87bf 100755 --- a/tools/espota.py +++ b/tools/espota.py @@ -6,6 +6,7 @@ # Modified since 2015-09-18 from Pascal Gollor (https://github.com/pgollor) # Modified since 2015-11-09 from Hristo Gochkov (https://github.com/me-no-dev) # Modified since 2016-01-03 from Matthew O'Gorman (https://githumb.com/mogorman) +# Modified since 2025-09-04 from Lucas Saavedra Vaz (https://github.com/lucasssvaz) # # This script will push an OTA update to the ESP # use it like: @@ -36,6 +37,19 @@ # - Incorporated exception handling to catch and handle potential errors. # - Made variable names more descriptive for better readability. # - Introduced constants for better code maintainability. +# +# Changes +# 2025-09-04: +# - Changed authentication to use PBKDF2-HMAC-SHA256 for challenge/response +# +# Changes +# 2025-09-18: +# - Fixed authentication when using old images with MD5 passwords +# +# Changes +# 2025-10-07: +# - Fixed authentication when images might use old MD5 hashes stored in the firmware + from __future__ import print_function import socket @@ -81,101 +95,284 @@ def update_progress(progress): sys.stderr.flush() -def serve(remote_addr, local_addr, remote_port, local_port, password, filename, command=FLASH): # noqa: C901 - # Create a TCP/IP socket - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - server_address = (local_addr, local_port) - logging.info("Starting on %s:%s", str(server_address[0]), str(server_address[1])) - try: - sock.bind(server_address) - sock.listen(1) - except Exception as e: - logging.error("Listen Failed: %s", str(e)) - return 1 - - content_size = os.path.getsize(filename) - with open(filename, "rb") as f: - file_md5 = hashlib.md5(f.read()).hexdigest() - logging.info("Upload size: %d", content_size) - message = "%d %d %d %s\n" % (command, local_port, content_size, file_md5) - - # Wait for a connection +def send_invitation_and_get_auth_challenge(remote_addr, remote_port, message): + """ + Send invitation to ESP device and get authentication challenge. + Returns (success, auth_data, error_message) tuple. + """ + remote_address = (remote_addr, int(remote_port)) inv_tries = 0 data = "" + msg = "Sending invitation to %s " % remote_addr sys.stderr.write(msg) sys.stderr.flush() + while inv_tries < 10: inv_tries += 1 sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - remote_address = (remote_addr, int(remote_port)) try: sent = sock2.sendto(message.encode(), remote_address) # noqa: F841 except: # noqa: E722 sys.stderr.write("failed\n") sys.stderr.flush() sock2.close() - logging.error("Host %s Not Found", remote_addr) - return 1 + return False, None, "Host %s Not Found" % remote_addr + sock2.settimeout(TIMEOUT) try: - data = sock2.recv(69).decode() # "AUTH " + 64-char SHA256 nonce + # Try to read up to 69 bytes for new protocol (SHA256) + # If device sends less (37 bytes), it's using old MD5 protocol + data = sock2.recv(69).decode() + sock2.close() break except: # noqa: E722 sys.stderr.write(".") sys.stderr.flush() sock2.close() + sys.stderr.write("\n") sys.stderr.flush() + if inv_tries == 10: - logging.error("No response from the ESP") + return False, None, "No response from the ESP" + + return True, data, None + + +def authenticate( + remote_addr, remote_port, password, use_md5_password, use_old_protocol, filename, content_size, file_md5, nonce +): + """ + Perform authentication with the ESP device. + + Args: + use_md5_password: If True, hash password with MD5 instead of SHA256 + use_old_protocol: If True, use old MD5 challenge/response protocol (pre-3.3.1) + + Returns (success, error_message) tuple. + """ + cnonce_text = "%s%u%s%s" % (filename, content_size, file_md5, remote_addr) + remote_address = (remote_addr, int(remote_port)) + + if use_old_protocol: + # Generate client nonce (cnonce) + cnonce = hashlib.md5(cnonce_text.encode()).hexdigest() + + # Old MD5 challenge/response protocol (pre-3.3.1) + # 1. Hash the password with MD5 + password_hash = hashlib.md5(password.encode()).hexdigest() + + # 2. Create challenge response + challenge = "%s:%s:%s" % (password_hash, nonce, cnonce) + response = hashlib.md5(challenge.encode()).hexdigest() + expected_response_length = 32 + else: + # Generate client nonce (cnonce) using SHA256 for new protocol + cnonce = hashlib.sha256(cnonce_text.encode()).hexdigest() + + # New PBKDF2-HMAC-SHA256 challenge/response protocol (3.3.1+) + # The password can be hashed with either MD5 or SHA256 + if use_md5_password: + # Use MD5 for password hash (for devices that stored MD5 hashes) + logging.warning( + "Using insecure MD5 hash for password due to legacy device support. " + "Please upgrade devices to ESP32 Arduino Core 3.3.1+ for improved security." + ) + password_hash = hashlib.md5(password.encode()).hexdigest() + else: + # Use SHA256 for password hash (recommended) + password_hash = hashlib.sha256(password.encode()).hexdigest() + + # 2. Derive key using PBKDF2-HMAC-SHA256 with the password hash + salt = nonce + ":" + cnonce + derived_key = hashlib.pbkdf2_hmac("sha256", password_hash.encode(), salt.encode(), 10000) + derived_key_hex = derived_key.hex() + + # 3. Create challenge response + challenge = derived_key_hex + ":" + nonce + ":" + cnonce + response = hashlib.sha256(challenge.encode()).hexdigest() + expected_response_length = 64 + + # Send authentication response + sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + message = "%d %s %s\n" % (AUTH, cnonce, response) + sock2.sendto(message.encode(), remote_address) + sock2.settimeout(10) + try: + data = sock2.recv(expected_response_length).decode() + except: # noqa: E722 + sock2.close() + return False, "No Answer to our Authentication" + + if data != "OK": + sock2.close() + return False, data + + sock2.close() + return True, None + except Exception as e: + sock2.close() + return False, str(e) + + +def serve( # noqa: C901 + remote_addr, local_addr, remote_port, local_port, password, md5_target, filename, command=FLASH +): + # Create a TCP/IP socket + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_address = (local_addr, local_port) + logging.info("Starting on %s:%s", str(server_address[0]), str(server_address[1])) + try: + sock.bind(server_address) + sock.listen(1) + except Exception as e: + logging.error("Listen Failed: %s", str(e)) return 1 + + content_size = os.path.getsize(filename) + with open(filename, "rb") as f: + file_md5 = hashlib.md5(f.read()).hexdigest() + logging.info("Upload size: %d", content_size) + message = "%d %d %d %s\n" % (command, local_port, content_size, file_md5) + + # Send invitation and get authentication challenge + success, data, error = send_invitation_and_get_auth_challenge(remote_addr, remote_port, message) + if not success: + logging.error(error) + return 1 + if data != "OK": if data.startswith("AUTH"): nonce = data.split()[1] + nonce_length = len(nonce) - # Generate client nonce (cnonce) - cnonce_text = "%s%u%s%s" % (filename, content_size, file_md5, remote_addr) - cnonce = hashlib.sha256(cnonce_text.encode()).hexdigest() - - # PBKDF2-HMAC-SHA256 challenge/response protocol - # The ESP32 stores the password as SHA256 hash, so we need to hash the password first - # 1. Hash the password with SHA256 (to match ESP32 storage) - password_hash = hashlib.sha256(password.encode()).hexdigest() + # Detect protocol version based on nonce length: + # - 32 chars = Old MD5 protocol (pre-3.3.1) + # - 64 chars = New SHA256 protocol (3.3.1+) - # 2. Derive key using PBKDF2-HMAC-SHA256 with the password hash - salt = nonce + ":" + cnonce - derived_key = hashlib.pbkdf2_hmac("sha256", password_hash.encode(), salt.encode(), 10000) - derived_key_hex = derived_key.hex() + if nonce_length == 32: + # Scenario 1: Old device (pre-3.3.1) using MD5 protocol + logging.info("Detected old MD5 protocol (pre-3.3.1)") + sys.stderr.write("Authenticating (MD5 protocol)...") + sys.stderr.flush() + auth_success, auth_error = authenticate( + remote_addr, + remote_port, + password, + use_md5_password=True, + use_old_protocol=True, + filename=filename, + content_size=content_size, + file_md5=file_md5, + nonce=nonce, + ) + + if not auth_success: + sys.stderr.write("FAIL\n") + logging.error("Authentication Failed: %s", auth_error) + return 1 - # 3. Create challenge response - challenge = derived_key_hex + ":" + nonce + ":" + cnonce - response = hashlib.sha256(challenge.encode()).hexdigest() + sys.stderr.write("OK\n") + logging.warning("====================================================================") + logging.warning("WARNING: Device is using old MD5 authentication protocol (pre-3.3.1)") + logging.warning("Please update to ESP32 Arduino Core 3.3.1+ for improved security.") + logging.warning("======================================================================") + + elif nonce_length == 64: + # New protocol (3.3.1+) - try SHA256 password first, then MD5 if it fails + + # Scenario 2: Try SHA256 password hash first (recommended for new devices) + if md5_target: + # User explicitly requested MD5 password hash + logging.info("Using MD5 password hash as requested") + sys.stderr.write("Authenticating (SHA256 protocol with MD5 password)...") + sys.stderr.flush() + auth_success, auth_error = authenticate( + remote_addr, + remote_port, + password, + use_md5_password=True, + use_old_protocol=False, + filename=filename, + content_size=content_size, + file_md5=file_md5, + nonce=nonce, + ) + else: + # Try SHA256 password hash first + sys.stderr.write("Authenticating...") + sys.stderr.flush() + auth_success, auth_error = authenticate( + remote_addr, + remote_port, + password, + use_md5_password=False, + use_old_protocol=False, + filename=filename, + content_size=content_size, + file_md5=file_md5, + nonce=nonce, + ) + + # Scenario 3: If SHA256 fails, try MD5 password hash (for devices with stored MD5 passwords) + if not auth_success: + logging.info("SHA256 password failed, trying MD5 password hash") + sys.stderr.write("Retrying with MD5 password...") + sys.stderr.flush() + + # Device is back in OTA_IDLE after auth failure, need to send new invitation + success, data, error = send_invitation_and_get_auth_challenge(remote_addr, remote_port, message) + if not success: + sys.stderr.write("FAIL\n") + logging.error("Failed to get new challenge for MD5 retry: %s", error) + return 1 + + if not data.startswith("AUTH"): + sys.stderr.write("FAIL\n") + logging.error("Expected AUTH challenge for MD5 retry, got: %s", data) + return 1 + + # Get new nonce for second attempt + nonce = data.split()[1] + + auth_success, auth_error = authenticate( + remote_addr, + remote_port, + password, + use_md5_password=True, + use_old_protocol=False, + filename=filename, + content_size=content_size, + file_md5=file_md5, + nonce=nonce, + ) + + if auth_success: + logging.warning("====================================================================") + logging.warning("WARNING: Device authenticated with MD5 password hash (deprecated)") + logging.warning("MD5 is cryptographically broken and should not be used.") + logging.warning( + "Please update your sketch to use either setPassword() or setPasswordHash()" + ) + logging.warning( + "with SHA256, then upload again to migrate to the new secure SHA256 protocol." + ) + logging.warning("======================================================================") + + if not auth_success: + sys.stderr.write("FAIL\n") + logging.error("Authentication Failed: %s", auth_error) + return 1 - sys.stderr.write("Authenticating...") - sys.stderr.flush() - message = "%d %s %s\n" % (AUTH, cnonce, response) - sock2.sendto(message.encode(), remote_address) - sock2.settimeout(10) - try: - data = sock2.recv(64).decode() # SHA256 produces 64 character response - except: # noqa: E722 - sys.stderr.write("FAIL\n") - logging.error("No Answer to our Authentication") - sock2.close() - return 1 - if data != "OK": - sys.stderr.write("FAIL\n") - logging.error("%s", data) - sock2.close() - sys.exit(1) + sys.stderr.write("OK\n") + else: + logging.error("Invalid nonce length: %d (expected 32 or 64)", nonce_length) return 1 - sys.stderr.write("OK\n") else: logging.error("Bad Answer: %s", data) - sock2.close() return 1 - sock2.close() logging.info("Waiting for device...") @@ -207,7 +404,9 @@ def serve(remote_addr, local_addr, remote_port, local_port, password, filename, try: connection.sendall(chunk) res = connection.recv(10) - last_response_contained_ok = "OK" in res.decode() + response_text = res.decode().strip() + last_response_contained_ok = "OK" in response_text + logging.debug("Chunk response: '%s'", response_text) except Exception as e: sys.stderr.write("\n") logging.error("Error Uploading: %s", str(e)) @@ -222,26 +421,43 @@ def serve(remote_addr, local_addr, remote_port, local_port, password, filename, sys.stderr.write("\n") logging.info("Waiting for result...") count = 0 - while count < 5: + received_any_response = False + while count < 10: # Increased from 5 to 10 attempts count += 1 - connection.settimeout(60) + connection.settimeout(30) # Reduced from 60s to 30s per attempt try: - data = connection.recv(32).decode() - logging.info("Result: %s", data) + data = connection.recv(32).decode().strip() + received_any_response = True + logging.info("Result attempt %d: '%s'", count, data) if "OK" in data: logging.info("Success") connection.close() return 0 + elif data: # Got some response but not OK + logging.warning("Unexpected response from device: '%s'", data) + except socket.timeout: + logging.debug("Timeout waiting for result (attempt %d/10)", count) + continue except Exception as e: - logging.error("Error receiving result: %s", str(e)) - connection.close() - return 1 - - logging.error("Error response from device") - connection.close() - return 1 + logging.debug("Error receiving result (attempt %d/10): %s", count, str(e)) + # Don't return error here, continue trying + continue + + # After all attempts, provide detailed error information + if received_any_response: + logging.warning( + "Upload completed but device sent unexpected response(s). This may still be successful." + ) + logging.warning("Device might be rebooting to apply firmware - this is normal.") + connection.close() + return 0 # Consider it successful if we got any response and upload completed + else: + logging.error("No response from device after upload completion") + logging.error("This could indicate device reboot (normal) or network issues") + connection.close() + return 1 except Exception as e: # noqa: E722 logging.error("Error: %s", str(e)) finally: @@ -269,6 +485,17 @@ def parse_args(unparsed_args): # authentication parser.add_argument("-a", "--auth", dest="auth", help="Set authentication password.", action="store", default="") + parser.add_argument( + "-m", + "--md5-target", + dest="md5_target", + help=( + "Use MD5 for password hashing (for devices with stored MD5 passwords). " + "By default, SHA256 is tried first, then MD5 as fallback." + ), + action="store_true", + default=False, + ) # image parser.add_argument("-f", "--file", dest="image", help="Image file.", metavar="FILE", default=None) @@ -335,7 +562,14 @@ def main(args): command = SPIFFS return serve( - options.esp_ip, options.host_ip, options.esp_port, options.host_port, options.auth, options.image, command + options.esp_ip, + options.host_ip, + options.esp_port, + options.host_port, + options.auth, + options.md5_target, + options.image, + command, ) diff --git a/variants/lolin_c3_pico/pins_arduino.h b/variants/lolin_c3_pico/pins_arduino.h index 45087c3f9fc..68897e6da05 100644 --- a/variants/lolin_c3_pico/pins_arduino.h +++ b/variants/lolin_c3_pico/pins_arduino.h @@ -14,8 +14,9 @@ static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; #define BUILTIN_LED LED_BUILTIN // backward compatibility #define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN // RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() -#define RGB_BUILTIN LED_BUILTIN -#define RGB_BRIGHTNESS 64 +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 64 +#define RGB_BUILTIN_LED_COLOR_ORDER LED_COLOR_ORDER_RGB static const uint8_t TX = 21; static const uint8_t RX = 20; diff --git a/variants/soldered_nula_mini_esp32c6/pins_arduino.h b/variants/soldered_nula_mini_esp32c6/pins_arduino.h new file mode 100644 index 00000000000..058ebdd3822 --- /dev/null +++ b/variants/soldered_nula_mini_esp32c6/pins_arduino.h @@ -0,0 +1,33 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "soc/soc_caps.h" + +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = 23; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t USER_BTN = 9; + +static const uint8_t TX = 16; +static const uint8_t RX = 17; + +static const uint8_t SDA = 6; +static const uint8_t SCL = 7; + +static const uint8_t SS = 2; +static const uint8_t MOSI = 3; +static const uint8_t MISO = 4; +static const uint8_t SCK = 5; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; +static const uint8_t A4 = 4; +static const uint8_t A5 = 5; +static const uint8_t A6 = 6; + +#endif /* Pins_Arduino_h */ diff --git a/variants/wesp32/pins_arduino.h b/variants/wesp32/pins_arduino.h index ad1ee1d225e..7be7f87f3f5 100644 --- a/variants/wesp32/pins_arduino.h +++ b/variants/wesp32/pins_arduino.h @@ -35,7 +35,7 @@ static const uint8_t T9 = 32; #define ETH_PHY_POWER -1 #define ETH_PHY_MDC 16 #define ETH_PHY_MDIO 17 -#define ETH_PHY_TYPE ETH_PHY_LAN8720 +#define ETH_PHY_TYPE ETH_PHY_RTL8201 #define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN #endif /* Pins_Arduino_h */